{"id":18725129,"url":"https://github.com/mypurecloud/local-key-manager","last_synced_at":"2025-04-12T15:50:52.311Z","repository":{"id":33965761,"uuid":"85101488","full_name":"MyPureCloud/local-key-manager","owner":"MyPureCloud","description":"Local key manager","archived":false,"fork":false,"pushed_at":"2025-04-04T14:16:31.000Z","size":5297,"stargazers_count":9,"open_issues_count":11,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-04T15:26:25.852Z","etag":null,"topics":["encryption","keys"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":false,"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/MyPureCloud.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":"2017-03-15T17:27:47.000Z","updated_at":"2025-01-22T13:25:43.000Z","dependencies_parsed_at":"2023-11-15T21:28:22.761Z","dependency_job_id":"70dbe1ad-0239-4562-9feb-7826e7c6ea5d","html_url":"https://github.com/MyPureCloud/local-key-manager","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MyPureCloud%2Flocal-key-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MyPureCloud%2Flocal-key-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MyPureCloud%2Flocal-key-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MyPureCloud%2Flocal-key-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MyPureCloud","download_url":"https://codeload.github.com/MyPureCloud/local-key-manager/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248591905,"owners_count":21130148,"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","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":["encryption","keys"],"created_at":"2024-11-07T14:09:10.565Z","updated_at":"2025-04-12T15:50:52.291Z","avatar_url":"https://github.com/MyPureCloud.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Local Key Encryption Service\n\nThis repository is an example local key management service written in Java with Spring. Although it is possible to use this service with a few small changes, it is important to note that this is merely an example of how to use the API.\n\n**Make sure that your local key manager implementations are reliable, highly available, and secure. If encryption keys are lost, it will no longer be possible to retrieve the recordings encrypted with them. Use this code at your own risk.**\n\n\n## General Documentation and Explanation of work flows\n\nBelow is an explanation on how to set up the service. Although this service contains almost everything you would need to generate\nkey pairs and decrypt incoming payloads, it is worth noting the requirements around key pairs and decryption in case you are wanting\nto use your own solution for key management. First, this part of the documentation will give an overview of the workflow, then\nget into more of the specific details around the service.\n\n### Registering a local key management service for your org with Genesys Cloud\n\nA general work flow to get your local service acknowledged and production ready is listed below.\n\nThe following values will need to be replaced in the sample REST exchanges below:\n* GENESYS_CLOUD_PUBLIC_API_PUBLIC_ADDRESS - Publicly addressable endpoint for API access to your organization's configuration (See  https://developer.genesys.cloud/api/rest/, for example this would be https://api.mypurecloud.com)\n* LOCAL_KEY_MANAGER_PUBLIC_ADDRESS - Publicly addressable endpoint your local key management service is listening on.\n\n\n1. First get your service running with https (port 443), and ensure all endpoints are working as expected, including authentication.\n   You should also make sure you have an options action around your decrypt endpoint, so that we can verify the endpoint exists (during step 4 below)\n\n\n2. Register a hawk authentication key for Genesys Cloud, so that Genesys Cloud can directly hit the service. Once you get the return values be sure to record them as you will need to send the results to the Genesys Cloud local configuration endpoint.\n\n   `POST https://[LOCAL_KEY_MANAGER_PUBLIC_ADDRESS]/key-management/v1/auth` with header `Content-Type: application/json`\n\n   ```\n   {\n       \"id\": \"KEY_IDENTIFIER\"\n   }\n   ```\n\n   Response of 200 with body:\n\n   ```\n   {\n     \"id\": \"KEY_IDENTIFIER\",\n     \"authKey\": \"GENERATED_AUTH_KEY\",\n     \"algorithm\": \"sha256\"\n   }\n   ```\n3. Register your application with Genesys Cloud and get the proper OAuth2 credentials to access the public api.\n\n4. Set up your local key manager key configuration in Genesys Cloud UI, see this article [Local key management](https://help.mypurecloud.com/articles/local-key-management/) for UI instruction. Or alternatively you could send over the api id, api key, decryption url and key configuration type to the public api key configuration endpoint.\n\n    `POST https://GENESYSCLOUD_PUBLIC_API_PUBLIC_ADDRESS/api/v2/recording/keyconfigurations`  with `Content-Type: application/json` AND OAuth2 headers\n\n    ```\n    {\n      \"url\": \"https://LOCAL_KEY_MANAGER_INSTANCE_ADDRESS/key-management/v1/decrypt\",\n      \"apiId\": \"KEY_IDENTIFIER\",\n      \"apiKey\": \"GENERATED_AUTH_KEY\",\n      \"keyConfigurationType\": \"LocalKeyManager\"\n    }\n    ```\n\n    Response status 200 with payload:\n\n    ```\n    {\n      \"id\": \"CONFIGURATION_ID\",\n      \"url\": \"https://LOCAL_KEY_MANAGER_INSTANCE_ADDRESS/key-management/v1/decrypt\",\n      \"apiId\": \"KEY_IDENTIFIER\",\n      \"apiKey\": \"GENERATED_AUTH_KEY\",\n      \"keyConfigurationType\":\"LocalKeyManager\",\n      \"encryptionDomain\":\"Recording\",\n      \"selfUri\":\"/api/v2/recording/keyconfigurations\"\n    }\n    ```\n\n   Make sure you record the configuration id returned, since it will be needed for creation of keypairs.\n\n5. Create a keypair using the generate keypair endpoint on your local service. \n       \n   The generated keypair id must be in UUID format ([RFC 4122](https://www.ietf.org/rfc/rfc4122.txt)).\n   \n   The publicKey must be a Base64 encoded RSA3072 key in [RFC 4716](https://www.ietf.org/rfc/rfc4716.txt) format. \n   This means that the public key's ASN.1 sequence should not contain a sequence with an object identifier, it should only be a sequence of two integers (This can be tested by inputting the Base64 string into a [ASN.1 decoder](https://lapo.it/asn1js/)).\n\n    `POST https://[LOCAL_KEY_MANAGER_PUBLIC_ADDRESS]/key-management/v1/keypair`\n\n    Response 200 with payload:\n\n    ```\n    {\n      \"id\": \"GENERATED_KEYPAIR_ID\",\n      \"publicKey\": \"PUBLIC_KEY_BASE64\",\n      \"dateCreated\": 1479389944924\n    }\n     ```\n\n\n6. Send the public key, config id, keypair id to the public api key creation endpoint. \n\n    The keypairId must be in UUID format ([RFC 4122](https://www.ietf.org/rfc/rfc4122.txt)).\n    \n    The publicKey must be a Base64 encoded RSA3072 key in [RFC 4716](https://www.ietf.org/rfc/rfc4716.txt) format. \n\n\n    `POST https://GENESYS_CLOUD_PUBLIC_API_PUBLIC_ADDRESS/api/v2/recording/localkeys`\n\n    ```\n    {\n       \"configId\": \"CONFIGURATION_ID\",\n       \"publicKey\": \"PUBLIC_KEY_BASE64\",\n       \"keypairId\": \"GENERATED_KEYPAIR_ID\"\n     }\n     ```\n\n     Response 200 with payload:\n     ```\n     {\n       \"id\": \"GENERATED_KEYPAIR_ID\",\n       \"createDate\": \"2016-11-17T14:24:19.211Z\",\n       \"selfUri\": \"/api/v2/recording/recordingkeys\"\n     }\n    ```\n\n7. If the request is accepted a status code 200 is returned and your service should be ready to accept decryption requests.\n\nAdditional notes:\n\nFor more details about Genesys Cloud's public api, please visit: https://developer.genesys.cloud/\n\nFor step 2, you can use all of the code here in the service to help set up hawk authentication. The library in the pom\ntakes care of most of the nuances involved in setting up the authentication. To experiment with hawk authentication with postman,\nyou can follow this tutorial here on how to set it up. http://blog.getpostman.com/2015/12/05/postman-v3-2-is-out-with-hawk-authentication-support/\n\nFor step 3, visit https://developer.genesys.cloud/api/tutorials.html to get a better understanding of our oauth flows.\nhttps://developer.genesys.cloud/api/rest/authorization/ also provides detailed information on how Genesys Cloud's authentication works.\n\nFor step 4, as mentioned above, make sure the decryption endpoint sent to Genesys Cloud has an OPTIONS method, so that Genesys Cloud\ncan verify if the endpoint exists or not. It is also worth mentioning that we require the endpoint to be accept a POST for decryption.\n\nFor step 5, Genesys Cloud currently requires RSA 3072 bit key pairs that are DER encoded. This is important because other types of\nkey encoding will NOT work. For security reasons, never share your private key with anyone. You may receive an error from Genesys Cloud\nmentioning you service isn't ready. We know this because we send a sample decrypt request immediately after the keypair is registered to verify\nthe endpoint works and exists.\n\nFor step 6, this is important. At this time, the Edge will start using the provided public key sent with the keypair for encyption.\nIf for whatever reason, your service is not up, you will not be able to transcode or download recordings encrypted with the local key pair.\nMake sure you do not remove ANY key pairs that have been used by Genesys Cloud at any point because those recordings will be locked forever.\n\nThe user id of the Genesys Cloud user making decryption requests or key pair generation requests that are sent to the local key encryption service via a HTTP header named `PureCloud-User-Id`.  \n\nEven if you plan on not using this service, please take a minute to look around and read the code comments as they explain\ncertain details of decryption workflow with more specifics.\n\n## Setting up the Environment\n\nIf you have ubuntu 14.04 (no other versions have been tested so use at your own risk),\nyou can run the mysql_setup.sh script provided in the root of this repository \nto get started by typing `bash mysql_setup.sh`.\nYou will be prompted with several questions, including java terms of use, mysql, and \nvarious packages wanting yes or no answers.\n\n## Running the Application\n\nOnce you have cloned the repository, in the directory root, run:\n\n\n`mvn clean package`\n\n`java -jar target/key-manager.jar`\n\n\nYou can change the port to whatever you like.\n\n## Using Different Databases\n\nCurrently, this service is using sqllite3, which is not suitable for production\nenvironments. We strongly recommend that you switch out the temporary database\nfor whichever you choose. Below will contain a few examples on how to configure\na couple popular databases.\n\n### Mysql\n\nUsing at least ubuntu 14.04, to install mysql from the command line type (if not using mysql_setup.sh):\n\n`sudo apt-get install mysql-server`\n\n`sudo mysql_secure_installation`\n\n`sudo mysql_install_db`\n\nYou will have to fill out your credentials for the database. Make sure you remember\nwhat they are because you will need them for later. You may be asked a series of\nsecurity based questions from there as well, so make sure you input the best options\nfor your company needs. Once you have installed mysql, you can verify that mysql service is running\nby typing `sudo service mysql start` in the command line type. It should say\nthat it is already running. Once verified login to mysql.\n\n\n`mysql -u \u003cyourUsername\u003e -p`\n\n\nThen type your password. Once you are logged in, input:\n\n\n`create database local_encryption;`\n\n\nOnce you have created the database, you can now exit the program by simply\ntyping `exit`. When you have exited mysql, go back to the local-key-encryption\nrepository on your machine. From there, use your favorite text editor to edit\nthe application.properties file in the root of the repository. The contents of that file should contain the \nconfigurations of the sqllite database. You can replace all of that with:\n\n\n```\nspring.datasource.url=jdbc:mysql://localhost/local_encryption\nspring.datasource.username=your_username\nspring.datasource.password=your_password\nspring.datasource.driverClassName=com.mysql.jdbc.Driver\nspring.jpa.hibernate.ddl-auto=update\n```\n\n\nNotice the last option is update, you can change that to `create-drop`, if you would\nlike the database to be dropped on each change to entity models. This is not recommended\nfor production environments.\n\nFrom there, run the application.\n\n\n\n## Working with SSL\n\nCurrently, there is a self signed certificate that is provided for ssl. This is not\nproduction ready, and it should be changed out with a properly signed certificate.\nThere are several services that offer signing of certificates. A great free solution\ncomes from Let's Encrypt (https://letsencrypt.org/). Below are some tutorials in how to setup\na certificate with Let's Encrypt. \n\nhttps://tty1.net/blog/2015/using-letsencrypt-in-manual-mode_en.html\n\nAfter you get the signed certificate, you will need to add the path to the application.properties file.\nYou will notice commented out properties in the application.properties file. Those will need to be uncommented to use the api. \nNote, based on the file type you choose, you may need to change the key-store-type from PKCS12 to whatever\nformat that you choose. It is worth noting that spring prefers jks for certificates.\nWhatever your format is you can search on how to convert your file's format to the jks format.\n\n\n## Using the local key manager API\n\nThe below documentation shows how to use the api. Even if you are not using \nthis service, it is very important to read the documentation below as it provides\nthe interface that is needed to interact with Genesys Cloud.\n\n\n### /key-management/v1/auth\n\nAll endpoints need some sort of authentication. Genesys Cloud's encryption endpoints require hawk authentication to\nbe able to use the application. Below are the endpoints and explanations for how to set up Hawk Authentication with the\nservice. \n\n\n#### POST\n\nFirst, you will need to set up an identification for Genesys Cloud's consuming api. In order to do this, you can send a post\nto the authentication endpoint.\n\n##### Input\n```\n{\n    \"id\": \"Identification of the hawk authentication\"\n}\n```\n##### Success Output\n```\n{\n    \"id\": \"Id Input\",\n    \"authKey\": \"The authorization key that will be shared with Genesys Cloud\",\n    \"algorithm\": \"Algorithm used for hawk model encryption\"\n}\n\n```\n\nOnce you have registered a hawk authenticate service, you can then send the details to Genesys Cloud local configuration resource.\nIt will require you to send the id, authkey, and the url to reach your service.\n\n### /key-management/v1/keypair\n\nThis endpoint allows you to generate a new keypair. You will need to be authenticated to use the endpoint.\n\n#### POST\n\nThe POST is an action endpoint and requires no body to generate a keypair. Whenever you generate a keypair, you will need to \nlet Purecloud know, so that we can encrypt recordings with the key. \n\nThe generated keypair id must be in UUID format ([RFC 4122](https://www.ietf.org/rfc/rfc4122.txt)).\n\nThe publicKey must be a Base64 encoded RSA3072 key in [RFC 4716](https://www.ietf.org/rfc/rfc4716.txt) format. \nThis means that the public key's ASN.1 sequence should not contain a sequence with an object identifier, it should only be a sequence of two integers (can be tested by inputting the Base64 string into a [ASN.1 decoder](https://lapo.it/asn1js/))\n\n##### Input \n```\nnothing : An action request\n```\n##### Success Output\n```\n{\n    \"id\": \"String\",\n    \"publicKey\": \"String\",\n    \"dateCreated\": \"Long\"\n}\n\n```\n\n#### GET\n\n##### Success Output\n```\n[{\n       \"id\": \"String\",\n       \"publicKey\": \"String\",\n       \"dateCreated\": \"Long\"\n}]\n\n```\n\n\n### /key-management/v1/keypair/{keypair-id}\n\nGets a single keypair\n\n#### GET\n\n##### Success Output\n```\n{\n    \"id\": \"String\",\n    \"publicKey\": \"String\",\n    \"dateCreated\": \"Long\"\n}\n\n```\n\nOnce you have created a keypair, you can send it to the post keypair endpoint. It will require knowing the local configuration id,\nthe base64 encoded public key, and the keypair id.\n\n\n### /key-management/v1/decrypt\n\nDecrypts an encrypted payload. This requires authentication as well.\n\n##### Input\n```\n\n{\n    \"keypairId\": \"String\",\n    \"body\": \"String\"\n}\n```\n##### Success Output\n```\n\n{\n    \"body\": \"String\"\n}\n\n```\n\n### key-management/v1/request-log\n\nThis feature is not required for key management or decryption, but is instead\npresented as an example of how to use the `PureCloud-User-Id` header to produce\nuseful request logging information.\n\nWhenever a request is made against an authenticated enpoint, the request is logged.  Logged information\nincludes the Genesys Cloud user id making the request, the request method (POST, PUT, GET, etc.), the URI used\nin the request, and the date and time of the request.\n\nThe request log can be retrieved by making GET request to `key-management/v1/request-log`.  By default, it\nwill retrieve up to 100 of the most recent log entries.  Query request parameters may be\nused in order to change the log entries retrieved.  You will need to be authenticated to use the endpoint.\n\nThe request log can be cleared of all existing entries by making a DELETE request to `key-management/v1/request-log`.  You will need to be authenticated to use the endpoint.\n\n#### GET\n##### Query parameters\n* **maxEntries**  Sets the maximum number of request log entries that will be returned\n* **earliestTime**  Sets the earliest/oldest date/time of request log entries that will be returned.  Must be specified in\nISO8601 format\n* **latestTime**  Sets the latest/newest date/time of request log entries that will be returned.  Must be specified in\n ISO8601 format\n\n##### Success Output (example)\n```\n[\n    {\n        \"id\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n        \"userId\": \"yyyyyyyy-yyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy\",\n        \"requestUri\": \"/key-management/v1/decrypt\",\n        \"requestMethod\": \"POST\",\n        \"timestamp\": [\n            2015,\n            8,\n            31,\n            13,\n            49,\n            22,\n            444000000\n        ],\n        \"timestamp-String\": \"2015-08-31T13:49:22.444\"\n    },\n    {\n        \"id\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n        \"userId\": \"yyyyyyyy-yyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy\",\n        \"requestUri\": \"/key-management/v1/decrypt\",\n        \"requestMethod\": \"OPTIONS\",\n        \"timestamp\": [\n            2015,\n            8,\n            29,\n            16,\n            17,\n            53,\n            952000000\n        ],\n        \"timestampString\": \"2015-08-29T16:17:53.952\"\n    }\n]\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmypurecloud%2Flocal-key-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmypurecloud%2Flocal-key-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmypurecloud%2Flocal-key-manager/lists"}