{"id":16696367,"url":"https://github.com/gbevan/vault-e2e-plugin","last_synced_at":"2026-06-19T08:32:38.668Z","repository":{"id":85850142,"uuid":"134152714","full_name":"gbevan/vault-e2e-plugin","owner":"gbevan","description":"Proof-of-concept Hashicorp Vault End-to-End Encryption Plugin with JSON secret interpolation","archived":false,"fork":false,"pushed_at":"2018-06-16T19:54:27.000Z","size":221,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-10T02:00:37.844Z","etag":null,"topics":["e2e-encryption","educational-project","encryption","enrollment","hashicorp-vault","json","secret"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gbevan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-20T13:24:43.000Z","updated_at":"2024-06-27T17:31:55.000Z","dependencies_parsed_at":"2023-03-06T20:45:47.069Z","dependency_job_id":null,"html_url":"https://github.com/gbevan/vault-e2e-plugin","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gbevan/vault-e2e-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbevan%2Fvault-e2e-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbevan%2Fvault-e2e-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbevan%2Fvault-e2e-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbevan%2Fvault-e2e-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gbevan","download_url":"https://codeload.github.com/gbevan/vault-e2e-plugin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gbevan%2Fvault-e2e-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34523982,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["e2e-encryption","educational-project","encryption","enrollment","hashicorp-vault","json","secret"],"created_at":"2024-10-12T17:27:59.241Z","updated_at":"2026-06-19T08:32:38.652Z","avatar_url":"https://github.com/gbevan.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hashicorp Vault End-to-End Encryption Plugin\n\nA proof-of-concept plugin for Hashicorp Vault to provide end-to-end encryption of\nsecret interpolated JSON payloads using RSA-2048 and AES256GCM.\n\nAllows for the enrolment of a recipient’s RSA public key, and use of this key\nto encrypt JSON encoded payloads which can only be decrypted using the\nrecipient's RSA private key.\n\nThis plugin was written for educational purposes while learning the Go\nlanguage (golang) and Hashicorp Vault.\n\n![Architecture](docs/plugin_arch.png)\n\n## Secret Interpolation\nThe plugin only supports kv secrets under it's own `/e2e/` mount point.\nA json payload can request these secrets to be interpolated into the payload,\ne.g.:\n```\n{\n  \"payload\": {\n    \"level1\": {\n      \"level2\": {\n        \"level3\": {\n          \"level4\": {\n            \"level5\": {\n              \"field1@/e2e/kv/Customer1/Actor1/secret-form.secret1\": true,\n              \"field2@/e2e/kv/Customer1/Actor1/secret-form.secret2\": true\n            }\n          }\n        }\n      },\n      \"fromdeep@/e2e/kv/Customer1/Actor1/secret-form.nested.level2.deepsecret\": true,\n      \"missing_novar@/e2e/kv/Customer1/Actor1/secret-form.willnotbefound\": true,\n      \"missing_nopath@/e2e/kv/Customer1/Actor1/nopath.willnotbefound\": true\n    }\n  }\n}\n```\nkeys like `fieldname@/e2e/pathto/secret.nested.field.value` can be encoded and\nthis will resolve to the field nested within the json encoded secret.\nThe value is then included in the returned encrypted payload as `\"fieldname\": \"value\"`.\n\nThe api returns:\n```\n{\n  \"request_id\": \"480a6c54-e23f-a04e-547e-80aa048753be\",\n  \"lease_id\": \"\",\n  \"renewable\": false,\n  \"lease_duration\": 0,\n  \"data\": {\n    \"errorcount\": 2,\n    \"errors\": [\n      \"  1) `missing_nopath@/e2e/kv/Customer1/Actor1/nopath.willnotbefound`: Error: path not found\",\n      \"  2) `missing_novar@/e2e/kv/Customer1/Actor1/secret-form.willnotbefound`: Error: template interpolation resolved to an empty string\"\n    ],\n    \"payload\": \"-----BEGIN E2E ENCRYPTED PAYLOAD-----\\nPAYLOAD_VERSION: 2.0\\n\\nAAE376QDTo8griCitf74dyy3v+NT+tANOK4vVduQKS1rnPKmZrw57WwpoaWtyMwhDz/zwen18BLT\\ndyDHer2eWTKlY58NLCfOnUZUlv5mAGmGOeL9omKNl+92Rg0X8NDycJQ1UgMdyMi3jjcfTuS0M+Nh\\nPQeYvnOfeKHjp4lvetZRmqPLTzLAfi7QoL0zT0UBrG3dZYYoS/RQQUW08ZdQ2noheqDAXn3ocSHM\\n7ZgBKKBRYbeJrVAdxYkZ97ogMmspfzzLlWWKstCCfiTdsjqhGTiUOnMf17QD+/bKGU1ndUQWOLcF\\nA8bBHZAygLd5dRlbbFpiyAWYG3d51011GoA7dKLcSBX4qA1LavwuiJx93KYWnCQU4zV6IAWPPuvo\\nYpeHgncaPSq5bq7OKT2IrYFem5oBfhmiC7FvAPHYCQaYx+JZMLTn3P53+7J1WqiCJET9bI/Cd3rY\\nVL7OEJxYcg3oKAPSlSasByfv/JoNO9VwMcmpoff5ORjJm8q2haNlDbyQjof5Xy+YQDDuC46NS4oX\\nj14fsXh7YmRx8eAnXhHg0zFAO42EKCok+cGDi/GuaO7myDadkLQ8A1qoflYgo50Uybe+jaQZPheK\\nU+i/khbZfHKy96c4Pv1Kp21wF86My55fMH/P0iXmrbHoQculJdKseOo4pyF+xjZHG5HKkRF8LVA2\\nwvyZ98Fj9TuShfmLm5xfonCjJS6Ot2mLye2XMiGhdXMmSvx4JSqpa8dX5NtHv/DkdXZ/qySEmZ1J\\nckmlpnBffC9Yyr7Qm0s89exf0TP5YKHnY84uR538fhc5j5E07P+MT4OyaL8O78H1z0XJ2UJ46Thn\\nPY8I1yN1dQy79Q==\\n-----END E2E ENCRYPTED PAYLOAD-----\"\n  },\n  \"wrap_info\": null,\n  \"warnings\": null,\n  \"auth\": null\n}\n```\npayload:\n```\n-----BEGIN E2E ENCRYPTED PAYLOAD-----\nPAYLOAD_VERSION: 2.0\n\nAAE376QDTo8griCitf74dyy3v+NT+tANOK4vVduQKS1rnPKmZrw57WwpoaWtyMwhDz/zwen18BLT\ndyDHer2eWTKlY58NLCfOnUZUlv5mAGmGOeL9omKNl+92Rg0X8NDycJQ1UgMdyMi3jjcfTuS0M+Nh\nPQeYvnOfeKHjp4lvetZRmqPLTzLAfi7QoL0zT0UBrG3dZYYoS/RQQUW08ZdQ2noheqDAXn3ocSHM\n7ZgBKKBRYbeJrVAdxYkZ97ogMmspfzzLlWWKstCCfiTdsjqhGTiUOnMf17QD+/bKGU1ndUQWOLcF\nA8bBHZAygLd5dRlbbFpiyAWYG3d51011GoA7dKLcSBX4qA1LavwuiJx93KYWnCQU4zV6IAWPPuvo\nYpeHgncaPSq5bq7OKT2IrYFem5oBfhmiC7FvAPHYCQaYx+JZMLTn3P53+7J1WqiCJET9bI/Cd3rY\nVL7OEJxYcg3oKAPSlSasByfv/JoNO9VwMcmpoff5ORjJm8q2haNlDbyQjof5Xy+YQDDuC46NS4oX\nj14fsXh7YmRx8eAnXhHg0zFAO42EKCok+cGDi/GuaO7myDadkLQ8A1qoflYgo50Uybe+jaQZPheK\nU+i/khbZfHKy96c4Pv1Kp21wF86My55fMH/P0iXmrbHoQculJdKseOo4pyF+xjZHG5HKkRF8LVA2\nwvyZ98Fj9TuShfmLm5xfonCjJS6Ot2mLye2XMiGhdXMmSvx4JSqpa8dX5NtHv/DkdXZ/qySEmZ1J\nckmlpnBffC9Yyr7Qm0s89exf0TP5YKHnY84uR538fhc5j5E07P+MT4OyaL8O78H1z0XJ2UJ46Thn\nPY8I1yN1dQy79Q==\n-----END E2E ENCRYPTED PAYLOAD-----\n```\nThe `payload` can then be sent to the recipient to be decrypted with their\nRSA private key.\n\n## Testing\nRun ./docker.sh to build the test docker container and run the tests.\nSee contents of the `test/bats` folder for the tests and example curl commands.\n\n## Decrypting\nA go program to decrypt the payload is available called `decrypt/decrypt.go`.\nTo run:\n```\nvault-e2e-plugin/test$ go run ../decrypt/decrypt.go -privkey test_key_rsa.pem \u003cpayload.txt |jq\n{\n  \"level1\": {\n    \"fromdeep\": \"this is a deep secret\",\n    \"level2\": {\n      \"level3\": {\n        \"level4\": {\n          \"level5\": {\n            \"field1\": \"this is secret 1\",\n            \"field2\": \"this is secret 2\"\n          }\n        }\n      }\n    },\n    \"missing_nopath@/e2e/kv/Customer1/Actor1/nopath.willnotbefound\": \"Error: path not found\",\n    \"missing_novar@/e2e/kv/Customer1/Actor1/secret-form.willnotbefound\": \"Error: template interpolation resolved to an empty string\"\n  }\n}\n```\n\n## Notes\n```\nvault write sys/plugins/catalog/e2e \\\n    sha_256=7db215b0a08eaae0bb111084ff598bd8f44b1faef85b230d7e1f8fa27096eff8 \\\n    command=\"vault-e2e-plugin\"\n\nvault secrets enable -path=e2e -plugin-name=e2e plugin\n```\n\n## Generate a RSA Key Pair (for testing)\n\n```\ngo run genrsapair/genrsapair.go [-prefix test/test_key]\n```\nto generate PEM key pair to stdout\n```\ngo run genrsapair/genrsapair.go \u0026\u0026  jq -Rsc . \u003c test/test_key_rsa_pub.pem \u003etest/test_key_rsa_pub_string.pem\n```\nto encode as json string array, that can be pasted into a curl command for\nenrolment.\n```\ncurl -s -H \"Accept: application/json\" \\\n  -H \"Content-type: application/json\" \\\n  --header \"X-Vault-Token: root\" \\\n  --request POST http://127.0.0.1:8210/v1/e2e/enrole/TEST \\\n  --data '{\"name\": \"TEST\", \"pubkey\":\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwbz8uJeyqUMfZe+dHYcq\\nAtQOtCjCzztLgPLNH/i+oQvlfiWZfmBtbYeEHVEPyd0O1hLM7cS3nUbY9JgHQQyC\\nYnVvGcz9/BrPzCksVqr6lyFM2/6hjkUqJv47xwVaaW464hwRB0dEDCxwJUtM4gIa\\nD4gwAfiHlU5BGRyDq0Cl0pwniN4othA12PZsFgM4F96MfpsLO5jNFmVcfjyFAq6k\\nEdYPjfHRgZmdkbOhlDLyx6FknE8L68QcANcQw3olGizgIW2MTdwCOuWk3oeohBvz\\nA0uYO6GdRxL1IIzOcy+IJqmhjbua6utwgOiiNQs7cxil4CEsmveYZ0Q8n18B+rIJ\\niQIDAQAB\\n-----END PUBLIC KEY-----\\n\"}'\n```\nCheck the enrolment entry in Vault E2E:\n```\ncurl -s -H \"Accept: application/json\" \\\n  -H \"Content-type: application/json\" \\\n  --header \"X-Vault-Token: root\" \\\n  http://127.0.0.1:8210/v1/e2e/enrole/TEST \\\n  -X GET | jq\n```\n```json\n{\n  \"request_id\": \"bc9f7b56-a22c-a80e-adec-f683ddb29bde\",\n  \"lease_id\": \"\",\n  \"renewable\": false,\n  \"lease_duration\": 0,\n  \"data\": {\n    \"enrole\": {\n      \"authorised\": false,\n      \"created\": \"2018-05-09T20:15:18.59043786Z\",\n      \"fingerprint\": \"Pubkey-finger-print-goes-here\",\n      \"name\": \"TEST\",\n      \"pubkey\": \"-----BEGIN RSA[2048] PUBLIC KEY-----\\nMIIBCgKCAQEAykQ6BB4ayKtzvQBoswbxOPaxblag6OMZ9an0ASMvkGAAkaIvkYUe\\nfVwNoeixWZsdFr7q8IVOonVWFBMCf5TFKm8GWN2HNnlePL5/GH3QOWYkbCBciF2D\\nEv9hiMRzoT9NmTH1m29x7sDfNTIndp2LGKTPLReGr866iPu7Res88chQQ+AC//wG\\n9Wqe9Xzlg4tCJd2TY36Ia6K2P0QTahp9hCha2U9pplzJZM37MpNhMqCHOxGuCLkL\\nPKy/F82AJ24+iHYLJnpDU0TVFjPoYTMKYh9R36bVl6yURPTIsW/CvYAYE9VBm5KS\\n6v5MZIfHqs16qq1AIVHZnfsXKDbmfBZEOwIDAQAB\\n-----END RSA[2048] PUBLIC KEY-----\\n\"\n    },\n    \"key\": \"enrole/TEST\"\n  },\n  \"wrap_info\": null,\n  \"warnings\": null,\n  \"auth\": null\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgbevan%2Fvault-e2e-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgbevan%2Fvault-e2e-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgbevan%2Fvault-e2e-plugin/lists"}