{"id":24617666,"url":"https://github.com/pacphi/cloudfoundry-and-nodejs-with-vault-demo","last_synced_at":"2025-08-30T02:04:20.640Z","repository":{"id":49186693,"uuid":"137181907","full_name":"pacphi/cloudfoundry-and-nodejs-with-vault-demo","owner":"pacphi","description":"This is a simple example of an integration between a REST API powered by NodeJS and Hashicorp Vault.","archived":false,"fork":false,"pushed_at":"2021-06-24T13:12:48.000Z","size":6,"stargazers_count":1,"open_issues_count":3,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-07-05T18:37:39.605Z","etag":null,"topics":["hashicorp-vault","nodejs","rest-api"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pacphi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-13T07:53:30.000Z","updated_at":"2022-01-05T04:10:06.000Z","dependencies_parsed_at":"2022-09-19T03:31:22.690Z","dependency_job_id":null,"html_url":"https://github.com/pacphi/cloudfoundry-and-nodejs-with-vault-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pacphi/cloudfoundry-and-nodejs-with-vault-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pacphi%2Fcloudfoundry-and-nodejs-with-vault-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pacphi%2Fcloudfoundry-and-nodejs-with-vault-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pacphi%2Fcloudfoundry-and-nodejs-with-vault-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pacphi%2Fcloudfoundry-and-nodejs-with-vault-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pacphi","download_url":"https://codeload.github.com/pacphi/cloudfoundry-and-nodejs-with-vault-demo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pacphi%2Fcloudfoundry-and-nodejs-with-vault-demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272793018,"owners_count":24993830,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-30T02:00:09.474Z","response_time":77,"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":["hashicorp-vault","nodejs","rest-api"],"created_at":"2025-01-24T23:39:51.810Z","updated_at":"2025-08-30T02:04:20.608Z","avatar_url":"https://github.com/pacphi.png","language":"JavaScript","readme":"# Using NodeJS and HashiCorp Vault with Cloud Foundry  \n\nThis is a simple example of an integration between REST API powered by NodeJS and [Hashicorp Vault](https://www.vaultproject.io).  \nA riff off the Spring Boot 2 and Spring Cloud Finchley implementation [here](https://github.com/pacphi/cloudfoundry-with-vault-demo).\n\n## Prerequisites\n\n* [CF CLI](https://github.com/cloudfoundry/cli#downloads) 6.37.0 or better if you want to push the application to a Cloud Foundry (CF) instance\n* [httpie](https://httpie.org/#installation) 0.9.9 or better to simplify interaction with API endpoints\n* Hashicorp [Vault](https://www.vaultproject.io/downloads.html) 0.12.0 or better\n* [NodeJS](https://nodejs.org/en/download/) 10.4.0 or better\n* [jq](https://stedolan.github.io/jq/) 1.5 or better to \n* [ngrok](https://ngrok.com) 2.28 or better to expose local servers behind NATs and firewalls to the public internet over secure tunnels\n\n\n## Clone\n\n```\ngit clone https://github.com/pacphi/cloudfoundry-and-nodejs-with-vault-demo.git\n```\n\n## How to build\n\n```\ncd cloudfoundry-and-nodejs-with-vault-demo\nnpm install\n```\n\n## How to run locally\n\n1. Start vault\n\n```bash\nvault server -config inmemory.conf\n```\n\n2. In another terminal set the VAULT_ADDR before initializing Vault\n\n```bash\nexport VAULT_ADDR=http://127.0.0.1:8200\n```   \n\n2. Initialize vault\n\n```bash\nvault operator init -key-shares=5 -key-threshold=2\n```\n\n3. Copy the `Initial Root Token` \n\n\u003e We will need it later.\n\n```bash\nexport VAULT_TOKEN=\u003ctoken\u003e\n```\n\nVault requires an authenticated access to proceed from here on. \nVault uses tokens as generic authentication on its transport level.\n\n4. Vault is in `sealed` mode, let's unseal it\n\n```\nvault operator unseal \u003ckey\u003e\nvault operator unseal \u003ckey\u003e\n```\n\n5. Verify that Vault is in `unsealed` mode\n\n```bash\nvault status | grep Sealed\n\nSealed: false\n```\n\n6. Write a secret into the `secret` backend\n\n```bash\nvault write secret/nodejs-vault-demo message='I find your lack of faith disturbing.'\n```\n\n7. Start the application in another terminal \n\n```bash\nexport VAULT_ADDR=http://127.0.0.1:8200\nexport VAULT_TOKEN=\u003ctoken\u003e\nnode app.js\n```\n\n8. Make a GET request to http://localhost:3000\n\n```bash\nhttp :3000\n\nI find your lack of faith disturbing.\n```\n\n9. Update the secret inside Vault\n\n```bash\nvault write secret/nodejs-vault-demo message='Now, young Skywalker, you will die.'\n```\n\n\u003e Changes to configuration are immediate\n\n12. Verify that the application knows about the latest secret\n\n```bash\nhttp :3000\n\nNow, young Skywalker, you will die.\n```\n\n## How to run on Cloud Foundry\n\n1. Using [Pivotal Web Services](https://run.pivotal.io/)\n\n\u003e This is Pivotal's Cloud Foundry as a Service offering\n\n```bash\ncf login -a api.run.pivotal.io\n```\n\n2. Get the [Open Service Broker API](https://www.openservicebrokerapi.org/) implementation from HashiCorp\n\n```bash\ngit clone https://github.com/hashicorp/vault-service-broker\n```\n\n3. You will  to change the `DefaultServiceID` and `DefaultServiceName` in the `main.go` file\n\n4. Deploy the broker\n   \n```bash\ncf push my-vault-broker-service -m 256M --random-route --no-start \n```\n   \nThe `--no-start` makes sure it is not started after it is deployed.\n\n5. Expose the locally running vault instance via [ngrok](https://ngrok.com/)\n\n```\nngrok http 8200\n\nForwarding http://3db1eef2.ngrok.io -\u003e localhost:8200\nForwarding https://3db1eef2.ngrok.io -\u003e localhost:8200\n```\n\n\u003e Note your ngrok URL will be different\n\n6. Open a browser and verify ngrok's web interface is available at `http://localhost:4040`\n\n7. Set the following environment variables\n\n```bash\nVAULT_ADDR=\u003cngrok_url\u003e\nVAULT_TOKEN=\u003ctoken\u003e\n```\n\nThe broker is configured to use basic authentication\n\n```bash\nVAULT_USERNAME=vault\nVAULT_PASSWORD=secret\n```\n\n\u003e You'll want to replace the username and password values above with your own.  Password must not contain `@`.\n\n8. Configure the environment variables\n\n```bash\ncf set-env my-vault-broker-service VAULT_ADDR ${VAULT_ADDR}\ncf set-env my-vault-broker-service VAULT_TOKEN ${VAULT_TOKEN}\ncf set-env my-vault-broker-service SECURITY_USER_NAME ${VAULT_USERNAME}\ncf set-env my-vault-broker-service SECURITY_USER_PASSWORD ${VAULT_PASSWORD}\n```\n\n9. Verify the configured environment variables \n\n```bash\ncf env my-vault-broker-service\n```\n\n10. Start the broker:\n\n```bash\ncf start my-vault-broker-service\n```\n\n11. Check the logs to verify a successful start\n\n```bash\ncf logs --recent my-vault-broker-service\n```\n\n12. Verify in the Ngrok Inspect UI the activity requests sent to the exposed Vault broker\n\n```bash\nGET /v1/sys/mounts\nPUT /v1/auth/token/renew-self\nPOST /v1/sys/mounts/cf/broker\nGET /v1/cf/broker\n```\n \n13. The service broker created a new mount\n \n```\nvault secrets list\n\n...\ncf/broker/  generic    generic_4c6ea7ec    n/a     system       system   false           replicated\n...\n``` \n\n14. View the running broker:\n\n```\ncf apps\n\nname                      requested state   instances   memory   disk   urls\nmy-vault-broker-service   started           1/1         256M     1G     vault-demo-twiggiest-sennit.cfapps.io\n```  \n\n15. Get the broker url\n\n```bash\nVAULT_BROKER_URL=$(cf app my-vault-broker-service | grep routes: | awk '{print $2}')\n```\n\n16. Get the catalog information:\n\n```bash\ncurl ${VAULT_USERNAME}:${VAULT_PASSWORD}@${VAULT_BROKER_URL}/v2/catalog | jq\n```\n\n```json\n{\n  \"services\": [\n    {\n      \"id\": \"42ff1ff1-244d-413a-87ab-b2334b801134\",\n      \"name\": \"my-hashicorp-vault\",\n      \"description\": \"HashiCorp Vault Service Broker\",\n      \"bindable\": true,\n      \"tags\": [\n        \"\"\n      ],\n      \"plan_updateable\": false,\n      \"plans\": [\n        {\n          \"id\": \"42ff1ff1-244d-413a-87ab-b2334b801134.shared\",\n          \"name\": \"shared\",\n          \"description\": \"Secure access to Vault's storage and transit backends\",\n          \"free\": true\n        }\n      ]\n    }\n  ]\n}\n```\n\n17. Create a service broker:\n\n```bash\ncf service-brokers\ncf create-service-broker my-vault-service-broker \"${VAULT_USERNAME}\" \"${VAULT_PASSWORD}\" \"https://${VAULT_BROKER_URL}\" --space-scoped\n```\n\n\u003e You need to specify the `--space-scoped` and the `service ids` and `service name` must be unique. See `https://docs.cloudfoundry.org/services/managing-service-brokers.html`\n\n18. Create a service instance\n\n```bash\ncf create-service my-hashicorp-vault shared my-vault-service\n``` \n\n\u003e Note that the first parameter to `cf create-service` must match the value of `DefaultServiceName` that you set in Step 3 above\n\n19. Verify the result\n\n```bash\ncf services\n\nname               service              plan     bound apps   last operation\nmy-vault-service   my-hashicorp-vault   shared                create succeeded\n```\n\n20. Verify the HTTP requests sent the exposed Vault service using the Ngrok Inspect UI:\n\n```bash\nPOST /v1/sys/mounts/cf/0b24f466-9a54-4215-852e-2bcfab428a82/secret\nPUT /v1/cf/broker/0b24f466-9a54-4215-852e-2bcfab428a82\nGET /v1/sys/mounts\nPOST /v1/sys/mounts/cf/0b24f466-9a54-4215-852e-2bcfab428a82/transit\nPOST /v1/sys/mounts/cf/be7eedf8-c813-49e1-98f8-2fc19370ee4d/secret\nPOST /v1/sys/mounts/cf/5f7b0811-d90a-47f2-a194-951eb324f867/secret\nPUT /v1/sys/policy/cf-0b24f466-9a54-4215-852e-2bcfab428a82\nPUT /v1/auth/token/roles/cf-0b24f466-9a54-4215-852e-2bcfab428a82\n```\n\nWhen  a new service instance is provisioned using the broker, the following paths will be mounted:\n\nMount the generic backend at /cf/\u003corganization_id\u003e/secret/\nMount the generic backend at /cf/\u003cspace_id\u003e/secret/\nMount the generic backend at /cf/\u003cinstance_id\u003e/secret/\nMount the transit backend at /cf/\u003cinstance_id\u003e/transit/\n\nA policy named `cf-\u003cinstance_id\u003e` is also created for this service instance which grants read-only access to `cf/\u003corganization_id\u003e/*`, read-write access to `cf/\u003cspace_id\u003e/*` and full access to `cf/\u003cinstance_id\u003e/*`\n\n21. Create a service key\n\n\u003e (This failed in Swisscom's Cloud Foundry)\n\n```bash\ncf create-service-key my-vault-service my-vault-service-key\ncf service-keys my-vault-service\n```\n\n18. Verify the received requests for Vault using the Ngrok Inspect UI\n\n```bash\nPUT /v1/auth/token/renew-self\nPUT /v1/auth/token/renew-self\nPUT /v1/cf/broker/0b24f466-9a54-4215-852e-2bcfab428a82/5cf104c9-4515-40f3-94de-a63ab77cb84b\nPOST /v1/auth/token/create/cf-0b24f466-9a54-4215-852e-2bcfab428a82\n```\n\n19. Retrieve credentials for this instance\n\n```bash\ncf service-key my-vault-service my-vault-service-key\n```\n\n```json\n{\n \"address\": \"https://1f81e0d3.ngrok.io/\",\n \"auth\": {\n  \"accessor\": \"3705e5b2-c0bb-6398-ecff-e05a9e6a7b28\",\n  \"token\": \"d5971c27-cf77-6ff0-f5c9-430fdfe07066\"\n },\n \"backends\": {\n  \"generic\": \"cf/0b24f466-9a54-4215-852e-2bcfab428a82/secret\",\n  \"transit\": \"cf/0b24f466-9a54-4215-852e-2bcfab428a82/transit\"\n },\n \"backends_shared\": {\n  \"organization\": \"cf/be7eedf8-c813-49e1-98f8-2fc19370ee4d/secret\",\n  \"space\": \"cf/5f7b0811-d90a-47f2-a194-951eb324f867/secret\"\n }\n}\n```\n\n20. Deploy the Vault client application\n\n```bash\ncf push --random-route --no-start \n```\n\n21. Bind the `my-vault-service` to the `nodejs-vault-demo` application\n\n```bash\ncf bind-service nodejs-vault-demo my-vault-service\n```\n\n22. Start the Vault client application\n\n```bash\ncf start nodejs-vault-demo\n```\n\n23. Verify that the application has started successfully and environment variables are as expected\n\n```bash\ncf logs --recent nodejs-vault-demo\ncf env nodejs-vault-demo\n```\n\n24. Let's write a secret into the Vault to the given generic backend and send a refresh command.\n\n```bash\nvault write cf/0b24f466-9a54-4215-852e-2bcfab428a82/secret/vault-demo message='Vault Rocks'\n```\n\n\u003e Replace application URL with your own\n\n25. We can verify that the secret is retrieved via\n\n```bash\nhttp get http://vault-demo-twiggiest-sennit.cfapps.io\n\nmessage: Vault Rocks\n```\n\n\u003e Replace application URL with your own\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpacphi%2Fcloudfoundry-and-nodejs-with-vault-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpacphi%2Fcloudfoundry-and-nodejs-with-vault-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpacphi%2Fcloudfoundry-and-nodejs-with-vault-demo/lists"}