New to Kestra?
Use blueprints to kickstart your first workflows.
Verify OpenPGP digital signatures and MDC payload integrity on partner data files, gate unauthenticated transfers, and alert Slack on tamper.
Automate cryptographic admission control for partner and vendor data files. This blueprint verifies OpenPGP digital signatures and Modification Detection Code (MDC) integrity packets before sensitive data reaches downstream ingestion systems. Unsigned files, mismatched signer identities, or tampered bytes are intercepted and routed to quarantine alerts in Slack.
scheduled_verification_cycle (Schedule, 0 */6 * * *, disabled by default) runs periodic compliance checks across staged partner payloads.stage_audit_payload (io.kestra.plugin.scripts.shell.Commands) stages an audit manifest batch file in Kestra internal storage.encrypt_and_sign_payload (io.kestra.plugin.crypto.openpgp.Encrypt) encrypts the payload with the recipient public key and applies an ASCII-armored OpenPGP one-pass digital signature using the sender secret key.decrypt_and_verify_signature (io.kestra.plugin.crypto.openpgp.Decrypt, with allowFailure: true) decrypts the payload with the recipient private key, enforces SHA-256 one-pass signature verification against trusted public keys, and asserts that the signing identity matches expected_signer_identity. RFC 9580 and RFC 4880 MDC integrity verification occurs automatically during stream decryption.evaluate_signature_status (io.kestra.plugin.core.flow.Switch) evaluates outputs.decrypt_and_verify_signature.uri is defined. On success (VALID), log_compliance_verified confirms the cryptographic check, and check_dry_run_dispatch (If) either logs promotion via log_payload_promoted (when dry_run=false) or logs dry-run verification via log_dry_run_verified (when dry_run=true).QUARANTINE), evaluate_quarantine_alert (If) dispatches an incident card to Slack via alert_signature_tamper if quarantine_on_tamper=true, or logs quiet suppression via log_quarantine_suppressed if quarantine_on_tamper=false.log_audit_cycle_summary (io.kestra.plugin.core.log.Log) records the final audit summary with execution telemetry.alert_on_flow_error (SlackIncomingWebhook) in the flow-level errors block notifies on-call teams if unexpected runtime exceptions occur.plugin-crypto and plugin-slack available.SLACK_WEBHOOK: Incoming Webhook URL for Slack security notifications.PGP_RECIPIENT_PUBLIC_KEY: ASCII-armored OpenPGP public key of the receiving system (gpg --armor --export recipient@internal.example.com).PGP_RECIPIENT_PRIVATE_KEY: ASCII-armored OpenPGP private key of the receiving system (gpg --armor --export-secret-keys recipient@internal.example.com).PGP_RECIPIENT_PRIVATE_KEY_PASSPHRASE: Passphrase protecting the recipient private key (leave empty string if unencrypted).PGP_SENDER_PUBLIC_KEY: ASCII-armored OpenPGP public key of the sender partner (gpg --armor --export partner-secops@vendor.example.com).PGP_SENDER_PRIVATE_KEY: ASCII-armored OpenPGP private key of the sender partner for signing.PGP_SENDER_PRIVATE_KEY_PASSPHRASE: Passphrase protecting the sender signing private key.For open-source (OSS) Kestra setups, provide secrets as base64-encoded environment variables:
export SECRET_SLACK_WEBHOOK=$(echo -n "https://hooks.slack.com/services/T00/B00/XXXX" | base64)
export SECRET_PGP_RECIPIENT_PUBLIC_KEY=$(echo -n "-----BEGIN PGP PUBLIC KEY BLOCK-----..." | base64)
export SECRET_PGP_RECIPIENT_PRIVATE_KEY=$(echo -n "-----BEGIN PGP PRIVATE KEY BLOCK-----..." | base64)
export SECRET_PGP_RECIPIENT_PRIVATE_KEY_PASSPHRASE=$(echo -n "secret-passphrase" | base64)
export SECRET_PGP_SENDER_PUBLIC_KEY=$(echo -n "-----BEGIN PGP PUBLIC KEY BLOCK-----..." | base64)
export SECRET_PGP_SENDER_PRIVATE_KEY=$(echo -n "-----BEGIN PGP PRIVATE KEY BLOCK-----..." | base64)
export SECRET_PGP_SENDER_PRIVATE_KEY_PASSPHRASE=$(echo -n "secret-passphrase" | base64)
docker run --rm -it alpine sh -c "apk add --no-cache gnupg && gpg --batch --passphrase '' --quick-generate-key 'partner-secops@vendor.example.com' default default never && gpg --armor --export 'partner-secops@vendor.example.com'"
docker run -d --name pgp-mock-store -p 8085:8085 alpine sh -c "while true; do sleep 3600; done"
docker network connect YOUR_KESTRA_NETWORK pgp-mock-store
(Run docker network ls to locate your active Kestra Docker bridge network).disabled: false on scheduled_verification_cycle to automate continuous monitoring.VALID case to consume the verified cleartext URI ({{ outputs.decrypt_and_verify_signature.uri }}).QUARANTINE case to preserve tampered payloads for forensic analysis.expected_signer_identity (STRING, default "partner-secops@vendor.example.com"): Expected signer User ID or email identity matching the key ring.quarantine_on_tamper (SELECT: "true", "false", default "true"): Log incident telemetry and route tampered payloads to quarantine alerting.dry_run (SELECT: "true", "false", default "true"): Audit signature verification and decryption without downstream cleartext promotion.stage_audit_payload.outputFiles['audit_manifest.json']: Staged audit manifest file storage URI.encrypt_and_sign_payload.uri: Internal storage URI of the encrypted and signed OpenPGP message.decrypt_and_verify_signature.uri: Internal storage URI of the verified decrypted cleartext payload.-----BEGIN PGP PUBLIC KEY BLOCK----- and -----END PGP PUBLIC KEY BLOCK----- headers and trailers.io.kestra.plugin.crypto.openpgp.Decrypt task strictly rejects legacy unauthenticated SED packets (RFC 9580 Section 5.7). Messages must be created with integrity protection (SEIP or AEAD).{{ secret('NAME') }} to prevent Pebble template parsing errors.requiredSignerUsers validates against the primary User ID or parsed email address within angle brackets. Ensure the identity string in expected_signer_identity matches the key metadata exactly.