├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── LICENSE ├── README.md ├── corda-pki-generator ├── README.md ├── copy_certs_to_helm_files.sh ├── generate_firewall_pki.sh └── pki-firewall │ ├── bin │ └── .gitignore │ └── generate_pki.sh ├── delete-deployment.sh ├── deploy.sh ├── docker-images ├── .gitignore ├── README.md ├── bin │ ├── .gitignore │ └── db_drivers │ │ └── .gitignore ├── build_docker_images.sh ├── corda_image_ent │ ├── Dockerfile │ ├── checkHealth.sh │ └── startCorda.sh ├── corda_image_firewall │ ├── Dockerfile │ └── startFirewall.sh ├── docker_config.sh ├── download_binaries.sh └── push_docker_images.sh ├── docs ├── ARCHITECTURE_OVERVIEW.md ├── CHECKLIST.md ├── CLOUD_SETUP.md ├── COST_CALCULATION.md ├── KEY_CONCEPTS.md ├── KubernetesDeploymentArchitecture.png ├── README.md ├── ROADMAP.md ├── SUPPORT_MATRIX.md └── USAGE.md ├── helm ├── .helmignore ├── Chart.yaml ├── README.md ├── delete-all.sh ├── files │ ├── certificates │ │ ├── firewall_tunnel │ │ │ └── .gitignore │ │ └── node │ │ │ └── .gitignore │ ├── conf │ │ ├── bridge-4.0.conf │ │ ├── bridge-4.1.conf │ │ ├── bridge-4.2.conf │ │ ├── bridge-4.3.conf │ │ ├── bridge-4.4.conf │ │ ├── bridge-4.5.conf │ │ ├── float-4.0.conf │ │ ├── float-4.1.conf │ │ ├── float-4.2.conf │ │ ├── float-4.3.conf │ │ ├── float-4.4.conf │ │ ├── float-4.5.conf │ │ ├── init-node.conf │ │ ├── node-4.0.conf │ │ ├── node-4.1.conf │ │ ├── node-4.2.conf │ │ ├── node-4.3.conf │ │ ├── node-4.4.conf │ │ └── node-4.5.conf │ ├── cordapps │ │ └── .gitignore │ ├── network │ │ └── .gitignore │ └── ping.sh ├── helm_compile.sh ├── initial_registration │ ├── Chart.yaml │ ├── initial_registration.sh │ ├── output │ │ └── corda │ │ │ └── templates │ │ │ └── .gitignore │ └── templates │ │ ├── initial_registration.sh.yml │ │ └── node.conf.yml ├── output │ └── .gitignore ├── requirements.yaml ├── templates │ ├── ConfigMap.yml │ ├── StorageClass.yml │ ├── copy-files.sh.yml │ ├── create-docker-secret.sh.yml │ ├── deployment-CordaBridge.yml │ ├── deployment-CordaFloat.yml │ ├── deployment-CordaNode.yml │ ├── secret-CordaNodeAzureFile.yml │ ├── volume-CordaBridge.yml │ ├── volume-CordaFloat.yml │ └── volume-CordaNode.yml └── values.yaml ├── one-time-setup.sh └── reset_environment.sh /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG] - " 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. On step '....' 16 | 2. Result is '....' 17 | 3. Additional relevant config '....' 18 | 4. See additional logs: 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. Windows 10, MacOS, Linux Ubuntu] 28 | - Version [e.g. 22] 29 | - Other relevant details 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE] " 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **First and foremost, review the [Roadmap](/ROADMAP.md), if the feature is already described there, that's the main place to update the description of this feature.** 11 | 12 | **Is your feature request related to a problem? Please describe.** 13 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 14 | 15 | **Describe the solution you'd like** 16 | A clear and concise description of what you want to happen. 17 | 18 | **Describe alternatives you've considered** 19 | A clear and concise description of any alternative solutions or features you've considered. 20 | 21 | **Additional context** 22 | Add any other context or screenshots about the feature request here. 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # file: ~/.gitignore_global 3 | 4 | # Comment the following row when you are making changes to values.yaml structure, but make sure you do not commit any of the user defined values! 5 | helm/values.yaml 6 | 7 | corda-pki-generator/pki-firewall/certs 8 | 9 | *.jar 10 | *.jks 11 | *.pem 12 | *.crl 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Corda Kubernetes Deployment 2 | 3 | The Corda Kubernetes Deployment is an open-source project and contributions are welcome. 4 | 5 | Please note that any changes will have to be of high-quality and be well documented. 6 | 7 | The contributors are listed in this document: [Contributors](CONTRIBUTORS.md) 8 | 9 | ## Branch naming 10 | 11 | Fixes should be named fix/, for example fix/container_registry_connection_issue. 12 | 13 | Larger pieces of work that are expected to be in progress for some time should be named wip/, for example wip/aws_support. 14 | WIP stands for Work In Progress. 15 | 16 | Huge new features can be named feat/, for example feat/. 17 | The idea is that just by looking at the branch name we can estimate the size of the changes contained within that branch. 18 | 19 | All new changes should be added from custom branches that are merged to master by way of a pull request. 20 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | # List of Contributors 2 | 3 | We'd like to thank the following people for contributing to the Corda Kubernetes Deployment. 4 | Some people may have moved to a different organisation since their contribution. 5 | Please forgive any omissions, and create a pull request, or email , if you wish to see changes to this list. 6 | 7 | * Henrik Carlström (R3) - Initial creator 8 | * Rémi Foult (Natixis) - Lead Blockchain Developer -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CORDA KUBERNETES DEPLOYMENT 2 | 3 | This repository () contains the means with which you can stand up a [Corda Enterprise](https://www.r3.com/corda-platform/) Node. 4 | 5 | This is meant to be a customizable version of the Node deployment that you can take as-is if it fits your needs or then customize it to your liking. 6 | 7 | **DISCLAIMER:** 8 | 9 | This Kubernetes deployment for a Corda Enterprise Node is considered a **reference implementation** and should not be used in a production environment until sufficient testing has been done. 10 | 11 | Licensed under [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0). 12 | 13 | --- 14 | 15 | ## IMPORTANT 16 | 17 | Kubernetes is a complex system and setting up a successful deployment for the first time can be challenging as well. 18 | 19 | Please make sure you step through the [SETUP CHECKLIST](#setup-checklist) section carefully the first time you deploy, to avoid problems down the road. 20 | 21 | It is strongly recommended you review the [documentation](docs/README.md) before setting this up for the first time to familiarize yourself with the topic at hand. 22 | 23 | --- 24 | 25 | ## SETUP CHECKLIST 26 | 27 | Since there are a number of prerequisites that need to be met and then a certain order of running everything, a checklist has been collated that you may find useful. 28 | 29 | Please see [CHECKLIST.md](docs/CHECKLIST.md) for more information. 30 | 31 | **Note!** 32 | It is strongly recommended you follow the CHECKLIST, to not skip an important step, especially the first time you set up this deployment, 33 | 34 | --- 35 | 36 | ## PREREQUISITES 37 | 38 | * A cloud environment with Kubernetes Cluster Services that has access to a Docker Container Registry, see [CLOUD_SETUP.md](docs/CLOUD_SETUP.md) 39 | * Building the images requires local [Docker](https://www.docker.com/) installation 40 | * [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) is used to manage Kubernetes cluster 41 | * [Helm](https://helm.sh/) version 2.x 42 | * Access to Corda Enterprise binary files or access to R3 Artifactory for Enterprise (licensed users) 43 | 44 | --- 45 | 46 | ## BINARIES 47 | 48 | This deployment is targeting an Enterprise deployment, which should include a Corda Node, but also the Corda Firewall, which is an Enterprise only feature. 49 | 50 | In order to execute the following scripts correctly, you will have to have access to the Corda Enterprise binaries. 51 | 52 | The files should be downloaded first and placed in the following folder: ``docker-images/bin`` 53 | 54 | You can use the helper script ``download_binaries.sh`` to download binaries for you, as long as you have the necessary login details available for the R3 Artifactory. 55 | 56 | If you have R3 Artifactory access, the download will be automatic as part of the ``one-time-setup.sh`` script, which is the recommended way of performing the first time setup. 57 | 58 | Please see [docker-images/README.md](docker-images/README.md) for more information. 59 | 60 | --- 61 | 62 | ## CONFIGURATION 63 | 64 | You must completely fill out the [helm/values.yaml](helm/values.yaml) file according to your configuration. 65 | For more details on how it should be filled out, follow the [CHECKLIST.md](docs/CHECKLIST.md) document. 66 | 67 | --- 68 | 69 | ## SHORT USAGE GUIDE (see [SETUP CHECKLIST](#setup-checklist) for a full guide) 70 | 71 | This is a brief view of the steps you will take, for the full set of steps, please review [CHECKLIST.md](docs/CHECKLIST.md). 72 | 73 | 1. Customize the Helm ``values.yaml`` file according to your deployment (this step is used by initial-registration and Helm compile, very important to fill in correctly and completely) 74 | 2. Execute ``one-time-setup.sh`` which will do the following (you can also step through the steps on your own, just follow what the one-time-setup.sh would have done): 75 | 1. Build the docker images and push them to the Container Registry 76 | 2. Generate the Corda Firewall PKI certificates 77 | 3. Execute initial registration step (which should copy certificates to the correct locations under ``helm/files``) 78 | 3. Build Helm templates and install them onto the Kubernetes Cluster (by way of executing either ``deploy.sh`` or ``helm/helm_compile.sh``) 79 | 4. Ensure that the deployment has been successful (log in to the pods and check that they are working correctly, please see below link for information on how to do that) 80 | 81 | --- 82 | 83 | ## DOCUMENTATION 84 | 85 | For more details and instructions it is strongly recommended to visit the documentation: 86 | 87 | [Documentation](docs/README.md) 88 | 89 | --- 90 | 91 | ## Contributing 92 | 93 | The Corda Kubernetes Deployment is an open-source project and contributions are welcome as seen here: [Contributing](CONTRIBUTING.md) 94 | 95 | The contributors can be found here: [Contributors](CONTRIBUTORS.md) 96 | 97 | --- 98 | 99 | ## Feedback 100 | 101 | Any suggestions / issues are welcome in the issues section: 102 | 103 | Fin. 104 | -------------------------------------------------------------------------------- /corda-pki-generator/README.md: -------------------------------------------------------------------------------- 1 | # CORDA PKI GENERATOR 2 | 3 | With this tool you can generate certs for the Corda Node deployment using Corda Firewall. 4 | 5 | Please either make sure that the tool (``generate_pki.sh``) can find the keytool executable in the path or then copy the required files into the bin folder. 6 | 7 | The files required on Windows are: ``keytool.exe``, ``jli.dll``, ``msvcr100.dll``. 8 | These files can normally be found in your JDK installation, for example: ``C:\Program Files\Java\jre1.8.0_201\bin`` 9 | 10 | Tested on Linux, Mac OS and Windows. 11 | 12 | ## Configuration 13 | 14 | The current configuration options can be found in the ``values.yaml`` file, see the section under ``corda.firewall``. 15 | -------------------------------------------------------------------------------- /corda-pki-generator/copy_certs_to_helm_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | set -eu 46 | 47 | checkStatus () { 48 | status=$1 49 | if [ $status -eq 0 ] 50 | then 51 | echo "." 52 | else 53 | echo -e "${RED}ERROR${NC}" 54 | echo "The previous step failed" 55 | exit 1 56 | fi 57 | return 0 58 | } 59 | 60 | ensureFileExistsAndCopy () { 61 | FROM=$1 62 | TO=$2 63 | if [ -f "$FROM" ] 64 | then 65 | if [ -f "$TO" ] 66 | then 67 | echo "Existing certificate already existed, but it is safe to replace, since this is just the Corda Firewall tunnel keys." 68 | fi 69 | cp -f $FROM $TO 70 | else 71 | echo -e "${RED}ERROR${NC}" 72 | echo "File did not exist, probably an issue with certificate creation: $FROM" 73 | exit 1 74 | fi 75 | } 76 | 77 | CopyCertificatesToHelmFolder () { 78 | echo "====== Copying PKI certificates to Helm folder next ... ====== " 79 | echo "Copying trust.jks ..." 80 | ensureFileExistsAndCopy $DIR/pki-firewall/certs/trust.jks $DIR/../helm/files/certificates/firewall_tunnel/trust.jks 81 | echo "Copying float.jks ..." 82 | ensureFileExistsAndCopy $DIR/pki-firewall/certs/float.jks $DIR/../helm/files/certificates/firewall_tunnel/float.jks 83 | echo "Copying bridge.jks ..." 84 | ensureFileExistsAndCopy $DIR/pki-firewall/certs/bridge.jks $DIR/../helm/files/certificates/firewall_tunnel/bridge.jks 85 | echo "====== Copying PKI certificates to Helm folder completed. ====== " 86 | } 87 | CopyCertificatesToHelmFolder 88 | -------------------------------------------------------------------------------- /corda-pki-generator/generate_firewall_pki.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | set -eu 46 | 47 | checkStatus () { 48 | status=$1 49 | if [ $status -eq 0 ] 50 | then 51 | echo "." 52 | else 53 | echo -e "${RED}ERROR${NC}" 54 | echo "The previous step failed" 55 | exit 1 56 | fi 57 | return 0 58 | } 59 | 60 | $DIR/pki-firewall/generate_pki.sh 61 | checkStatus $? 62 | $DIR/copy_certs_to_helm_files.sh 63 | checkStatus $? 64 | -------------------------------------------------------------------------------- /corda-pki-generator/pki-firewall/bin/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /corda-pki-generator/pki-firewall/generate_pki.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | 46 | PKI_Prerequisites () { 47 | WORKDIR=$DIR/certs 48 | mkdir $WORKDIR -p 49 | rm $WORKDIR/* -rf 50 | 51 | # C:\Program Files\Java\jre1.8.0_201\bin or if in PATH just keytool.exe 52 | KEYTOOL_EXE=keytool 53 | $KEYTOOL_EXE &>/dev/null 54 | if [ "$?" -ne "0" ]; then 55 | KEYTOOL_EXE=$DIR/bin/keytool.exe 56 | $KEYTOOL_EXE &>/dev/null 57 | if [ "$?" -ne "0" ]; then 58 | KEYTOOL_EXE=/usr/bin/keytool 59 | $KEYTOOL_EXE &>/dev/null 60 | if [ "$?" -ne "0" ]; then 61 | echo -e "${RED}ERROR${NC}" 62 | echo "!!! Keytool not found, please check to make sure you have it installed and in the path or in path $DIR/bin/ !!!" 63 | exit 1 64 | fi 65 | fi 66 | fi 67 | 68 | $KEYTOOL_EXE &>/dev/null 69 | status=$? 70 | if [ $status -eq 0 ] 71 | then 72 | echo "Keytool is ready..." 73 | else 74 | echo -e "${RED}ERROR${NC}" 75 | echo "!!! Keytool is not available, make sure your Keytool is configured correctly !!!" 76 | exit 1 77 | fi 78 | } 79 | PKI_Prerequisites 80 | 81 | set +x 82 | 83 | GeneratePKI () { 84 | echo "====== Generating Corda Firewall PKI hierarchy next ... ====== " 85 | # Read values.yaml for configuration 86 | VALUES_YAML=$DIR/../../helm/values.yaml 87 | FIREWALL_CONF_RAW=$(grep -A 14 ' firewall:' $VALUES_YAML) # Find configuration path .Values.corda.firewall.conf 88 | echo "Reading values.yaml file ($VALUES_YAML)" 89 | CERTIFICATE_VALIDITY_DAYS=$(echo "$FIREWALL_CONF_RAW" | grep 'certificateValidityInDays: "' | cut -d '"' -f 2) 90 | TRUST_PASSWORD=$(echo "$FIREWALL_CONF_RAW" | grep 'truststorePassword: "' | cut -d '"' -f 2) 91 | BRIDGE_PASSWORD=$(echo "$FIREWALL_CONF_RAW" | grep 'bridgeKeystorePassword: "' | cut -d '"' -f 2) 92 | FLOAT_PASSWORD=$(echo "$FIREWALL_CONF_RAW" | grep 'floatKeystorePassword: "' | cut -d '"' -f 2) 93 | CA_KEYSTORE_PASSWORD=$(echo "$FIREWALL_CONF_RAW" | grep 'keystorePasswordCA: "' | cut -d '"' -f 2) 94 | CA_KEY_PASSWORD=$(echo "$FIREWALL_CONF_RAW" | grep 'keyPasswordCA: "' | cut -d '"' -f 2) 95 | 96 | set -eu 97 | 98 | if [ "$CERTIFICATE_VALIDITY_DAYS" = "" -o "$TRUST_PASSWORD" = "" -o "$BRIDGE_PASSWORD" = "" -o "$FLOAT_PASSWORD" = "" -o "$CA_KEYSTORE_PASSWORD" = "" -o "$CA_KEY_PASSWORD" = "" ]; then 99 | echo -e "${RED}ERROR${NC}" 100 | echo "Some values were not set correctly from values.yaml file, please check the following values in the values.yaml file:" 101 | echo "CERTIFICATE_VALIDITY_DAYS=$CERTIFICATE_VALIDITY_DAYS" 102 | echo "TRUST_PASSWORD=$TRUST_PASSWORD" 103 | echo "BRIDGE_PASSWORD=$BRIDGE_PASSWORD" 104 | echo "FLOAT_PASSWORD=$FLOAT_PASSWORD" 105 | echo "CA_KEYSTORE_PASSWORD=$CA_KEYSTORE_PASSWORD" 106 | echo "CA_KEY_PASSWORD=$CA_KEY_PASSWORD" 107 | echo "---" 108 | echo "The raw contents that was read from values.yaml: $FIREWALL_CONF_RAW" 109 | exit 1 110 | fi 111 | 112 | $KEYTOOL_EXE -genkeypair -keyalg EC -keysize 256 -alias firewallroot -validity $CERTIFICATE_VALIDITY_DAYS -dname "CN=Firewall Root,O=Local Only,L=London,C=GB" -ext bc:ca:true,pathlen:1 -keystore $WORKDIR/firewallca.jks -storepass $CA_KEYSTORE_PASSWORD -keypass $CA_KEY_PASSWORD 113 | $KEYTOOL_EXE -genkeypair -keyalg EC -keysize 256 -alias bridgecert -validity $CERTIFICATE_VALIDITY_DAYS -dname "CN=Bridge Local,O=Local Only,L=London,C=GB" -ext bc:ca:false -keystore $WORKDIR/bridge.jks -storepass $BRIDGE_PASSWORD -keypass $BRIDGE_PASSWORD 114 | $KEYTOOL_EXE -genkeypair -keyalg EC -keysize 256 -alias floatcert -validity $CERTIFICATE_VALIDITY_DAYS -dname "CN=Float Local,O=Local Only,L=London,C=GB" -ext bc:ca:false -keystore $WORKDIR/float.jks -storepass $FLOAT_PASSWORD -keypass $FLOAT_PASSWORD 115 | 116 | $KEYTOOL_EXE -exportcert -rfc -alias firewallroot -keystore $WORKDIR/firewallca.jks -storepass $CA_KEYSTORE_PASSWORD -keypass $CA_KEY_PASSWORD > $WORKDIR/root.pem 117 | $KEYTOOL_EXE -importcert -noprompt -file $WORKDIR/root.pem -alias root -keystore $WORKDIR/trust.jks -storepass $TRUST_PASSWORD 118 | 119 | $KEYTOOL_EXE -certreq -alias bridgecert -keystore $WORKDIR/bridge.jks -storepass $BRIDGE_PASSWORD -keypass $BRIDGE_PASSWORD | $KEYTOOL_EXE -gencert -ext ku:c=dig,keyEncipherment -ext: eku:true=serverAuth,clientAuth -rfc -keystore $WORKDIR/firewallca.jks -alias firewallroot -validity $CERTIFICATE_VALIDITY_DAYS -storepass $CA_KEYSTORE_PASSWORD -keypass $CA_KEY_PASSWORD > $WORKDIR/bridge.pem 120 | cat $WORKDIR/root.pem $WORKDIR/bridge.pem >> $WORKDIR/bridgechain.pem 121 | $KEYTOOL_EXE -importcert -noprompt -file $WORKDIR/bridgechain.pem -alias bridgecert -keystore $WORKDIR/bridge.jks -storepass $BRIDGE_PASSWORD -keypass $BRIDGE_PASSWORD 122 | 123 | $KEYTOOL_EXE -certreq -alias floatcert -keystore $WORKDIR/float.jks -storepass $FLOAT_PASSWORD -keypass $FLOAT_PASSWORD | $KEYTOOL_EXE -gencert -ext ku:c=dig,keyEncipherment -ext: eku::true=serverAuth,clientAuth -rfc -keystore $WORKDIR/firewallca.jks -alias firewallroot -validity $CERTIFICATE_VALIDITY_DAYS -storepass $CA_KEYSTORE_PASSWORD -keypass $CA_KEY_PASSWORD > $WORKDIR/float.pem 124 | cat $WORKDIR/root.pem $WORKDIR/float.pem >> $WORKDIR/floatchain.pem 125 | $KEYTOOL_EXE -importcert -noprompt -file $WORKDIR/floatchain.pem -alias floatcert -keystore $WORKDIR/float.jks -storepass $FLOAT_PASSWORD -keypass $FLOAT_PASSWORD 126 | echo "====== Generating Corda Firewall PKI hierarchy completed. ====== " 127 | } 128 | GeneratePKI 129 | -------------------------------------------------------------------------------- /delete-deployment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | set -eu 46 | 47 | checkStatus () { 48 | status=$1 49 | if [ $status -eq 0 ] 50 | then 51 | echo "." 52 | else 53 | echo -e "${RED}ERROR${NC}" 54 | echo "The previous step failed" 55 | exit 1 56 | fi 57 | return 0 58 | } 59 | 60 | $DIR/helm/delete-all.sh 61 | checkStatus $? 62 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | set -eu 46 | 47 | checkStatus () { 48 | status=$1 49 | if [ $status -eq 0 ] 50 | then 51 | echo "." 52 | else 53 | echo -e "${RED}ERROR${NC}" 54 | echo "The previous step failed" 55 | exit 1 56 | fi 57 | return 0 58 | } 59 | 60 | $DIR/helm/helm_compile.sh 61 | checkStatus $? 62 | -------------------------------------------------------------------------------- /docker-images/.gitignore: -------------------------------------------------------------------------------- 1 | docker_config.sh 2 | **/*.jar -------------------------------------------------------------------------------- /docker-images/README.md: -------------------------------------------------------------------------------- 1 | # CORDA DOCKER IMAGES 2 | 3 | In this section we define the structure of the Docker images that our deployment will be using. 4 | 5 | The scripts we will be using are as follows: 6 | 7 | - ``docker_config.sh``, contains the customisation options that are read automatically from values.yaml, the following scripts use this file 8 | - ``download_binaries.sh``, downloads the required Corda binaries (as specified in values.yaml, cordaVersion) 9 | - ``build_docker_images.sh``, this script will compile the Docker images based on the Docker files and necessary binaries 10 | - ``push_docker_images.sh``, this script will push the local Docker images to a remote repository, the Container Registry. Please note that your Kubernetes Cluster should have access to the Container Registry, please see root README.md for more information 11 | 12 | ## PREREQUISITES 13 | 14 | Before executing the above mentioned scripts, the scripts need access to the Corda Enterprise binaries, these files should be placed in the ``bin``-folder, namely: 15 | 16 | - Corda Enterprise Node jar file, e.g. [R3 Artifactory: corda-ent-4.0.jar](https://ci-artifactory.corda.r3cev.com/artifactory/corda-enterprise/com/r3/corda/corda/4.0/corda-4.0.jar) 17 | - Corda Firewall jar file, e.g. [R3 Artifactory: corda-firewall-4.0.jar](https://ci-artifactory.corda.r3cev.com/artifactory/corda-enterprise/com/r3/corda/corda-firewall/4.0/corda-firewall-4.0.jar) 18 | - Corda Health Survey Tool jar file, e.g. [R3 Artifactory: corda-tools-health-survey-4.2.20191122.jar](https://ci-artifactory.corda.r3cev.com/artifactory/corda-enterprise/com/r3/corda/corda-tools-health-survey/4.0/corda-tools-health-survey-4.0.jar) 19 | 20 | Either you can download them from the [R3 Artifactory](https://ci-artifactory.corda.r3cev.com/artifactory/webapp/#/artifacts/browse/tree/General/corda-enterprise) (login details required) 21 | or then you may have these files shared with you separately, in which case you just have to copy them to the correct folder. 22 | The recommended way is however to use the functionality within ``download_binaries.sh`` and have the scripts download the binaries for you. (the R3 Artifactory user details have to be set for this step to work) 23 | 24 | If you do not have a license for Corda Enterprise, you can apply for an evaluation version here (you have to sign the Corda evaluation license agreement): 25 | [Corda Enterprise Evaluation](https://www.r3.com/download-corda-enterprise/) 26 | 27 | ## CONFIGURATION 28 | 29 | All the relevant configuration options can be found in the file ``helm/values.yaml``. 30 | -------------------------------------------------------------------------------- /docker-images/bin/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /docker-images/bin/db_drivers/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /docker-images/build_docker_images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | set -eu 46 | 47 | NO_CACHE= 48 | if [ "${1-}" = "no-cache" ] 49 | then 50 | NO_CACHE=--no-cache 51 | fi 52 | 53 | . $DIR/docker_config.sh 54 | . $DIR/download_binaries.sh 55 | 56 | BuildDockerImages () { 57 | echo "====== Building Docker images next ... ====== " 58 | if [ ! -f "$DIR/bin/$CORDA_VERSION.jar" -o ! -f "$DIR/bin/$CORDA_HEALTH_CHECK_VERSION.jar" -o ! -f "$DIR/bin/$CORDA_FIREWALL_VERSION.jar" ]; then 59 | echo -e "${RED}ERROR${NC}" 60 | echo "Missing binaries, check that you have the correct files with the correct names in the following folder $DIR/bin" 61 | echo "$DIR/bin/$CORDA_VERSION.jar" 62 | echo "$DIR/bin/$CORDA_FIREWALL_VERSION.jar" 63 | echo "$DIR/bin/$CORDA_HEALTH_CHECK_VERSION.jar" 64 | echo "$DIR/bin folder contents:" 65 | ls -al $DIR/bin 66 | exit 1 67 | fi 68 | 69 | echo "Building Corda Enterprise Docker image..." 70 | cp $DIR/bin/$CORDA_VERSION.jar $DIR/$CORDA_IMAGE_PATH/corda.jar 71 | cp $DIR/bin/$CORDA_HEALTH_CHECK_VERSION.jar $DIR/$CORDA_IMAGE_PATH/corda-tools-health-survey.jar 72 | cd $DIR/$CORDA_IMAGE_PATH 73 | $DOCKER_CMD build -t $CORDA_IMAGE_PATH:$CORDA_DOCKER_IMAGE_VERSION . -f Dockerfile $NO_CACHE 74 | rm corda.jar 75 | rm corda-tools-health-survey.jar 76 | cd .. 77 | 78 | echo "Building Corda Firewall Docker image..." 79 | cp $DIR/bin/$CORDA_FIREWALL_VERSION.jar $DIR/$CORDA_FIREWALL_IMAGE_PATH/corda-firewall.jar 80 | cd $DIR/$CORDA_FIREWALL_IMAGE_PATH 81 | $DOCKER_CMD build -t $CORDA_FIREWALL_IMAGE_PATH:$FIREWALL_DOCKER_IMAGE_VERSION . -f Dockerfile $NO_CACHE 82 | rm corda-firewall.jar 83 | cd .. 84 | 85 | echo "Listing all images starting with name 'corda_' (you should see at least 2 images, one for Corda Enterprise and one for the Corda firewall):" 86 | $DOCKER_CMD images "corda_*" 87 | echo "====== Building Docker images completed. ====== " 88 | } 89 | BuildDockerImages 90 | -------------------------------------------------------------------------------- /docker-images/corda_image_ent/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM azul/zulu-openjdk-alpine:8u192 2 | 3 | RUN apk upgrade --update && \ 4 | apk add --update --no-cache bash iputils nfs-utils nss curl netcat-openbsd lftp openssh-client openssh-server jq && \ 5 | rm -rf /var/cache/apk/* && \ 6 | # Add user to run the app && \ 7 | addgroup corda && \ 8 | adduser -G corda -D -s /bin/bash corda && \ 9 | # Create /opt/corda directory && \ 10 | mkdir -p /opt/corda/workspace 11 | 12 | ADD --chown=corda:corda corda.jar /opt/corda/corda.jar 13 | ADD --chown=corda:corda corda-tools-health-survey.jar /opt/corda/corda-tools-health-survey.jar 14 | ADD --chown=corda:corda startCorda.sh /opt/corda/startCorda.sh 15 | ADD --chown=corda:corda checkHealth.sh /opt/corda/checkHealth.sh 16 | 17 | # Permissioning 18 | RUN chown -R corda:corda /opt/corda 19 | 20 | RUN dos2unix /opt/corda/startCorda.sh /opt/corda/startCorda.sh 21 | RUN chmod +x /opt/corda/startCorda.sh 22 | RUN dos2unix /opt/corda/checkHealth.sh /opt/corda/checkHealth.sh 23 | RUN chmod +x /opt/corda/checkHealth.sh 24 | 25 | # Working directory for the Node 26 | WORKDIR /opt/corda 27 | ENV HOME=/opt/corda 28 | USER corda 29 | 30 | # Informational Port exposure below (recommended ports to use) 31 | # P2P 32 | EXPOSE 40000 33 | # RPC 34 | EXPOSE 30000 35 | # H2 DB console access (only for development use) 36 | EXPOSE 55555 37 | # SSH 38 | EXPOSE 2223 39 | 40 | # Start it 41 | CMD ./startCorda.sh -------------------------------------------------------------------------------- /docker-images/corda_image_ent/checkHealth.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | java -jar /opt/corda/corda-tools-health-survey.jar --text-format --base-directory /opt/corda/workspace/ --bridge-configuration /opt/corda/workspace/bridge.conf --float-configuration /opt/corda/workspace/float.conf --config-validate -------------------------------------------------------------------------------- /docker-images/corda_image_ent/startCorda.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | echoMessage () { 8 | message=$1 9 | echo "====== $message ======" 10 | } 11 | 12 | checkStatus () { 13 | status=$1 14 | if [ $status -eq 0 ]; then 15 | echoMessage "Success" 16 | else 17 | echo -e "${RED}ERROR${NC}" 18 | echoMessage "The previous step failed" 19 | exit 1 20 | fi 21 | return 0 22 | } 23 | 24 | isRegistered () { 25 | IS_REGISTERED=0 26 | if grep -q "compatibilityZoneURL" ./workspace/node.conf ; then 27 | NODE_KEY_STORE="./workspace/certificates/nodekeystore.jks"; 28 | if [ -f "$NODE_KEY_STORE" ]; then 29 | IS_REGISTERED=1 30 | fi 31 | else 32 | NODE_INFOS=(./workspace/nodeInfo-*) 33 | # Check if NODE_INFOS is an glob array of size larger than zero and then check first array element if valid file 34 | if [ ${#NODE_INFOS[@]} -gt 0 -a -f "${NODE_INFOS[0]}" ]; then 35 | IS_REGISTERED=1 36 | fi 37 | fi 38 | 39 | return $IS_REGISTERED 40 | } 41 | 42 | waitForOtherCordaNodeProcessToExit () { 43 | let PROCESS_ID_ACCESSIBLE=0 44 | while [ ${PROCESS_ID_ACCESSIBLE} -eq 0 ] 45 | do 46 | sleep 2 47 | echoMessage "Checking access for process-id file..." 48 | PROCESS_ID_FILE=./workspace/process-id 49 | if [ -f $PROCESS_ID_FILE ]; then 50 | echoMessage "File process-id exists, checking lock status..." 51 | #flock -n /tmp/test.lock -c $PROCESS_ID_FILE 52 | ( flock -n 200 || exit 1 53 | echo "In critical section" 54 | echo "Random write" >> $PROCESS_ID_FILE 55 | ) 200>$PROCESS_ID_FILE 56 | if [ $? -ne 1 ]; then 57 | echoMessage "File process-id is not locked by another process, we can start Corda Node!" 58 | let PROCESS_ID_ACCESSIBLE=1 59 | fi 60 | else 61 | let PROCESS_ID_ACCESSIBLE=1 62 | fi 63 | done 64 | } 65 | 66 | checkIfNetworkParametersIsAvailable () { 67 | let NETWORK_PARAMETERS_EXISTS=0 68 | while [ ${NETWORK_PARAMETERS_EXISTS} -eq 0 ] 69 | do 70 | sleep 2 71 | echoMessage "Checking for network-parameters file..." 72 | if [ -f ./workspace/network-parameters ] 73 | then 74 | echoMessage "Found network-parameters file!" 75 | let NETWORK_PARAMETERS_EXISTS=1 76 | fi 77 | done 78 | } 79 | 80 | checkIfIdentityManagerIsUpAndRunning () { 81 | echoMessage "Trying to contact Identity Manager @ ($IDENTITY_MANAGER_ADDRESS)..." 82 | curl -m5 -s $IDENTITY_MANAGER_ADDRESS/status > /dev/null 83 | result=$? 84 | 85 | if [ $result -eq 0 ]; then 86 | echoMessage "Identity Manager is up and running" 87 | else 88 | echo -e "${YELLOW}Warning${NC}" 89 | echoMessage "Identity Manager is unavailable" 90 | fi 91 | } 92 | 93 | checkIfNetworkMapIsUpAndRunning () { 94 | echoMessage "Trying to contact network map @ ($NETMAP_ADDRESS)..." 95 | curl -m5 -s $NETMAP_ADDRESS/network-map/my-hostname > /dev/null 96 | let EXIT_CODE=$? 97 | result=$? 98 | 99 | if [ $result -eq 0 ]; then 100 | echoMessage "Network map is up and running" 101 | else 102 | echo -e "${YELLOW}Warning${NC}" 103 | echoMessage "Network map is unavailable" 104 | fi 105 | } 106 | 107 | checkNetworkMap () { 108 | hash="" 109 | while [ -z "${hash}" -o "${hash}" = "null" ] 110 | do 111 | sleep 2 112 | echoMessage "Checking network map for notary NodeInfo..." 113 | hash=$(curl -m5 -s $NETMAP_ADDRESS/network-map-user/network-map | jq -r '.[0]') 114 | if [ "$hash" = "null" ] 115 | then 116 | echoMessage "The network map is currently empty, waiting for first registrations..." 117 | fi 118 | done 119 | echoMessage "We found a hash from network map: $hash" 120 | # curl -m5 -s "http://enm-netmap-service:20000/network-map/network-parameters/$hash" 121 | # echoMessage "" 122 | # curl -m5 -s "http://enm-netmap-service:20000/network-map/network-parameters/$hash" > /opt/corda/workspace/network-params 123 | # let EXIT_CODE=$? 124 | # if [ ${EXIT_CODE} -gt 0 ] 125 | # then 126 | # echoMessage "Error downloading network-parameters, exiting..." 127 | # echoMessage "$EXIT_CODE" 128 | # exit 1 129 | # else 130 | # echoMessage "Downloaded network-parameters successfully" 131 | # ls /opt/corda/workspace/network-params 132 | # cat /opt/corda/workspace/network-params 133 | # return 0 134 | # fi 135 | } 136 | 137 | startNode () { 138 | java -jar corda.jar --base-directory ./workspace 139 | checkStatus $? 140 | } 141 | 142 | launchCordaNode () { 143 | echoMessage "Checking if other Corda Node process is running..." 144 | waitForOtherCordaNodeProcessToExit 145 | 146 | echoMessage "Checking Identity Manager's availability" 147 | checkIfIdentityManagerIsUpAndRunning 148 | 149 | echoMessage "Checking network map's availability" 150 | checkIfNetworkMapIsUpAndRunning 151 | 152 | echoMessage "Starting the node" 153 | startNode 154 | } 155 | launchCordaNode -------------------------------------------------------------------------------- /docker-images/corda_image_firewall/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM azul/zulu-openjdk-alpine:8u192 2 | 3 | RUN apk upgrade --update && \ 4 | apk add --update --no-cache bash iputils nfs-utils nss curl netcat-openbsd lftp openssh-client openssh-server && \ 5 | rm -rf /var/cache/apk/* && \ 6 | # Add user to run the app && \ 7 | addgroup corda && \ 8 | adduser -G corda -D -s /bin/bash corda && \ 9 | # Create /opt/corda directory && \ 10 | mkdir -p /opt/corda/workspace 11 | 12 | ADD --chown=corda:corda corda-firewall.jar /opt/corda/corda-firewall.jar 13 | ADD --chown=corda:corda startFirewall.sh /opt/corda/startFirewall.sh 14 | 15 | # Permissioning 16 | RUN chown -R corda:corda /opt/corda 17 | RUN dos2unix /opt/corda/startFirewall.sh /opt/corda/startFirewall.sh 18 | RUN chmod +x /opt/corda/startFirewall.sh 19 | 20 | # Working directory for the Firewall 21 | WORKDIR /opt/corda 22 | ENV HOME=/opt/corda 23 | USER corda 24 | 25 | # Informational Port exposure below (recommended ports to use) 26 | # P2P to other nodes 27 | EXPOSE 40000 28 | # BRIDGE P2P 29 | EXPOSE 39999 30 | 31 | # Start it 32 | CMD ./startFirewall.sh -------------------------------------------------------------------------------- /docker-images/corda_image_firewall/startFirewall.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | echoMessage () { 8 | message=$1 9 | 10 | echo "====== $message ======" 11 | } 12 | 13 | checkStatus () { 14 | status=$1 15 | if [ $status -eq 0 ] 16 | then 17 | echoMessage "Success" 18 | else 19 | echo -e "${RED}ERROR${NC}" 20 | echoMessage "The previous step failed" 21 | exit 1 22 | fi 23 | } 24 | 25 | ifSharedFolderAndFilesExists () { 26 | if [ -d /opt/corda/shared/ -a -f /opt/corda/shared/network-parameters -a -f /opt/corda/shared/certificates/sslkeystore.jks -a -f /opt/corda/shared/certificates/truststore.jks ] 27 | then 28 | return 1 29 | else 30 | return 0 31 | fi 32 | } 33 | 34 | copySharedFiles () { 35 | let EXIT_CODE=0 36 | while [ ${EXIT_CODE} -eq 0 ] 37 | do 38 | sleep 2 39 | echoMessage "Checking shared folder for required files..." 40 | ifSharedFolderAndFilesExists 41 | let EXIT_CODE=$? 42 | done 43 | echoMessage "Shared folder & files exists." 44 | 45 | echoMessage "Copying network-parameters & certificates from shared folder (from node)." 46 | cp /opt/corda/shared/network-parameters ./workspace/ 47 | mkdir ./workspace/certificates/ 48 | cp /opt/corda/shared/certificates/sslkeystore.jks ./workspace/certificates/ 49 | cp /opt/corda/shared/certificates/truststore.jks ./workspace/certificates/ 50 | echoMessage "Copied network-parameters & certificates from shared folder (from node), ready to start Corda Firewall." 51 | return 1 52 | } 53 | 54 | waitForOtherCordaFirewallProcessToExit () { 55 | let PROCESS_ID_ACCESSIBLE=0 56 | while [ ${PROCESS_ID_ACCESSIBLE} -eq 0 ] 57 | do 58 | sleep 2 59 | echoMessage "Checking access for firewall-process-id file..." 60 | PROCESS_ID_FILE=./workspace/firewall-process-id 61 | if [ -f $PROCESS_ID_FILE ] 62 | then 63 | echoMessage "File firewall-process-id exists, checking lock status..." 64 | #flock -n /tmp/test.lock -c $PROCESS_ID_FILE 65 | ( flock -n 200 || exit 1 66 | echo "In critical section" 67 | echo "Random write" >> $PROCESS_ID_FILE 68 | ) 200>$PROCESS_ID_FILE 69 | if [ $? -ne 1 ]; then 70 | echoMessage "File firewall-process-id is not locked by another process, we can start Corda Firewall!" 71 | let PROCESS_ID_ACCESSIBLE=1 72 | fi 73 | else 74 | let PROCESS_ID_ACCESSIBLE=1 75 | fi 76 | done 77 | } 78 | 79 | startFirewall () { 80 | if [ ! -f ./workspace/network-parameters -a -f ./workspace/certificates/sslkeystore.jks -a -f ./workspace/certificates/truststore.jks ] 81 | then 82 | copySharedFiles 83 | fi 84 | 85 | echoMessage "Checking if other Corda Firewall process is running..." 86 | waitForOtherCordaFirewallProcessToExit 87 | echoMessage "Starting the firewall" 88 | java -jar corda-firewall.jar --base-directory ./workspace --verbose --logging-level=INFO 89 | status=$? 90 | if [ $status -ne 0 ] 91 | then 92 | echo "DEBUG INFO on CRITICAL ERROR:" 93 | ls /opt/corda -R -al 94 | echo "Active firewall.conf file:" 95 | less /opt/corda/workspace/firewall.conf 96 | MACHINE_NAME=$(cat /proc/sys/kernel/hostname) 97 | LOG_FILE="/opt/corda/workspace/logs/corda-firewall-${MACHINE_NAME}.log" 98 | echo "Content of log file (${LOG_FILE}):" 99 | tail -n 500 $LOG_FILE 100 | fi 101 | checkStatus $status 102 | } 103 | 104 | startFirewall 105 | -------------------------------------------------------------------------------- /docker-images/docker_config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | SCRIPT_SRC="" 11 | set +u 12 | if [ "$BASH_SOURCE" = "" ]; then SCRIPT_SRC=""; else SCRIPT_SRC="${BASH_SOURCE[0]}"; fi 13 | if [ "$SCRIPT_SRC" = "" ]; then SCRIPT_SRC=$0; fi 14 | set -u 15 | 16 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 17 | set +e 18 | ABS_PATH=$(readlink -f "${SCRIPT_SRC}" 2>&1) 19 | if [ "$?" -ne "0" ]; then 20 | echo "Using macOS alternative to readlink -f command..." 21 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 22 | TARGET_FILE=$SCRIPT_SRC 23 | 24 | cd $(dirname $TARGET_FILE) 25 | TARGET_FILE=$(basename $TARGET_FILE) 26 | ITERATIONS=0 27 | 28 | # Iterate down a (possible) chain of symlinks 29 | while [ -L "$TARGET_FILE" ] 30 | do 31 | TARGET_FILE=$(readlink $TARGET_FILE) 32 | cd $(dirname $TARGET_FILE) 33 | TARGET_FILE=$(basename $TARGET_FILE) 34 | ITERATIONS=$((ITERATIONS + 1)) 35 | if [ "$ITERATIONS" -gt 1000 ]; then 36 | echo "symlink loop. Critical exit." 37 | exit 1 38 | fi 39 | done 40 | 41 | # Compute the canonicalized name by finding the physical path 42 | # for the directory we're in and appending the target file. 43 | PHYS_DIR=$(pwd -P) 44 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 45 | fi 46 | 47 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 48 | DIR=$(dirname "$ABS_PATH") 49 | } 50 | GetPathToCurrentlyExecutingScript 51 | set -eu 52 | 53 | DOCKER_CMD='docker' 54 | EnsureDockerIsAvailableAndReachable () { 55 | # Make sure Docker is ready 56 | set +e 57 | $DOCKER_CMD ps > /dev/null 2>&1 58 | status=$? 59 | if [ $status -eq 0 ] 60 | then 61 | echo "Docker is available and reachable..." 62 | else 63 | $DOCKER_CMD ps 2>&1 | grep -q "permission denied" 64 | status=$? 65 | if [ $status -eq 0 ]; then 66 | echo -e "${YELLOW}Warning${NC}" 67 | echo "Docker requires sudo to execute, trying to substitute using 'sudo docker'" 68 | DOCKER_CMD='sudo docker' 69 | $DOCKER_CMD ps 2>&1 | grep -q "permission denied" 70 | status=$? 71 | if [ $status -eq 0 ]; then 72 | echo -e "${RED}ERROR${NC}" 73 | echo "Still issues with permissions, try a manual workaround where you set 'alias docker='sudo docker'' then run 'docker ps' to check that there is no 'permission denied' errors." 74 | exit 1 75 | else 76 | echo "Docker now accessible by way of sudo, continuing..." 77 | fi 78 | else 79 | echo -e "${RED}ERROR${NC}" 80 | echo "!!! Docker engine not available, make sure your Docker is running and responds to command 'docker ps' !!!" 81 | exit 1 82 | fi 83 | fi 84 | set -e 85 | } 86 | EnsureDockerIsAvailableAndReachable 87 | 88 | DOCKER_REGISTRY="" 89 | DOCKER_CONF_RAW=$(grep -A 8 'containerRegistry:' $DIR/../helm/values.yaml) # Find configuration path .Values.config.containerRegistry: 90 | DOCKER_REGISTRY=$(echo "$DOCKER_CONF_RAW" | grep 'serverAddress: "' | cut -d '"' -f 2) 91 | DOCKER_USER=$(echo "$DOCKER_CONF_RAW" | grep 'username: "' | cut -d '"' -f 2) 92 | DOCKER_PASSWORD=$(echo "$DOCKER_CONF_RAW" | grep 'password: "' | cut -d '"' -f 2) 93 | 94 | VERSION="" 95 | VERSION=$(grep 'cordaVersion:' $DIR/../helm/values.yaml | cut -d '"' -f 2 | tr '[:upper:]' '[:lower:]') 96 | HEALTH_CHECK_VERSION=$VERSION 97 | 98 | CORDA_VERSION="corda-ent-$VERSION" 99 | CORDA_IMAGE_PATH="corda_image_ent" 100 | CORDA_DOCKER_IMAGE_VERSION="v1.00" 101 | 102 | CORDA_FIREWALL_VERSION="corda-firewall-$VERSION" 103 | CORDA_FIREWALL_IMAGE_PATH="corda_image_firewall" 104 | FIREWALL_DOCKER_IMAGE_VERSION="v1.00" 105 | 106 | CORDA_HEALTH_CHECK_VERSION="corda-tools-health-survey-$HEALTH_CHECK_VERSION" 107 | -------------------------------------------------------------------------------- /docker-images/download_binaries.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | set +x 9 | 10 | DIR="." 11 | GetPathToCurrentlyExecutingScript () { 12 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 13 | set +e 14 | ABS_PATH=$(readlink -f "$0" 2>&1) 15 | if [ "$?" -ne "0" ]; then 16 | echo "Using macOS alternative to readlink -f command..." 17 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 18 | TARGET_FILE=$0 19 | 20 | cd $(dirname $TARGET_FILE) 21 | TARGET_FILE=$(basename $TARGET_FILE) 22 | ITERATIONS=0 23 | 24 | # Iterate down a (possible) chain of symlinks 25 | while [ -L "$TARGET_FILE" ] 26 | do 27 | TARGET_FILE=$(readlink $TARGET_FILE) 28 | cd $(dirname $TARGET_FILE) 29 | TARGET_FILE=$(basename $TARGET_FILE) 30 | ITERATIONS=$((ITERATIONS + 1)) 31 | if [ "$ITERATIONS" -gt 1000 ]; then 32 | echo "symlink loop. Critical exit." 33 | exit 1 34 | fi 35 | done 36 | 37 | # Compute the canonicalized name by finding the physical path 38 | # for the directory we're in and appending the target file. 39 | PHYS_DIR=$(pwd -P) 40 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 41 | fi 42 | 43 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 44 | DIR=$(dirname "$ABS_PATH") 45 | } 46 | GetPathToCurrentlyExecutingScript 47 | 48 | set -eu 49 | 50 | . $DIR/docker_config.sh 51 | 52 | set +x 53 | 54 | echoMessage () { 55 | message=$1 56 | 57 | echo "====== $message ======" 58 | } 59 | 60 | checkStatus () { 61 | status=$1 62 | if [ $status -eq 0 ] 63 | then 64 | echoMessage "Success" 65 | else 66 | echo -e "${RED}ERROR${NC}" 67 | echoMessage "The previous step failed" 68 | exit 1 69 | fi 70 | return 0 71 | } 72 | 73 | wgetDownload () { 74 | OUTPUT_FILE=$1 75 | URL=$2 76 | echo "Downloading $OUTPUT_FILE from $URL:" 77 | set +e 78 | wget --help > /dev/null 2>&1 79 | status=$? 80 | set -e 81 | if [ $status -ne 0 ]; then 82 | echo -e "${RED}ERROR${NC}" 83 | echo "wget missing, cannot continue (please install wget: https://stackoverflow.com/questions/33886917/how-to-install-wget-in-macos)!" 84 | exit 1 85 | else 86 | wget --user ${ARTIFACTORY_USER} --password ${ARTIFACTORY_PASSWORD} -S --spider $URL 2>&1 | grep 'HTTP/1.1 200 OK' 87 | status=$? 88 | if [ $status -eq 0 ]; then 89 | echo "URL check passed, target exists!" 90 | else 91 | echo -e "${RED}ERROR${NC}" 92 | echo "URL check failed, file not found! Check your version definition in values.yaml file!" 93 | echo "URL: $URL" 94 | exit 1 95 | fi 96 | 97 | set +e 98 | echo "test for sed -u availability..." | sed -u -e "s,\.,,g" > /dev/null 2>&1 99 | status=$? 100 | set -e 101 | 102 | SED_U_OPTION="-u" 103 | if [ $status -ne 0 ]; then 104 | SED_U_OPTION="" 105 | fi 106 | 107 | echo "Now downloading (please be patient) ..." 108 | echo -n " " 109 | wget -nc --user ${ARTIFACTORY_USER} --password ${ARTIFACTORY_PASSWORD} --progress=dot $URL -O $OUTPUT_FILE 2>&1 | grep --line-buffered "%" | sed $SED_U_OPTION -e "s,\.,,g" | awk '{printf("\b\b\b\b%4s", $2)}' 110 | echo -ne "\b\b\b\b" 111 | echo " DONE" 112 | fi 113 | } 114 | 115 | downloadBinaries () { 116 | echoMessage "Downloading necessary binaries for Corda Enterprise version $CORDA_VERSION ..." 117 | cd $DIR/bin 118 | 119 | CORDA_DOWNLOAD_URL="https://software.r3.com/artifactory/r3-corda-releases/com/r3/corda/corda/${VERSION}/corda-${VERSION}.jar" 120 | CORDA_FIREWALL_DOWNLOAD_URL="https://software.r3.com/artifactory/r3-corda-releases/com/r3/corda/corda-firewall/${VERSION}/corda-firewall-${VERSION}.jar" 121 | CORDA_HEALTH_CHECK_DOWNLOAD_URL="https://software.r3.com/artifactory/r3-corda-releases/com/r3/corda/corda-tools-health-survey/${VERSION}/corda-tools-health-survey-${VERSION}.jar" 122 | CORDA_FINANCE_WORKFLOWS_DOWNLOAD_URL="https://software.r3.com/artifactory/r3-corda-releases/com/r3/corda/corda-finance-workflows/${VERSION}/corda-finance-workflows-${VERSION}.jar" 123 | CORDA_FINANCE_CONTRACT_DOWNLOAD_URL="https://software.r3.com/artifactory/corda-releases/net/corda/corda-finance-contracts/${VERSION}/corda-finance-contracts-${VERSION}.jar" 124 | 125 | echo "Checking that wget exists..." 126 | set +e 127 | wget --help > /dev/null 2>&1 128 | status=$? 129 | set -e 130 | if [ $status -ne 0 ]; then 131 | echo -e "${YELLOW}Warning${NC}" 132 | echo "wget is not installed. You need to install it in order to download the binaries using this script. You may also download them manually." 133 | echo "Manual download instructions, please download the following links and save as the name suggests:" 134 | echo "docker-images/bin/$CORDA_VERSION.jar = $CORDA_DOWNLOAD_URL" 135 | echo "docker-images/bin/$CORDA_FIREWALL_VERSION.jar = $CORDA_FIREWALL_DOWNLOAD_URL" 136 | echo "docker-images/bin/$CORDA_HEALTH_CHECK_VERSION.jar = $CORDA_HEALTH_CHECK_DOWNLOAD_URL" 137 | echo "docker-images/bin/corda-finance-workflows-${VERSION}.jar = $CORDA_FINANCE_WORKFLOWS_DOWNLOAD_URL" 138 | echo "docker-images/bin/corda-finance-contracts-${VERSION}.jar = $CORDA_FINANCE_CONTRACT_DOWNLOAD_URL" 139 | fi 140 | 141 | if [ ! -f "$CORDA_VERSION.jar" ]; then 142 | wgetDownload $CORDA_VERSION.jar "$CORDA_DOWNLOAD_URL" 143 | checkStatus $? 144 | else 145 | echo "$CORDA_VERSION.jar already downloaded." 146 | fi 147 | 148 | if [ ! -f "$CORDA_FIREWALL_VERSION.jar" ]; then 149 | wgetDownload $CORDA_FIREWALL_VERSION.jar "$CORDA_FIREWALL_DOWNLOAD_URL" 150 | checkStatus $? 151 | else 152 | echo "$CORDA_FIREWALL_VERSION.jar already downloaded." 153 | fi 154 | 155 | if [ ! -f "$CORDA_HEALTH_CHECK_VERSION.jar" ]; then 156 | wgetDownload $CORDA_HEALTH_CHECK_VERSION.jar "$CORDA_HEALTH_CHECK_DOWNLOAD_URL" 157 | checkStatus $? 158 | else 159 | echo "$CORDA_HEALTH_CHECK_VERSION.jar already downloaded." 160 | fi 161 | 162 | if [ ! -f "corda-finance-workflows-${VERSION}.jar" ]; then 163 | wgetDownload corda-finance-workflows-${VERSION}.jar "$CORDA_FINANCE_WORKFLOWS_DOWNLOAD_URL" 164 | checkStatus $? 165 | else 166 | echo "corda-finance-workflows-${VERSION}.jar already downloaded." 167 | fi 168 | 169 | if [ ! -f "corda-finance-contracts-${VERSION}.jar" ]; then 170 | wgetDownload corda-finance-contracts-${VERSION}.jar "$CORDA_FINANCE_CONTRACT_DOWNLOAD_URL" 171 | checkStatus $? 172 | else 173 | echo "corda-finance-contracts-${VERSION}.jar already downloaded." 174 | fi 175 | 176 | if [ ! -f apache-artemis-2.6.4-bin.tar.gz ] 177 | then 178 | echoMessage "Downloading apache-artemis-2.6.4-bin.tar.gz..." 179 | curl -sSL https://www.apache.org/dist/activemq/activemq-artemis/2.6.4/apache-artemis-2.6.4-bin.tar.gz -o apache-artemis-2.6.4-bin.tar.gz 180 | #tar xzf apache-artemis-2.6.4-bin.tar.gz 181 | else 182 | echo "apache-artemis-2.6.4-bin.tar.gz already downloaded." 183 | fi 184 | 185 | if [ ! -f db_drivers/mssql-jdbc-7.2.0.jre8.jar ] 186 | then 187 | echoMessage "Downloading mssql-jdbc-7.2.0.jre8.jar..." 188 | curl -sSL https://github.com/Microsoft/mssql-jdbc/releases/download/v7.2.0/mssql-jdbc-7.2.0.jre8.jar -o db_drivers/mssql-jdbc-7.2.0.jre8.jar 189 | else 190 | echo "mssql-jdbc-7.2.0.jre8.jar already downloaded." 191 | fi 192 | 193 | if [ ! -f db_drivers/ojdbc8.jar ] 194 | then 195 | echoMessage "Downloading ojdbc8.jar..." 196 | curl -sSL https://download.oracle.com/otn-pub/otn_software/jdbc/197/ojdbc8.jar -o db_drivers/ojdbc8.jar 197 | else 198 | echo "ojdbc8.jar already downloaded." 199 | fi 200 | 201 | if [ ! -f db_drivers/postgresql-42.2.14.jar ] 202 | then 203 | echoMessage "Downloading postgresql-42.2.14.jar..." 204 | curl -sSL https://jdbc.postgresql.org/download/postgresql-42.2.14.jar -o db_drivers/postgresql-42.2.14.jar 205 | else 206 | echo "postgresql-42.2.14.jar already downloaded." 207 | fi 208 | 209 | cd .. 210 | echoMessage "Binaries downloaded." 211 | return 0 212 | } 213 | 214 | askForArtifactoryLoginInformation () { 215 | if [ "$ARTIFACTORY_USER" = "" ]; then 216 | echo -e "${YELLOW}Warning${NC}" 217 | echo "There is no value defined for artifactory_username in values.yaml, you can either interrupt this script with CTRL+C or enter your R3 Artifactory username next." 218 | read -p "Enter your R3 Artifactory username to continue: " ARTIFACTORY_USER 219 | fi 220 | 221 | if [ "$ARTIFACTORY_PASSWORD" = "" ]; then 222 | echo -e "${YELLOW}Warning${NC}" 223 | echo "There is no value defined for artifactory_password in values.yaml, you can either interrupt this script with CTRL+C or enter your R3 Artifactory password next." 224 | read -p "Enter your R3 Artifactory password to continue: " ARTIFACTORY_PASSWORD 225 | fi 226 | 227 | if [ "$ARTIFACTORY_USER" = "" -o "$ARTIFACTORY_PASSWORD" = "" ]; then 228 | echo -e "${RED}ERROR${NC}" 229 | echo "R3 Artifactory username or password missing!" 230 | exit 1 231 | fi 232 | } 233 | 234 | main () { 235 | ARTIFACTORY_CONFIG_RAW=$(grep -A 5 'artifactoryR3:' $DIR/../helm/values.yaml) 236 | ARTIFACTORY_USER=$(echo "$ARTIFACTORY_CONFIG_RAW" | grep 'artifactory_username: "' | cut -d '"' -f 2) 237 | ARTIFACTORY_PASSWORD=$(echo "$ARTIFACTORY_CONFIG_RAW" | grep 'artifactory_password: "' | cut -d '"' -f 2) 238 | ARTEMIS_OOP_ENABLED=$(grep -A 3 'artemis:' $DIR/../helm/values.yaml | grep 'enabled: "' | cut -d ':' -f 2) 239 | askForArtifactoryLoginInformation 240 | downloadBinaries 241 | return 0 242 | } 243 | 244 | main 245 | -------------------------------------------------------------------------------- /docker-images/push_docker_images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | set -eu 46 | 47 | . $DIR/docker_config.sh 48 | 49 | PushDockerImages () { 50 | echo "====== Pushing Docker images next ... ====== " 51 | if [ "$DOCKER_REGISTRY" = "" ]; then 52 | echo -e "${RED}ERROR${NC}" 53 | echo "You must specify a valid container registry in the values.yaml file" 54 | exit 1 55 | fi 56 | 57 | echo "Logging in to Docker registry..." 58 | $DOCKER_CMD login $DOCKER_REGISTRY --username $DOCKER_USER --password $DOCKER_PASSWORD 59 | 60 | echo "Tagging Docker images..." 61 | $DOCKER_CMD tag ${CORDA_IMAGE_PATH}:$CORDA_DOCKER_IMAGE_VERSION $DOCKER_REGISTRY/${CORDA_IMAGE_PATH}_$VERSION:$CORDA_DOCKER_IMAGE_VERSION 62 | $DOCKER_CMD tag ${CORDA_FIREWALL_IMAGE_PATH}:$FIREWALL_DOCKER_IMAGE_VERSION $DOCKER_REGISTRY/${CORDA_FIREWALL_IMAGE_PATH}_$VERSION:$FIREWALL_DOCKER_IMAGE_VERSION 63 | 64 | echo "Pushing Docker images to Docker repository..." 65 | CORDA_DOCKER_REPOSITORY=$(echo $DOCKER_REGISTRY/${CORDA_IMAGE_PATH}_$VERSION:$CORDA_DOCKER_IMAGE_VERSION 2>&1 | tr '[:upper:]' '[:lower:]') 66 | CORDA_FIREWALL_DOCKER_REPOSITORY=$(echo $DOCKER_REGISTRY/${CORDA_FIREWALL_IMAGE_PATH}_$VERSION:$FIREWALL_DOCKER_IMAGE_VERSION 2>&1 | tr '[:upper:]' '[:lower:]') 67 | echo "Push for Corda Enterprise Docker image:" 68 | $DOCKER_CMD push $CORDA_DOCKER_REPOSITORY 69 | echo "Push for Corda Firewall Docker image:" 70 | $DOCKER_CMD push $CORDA_FIREWALL_DOCKER_REPOSITORY 71 | echo "====== Pushing Docker images completed. ====== " 72 | } 73 | PushDockerImages -------------------------------------------------------------------------------- /docs/CHECKLIST.md: -------------------------------------------------------------------------------- 1 | # Corda Kubernetes Deployment checklist 2 | 3 | Tested with: 4 | 5 | Corda Enterprise versions 4.0, 4.1, 4.2, 4.3, 4.4, 4.5 6 | 7 | --- 8 | 9 | ## Prerequisites: 10 | 11 | - Clone the repository to any local folder 12 | - Installation requires the following tools: 13 | - **Docker** (tested with Docker 19.03.5, API 1.40, newer versions should be fine) 14 | - **kubectl** (tested with kubectl v1.12.8, newer versions should be fine) 15 | - **Helm** (requires Helm version 2.x, tested with Helm v2.14.3, newer v2.x versions should be fine) 16 | - Cloud specific **CLI**: 17 | - Azure CLI (tested with az cli 2.1.0, newer versions should be fine) [az](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) 18 | - AWS CLI (tested with aws cli 2, newer versions should be fine) [aws](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) 19 | - Google CLI (tested with gcloud 290.0.1, newer versions should be fine) [gcloud](https://cloud.google.com/sdk/gcloud) 20 | 21 | --- 22 | 23 | ## Cloud setup, follow one of the following: Azure, AWS, GCP 24 | 25 | Note, that if you already have your Kubernetes cluster with attached Container Registry and Persistent storage, you can skip this whole cloud setup section and skip straight to [Deployment configuration](#deployment-configuration). 26 | 27 | See [CLOUD_SETUP.md](CLOUD_SETUP.md) for more information on setup steps. 28 | 29 | ### Microsoft Azure cloud setup checklist: 30 | 31 | #### Azure Setup 32 | 33 | - Azure Account connected to a subscription with permissions to create resources 34 | - Azure Kubernetes Service 35 | - Azure Container Registry 36 | - Azure Service Principals 37 | - Azure Storage Account, create three new File shares for each of the following: 38 | - node, named for example node--storage, where name would match the nodes x500 name to some degree and should match values.yaml files "fileShareName" parameter as well 39 | - bridge, named for example bridge--storage, where name would match the nodes x500 name to some degree and should match values.yaml files "fileShareName" parameter as well 40 | - float, named for example float--storage, where name would match the nodes x500 name to some degree and should match values.yaml files "fileShareName" parameter as well 41 | - Public IP Addresses in the "KubernetesPlayground-NodePool" resource group 42 | - Node, to enable RPC connections from GUI, named for example node--ip 43 | - Float, to enable inbound connections from other nodes on the network, named for example float--ip 44 | - NOTE! SKU type for the Public IP must match the Load Balancer for the Kubernetes cluster (or you will get an error while the LoadBalancer is trying to set up the external IP connection) 45 | 46 | #### Azure Config 47 | 48 | - az login, make sure at this point that if you have many subscriptions, that the one you want to use has isDefault=true, if not use "az account list" and "az account set -s " to fix it 49 | - az aks get-credentials --resource-group KubernetesPlayground --name KubernetesPlaygroundAKS # KubernetesPlayground is just an example name, use your own resource names 50 | - kubectl create namespace # name could be for example firstname-lastname in lowercase, if you are deploying many instances in a test environment 51 | - kubectl config set-context --current --namespace 52 | 53 | --- 54 | 55 | ### Amazon Web Services (AWS) cloud setup checklist: 56 | 57 | #### AWS Setup 58 | 59 | - AWS account with a subscription that has necessary permissions to create resources 60 | - AWS VPC for the Kubernetes cluster 61 | - AWS EKS (Elastic Kubernetes Service), with at least one VM (t3.medium or better recommended) 62 | - AWS ECR (Elastic Container Registry) 63 | - AWS EBS (Elastic Block System), with 3 dedicated volumes set up and mounted to the VM that the pods will be running on 64 | - node volume, size 2Gb 65 | - bridge volume, size 1Gb 66 | - float volume, size 1Gb 67 | 68 | #### AWS Config 69 | 70 | - kubectl config, follow https://docs.aws.amazon.com/eks/latest/userguide/create-kubeconfig.html 71 | - kubectl create namespace # name could be for example firstname-lastname in lowercase, if you are deploying many instances in a test environment 72 | - kubectl config set-context --current --namespace 73 | 74 | --- 75 | 76 | ### Google Cloud Platform (GCP) cloud setup checklist: 77 | 78 | #### GCP Setup 79 | 80 | - GCP account with a subscription that has necessary permissions to create resources 81 | - GCP GKE (Google Kubernetes Engine), with at least one VM (n1-standard-4 or better recommended) 82 | - GCP GCR (Google Container Registry) 83 | - GCP PD (Persistent Disk), with 3 dedicated volumes set up and mounted to the VM that the pods will be running on 84 | - node volume, size 10Gb 85 | - bridge volume, size 10Gb 86 | - float volume, size 10Gb 87 | 88 | #### GCP Config 89 | 90 | - kubectl config, follow https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl 91 | - kubectl create namespace # name could be for example firstname-lastname in lowercase, if you are deploying many instances in a test environment 92 | - kubectl config set-context --current --namespace 93 | 94 | --- 95 | 96 | ## Deployment configuration: 97 | 98 | ### Deployment folder (repository folder) 99 | 100 | #### MAIN CONFIG in ``values.yaml``: 101 | 102 | - Define cordaVersion, which Corda Enterprise version to use, for example 4.0, 4.1 or 4.5-SNAPSHOT. (any releases that are tagged are fine) 103 | - Configure the containerRegistry section in its entirety, you'll find the details from your Container Registry you created in the Cloud setup 104 | - Configure the storage section in its entirety, you'll find the details from your Persistent Storage you created in the Cloud setup 105 | - Set the fileShareName for node/bridge/float to match the volumes you created in your Persistent Storage 106 | - Set the identityManagerAddress and networkmapAddress (with the http:// protocol prefix and the port number, eg. http://my-idman:1000) 107 | - You can use any network, but for Testnet see next line 108 | - Testnet - if you want to use Corda Testnet, follow the [Corda Testnet configuration](#corda-testnet-configuration) section 109 | - Set the resourceName to reflect the x500 name of the node, please note to use lowercase letters and numbers only 110 | - Set the legalName to define the x500 name of the node and a matching emailAddress as contact information 111 | - Define the p2pAddress where the Node will be reached by other nodes on the network (if deploying a Float, it should be the Floats DNS name) 112 | - Define the nodeLoadBalancerIP (it should map the Public STATIC IP address NUMBER of the Node, do not use a DNS name here) 113 | - Define the floatLoadBalancerIP (it should map the Public STATIC IP address NUMBER of the Float, do not use a DNS name here) 114 | 115 | #### Network setup 116 | 117 | - Download network root truststore to ./helm/files/network with the name ``networkRootTrustStore.jks`` (must match spelling exactly) 118 | - Configure matching truststorePassword to the truststore. 119 | 120 | #### Binaries, jar files (the name of the jars should match the configuration) 121 | 122 | Use ``docker-images/download_binaries.sh`` to automatically download the binaries for the cordaVersion specified in ``values.yaml``. 123 | 124 | ``docker-images/bin`` should contain the following: 125 | 126 | - Corda Enterprise jar (eg. corda-ent-4.0.jar) 127 | - Health-survey-tool jar (eg. corda-tools-healthsurvey-4.0.jar) 128 | - Corda Firewall jar (eg. corda-firewall-4.0.jar) 129 | 130 | ``pki-firewall/bin`` Optional step on Windows (normally this step can be skipped as long as keytool.exe is in PATH): 131 | 132 | - Copy Key tool binary + dll to bin folder (pki-firewall/bin) 133 | 134 | ### Execution 135 | 136 | #### Run ``one-time-setup.sh`` once, which does the following: 137 | 138 | - Creates and pushes Docker images to the container registry 139 | - Generates certificates for the Corda Firewall TLS tunnel 140 | - Performs initial registration of the node 141 | - Copies the generates certificates for the next step, which is the deployment 142 | - Copies the network-parameters file to /helm/files/network/network_parameters.file 143 | 144 | #### Deploy using ``deploy.sh`` or ``helm/helm_compile.sh``, which does the following: 145 | 146 | - Compiles the Helm charts from templates to Kubernetes resource definition files 147 | - Applies the generated Kubernetes resources definition files to the Kubernetes cluster 148 | - Three pods should be at status ‘Runningʼ for node, bridge and float after a while 149 | - Please have a look at the logs files for the three pods to make sure they are running without errors (kubectl get pods + kubectl logs -f ) 150 | - Run delete_all.sh to remove all resources from the Kubernetes cluster if you need to start fresh 151 | 152 | --- 153 | 154 | ## Corda Testnet configuration: 155 | 156 | This section is only relevant should you choose to deploy your node to Corda Testnet. For more information on Corda Testnet see [Joining Corda Testnet](https://docs.corda.net/docs/corda-os/4.4/corda-testnet-intro.html). 157 | 158 | ### Retrieve certificates and config: 159 | 160 | - Register on R3 Corda Marketplace: https://marketplace.r3.com/register 161 | - Go to https://marketplace.r3.com/network/testnet/dashboard 162 | - Click Create Node: https://marketplace.r3.com/network/testnet/install-node 163 | - Choose: Node version: "Enterprise" 164 | - Choose: Corda version: 4.0 (or whichever matches your version you are deploying) 165 | - Click on "Create new node" 166 | - Click on "Download Corda Node". A "node.zip" file should be prepared and downloaded 167 | 168 | ### Update certificates with legal entity keys ("identity-private-key" section in "nodekeystore.jks"): 169 | 170 | - Unzip the "node.zip" to a folder with JVM 1.8 installed and Internet access. (Let's call the full path to download folder NODE_DIR) 171 | - Edit "node.conf" and change "p2pAddress" from "0.0.0.0" to "localhost" 172 | - Run in a shell: "java -jar corda.jar" 173 | - Wait for node to start. This will enrich "certificates/nodekeystore.jks" with the Nodes legal entity key pair 174 | - Kill the node process (ctrl+c) 175 | - Copy certificates from Testnet node folder to deployment folder: "cp NODE_DIR/certificates/*.jks ./helm/files/certificates/node" 176 | - Copy network-parameters from Testnet node folder to deployment folder `cp NODE_DIR/network_parameters ./helm/files/network/network_parameters.file` 177 | 178 | ### In "helm/values.yaml": 179 | 180 | - Copy variables "keystorePassword" and "truststorePassword" from unzipped "node.conf" to sections matching paths ".Values.corda.node.conf.keystorePassword" and ".Values.corda.node.conf.truststorePassword" respectively 181 | - Fill variable "myLegalName" from "node.conf" to ".Values.corda.node.conf.legalName" 182 | - Fill variable "corda.node.conf.compatibilityZoneEnabled" with "true" 183 | - Fill variable "corda.node.conf.compatibilityZoneURL" with "https://netmap.testnet.r3.com" 184 | 185 | --- 186 | 187 | ## Useful commands: 188 | 189 | - Check deployment status with: ``kubectl get pods``, expect to see 'Running' if the pods are working normally 190 | - Check logs of running components with: ``kubectl logs -f `` 191 | - If the pods are not running correctly, investigate why with command: ``kubectl decribe `` 192 | - Investigate Corda Node log by gaining a shell into the running pod with: ``(prefix with 'winpty' on Windows) kubectl exec -it bash``, then cd to folder /opt/corda/workspace/logs and look at most recent node log file 193 | 194 | --- 195 | -------------------------------------------------------------------------------- /docs/CLOUD_SETUP.md: -------------------------------------------------------------------------------- 1 | # CLOUD INFRASTRUCTURE SETUP INSTRUCTIONS 2 | 3 | In order to use the Corda Kubernetes Deployment, you will need to have the necessary platform on which to deploy. 4 | This comes in the shape of a Kubernetes cluster and Container registry, but also should have persistent storage set up. 5 | Next are some instructions on how to set up the infrastructure. 6 | Setting up the relevant cloud services is currently left to the reader, this may change in future versions of the scripts to be more automated. 7 | 8 | --- 9 | 10 | ## Azure cloud instructions 11 | 12 | These are the services you will need to have set up in order to execute the deployment scripts correctly using Microsoft Azure. 13 | 14 | ### Azure Kubernetes Service (AKS) 15 | 16 | This is the main Kubernetes cluster that we will be using. Setting up the AKS will also set up a NodePool resource group. The NodePool should also have a few public IP addresses configured as Front End IP addresses for the AKS cluster. 17 | 18 | A good guide to follow for setting up AKS: [Quickstart: Deploy an Azure Kubernetes Service cluster using the Azure CLI](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough). 19 | 20 | Worth reading the ACR section at the same time to combine the knowledge and setup process. 21 | 22 | ### Azure Container Registry (ACR) 23 | 24 | The ACR provides the Docker images for the AKS to use. Please make sure that the AKS can connect to the ACR using appropriate Service Principals. See: [Azure Container Registry authentication with service principals](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-auth-service-principal). 25 | 26 | Guide for setting up ACR: [Tutorial: Deploy and use Azure Container Registry](https://docs.microsoft.com/en-us/azure/aks/tutorial-kubernetes-prepare-acr). 27 | 28 | Guide for connecting ACR and AKS: [Authenticate with Azure Container Registry from Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/cluster-container-registry-integration). 29 | 30 | Worth reading the AKS section at the same time to combine the knowledge and setup process. 31 | 32 | ### Azure Service Principals 33 | 34 | Service Principals is Azures way of delegating permissions between different services within Azure. There should be at least one Service Principal for AKS which can access ACR to pull the Docker images from there. 35 | 36 | Here is a guide to get your started on SPs: [Service principals with Azure Kubernetes Service (AKS)](https://docs.microsoft.com/en-us/azure/aks/kubernetes-service-principal). 37 | 38 | ### Azure Storage Account 39 | 40 | In addition to that there should be a storage account that will host the persistent volumes (File storage). 41 | 42 | Guide on setting up Storage Accounts: [Create an Azure Storage account](https://docs.microsoft.com/en-us/azure/storage/common/storage-account-create?tabs=azure-portal). 43 | 44 | ### Public IP addresses 45 | 46 | You should have a few static public IP addresses available for each deployment. One for the Node to accept incoming RPC connections from an UI level and another one if running the Float component within the cluster, this would then be the public IP address that other nodes would see and connect to. 47 | 48 | A guide on setting up Public IP addresses in Azure: [Create, change, or delete a public IP address](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-public-ip-address). 49 | 50 | --- 51 | 52 | ## AWS cloud instructions 53 | 54 | These are the services you will need to have set up in order to execute the deployment scripts correctly using Amazon Web Services. 55 | 56 | ### Amazon EKS - Elastic Kubernetes Service (EKS) 57 | 58 | Amazon EKS is the Kubernetes cluster on AWS. 59 | 60 | Here is a nice guide on setting up an EKS [Creating an Amazon EKS cluster](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html). 61 | 62 | You will need to create a VPC and IAM role for this to work, but the guide describes it quite well. 63 | 64 | We will need to set one up along with a node group (node pool), [Guide on node group setup](https://docs.aws.amazon.com/eks/latest/userguide/launch-workers.html). 65 | 66 | ### Amazon ECR - Elastic Container Registry (ECR) 67 | 68 | The ECR is the container registry, and it is required in order to host our custom built Docker images. 69 | [Creating a Repository](https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-create.html). 70 | 71 | In addition to creating this ECR, you will have to remember to set the containerRegistry.username as "AWS" in the values.yaml file in the helm sub folder. 72 | 73 | ### Amazon EBS - Elastic Block Storage (EBS) 74 | 75 | The way Amazon handles persistent storage for Kubernetes clusters is by way of EBS. We will have to provision some EBS volumes and dedicate a host for them. 76 | In order to set them up we should start by following this guide: [EC2 + EBS volumes](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/add-instance-store-volumes.html). 77 | 78 | Please make sure you create at least the following: 79 | 80 | * 1Gb EBS volume for the Float component 81 | * 1Gb EBS volume for the Bridge component 82 | * 2Gb EBS volume for the Node 83 | 84 | The volumes have to be assigned to a specific host, and that host also has to be specified in the values.yaml file in the helm sub folder later on in the installation, so keep the volume IDs and the host name (Private DNS) of the EC2 instance ready. 85 | 86 | The reason for this is that we will have to use [Topology-Aware Volume Provisioning in Kubernetes](https://kubernetes.io/blog/2018/10/11/topology-aware-volume-provisioning-in-kubernetes/). 87 | 88 | For more information on Amazons EBS read [Block Device Mapping](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html). 89 | 90 | The Kubernetes deployments will later on also be using nodeAffinity [](https://success.docker.com/article/how-to-control-container-placement-in-kubernetes-deployments) to successfully target the specific EC2 instance. 91 | 92 | --- 93 | 94 | ## GCP cloud instructions 95 | 96 | These are the services you will need to have set up in order to execute the deployment scripts correctly using Google Cloud Platform. 97 | 98 | ### Google Kubernetes Engine (GKE) 99 | 100 | GKE is the Kubernetes cluster on Google Cloud Platform. 101 | 102 | Setting up a GKE is quite easy using the [Google cloud console](https://console.cloud.google.com/). 103 | 104 | Here is a nice guide on setting up a GKE using gcloud [Creating a regional cluster](https://cloud.google.com/kubernetes-engine/docs/how-to/creating-a-regional-cluster). 105 | 106 | We will need to set up a node group (node pool), [Guide on node group setup](https://cloud.google.com/kubernetes-engine/docs/how-to/upgrading-a-cluster). 107 | 108 | For starters I would recommend creating a node pool with one VM backing it with 4 vCPU and 15 GB memory (n1-standard-4). Although by tweaking the deployment scripts minimum requirements for cpu you can deploy using a n1-standard-2 as well. 109 | 110 | ### Google Container Registry (GCR) 111 | 112 | The GCR is the container registry, and it is required in order to host our custom built Docker images. 113 | 114 | In order to create your first Google Container Registry, you should read the following page: [Pushing and pulling images](https://cloud.google.com/container-registry/docs/pushing-and-pulling). 115 | 116 | ### Google Persistent Disk (GCP PD) 117 | 118 | The way GCP handles persistent storage for Kubernetes clusters is by way of PD. We will have to provision some PD volumes for our components. 119 | 120 | You can create the disks directly from [Google cloud console](https://console.cloud.google.com/compute/disks). 121 | 122 | Please make sure you create at least the following (10Gb is the minimum size for PD's): 123 | 124 | * 10Gb PD volume for the Float component 125 | * 10Gb PD volume for the Bridge component 126 | * 10Gb PD volume for the Node 127 | 128 | Please make sure you create the volumes in the same zone as the node pools VM, so the node can mount the volumes. 129 | Also take note of the names of the PD's you create, since you will need to fill them into the ``values.yaml`` file in the helm sub folder. 130 | 131 | --- 132 | -------------------------------------------------------------------------------- /docs/COST_CALCULATION.md: -------------------------------------------------------------------------------- 1 | # COST CALCULATION & COMPARISON 2 | 3 | ## Overview 4 | 5 | Cost calculation of Kubernetes deployment versus a traditional bare-metal deployment in a production environment. 6 | 7 | We have received many requests to compare the cost of deploying using Kubernetes versus a traditional bare-metal based installation. 8 | 9 | Although the answer will be dependent on the use-case specific details, for example are we talking about high-frequency trading with high number of transactions per second or 10 | are we talking about high quality asset issuance which occurs much less frequently, we can still generate some rough estimates that hopefully will be useful as indications. 11 | 12 | #### Notes 13 | 14 | Note that if you just want to use this deployment for testing, you will have a fraction of the costs available to you. 15 | You can eliminate the database costs by using H2 file database (built-in to Corda). 16 | You can also use just 1 large server (4 cores and 16 GB RAM) or 2 mid-sized servers (2 cores and 8 GB RAM) to host the whole cluster. 17 | 18 | ## Basic building blocks 19 | 20 | Let's start by defining the basic building blocks that we will be using in both the bare-metal and the Kubernetes deployment cost calculations. 21 | This may not be the most realistic case, you may end up using slightly different sized machines in the two scenarios, but for the sake of comparison, we'll make this simplification. 22 | 23 | So let's start with the virtual machine (VM), we'll use a typical server with 2 cores and 8 GB of memory as the base building block. See the details in the specification section below. 24 | 25 | The reason why we chose this type is that it should be sufficient to run most Corda applications without issues, but still it is considered one of the smallest sizes available, which means, if you wanted to increase performance, so would the cost increase. 26 | For more information on sizing and performance please see [Corda Sizing & Performance](https://docs.corda.net/docs/corda-enterprise/4.4/node/sizing-and-performance.html#sizing-and-performance). 27 | 28 | Let's add more detail to the deployment, let's look at a typical deployment of Corda, which is comprised of a Corda node, Corda firewall, a vault database, a webserver, loadbalancer and a cloud HSM. 29 | 30 | #### Corda Enterprise Network Manager (CENM) 31 | 32 | We will also add the CENM setup to the list, just to have an overview of what it might mean if you were running your own private Corda network with the Corda Enterprise Network Manager. 33 | A CENM setup is comprised of an Identity Manager, a Signing Service, a Network Map and a Notary cluster. 34 | 35 | Please see [Corda Enterprise Network Manager](https://docs.corda.net/docs/cenm/1.2.html) for more details. 36 | 37 | You will also require a license, see [CENM Evaluation License](https://www.r3.com/download-corda-enterprise-network-manager/) for more information. 38 | 39 | --- 40 | 41 | ## Specification 42 | 43 | VM spec (2 cores and 8 GB of memory): 44 | 45 | - AWS: m4-large ($0.10/h, $73/month) 46 | - Azure: Standard_D2s_v3 ($0.117/h, $85.41/month) 47 | - GCP: n2-standard-2 ($0.0971/h, $70.883/month) 48 | 49 | HDD spec: 50 | 51 | - AWS: 100GB ($4.50/month) 52 | - Azure: 100GB ($4.60/month) 53 | - GCP: 100GB ($4.00/month) 54 | 55 | Database (DB) spec (*): 56 | 4 vCores, 500GB storage (some discrepancy between the different cloud providers make comparison slightly uncertain, please be skeptical on GCP DB pricing in particular) 57 | 58 | - AWS: db.m5.xlarge SQL Server ($1.224/h, $893.52/month) + storage SSD 500 GB ($112.50) = $1006.02 total/month (https://aws.amazon.com/rds/sqlserver/pricing/?nc=sn&loc=4) 59 | - Azure: Microsoft.SQLDatabase 4vCore + data max size 500 GB ($925.66/month) (https://azure.microsoft.com/en-gb/pricing/calculator/) 60 | - GCP: 4vCPU, 16 GB RAM, 4x$30.15+4x$5.11+500*$0.170/month = $120.6+$20.44+$85=$221+license $343.1 = $564.1 total/month (https://cloud.google.com/sql/pricing#sql-server) 61 | 62 | ## Cost calculation: CENM in traditional bare-metal setup 63 | 64 | Keep in mind, that if you are using the Corda Network, this setup is hosted by the Corda Network Foundation and you should not have to consider this cost. 65 | 66 | Please note that all costs are per month in this table and in USD. (only direct VM cost + HDD cost considered) 67 | Cloud HSM is listed but not calculated, the pricing models will vary wildly depending on how you use them. 68 | 69 | 70 | | Type | VMs | HDD | AWS | Azure | GCP | 71 | | ----------------- |:---:|:------:| ---------:| ---------:| ---------:| 72 | | Identity Manager | 1 | 100 GB | $77.50 | $90.01 | $74.88 | 73 | | Signing Service | 1 | 100 GB | $77.50 | $90.01 | $74.88 | 74 | | Network Map | 1 | 100 GB | $77.50 | $90.01 | $74.88 | 75 | | CENM Database(HA) | 2* | 500 GB | $2012.04 | $1851.32 | $1128.20 | 76 | | Notary Cluster | 3 | 100 GB | $232.50 | $270.03 | $224.65 | 77 | | Notary Cluster DB | 3* | 500 GB | $3018.06 | $2776.98 | $1692.30 | 78 | | Cloud HSM Keys x3 | - | - | - | - | - | 79 | | | | | | | | 80 | | **Total** | 6 | - | $5495.10 | $5168.36 | $3269.78 | 81 | 82 | --- 83 | 84 | ## Cost calculation: Corda Node in traditional bare-metal setup 85 | 86 | Please note that all costs are per month in this table and in USD. (only direct VM cost + HDD cost considered) 87 | 88 | Cloud HSM keys breakdown: 89 | (1 Node CA per node + 1 Legal Identity per node + 1 TLS per node) x 2 (the reason for two nodes is we are using Hot-Cold HA (High availability)) 90 | (optionally 1 Artemis access token + 1 artemis root in HSM) (Artemis can be used as a standalone component, which is the recommendation for high throughput) 91 | (optionally 1 tunnel root + 1 tunnel key + 1 bridge key in HSM) (Corda firewall is an optional component which is recommended to achieve high security) 92 | 93 | 94 | | Type | VMs | HDD | AWS | Azure | GCP | 95 | | ----------------- |:---:|:------:| ---------:| ---------:| ---------:| 96 | | Corda Node | 2 | 100 GB | $155.00 | $180.02 | $149.76 | 97 | | Node Database(HA) | 2* | 500 GB | $2012.04 | $1851.32 | $1128.20 | 98 | | Artemis MQ | 2 | 100 GB | $155.00 | $180.02 | $149.76 | 99 | | Corda Bridge | 2 | 100 GB | $155.00 | $180.02 | $149.76 | 100 | | Corda Float | 2 | 100 GB | $155.00 | $180.02 | $149.76 | 101 | | Webserver | 2 | 100 GB | $155.00 | $180.02 | $149.76 | 102 | | Loadbalancer | - | - | $22.42 | $23.25 | $18.25 | 103 | | Cloud HSM Keys x6 | - | - | - | - | - | 104 | | | | | | | | 105 | | **Total** | 10 | - | $2809.46 | $2774.67 | $1895.25 | 106 | 107 | --- 108 | 109 | ## Cost calculation: CENM using Kubernetes cluster 110 | 111 | The main difference comes from the fact that we can pool together VMs to serve many components, based on load. 112 | The storage requirements remain the same, as do the databases (the databases are expected to be provisioned outside of the cluster). 113 | 114 | | Type | VMs | HDD | AWS | Azure | GCP | 115 | | ----------------- |:---:|:------:| ---------:| ---------:| ---------:| 116 | | Identity Manager | 2 | 100 GB | $150.50 | $175.42 | $145.76 | 117 | | Signing Service | - | 100 GB | $4.50 | $4.60 | $4.00 | 118 | | Network Map | - | 100 GB | $4.50 | $4.60 | $4.00 | 119 | | CENM Database(HA) | 2* | 500 GB | $2012.04 | $1851.32 | $1128.20 | 120 | | Notary Cluster | 3 | 100 GB | $232.50 | $270.03 | $224.65 | 121 | | Notary Cluster DB | 3* | 500 GB | $3018.06 | $2776.98 | $1692.30 | 122 | | Cloud HSM Keys x3 | - | - | - | - | - | 123 | | | | | | | | 124 | | **Total** | 5 | - | $5422.10 | $5082.95 | $3198.90 | 125 | 126 | Cost saving of 1 VM for each column. The cost savings of running CENM inside a Kubernetes cluster are not huge, but they are measurable. 127 | The big advantage of using Kubernetes for CENM comes from the uptime and availability of the system as a whole. 128 | Kubernetes will be auto-restarting failed components, while in a traditional setting, you might have to do manual investigation and remediation. 129 | 130 | --- 131 | 132 | ## Cost calculation: Corda Node using Kubernetes cluster 133 | 134 | A large cost saving comes from the fact that Kubernetes maintains the HA. Which means we can drastically reduce the VMs required. 135 | 136 | | Type | VMs | HDD | AWS | Azure | GCP | 137 | | ----------------- |:---:|:------:| ---------:| ---------:| ---------:| 138 | | Corda Node | 1 | 100 GB | $77.50 | $90.01 | $74.88 | 139 | | Node Database(HA) | 2* | 500 GB | $2012.04 | $1851.32 | $1128.20 | 140 | | Artemis MQ | 1 | 100 GB | $77.50 | $90.01 | $74.88 | 141 | | Corda Bridge | 1 | 100 GB | $77.50 | $90.01 | $74.88 | 142 | | Corda Float | 1 | 100 GB | $77.50 | $90.01 | $74.88 | 143 | | Webserver | 1 | 100 GB | $77.50 | $90.01 | $74.88 | 144 | | Loadbalancer | - | - | $22.42 | $23.25 | $18.25 | 145 | | Cloud HSM Keys x3 | - | - | - | - | - | 146 | | | | | | | | 147 | | **Total** | 5 | - | $2421.96 | $2324.62 | $1520.85 | 148 | 149 | Cost saving of 5 VM for each column compared to traditional bare-metal installation. This equates to 50% cost reduction for VMs and total cost reduction of 14-20%. 150 | (also note we use 50% less HSM Keys, due to just having one node instead of two in the traditional Hot-Cold HA setup) 151 | 152 | --- 153 | 154 | ## CONCLUSION 155 | 156 | This cost calculation implies that there is a considerable amount of reduction of cost if using Kubernetes. 157 | In addition Kubernetes provides many other benefits, such as self-healing (high-availability), portability and scalability. 158 | Do take any calculations as a starting point and perform your own cost calculations, especially factoring in load scenarios you would be expecting. 159 | As mentioned previously, a system that would be catering to high network throughput would surely have to be scaled up vertically by a big factor. 160 | -------------------------------------------------------------------------------- /docs/KEY_CONCEPTS.md: -------------------------------------------------------------------------------- 1 | # KEY CONCEPTS / TOOLS 2 | 3 | ## Docker image generation 4 | 5 | We need to have the relevant Docker images in the Container Registry for Kubernetes to access. 6 | This is accomplished by the following two scripts in the folder ``docker-images``: 7 | 8 | * build_docker_images.sh 9 | Will compile the Dockerfiles into Docker images and tag them with the appropriate tags (that are customisable). 10 | * push_docker_images.sh 11 | Pushes the created Docker images to the assigned Docker Registry. 12 | 13 | Both of the above scripts rely on configuration settings in the file ``values.yaml``. 14 | 15 | Execute build_docker_images.sh to compile the Docker image we will be using. 16 | 17 | Running docker images "corda_*" should reveal the newly created image: 18 | 19 | ``` 20 | REPOSITORY TAG IMAGE ID CREATED SIZE 21 | corda_image_ent_4.0 v1.0 4c037385e632 5 minutes ago 363MB 22 | ``` 23 | 24 | ## HELM 25 | 26 | Helm is an orchestrator for Kubernetes, which allows us to parametrize the whole installation into a few simple values in one file (``helm/values.yaml``). 27 | This file is also used for the initial registration phase. 28 | 29 | ## CONFIGURATION 30 | 31 | Notable configuration options in the Helm values file include the following: 32 | 33 | - Enable / disable Corda Firewall use 34 | - Enable / disable out-of-process Artemis use, with / without High-Availability setup 35 | - Enable / disable HSM (Hardware Security Module) use 36 | 37 | ## Public Key Infrastructure (PKI) generation 38 | 39 | Some parts of the deployment use independent PKI structure. This is true for the Corda Firewall. 40 | The two components of the Corda Firewall, the Bridge and the Float communicate with each other using mutually authenticated TLS using a common certificate hierarchy with a shared trust root. 41 | One way to generate this certificate hierarchy is by use of the tools located in the folder ``corda-pki-generator``. 42 | This is just an example for setting up the necessary PKI structure and does not support storing the keys in HSMs, for that additional work is required and that is expected in an upcoming version of the scripts. 43 | 44 | ## INITIAL REGISTRATION 45 | 46 | The initial registration of a Corda Node is a one-time step that issues a Certificate Signing Request (CSR) to the Identity Manager 47 | on the Corda Network and once approved returns with the capability to generate a full certificate chain which links the Corda Network Root CA 48 | to the Subordinate CA which in turn links to the Identity Manager CA and finally to the Node CA. 49 | This Node CA is then capable of generating the necessary TLS certificate and signing keys for use in transactions on the network. 50 | 51 | This process is generally initiated by executing ``java -jar corda.jar initial-registration``. 52 | The process will always need access to the Corda Network root truststore. 53 | This is usually assigned to the above command with additional parameters: 54 | ``--network-root-truststore-password $TRUSTSTORE_PASSWORD --network-root-truststore ./workspace/networkRootTrustStore.jks``. 55 | 56 | The ``networkRootTrustStore.jks`` file should be placed in folder ``helm/files/network``. 57 | 58 | Once initiated the Corda Node will start the CSR request and wait indefinitely until the CSR request returns or is canceled. 59 | If the CSR returns successfully, next the Node will generate the certificates in the folder ``certificates``. 60 | The generated files from this folder should then be copied to the following folder: ``helm/files/certificates/node``. 61 | 62 | The following is performed by initiating an initial-registration step: 63 | 64 | - Contacts the [Corda Network](https://corda.network/) or a private Corda Network with a request to join the network with a CSR (Certificate Signing Request). 65 | - Generates Node signing keys and TLS keys for communicating with other Nodes on the network 66 | 67 | The scripted initial-registration step can be found in the following folder ``helm/initial-registration/``. 68 | 69 | Just run script ``initial-registration.sh`` 70 | 71 | The following steps should also be performed in a scripted manner, however, they are not implemented yet: 72 | 73 | - Places the Private keys corresponding to the generated certificates in an HSM (if HSM is configured to be used) 74 | - Generates Artemis configuration with / without High-Availability setup 75 | -------------------------------------------------------------------------------- /docs/KubernetesDeploymentArchitecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/corda/corda-kubernetes-deployment/f0016325af7b002cf626a87fa355e258e5b2556d/docs/KubernetesDeploymentArchitecture.png -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Corda Kubernetes Deployment 2 | 3 | ## Overview 4 | 5 | Kubernetes shines in orchestrating complex connection scenarios between multiple components and allowing these components to self-heal and recover from errors. 6 | The Corda Node is quite a complex system to deploy when it is deployed with Corda Firewall and potentially utilising HSM for storing private key material. 7 | This Kubernetes deployment is created to show you how to set up the different components in a Kubernetes cluster while still catering to best security practices. 8 | 9 | The old documentation section was hosted at https://solutions.corda.net/deployment/kubernetes/intro.html (link to be removed in the future) 10 | 11 | ## TOPICS 12 | 13 | ### Architecture Overview 14 | 15 | If you would like to see the high-level architectural view of the deployment, this is where you will find that information. 16 | 17 | [Architecture Overview](ARCHITECTURE_OVERVIEW.md) 18 | 19 | --- 20 | 21 | ### Usage: Deployment & Debugging issues 22 | 23 | In order to figure out how to perform the deployment successfully, and how to handle any issues that may come your way, please review the following: 24 | 25 | [Usage](USAGE.md) 26 | 27 | --- 28 | 29 | ### KEY CONCEPTS & TOOLS 30 | 31 | You may want to familiarize yourself with the key concepts of a production grade deployment and the tools being used in this deployment. 32 | You can find the information in: 33 | 34 | [Key Concepts](KEY_CONCEPTS.md) 35 | 36 | --- 37 | 38 | ### SETUP CHECKLIST 39 | 40 | Since there are a number of prerequisites that need to be met and then a certain order of running everything, a checklist has been collated that you may find useful. 41 | 42 | **Note!** 43 | It is strongly recommended you follow the CHECKLIST line by line, to not skip an important step, especially the first time you set up this deployment. 44 | 45 | Please find the complete list here: 46 | 47 | [Checklist](CHECKLIST.md) 48 | 49 | --- 50 | 51 | ### Cloud infrastructure setup 52 | 53 | This deployment requires a working cloud environment with Kubernetes Cluster Services that has access to a Docker Container Registry. 54 | In order to set everything up, you may find the following document helpful: 55 | 56 | [Cloud Setup](CLOUD_SETUP.md) 57 | 58 | --- 59 | 60 | ### Cost calculation of Kubernetes deployment versus a traditional bare-metal deployment 61 | 62 | We have received many requests to compare the cost of deploying using Kubernetes versus a traditional bare-metal based installation. 63 | 64 | Although the answer will be dependent on the use-case specific details, for example are we talking about high-frequency trading with high number of transactions per second or 65 | are we talking about high quality asset issuance which occurs much less frequently, we can still generate some rough estimates that hopefully will be useful as indications. 66 | 67 | The details can be found in this dedicated document: 68 | 69 | [Cost calculation & comparison](COST_CALCULATION.md) 70 | 71 | --- 72 | 73 | ### TESTED WITH 74 | 75 | This deployment has been tested and verified with the following information: 76 | 77 | [Support Matrix](SUPPORT_MATRIX.md) 78 | 79 | --- 80 | 81 | ### ROADMAP 82 | 83 | To see the intended direction that this deployment should take, please have a look at the 84 | 85 | [Roadmap](ROADMAP.md) 86 | 87 | --- 88 | 89 | -------------------------------------------------------------------------------- /docs/ROADMAP.md: -------------------------------------------------------------------------------- 1 | # CORDA KUBERNETES DEPLOYMENT ROADMAP 2 | 3 | This repository () is not complete, here is the roadmap for the next features to make the deployment more complete. 4 | 5 | --- 6 | 7 | ## HA utilities support 8 | 9 | [HA utilities]() adds support for Corda Firewall PKI generation and HSM integration for the initial registration phase. 10 | It can even generate the configuration required to set up external Artemis (out-of-process Artemis). 11 | 12 | ### Goals: 13 | 14 | - Change Initial registration step to use HA utilities. 15 | 16 | --- 17 | 18 | ## Artemis support 19 | 20 | Artemis is the message queue that the Corda Node uses to communicate with other nodes on the network, whether it be via a Corda Firewall or not. 21 | Adding support for Artemis allows the option to host multiple Corda Nodes behind a shared Artemis <> Bridge <> Float setup. 22 | This can be both a cost benefit but also helps define the High Availability (HA) setup. 23 | 24 | ### Goals: 25 | 26 | - Enable Initial registration step to generate the Artemis configuration and potentially the full installation of Artemis that could can then be deployed in between Corda Node and Corda Firewalls Bridge component. 27 | 28 | --- 29 | 30 | ## HSM support 31 | 32 | Hardware Security Modules (HSM) are a must in order to keep private key material absolutely private. 33 | There are options to keep private key material safe, but by using an HSM it can be completely private. 34 | This is a requirement for many larger corporations and banks. 35 | 36 | ### Goals: 37 | 38 | - Enable Initial registration step to use HA utilities to add private key material directly to HSM. 39 | - Add support for the Corda Node and the Corda Firewall components to use the keys from the HSM. 40 | 41 | --- 42 | 43 | ## Support for local Kubernetes clusters 44 | 45 | Consider the addition of support for local Kubernetes clusters, for example minikube, OpenShift etc. 46 | 47 | ### Goals: 48 | 49 | - Add support for deploying this setup on a local cluster 50 | 51 | --- 52 | 53 | ## CorDapp distribution 54 | 55 | The CorDapps are currently installed by a direct copy command during the deployment step. 56 | This may not be the best way to handle CorDapps in the future, for example in order to handle upgrade scenarios. 57 | 58 | ### Goals: 59 | 60 | - Investigate different ways to handle CorDapp distribution for the deployment 61 | - Define a working design for the necessary new distribution options and add them back to the roadmap 62 | 63 | --- 64 | 65 | ## Upgrading scenarios 66 | 67 | There are many upgrading scenarios that should be tackled. These include, but are not necessarily limited to: 68 | 69 | - Corda Network upgrades, network-parameters (minimumPlatformVersion, whitelisted notaries etc.) 70 | - Corda version upgrades, if a new version of Corda is required, steps to upgrade it in a reliable manner 71 | - CorDapp version upgrades, if a new version of the CorDapp is required, steps to upgrade it in a reliable manner 72 | 73 | ### Goals: 74 | 75 | - Define upgrading best practices for the deployment to tackle the above 3 scenarios 76 | - Define the designs for these upgrading options and place them in the roadmap 77 | 78 | --- 79 | 80 | ## Monitoring and Health Probes 81 | 82 | It is important to be able to monitor and probe the pods health to be able to react to any detrimental changes over time. 83 | For example, if the memory usage goes above 80%, take an action. Or if the pod is restarting regularly, take an action. 84 | 85 | ### Goals: 86 | 87 | - Define the best practices of health probing for the different components 88 | - Define and design a monitoring solution that is standardized 89 | 90 | --- 91 | 92 | ## Testing 93 | 94 | ### Performance testing 95 | 96 | An extensive set of performance tests should be executed on the deployment to figure out potential bottlenecks and then address those issues accordingly. 97 | 98 | ### Penetration testing 99 | 100 | An extensive set of penetration tests should be executed on the deployment to figure out potential security issues and then address those issues accordingly. 101 | 102 | --- 103 | 104 | ## Distribution-less Docker Images 105 | 106 | High security environments demand that the Docker image is not based on a specific Distribution, it should be custom built, as in define exactly what it will contain. 107 | 108 | ### Goals: 109 | 110 | - Add support for Distribution-less Docker images 111 | 112 | --- 113 | 114 | ## Production grade pipelines 115 | 116 | In production you want to have everything run as smoothly as possible. In order to do so, we would like to automate the deployment of resources by use of a pipeline. 117 | There are many ways to build a fully automated pipeline that at the end of it deploys into Kubernetes. 118 | We can use CI/CD pipelines that we define ourselves, or use the Kubernetes Operator framework to define an implementation ourselves or use an existing framework, for example Flux, https://github.com/fluxcd/flux. 119 | 120 | ### Goals: 121 | 122 | - Define the different options and for each, pros and cons 123 | - Decide on one to try out and if reasonable add as a reference implementation to this repository 124 | 125 | --- 126 | -------------------------------------------------------------------------------- /docs/SUPPORT_MATRIX.md: -------------------------------------------------------------------------------- 1 | # SUPPORT MATRIX 2 | 3 | The Corda Kubernetes Deployment has been tested and verified to work with the following setup. 4 | 5 | Please note that you may be able to work with other setups than the ones that have been tested, but for first time deployment you really should go with one of the tested ones. 6 | 7 | ## Database support 8 | 9 | This deployment supports the following databases: 10 | 11 | | Vendor | Version | JDBC Driver | 12 | | ------------- |:-------:|:-------------------------------| 13 | | MS SQL Server | 2017 | Microsoft JDBC | 14 | | PostgreSQL | 9.6 | PostgreSQL JDBC Driver 42.2.14 | 15 | | Oracle | 12cR2 | Oracle JDBC 8 | 16 | 17 | Please note that the JDBC driver is downloaded automatically as part of the deployment and may end up downloading another version in the future. 18 | 19 | ## Operating system support 20 | 21 | Operating systems supported in deployment: 22 | 23 | | Platform | Version | 24 | | ------------- |:-------:| 25 | | MS Windows | 10 | 26 | | Linux Ubuntu | 18.04 | 27 | | Apple macOS | 10.15 | 28 | 29 | Great effort has been done to keep all 3 major OS supported. 30 | 31 | ## Cloud vendor support 32 | 33 | This deployment has been tested and verified against the 3 major cloud providers. 34 | 35 | | Vendor | Complete vendor name | 36 | | ------- |:------------------------| 37 | | Azure | Microsoft Azure | 38 | | AWS | Amazon Web Services | 39 | | GCP | Google Cloud Platform | 40 | 41 | Best effort to be cloud agnostic regarding the support for the different cloud providers. 42 | 43 | ## Software support 44 | 45 | The deployment usually requires a minimum version of software and higher version numbers are usually fine, there are some exceptions though as listed below. 46 | 47 | | Software | Minimum recommended version | Limitations | 48 | | ---------- |:-------------------------------------|:-------------------------------------------------| 49 | | Docker | tested with Docker 19.03.5, API 1.40 | newer versions should be fine | 50 | | kubectl | tested with kubectl v1.12.8 | newer versions should be fine | 51 | | Helm | tested with Helm v2.14.3 | requires Helm version 2.x (3.x has known issues) | 52 | | Azure CLI | tested with az cli 2.1.0 | newer versions should be fine | 53 | | AWS CLI | tested with aws cli 2 | newer versions should be fine | 54 | | Google CLI | tested with gcloud 290.0.1 | newer versions should be fine | 55 | 56 | Should you try and use versions older than the tested ones, you are in uncharted waters and may run into issues, please consider updating the relevant software! 57 | 58 | ## Infrastructure minimum requirements 59 | 60 | For the underlying infrastructure here are some minimum requirements that have been tested. 61 | 62 | ### Kubernetes Cluster 63 | 64 | A node pool that has the following resources available: 65 | 66 | - 2x Standard DS2 v2 (2 vcpus, 7 GiB memory) 67 | 68 | ### Storage account 69 | 70 | 3 file shares with the minimum storage requirements of: 71 | 72 | - Node, 2GB 73 | - Bridge, 1GB 74 | - Float, 1GB 75 | 76 | (please note that these are bare minimums to stand up the relevant components and should not be expected to last for years in production) 77 | 78 | ## Disclaimer 79 | 80 | These are tested with versions, but that does not mean that there cannot be any issues arising later from using any of these combinations of systems. 81 | Completing an end to end transaction between two nodes in a simple setup has different expectations compared to running a node in production for many years. 82 | It is strongly recommended that you perform your own in-depth tests with the setup you deem most relevant to your deployment. 83 | -------------------------------------------------------------------------------- /helm/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | # Common VCS dirs 5 | .git/ 6 | .gitignore 7 | -------------------------------------------------------------------------------- /helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | description: Corda Deployment Chart 2 | name: corda 3 | version: 0.1.2 4 | -------------------------------------------------------------------------------- /helm/README.md: -------------------------------------------------------------------------------- 1 | # Corda Kubernetes Deployment Chart 2 | 3 | This directory contains two Helm charts, one for initial registration of a Corda Node and one for deploying the Corda Node along with optional Corda Firewall to a Kubernetes cluster. 4 | 5 | --- 6 | 7 | ## Prerequisites 8 | 9 | - Corda Enterprise binaries available in ``docker-images/bin`` folder as per previous steps in ``corda-kubernetes-deployment`` 10 | - Kubernetes cluster set up with access to a Docker Container Registry 11 | - Docker Container Registry 12 | - StorageClass linked to correctly set up Cloud storage 13 | - Database cluster with JDBC connection string 14 | - kubectl is used to manage Kubernetes cluster (https://kubernetes.io/docs/tasks/tools/install-kubectl/) 15 | - Helm (https://helm.sh/) 16 | 17 | --- 18 | 19 | ## Configuration 20 | 21 | All the values listed in `values.yaml` can be modified to customise the deployment of the Corda Node. 22 | Please pay attention to correct spelling of the content of each variable. 23 | 24 | ## Initial registration 25 | 26 | The one time registration of a Corda Node to a Corda Network has to be performed before deploying the Nodes to the Kubernetes cluster. 27 | This can be done by executing the script ``initial_registration/initial_registration.sh`` 28 | 29 | NOTE! Make sure you have completed ALL prerequisites (also in corda-kubernetes-deployment) and filled in ``values.yaml`` entirely 30 | 31 | ## Installation 32 | 33 | Executing ``helm_compile.sh`` will compile the Helm charts into Kubernetes templates and apply them directly to the Kubernetes cluster. 34 | 35 | This is the recommended mode of operation. (you may use ``delete-all.sh`` to clean out the cluster for a fresh deploy) 36 | 37 | ## Manual Installation 38 | 39 | First we have to create a namespace for this installation, if installing multiple nodes, the namespace should be customized per installation (and configured in ``values.yaml`` as well). 40 | 41 | kubectl create namespace corda 42 | 43 | Next we generate the Kubernetes templates that we will be deploying to the Kubernetes Cluster. 44 | 45 | helm template . --name corda --namespace corda --output-dir output 46 | 47 | Next we deploy the template to the cluster. 48 | 49 | kubectl apply -f output --namespace=corda 50 | 51 | This step can be repeated if you change any of the parameters in the template. 52 | -------------------------------------------------------------------------------- /helm/delete-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | DeleteAllKubernetesResources () { 6 | echo "====== Deleting all Kubernetes resources next ... ====== " 7 | kubectl delete --all jobs --wait=false 8 | kubectl delete --all pods --wait=false 9 | kubectl delete --all services --wait=false 10 | kubectl delete --all deployments --wait=false 11 | kubectl delete --all statefulsets --wait=false 12 | kubectl delete --all configmaps --wait=false 13 | kubectl delete --all svc --wait=false 14 | kubectl delete --all pvc --wait=false 15 | kubectl delete --all pv --wait=false 16 | 17 | while :; do 18 | n=$(kubectl get pods | wc -l) 19 | if [[ n -eq 0 ]]; then 20 | break 21 | fi 22 | sleep 5 23 | done 24 | echo "====== Deleting all Kubernetes resources completed. ====== " 25 | } 26 | DeleteAllKubernetesResources 27 | -------------------------------------------------------------------------------- /helm/files/certificates/firewall_tunnel/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /helm/files/certificates/node/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /helm/files/conf/bridge-4.0.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "BridgeInner" 2 | 3 | networkParametersPath: "./workspace/network-parameters" 4 | 5 | outboundConfig: { 6 | artemisBrokerAddress: "{{ .Values.config.resourceName }}-node-internal:{{ .Values.corda.node.conf.p2pPort }}" 7 | alternateArtemisBrokerAddresses: [] 8 | } 9 | 10 | bridgeInnerConfig: { 11 | floatAddresses: [ "{{- if ne .Values.corda.node.conf.floatInternalAddress "" }} 12 | {{- .Values.corda.node.conf.floatInternalAddress }} 13 | {{- else }} 14 | {{- if and .Values.setup.cordaFirewall.enabled .Values.setup.cordaFirewall.destination.internalKubernetesCluster.enabled }} 15 | {{- .Values.config.resourceName }}-float-internal 16 | {{- else }} 17 | {{- .Values.corda.node.conf.p2pAddress }} 18 | {{- end }} 19 | {{- end }}:{{ .Values.corda.node.conf.bridgeTunnelPort }}" ] 20 | expectedCertificateSubject: "CN=Float Local,O=Local Only,L=London,C=GB" 21 | tunnelSSLConfiguration { 22 | keyStorePassword: "{{ .Values.corda.firewall.conf.bridgeKeystorePassword }}" 23 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 24 | sslKeystore: "./workspace/certificates/bridge.jks" 25 | trustStoreFile: "./workspace/certificates/trust.jks" 26 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 27 | } 28 | } 29 | 30 | certificatesDirectory: "./workspace/certificates" 31 | sslKeystore: "./workspace/certificates/sslkeystore.jks" 32 | trustStoreFile: "./workspace/certificates/truststore.jks" 33 | keyStorePassword: "{{ .Values.corda.node.conf.keystorePassword }}" 34 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 35 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 36 | silencedIPs: [] 37 | 38 | enableAMQPPacketTrace: false 39 | artemisReconnectionIntervalMin: 5000 40 | artemisReconnectionIntervalMax: 60000 41 | politeShutdownPeriod: 1000 42 | p2pConfirmationWindowSize: 1048576 43 | auditServiceConfiguration: { 44 | loggingIntervalSec: 60 45 | } 46 | -------------------------------------------------------------------------------- /helm/files/conf/bridge-4.1.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "BridgeInner" 2 | 3 | networkParametersPath: "./workspace/network-parameters" 4 | 5 | outboundConfig: { 6 | artemisBrokerAddress: "{{ .Values.config.resourceName }}-node-internal:{{ .Values.corda.node.conf.p2pPort }}" 7 | alternateArtemisBrokerAddresses: [] 8 | } 9 | 10 | bridgeInnerConfig: { 11 | floatAddresses: [ "{{- if ne .Values.corda.node.conf.floatInternalAddress "" }} 12 | {{- .Values.corda.node.conf.floatInternalAddress }} 13 | {{- else }} 14 | {{- if and .Values.setup.cordaFirewall.enabled .Values.setup.cordaFirewall.destination.internalKubernetesCluster.enabled }} 15 | {{- .Values.config.resourceName }}-float-internal 16 | {{- else }} 17 | {{- .Values.corda.node.conf.p2pAddress }} 18 | {{- end }} 19 | {{- end }}:{{ .Values.corda.node.conf.bridgeTunnelPort }}" ] 20 | expectedCertificateSubject: "CN=Float Local,O=Local Only,L=London,C=GB" 21 | tunnelSSLConfiguration { 22 | keyStorePassword: "{{ .Values.corda.firewall.conf.bridgeKeystorePassword }}" 23 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 24 | sslKeystore: "./workspace/certificates/bridge.jks" 25 | trustStoreFile: "./workspace/certificates/trust.jks" 26 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 27 | } 28 | } 29 | 30 | certificatesDirectory: "./workspace/certificates" 31 | sslKeystore: "./workspace/certificates/sslkeystore.jks" 32 | trustStoreFile: "./workspace/certificates/truststore.jks" 33 | keyStorePassword: "{{ .Values.corda.node.conf.keystorePassword }}" 34 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 35 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 36 | silencedIPs: [] 37 | 38 | enableAMQPPacketTrace: false 39 | artemisReconnectionIntervalMin: 5000 40 | artemisReconnectionIntervalMax: 60000 41 | politeShutdownPeriod: 1000 42 | p2pConfirmationWindowSize: 1048576 43 | auditServiceConfiguration: { 44 | loggingIntervalSec: 60 45 | } 46 | -------------------------------------------------------------------------------- /helm/files/conf/bridge-4.2.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "BridgeInner" 2 | 3 | networkParametersPath: "network-parameters" 4 | 5 | outboundConfig: { 6 | artemisBrokerAddress: "{{ .Values.config.resourceName }}-node-internal:{{ .Values.corda.node.conf.p2pPort }}" 7 | alternateArtemisBrokerAddresses: [] 8 | } 9 | 10 | bridgeInnerConfig: { 11 | floatAddresses: [ "{{- if ne .Values.corda.node.conf.floatInternalAddress "" }} 12 | {{- .Values.corda.node.conf.floatInternalAddress }} 13 | {{- else }} 14 | {{- if and .Values.setup.cordaFirewall.enabled .Values.setup.cordaFirewall.destination.internalKubernetesCluster.enabled }} 15 | {{- .Values.config.resourceName }}-float-internal 16 | {{- else }} 17 | {{- .Values.corda.node.conf.p2pAddress }} 18 | {{- end }} 19 | {{- end }}:{{ .Values.corda.node.conf.bridgeTunnelPort }}" ] 20 | expectedCertificateSubject: "CN=Float Local,O=Local Only,L=London,C=GB" 21 | tunnelSSLConfiguration { 22 | keyStorePassword: "{{ .Values.corda.firewall.conf.bridgeKeystorePassword }}" 23 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 24 | sslKeystore: "certificates/bridge.jks" 25 | trustStoreFile: "certificates/trust.jks" 26 | } 27 | } 28 | 29 | {{- if .Values.corda.node.conf.crlCheckSoftFail }} 30 | revocationConfig: { mode: "OFF"}) 31 | {{- end }} 32 | 33 | certificatesDirectory: "certificates" 34 | sslKeystore: "certificates/sslkeystore.jks" 35 | trustStoreFile: "certificates/truststore.jks" 36 | keyStorePassword: "{{ .Values.corda.node.conf.keystorePassword }}" 37 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 38 | silencedIPs: [] 39 | 40 | enableAMQPPacketTrace: false 41 | artemisReconnectionIntervalMin: 5000 42 | artemisReconnectionIntervalMax: 60000 43 | politeShutdownPeriod: 1000 44 | p2pConfirmationWindowSize: 1048576 45 | auditServiceConfiguration: { 46 | loggingIntervalSec: 60 47 | } 48 | -------------------------------------------------------------------------------- /helm/files/conf/bridge-4.3.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "BridgeInner" 2 | 3 | networkParametersPath: "network-parameters" 4 | 5 | outboundConfig: { 6 | artemisBrokerAddress: "{{ .Values.config.resourceName }}-node-internal:{{ .Values.corda.node.conf.p2pPort }}" 7 | alternateArtemisBrokerAddresses: [] 8 | } 9 | 10 | bridgeInnerConfig: { 11 | floatAddresses: [ "{{- if ne .Values.corda.node.conf.floatInternalAddress "" }} 12 | {{- .Values.corda.node.conf.floatInternalAddress }} 13 | {{- else }} 14 | {{- if and .Values.setup.cordaFirewall.enabled .Values.setup.cordaFirewall.destination.internalKubernetesCluster.enabled }} 15 | {{- .Values.config.resourceName }}-float-internal 16 | {{- else }} 17 | {{- .Values.corda.node.conf.p2pAddress }} 18 | {{- end }} 19 | {{- end }}:{{ .Values.corda.node.conf.bridgeTunnelPort }}" ] 20 | expectedCertificateSubject: "CN=Float Local,O=Local Only,L=London,C=GB" 21 | tunnelSSLConfiguration { 22 | keyStorePassword: "{{ .Values.corda.firewall.conf.bridgeKeystorePassword }}" 23 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 24 | sslKeystore: "certificates/bridge.jks" 25 | trustStoreFile: "certificates/trust.jks" 26 | } 27 | } 28 | 29 | {{- if .Values.corda.node.conf.crlCheckSoftFail }} 30 | revocationConfig: { mode: "OFF"}) 31 | {{- end }} 32 | 33 | certificatesDirectory: "certificates" 34 | sslKeystore: "certificates/sslkeystore.jks" 35 | trustStoreFile: "certificates/truststore.jks" 36 | keyStorePassword: "{{ .Values.corda.node.conf.keystorePassword }}" 37 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 38 | silencedIPs: [] 39 | 40 | enableAMQPPacketTrace: false 41 | artemisReconnectionIntervalMin: 5000 42 | artemisReconnectionIntervalMax: 60000 43 | politeShutdownPeriod: 1000 44 | p2pConfirmationWindowSize: 1048576 45 | auditServiceConfiguration: { 46 | loggingIntervalSec: 60 47 | } 48 | -------------------------------------------------------------------------------- /helm/files/conf/bridge-4.4.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "BridgeInner" 2 | 3 | networkParametersPath: "network-parameters" 4 | 5 | outboundConfig: { 6 | artemisBrokerAddress: "{{ .Values.config.resourceName }}-node-internal:{{ .Values.corda.node.conf.p2pPort }}" 7 | alternateArtemisBrokerAddresses: [] 8 | } 9 | 10 | bridgeInnerConfig: { 11 | floatAddresses: [ "{{- if ne .Values.corda.node.conf.floatInternalAddress "" }} 12 | {{- .Values.corda.node.conf.floatInternalAddress }} 13 | {{- else }} 14 | {{- if and .Values.setup.cordaFirewall.enabled .Values.setup.cordaFirewall.destination.internalKubernetesCluster.enabled }} 15 | {{- .Values.config.resourceName }}-float-internal 16 | {{- else }} 17 | {{- .Values.corda.node.conf.p2pAddress }} 18 | {{- end }} 19 | {{- end }}:{{ .Values.corda.node.conf.bridgeTunnelPort }}" ] 20 | expectedCertificateSubject: "CN=Float Local,O=Local Only,L=London,C=GB" 21 | tunnelSSLConfiguration { 22 | keyStorePassword: "{{ .Values.corda.firewall.conf.bridgeKeystorePassword }}" 23 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 24 | sslKeystore: "certificates/bridge.jks" 25 | trustStoreFile: "certificates/trust.jks" 26 | } 27 | } 28 | 29 | {{- if .Values.corda.node.conf.crlCheckSoftFail }} 30 | revocationConfig: { mode: "OFF"}) 31 | {{- end }} 32 | 33 | certificatesDirectory: "certificates" 34 | sslKeystore: "certificates/sslkeystore.jks" 35 | trustStoreFile: "certificates/truststore.jks" 36 | keyStorePassword: "{{ .Values.corda.node.conf.keystorePassword }}" 37 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 38 | silencedIPs: [] 39 | 40 | enableAMQPPacketTrace: false 41 | artemisReconnectionIntervalMin: 5000 42 | artemisReconnectionIntervalMax: 60000 43 | politeShutdownPeriod: 1000 44 | p2pConfirmationWindowSize: 1048576 45 | auditServiceConfiguration: { 46 | loggingIntervalSec: 60 47 | } 48 | -------------------------------------------------------------------------------- /helm/files/conf/bridge-4.5.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "BridgeInner" 2 | 3 | networkParametersPath: "network-parameters" 4 | 5 | outboundConfig: { 6 | artemisBrokerAddress: "{{ .Values.config.resourceName }}-node-internal:{{ .Values.corda.node.conf.p2pPort }}" 7 | alternateArtemisBrokerAddresses: [] 8 | } 9 | 10 | bridgeInnerConfig: { 11 | floatAddresses: [ "{{- if ne .Values.corda.node.conf.floatInternalAddress "" }} 12 | {{- .Values.corda.node.conf.floatInternalAddress }} 13 | {{- else }} 14 | {{- if and .Values.setup.cordaFirewall.enabled .Values.setup.cordaFirewall.destination.internalKubernetesCluster.enabled }} 15 | {{- .Values.config.resourceName }}-float-internal 16 | {{- else }} 17 | {{- .Values.corda.node.conf.p2pAddress }} 18 | {{- end }} 19 | {{- end }}:{{ .Values.corda.node.conf.bridgeTunnelPort }}" ] 20 | expectedCertificateSubject: "CN=Float Local,O=Local Only,L=London,C=GB" 21 | tunnelSSLConfiguration { 22 | keyStorePassword: "{{ .Values.corda.firewall.conf.bridgeKeystorePassword }}" 23 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 24 | sslKeystore: "certificates/bridge.jks" 25 | trustStoreFile: "certificates/trust.jks" 26 | } 27 | } 28 | 29 | {{- if .Values.corda.node.conf.crlCheckSoftFail }} 30 | revocationConfig: { mode: "OFF"}) 31 | {{- end }} 32 | 33 | certificatesDirectory: "certificates" 34 | sslKeystore: "certificates/sslkeystore.jks" 35 | trustStoreFile: "certificates/truststore.jks" 36 | keyStorePassword: "{{ .Values.corda.node.conf.keystorePassword }}" 37 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 38 | silencedIPs: [] 39 | 40 | enableAMQPPacketTrace: false 41 | artemisReconnectionIntervalMin: 5000 42 | artemisReconnectionIntervalMax: 60000 43 | politeShutdownPeriod: 1000 44 | p2pConfirmationWindowSize: 1048576 45 | auditServiceConfiguration: { 46 | loggingIntervalSec: 60 47 | } 48 | -------------------------------------------------------------------------------- /helm/files/conf/float-4.0.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "FloatOuter" 2 | 3 | networkParametersPath: "./network-parameters" 4 | 5 | inboundConfig: { 6 | listeningAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 7 | } 8 | 9 | floatOuterConfig: { 10 | floatAddress: "0.0.0.0:{{ .Values.corda.node.conf.bridgeTunnelPort }}" 11 | expectedCertificateSubject: "CN=Bridge Local,O=Local Only,L=London,C=GB" 12 | tunnelSSLConfiguration: { 13 | keyStorePassword: "{{ .Values.corda.firewall.conf.floatKeystorePassword }}" 14 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 15 | sslKeystore: "./workspace/certificates/float.jks" 16 | trustStoreFile: "./workspace/certificates/trust.jks" 17 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 18 | } 19 | } 20 | 21 | certificatesDirectory: "./workspace/certificates" 22 | sslKeystore: "./workspace/certificates/sslkeystore.jks" 23 | trustStoreFile: "./workspace/certificates/truststore.jks" 24 | keyStorePassword: "cordacadevpass" 25 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 26 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 27 | silencedIPs: [] 28 | 29 | enableAMQPPacketTrace: false 30 | artemisReconnectionIntervalMin: 5000 31 | artemisReconnectionIntervalMax: 60000 32 | politeShutdownPeriod: 1000 33 | p2pConfirmationWindowSize: 1048576 34 | auditServiceConfiguration: { 35 | loggingIntervalSec: 60 36 | } 37 | -------------------------------------------------------------------------------- /helm/files/conf/float-4.1.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "FloatOuter" 2 | 3 | networkParametersPath: "./network-parameters" 4 | 5 | inboundConfig: { 6 | listeningAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 7 | } 8 | 9 | floatOuterConfig: { 10 | floatAddress: "0.0.0.0:{{ .Values.corda.node.conf.bridgeTunnelPort }}" 11 | expectedCertificateSubject: "CN=Bridge Local,O=Local Only,L=London,C=GB" 12 | tunnelSSLConfiguration: { 13 | keyStorePassword: "{{ .Values.corda.firewall.conf.floatKeystorePassword }}" 14 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 15 | sslKeystore: "./workspace/certificates/float.jks" 16 | trustStoreFile: "./workspace/certificates/trust.jks" 17 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 18 | } 19 | } 20 | 21 | certificatesDirectory: "./workspace/certificates" 22 | sslKeystore: "./workspace/certificates/sslkeystore.jks" 23 | trustStoreFile: "./workspace/certificates/truststore.jks" 24 | keyStorePassword: "cordacadevpass" 25 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 26 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 27 | silencedIPs: [] 28 | 29 | enableAMQPPacketTrace: false 30 | artemisReconnectionIntervalMin: 5000 31 | artemisReconnectionIntervalMax: 60000 32 | politeShutdownPeriod: 1000 33 | p2pConfirmationWindowSize: 1048576 34 | auditServiceConfiguration: { 35 | loggingIntervalSec: 60 36 | } 37 | -------------------------------------------------------------------------------- /helm/files/conf/float-4.2.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "FloatOuter" 2 | 3 | networkParametersPath: "network-parameters" 4 | 5 | inboundConfig: { 6 | listeningAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 7 | } 8 | 9 | floatOuterConfig: { 10 | floatAddress: "0.0.0.0:{{ .Values.corda.node.conf.bridgeTunnelPort }}" 11 | expectedCertificateSubject: "CN=Bridge Local,O=Local Only,L=London,C=GB" 12 | tunnelSSLConfiguration: { 13 | keyStorePassword: "{{ .Values.corda.firewall.conf.floatKeystorePassword }}" 14 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 15 | sslKeystore: "certificates/float.jks" 16 | trustStoreFile: "certificates/trust.jks" 17 | } 18 | } 19 | 20 | {{- if .Values.corda.node.conf.crlCheckSoftFail }} 21 | revocationConfig: { mode: "EXTERNAL_SOURCE"}) 22 | {{- end }} 23 | 24 | certificatesDirectory: "certificates" 25 | sslKeystore: "certificates/sslkeystore.jks" 26 | trustStoreFile: "certificates/truststore.jks" 27 | keyStorePassword: "cordacadevpass" 28 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 29 | silencedIPs: [] 30 | 31 | enableAMQPPacketTrace: false 32 | artemisReconnectionIntervalMin: 5000 33 | artemisReconnectionIntervalMax: 60000 34 | politeShutdownPeriod: 1000 35 | p2pConfirmationWindowSize: 1048576 36 | auditServiceConfiguration: { 37 | loggingIntervalSec: 60 38 | } 39 | -------------------------------------------------------------------------------- /helm/files/conf/float-4.3.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "FloatOuter" 2 | 3 | networkParametersPath: "network-parameters" 4 | 5 | inboundConfig: { 6 | listeningAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 7 | } 8 | 9 | floatOuterConfig: { 10 | floatAddress: "0.0.0.0:{{ .Values.corda.node.conf.bridgeTunnelPort }}" 11 | expectedCertificateSubject: "CN=Bridge Local,O=Local Only,L=London,C=GB" 12 | tunnelSSLConfiguration: { 13 | keyStorePassword: "{{ .Values.corda.firewall.conf.floatKeystorePassword }}" 14 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 15 | sslKeystore: "certificates/float.jks" 16 | trustStoreFile: "certificates/trust.jks" 17 | } 18 | } 19 | 20 | {{- if .Values.corda.node.conf.crlCheckSoftFail }} 21 | revocationConfig: { mode: "EXTERNAL_SOURCE"}) 22 | {{- end }} 23 | 24 | certificatesDirectory: "certificates" 25 | sslKeystore: "certificates/sslkeystore.jks" 26 | trustStoreFile: "certificates/truststore.jks" 27 | keyStorePassword: "cordacadevpass" 28 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 29 | silencedIPs: [] 30 | 31 | enableAMQPPacketTrace: false 32 | artemisReconnectionIntervalMin: 5000 33 | artemisReconnectionIntervalMax: 60000 34 | politeShutdownPeriod: 1000 35 | p2pConfirmationWindowSize: 1048576 36 | auditServiceConfiguration: { 37 | loggingIntervalSec: 60 38 | } 39 | -------------------------------------------------------------------------------- /helm/files/conf/float-4.4.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "FloatOuter" 2 | 3 | networkParametersPath: "network-parameters" 4 | 5 | inboundConfig: { 6 | listeningAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 7 | } 8 | 9 | floatOuterConfig: { 10 | floatAddress: "0.0.0.0:{{ .Values.corda.node.conf.bridgeTunnelPort }}" 11 | expectedCertificateSubject: "CN=Bridge Local,O=Local Only,L=London,C=GB" 12 | tunnelSSLConfiguration: { 13 | keyStorePassword: "{{ .Values.corda.firewall.conf.floatKeystorePassword }}" 14 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 15 | sslKeystore: "certificates/float.jks" 16 | trustStoreFile: "certificates/trust.jks" 17 | } 18 | } 19 | 20 | {{- if .Values.corda.node.conf.crlCheckSoftFail }} 21 | revocationConfig: { mode: "EXTERNAL_SOURCE"}) 22 | {{- end }} 23 | 24 | certificatesDirectory: "certificates" 25 | sslKeystore: "certificates/sslkeystore.jks" 26 | trustStoreFile: "certificates/truststore.jks" 27 | keyStorePassword: "cordacadevpass" 28 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 29 | silencedIPs: [] 30 | 31 | enableAMQPPacketTrace: false 32 | artemisReconnectionIntervalMin: 5000 33 | artemisReconnectionIntervalMax: 60000 34 | politeShutdownPeriod: 1000 35 | p2pConfirmationWindowSize: 1048576 36 | auditServiceConfiguration: { 37 | loggingIntervalSec: 60 38 | } 39 | -------------------------------------------------------------------------------- /helm/files/conf/float-4.5.conf: -------------------------------------------------------------------------------- 1 | firewallMode: "FloatOuter" 2 | 3 | networkParametersPath: "network-parameters" 4 | 5 | inboundConfig: { 6 | listeningAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 7 | } 8 | 9 | floatOuterConfig: { 10 | floatAddress: "0.0.0.0:{{ .Values.corda.node.conf.bridgeTunnelPort }}" 11 | expectedCertificateSubject: "CN=Bridge Local,O=Local Only,L=London,C=GB" 12 | tunnelSSLConfiguration: { 13 | keyStorePassword: "{{ .Values.corda.firewall.conf.floatKeystorePassword }}" 14 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 15 | sslKeystore: "certificates/float.jks" 16 | trustStoreFile: "certificates/trust.jks" 17 | } 18 | } 19 | 20 | {{- if .Values.corda.node.conf.crlCheckSoftFail }} 21 | revocationConfig: { mode: "EXTERNAL_SOURCE"}) 22 | {{- end }} 23 | 24 | certificatesDirectory: "certificates" 25 | sslKeystore: "certificates/sslkeystore.jks" 26 | trustStoreFile: "certificates/truststore.jks" 27 | keyStorePassword: "cordacadevpass" 28 | trustStorePassword: "{{ .Values.corda.firewall.conf.truststorePassword }}" 29 | silencedIPs: [] 30 | 31 | enableAMQPPacketTrace: false 32 | artemisReconnectionIntervalMin: 5000 33 | artemisReconnectionIntervalMax: 60000 34 | politeShutdownPeriod: 1000 35 | p2pConfirmationWindowSize: 1048576 36 | auditServiceConfiguration: { 37 | loggingIntervalSec: 60 38 | } 39 | -------------------------------------------------------------------------------- /helm/files/conf/init-node.conf: -------------------------------------------------------------------------------- 1 | myLegalName: "{{ .Values.corda.node.conf.legalName }}" 2 | emailAddress: "{{ .Values.corda.node.conf.emailAddress }}" 3 | p2pAddress: "localhost:{{ .Values.corda.node.conf.p2pPort }}" 4 | {{- if .Values.corda.node.conf.compatibilityZoneEnabled }} 5 | compatibilityZoneURL: "{{ .Values.corda.node.conf.compatibilityZoneURL }}" 6 | {{- else }} 7 | networkServices: { 8 | doormanURL: "{{ .Values.corda.node.conf.identityManagerAddress }}", 9 | networkMapURL: "{{ .Values.corda.node.conf.networkmapAddress }}" 10 | } 11 | {{- end }} 12 | rpcSettings: { 13 | address: "0.0.0.0:{{ .Values.corda.node.conf.rpc.port }}", 14 | adminAddress: "0.0.0.0:{{ .Values.corda.node.conf.rpc.adminPort }}" 15 | } 16 | devMode: false 17 | -------------------------------------------------------------------------------- /helm/files/conf/node-4.0.conf: -------------------------------------------------------------------------------- 1 | myLegalName: "{{ .Values.corda.node.conf.legalName }}" 2 | emailAddress: "{{ .Values.corda.node.conf.emailAddress }}" 3 | p2pAddress: "{{ .Values.corda.node.conf.p2pAddress }}:{{ .Values.corda.node.conf.p2pPort }}" 4 | {{- if .Values.corda.node.conf.compatibilityZoneEnabled }} 5 | compatibilityZoneURL: "{{ .Values.corda.node.conf.compatibilityZoneURL }}" 6 | {{- else }} 7 | networkServices: { 8 | doormanURL: "{{ .Values.corda.node.conf.identityManagerAddress }}", 9 | networkMapURL: "{{ .Values.corda.node.conf.networkmapAddress }}" 10 | } 11 | {{- end }} 12 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 13 | {{- if ne .Values.corda.node.conf.tlsCertCrlDistPoint "" }} 14 | tlsCertCrlDistPoint: "{{ .Values.corda.node.conf.tlsCertCrlDistPoint }}", 15 | tlsCertCrlIssuer: "{{ .Values.corda.node.conf.tlsCertCrlIssuer }}" 16 | {{- end }} 17 | devMode: {{ .Values.corda.node.conf.devMode }} 18 | {{- if .Values.corda.node.conf.ssh.enabled }} 19 | sshd: { 20 | port: {{ .Values.corda.node.conf.ssh.sshdPort }} 21 | } 22 | {{- end }} 23 | rpcSettings: { 24 | address: "0.0.0.0:{{ .Values.corda.node.conf.rpc.port }}", 25 | adminAddress: "0.0.0.0:{{ .Values.corda.node.conf.rpc.adminPort }}" 26 | } 27 | rpcUsers: [ 28 | {{- range $user := .Values.corda.node.conf.rpc.users }} 29 | { 30 | user: "{{ $user.name }}", 31 | password: "{{ $user.password }}", 32 | permissions: [ 33 | "{{ $user.permissions }}" 34 | ] 35 | } 36 | {{- end }} 37 | ] 38 | {{- if .Values.corda.node.conf.monitoring.enabled }} 39 | jmxMonitoringHttpPort: {{ .Values.corda.node.conf.monitoring.port }} 40 | {{- end }} 41 | 42 | dataSourceProperties: { 43 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 44 | dataSourceClassName: "{{ .Values.corda.node.conf.dataSource.className }}", 45 | dataSource.url: "{{ .Values.corda.node.conf.dataSource.url }}", 46 | {{- end}} 47 | dataSource.user: "{{ .Values.corda.node.conf.dataSource.user }}", 48 | dataSource.password: "{{ .Values.corda.node.conf.dataSource.password }}" 49 | } 50 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 51 | database = { 52 | {{- if eq .Values.corda.node.conf.dataSource.className "oracle.jdbc.pool.OracleDataSource" }} 53 | transactionIsolationLevel = READ_COMMITTED 54 | schema = xe 55 | {{- end}} 56 | runMigration = true 57 | } 58 | {{- end}} 59 | 60 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 61 | keyStorePassword : "{{ .Values.corda.node.conf.keystorePassword }}" 62 | detectPublicIp: false 63 | messagingServerAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 64 | messagingServerExternal: false 65 | enterpriseConfiguration: { 66 | externalBridge: true 67 | } 68 | {{- if .Values.corda.node.conf.allowDevCorDapps.enabled }} 69 | cordappSignerKeyFingerprintBlacklist: [ 70 | ] 71 | {{- end }} -------------------------------------------------------------------------------- /helm/files/conf/node-4.1.conf: -------------------------------------------------------------------------------- 1 | myLegalName: "{{ .Values.corda.node.conf.legalName }}" 2 | emailAddress: "{{ .Values.corda.node.conf.emailAddress }}" 3 | p2pAddress: "{{ .Values.corda.node.conf.p2pAddress }}:{{ .Values.corda.node.conf.p2pPort }}" 4 | {{- if .Values.corda.node.conf.compatibilityZoneEnabled }} 5 | compatibilityZoneURL: "{{ .Values.corda.node.conf.compatibilityZoneURL }}" 6 | {{- else }} 7 | networkServices: { 8 | doormanURL: "{{ .Values.corda.node.conf.identityManagerAddress }}", 9 | networkMapURL: "{{ .Values.corda.node.conf.networkmapAddress }}" 10 | } 11 | {{- end }} 12 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 13 | {{- if ne .Values.corda.node.conf.tlsCertCrlDistPoint "" }} 14 | tlsCertCrlDistPoint: "{{ .Values.corda.node.conf.tlsCertCrlDistPoint }}", 15 | tlsCertCrlIssuer: "{{ .Values.corda.node.conf.tlsCertCrlIssuer }}" 16 | {{- end }} 17 | devMode: {{ .Values.corda.node.conf.devMode }} 18 | {{- if .Values.corda.node.conf.ssh.enabled }} 19 | sshd: { 20 | port: {{ .Values.corda.node.conf.ssh.sshdPort }} 21 | } 22 | {{- end }} 23 | rpcSettings: { 24 | address: "0.0.0.0:{{ .Values.corda.node.conf.rpc.port }}", 25 | adminAddress: "0.0.0.0:{{ .Values.corda.node.conf.rpc.adminPort }}" 26 | } 27 | rpcUsers: [ 28 | {{- range $user := .Values.corda.node.conf.rpc.users }} 29 | { 30 | user: "{{ $user.name }}", 31 | password: "{{ $user.password }}", 32 | permissions: [ 33 | "{{ $user.permissions }}" 34 | ] 35 | } 36 | {{- end }} 37 | ] 38 | {{- if .Values.corda.node.conf.monitoring.enabled }} 39 | jmxMonitoringHttpPort: {{ .Values.corda.node.conf.monitoring.port }} 40 | {{- end }} 41 | 42 | dataSourceProperties: { 43 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 44 | dataSourceClassName: "{{ .Values.corda.node.conf.dataSource.className }}", 45 | dataSource.url: "{{ .Values.corda.node.conf.dataSource.url }}", 46 | {{- end}} 47 | dataSource.user: "{{ .Values.corda.node.conf.dataSource.user }}", 48 | dataSource.password: "{{ .Values.corda.node.conf.dataSource.password }}" 49 | } 50 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 51 | database = { 52 | {{- if eq .Values.corda.node.conf.dataSource.className "oracle.jdbc.pool.OracleDataSource" }} 53 | transactionIsolationLevel = READ_COMMITTED 54 | schema = xe 55 | {{- end}} 56 | runMigration = true 57 | } 58 | {{- end}} 59 | 60 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 61 | keyStorePassword : "{{ .Values.corda.node.conf.keystorePassword }}" 62 | detectPublicIp: false 63 | messagingServerAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 64 | messagingServerExternal: false 65 | enterpriseConfiguration: { 66 | externalBridge: true 67 | } 68 | {{- if .Values.corda.node.conf.allowDevCorDapps.enabled }} 69 | cordappSignerKeyFingerprintBlacklist: [ 70 | ] 71 | {{- end }} -------------------------------------------------------------------------------- /helm/files/conf/node-4.2.conf: -------------------------------------------------------------------------------- 1 | myLegalName: "{{ .Values.corda.node.conf.legalName }}" 2 | emailAddress: "{{ .Values.corda.node.conf.emailAddress }}" 3 | p2pAddress: "{{ .Values.corda.node.conf.p2pAddress }}:{{ .Values.corda.node.conf.p2pPort }}" 4 | {{- if .Values.corda.node.conf.compatibilityZoneEnabled }} 5 | compatibilityZoneURL: "{{ .Values.corda.node.conf.compatibilityZoneURL }}" 6 | {{- else }} 7 | networkServices: { 8 | doormanURL: "{{ .Values.corda.node.conf.identityManagerAddress }}", 9 | networkMapURL: "{{ .Values.corda.node.conf.networkmapAddress }}" 10 | } 11 | {{- end }} 12 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 13 | {{- if ne .Values.corda.node.conf.tlsCertCrlDistPoint "" }} 14 | tlsCertCrlDistPoint: "{{ .Values.corda.node.conf.tlsCertCrlDistPoint }}", 15 | tlsCertCrlIssuer: "{{ .Values.corda.node.conf.tlsCertCrlIssuer }}" 16 | {{- end }} 17 | devMode: {{ .Values.corda.node.conf.devMode }} 18 | {{- if .Values.corda.node.conf.ssh.enabled }} 19 | sshd: { 20 | port: {{ .Values.corda.node.conf.ssh.sshdPort }} 21 | } 22 | {{- end }} 23 | rpcSettings: { 24 | address: "0.0.0.0:{{ .Values.corda.node.conf.rpc.port }}", 25 | adminAddress: "0.0.0.0:{{ .Values.corda.node.conf.rpc.adminPort }}" 26 | } 27 | rpcUsers: [ 28 | {{- range $user := .Values.corda.node.conf.rpc.users }} 29 | { 30 | user: "{{ $user.name }}", 31 | password: "{{ $user.password }}", 32 | permissions: [ 33 | "{{ $user.permissions }}" 34 | ] 35 | } 36 | {{- end }} 37 | ] 38 | {{- if .Values.corda.node.conf.monitoring.enabled }} 39 | jmxMonitoringHttpPort: {{ .Values.corda.node.conf.monitoring.port }} 40 | {{- end }} 41 | 42 | dataSourceProperties: { 43 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 44 | dataSourceClassName: "{{ .Values.corda.node.conf.dataSource.className }}", 45 | dataSource.url: "{{ .Values.corda.node.conf.dataSource.url }}", 46 | {{- end}} 47 | dataSource.user: "{{ .Values.corda.node.conf.dataSource.user }}", 48 | dataSource.password: "{{ .Values.corda.node.conf.dataSource.password }}" 49 | } 50 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 51 | database = { 52 | {{- if eq .Values.corda.node.conf.dataSource.className "oracle.jdbc.pool.OracleDataSource" }} 53 | transactionIsolationLevel = READ_COMMITTED 54 | schema = xe 55 | {{- end}} 56 | runMigration = true 57 | } 58 | {{- end}} 59 | 60 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 61 | keyStorePassword : "{{ .Values.corda.node.conf.keystorePassword }}" 62 | detectPublicIp: false 63 | messagingServerAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 64 | messagingServerExternal: false 65 | enterpriseConfiguration: { 66 | externalBridge: true 67 | } 68 | {{- if .Values.corda.node.conf.allowDevCorDapps.enabled }} 69 | cordappSignerKeyFingerprintBlacklist: [ 70 | ] 71 | {{- end }} 72 | -------------------------------------------------------------------------------- /helm/files/conf/node-4.3.conf: -------------------------------------------------------------------------------- 1 | myLegalName: "{{ .Values.corda.node.conf.legalName }}" 2 | emailAddress: "{{ .Values.corda.node.conf.emailAddress }}" 3 | p2pAddress: "{{ .Values.corda.node.conf.p2pAddress }}:{{ .Values.corda.node.conf.p2pPort }}" 4 | {{- if .Values.corda.node.conf.compatibilityZoneEnabled }} 5 | compatibilityZoneURL: "{{ .Values.corda.node.conf.compatibilityZoneURL }}" 6 | {{- else }} 7 | networkServices: { 8 | doormanURL: "{{ .Values.corda.node.conf.identityManagerAddress }}", 9 | networkMapURL: "{{ .Values.corda.node.conf.networkmapAddress }}" 10 | } 11 | {{- end }} 12 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 13 | {{- if ne .Values.corda.node.conf.tlsCertCrlDistPoint "" }} 14 | tlsCertCrlDistPoint: "{{ .Values.corda.node.conf.tlsCertCrlDistPoint }}", 15 | tlsCertCrlIssuer: "{{ .Values.corda.node.conf.tlsCertCrlIssuer }}" 16 | {{- end }} 17 | devMode: {{ .Values.corda.node.conf.devMode }} 18 | {{- if .Values.corda.node.conf.ssh.enabled }} 19 | sshd: { 20 | port: {{ .Values.corda.node.conf.ssh.sshdPort }} 21 | } 22 | {{- end }} 23 | rpcSettings: { 24 | address: "0.0.0.0:{{ .Values.corda.node.conf.rpc.port }}", 25 | adminAddress: "0.0.0.0:{{ .Values.corda.node.conf.rpc.adminPort }}" 26 | } 27 | rpcUsers: [ 28 | {{- range $user := .Values.corda.node.conf.rpc.users }} 29 | { 30 | user: "{{ $user.name }}", 31 | password: "{{ $user.password }}", 32 | permissions: [ 33 | "{{ $user.permissions }}" 34 | ] 35 | } 36 | {{- end }} 37 | ] 38 | {{- if .Values.corda.node.conf.monitoring.enabled }} 39 | jmxMonitoringHttpPort: {{ .Values.corda.node.conf.monitoring.port }} 40 | {{- end }} 41 | 42 | dataSourceProperties: { 43 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 44 | dataSourceClassName: "{{ .Values.corda.node.conf.dataSource.className }}", 45 | dataSource.url: "{{ .Values.corda.node.conf.dataSource.url }}", 46 | {{- end}} 47 | dataSource.user: "{{ .Values.corda.node.conf.dataSource.user }}", 48 | dataSource.password: "{{ .Values.corda.node.conf.dataSource.password }}" 49 | } 50 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 51 | database = { 52 | {{- if eq .Values.corda.node.conf.dataSource.className "oracle.jdbc.pool.OracleDataSource" }} 53 | transactionIsolationLevel = READ_COMMITTED 54 | schema = xe 55 | {{- end}} 56 | runMigration = true 57 | } 58 | {{- end}} 59 | 60 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 61 | keyStorePassword : "{{ .Values.corda.node.conf.keystorePassword }}" 62 | detectPublicIp: false 63 | messagingServerAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 64 | messagingServerExternal: false 65 | enterpriseConfiguration: { 66 | externalBridge: true 67 | } 68 | {{- if .Values.corda.node.conf.allowDevCorDapps.enabled }} 69 | cordappSignerKeyFingerprintBlacklist: [ 70 | ] 71 | {{- end }} -------------------------------------------------------------------------------- /helm/files/conf/node-4.4.conf: -------------------------------------------------------------------------------- 1 | myLegalName: "{{ .Values.corda.node.conf.legalName }}" 2 | emailAddress: "{{ .Values.corda.node.conf.emailAddress }}" 3 | p2pAddress: "{{ .Values.corda.node.conf.p2pAddress }}:{{ .Values.corda.node.conf.p2pPort }}" 4 | {{- if .Values.corda.node.conf.compatibilityZoneEnabled }} 5 | compatibilityZoneURL: "{{ .Values.corda.node.conf.compatibilityZoneURL }}" 6 | {{- else }} 7 | networkServices: { 8 | doormanURL: "{{ .Values.corda.node.conf.identityManagerAddress }}", 9 | networkMapURL: "{{ .Values.corda.node.conf.networkmapAddress }}" 10 | } 11 | {{- end }} 12 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 13 | {{- if ne .Values.corda.node.conf.tlsCertCrlDistPoint "" }} 14 | tlsCertCrlDistPoint: "{{ .Values.corda.node.conf.tlsCertCrlDistPoint }}", 15 | tlsCertCrlIssuer: "{{ .Values.corda.node.conf.tlsCertCrlIssuer }}" 16 | {{- end }} 17 | devMode: {{ .Values.corda.node.conf.devMode }} 18 | {{- if .Values.corda.node.conf.ssh.enabled }} 19 | sshd: { 20 | port: {{ .Values.corda.node.conf.ssh.sshdPort }} 21 | } 22 | {{- end }} 23 | rpcSettings: { 24 | address: "0.0.0.0:{{ .Values.corda.node.conf.rpc.port }}", 25 | adminAddress: "0.0.0.0:{{ .Values.corda.node.conf.rpc.adminPort }}" 26 | } 27 | rpcUsers: [ 28 | {{- range $user := .Values.corda.node.conf.rpc.users }} 29 | { 30 | user: "{{ $user.name }}", 31 | password: "{{ $user.password }}", 32 | permissions: [ 33 | "{{ $user.permissions }}" 34 | ] 35 | } 36 | {{- end }} 37 | ] 38 | {{- if .Values.corda.node.conf.monitoring.enabled }} 39 | jmxMonitoringHttpPort: {{ .Values.corda.node.conf.monitoring.port }} 40 | {{- end }} 41 | 42 | dataSourceProperties: { 43 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 44 | dataSourceClassName: "{{ .Values.corda.node.conf.dataSource.className }}", 45 | dataSource.url: "{{ .Values.corda.node.conf.dataSource.url }}", 46 | {{- end}} 47 | dataSource.user: "{{ .Values.corda.node.conf.dataSource.user }}", 48 | dataSource.password: "{{ .Values.corda.node.conf.dataSource.password }}" 49 | } 50 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 51 | database = { 52 | {{- if eq .Values.corda.node.conf.dataSource.className "oracle.jdbc.pool.OracleDataSource" }} 53 | transactionIsolationLevel = READ_COMMITTED 54 | schema = xe 55 | {{- end}} 56 | runMigration = true 57 | } 58 | {{- end}} 59 | 60 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 61 | keyStorePassword : "{{ .Values.corda.node.conf.keystorePassword }}" 62 | detectPublicIp: false 63 | messagingServerAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 64 | messagingServerExternal: false 65 | enterpriseConfiguration: { 66 | externalBridge: true 67 | } 68 | {{- if .Values.corda.node.conf.allowDevCorDapps.enabled }} 69 | cordappSignerKeyFingerprintBlacklist: [ 70 | ] 71 | {{- end }} -------------------------------------------------------------------------------- /helm/files/conf/node-4.5.conf: -------------------------------------------------------------------------------- 1 | myLegalName: "{{ .Values.corda.node.conf.legalName }}" 2 | emailAddress: "{{ .Values.corda.node.conf.emailAddress }}" 3 | p2pAddress: "{{ .Values.corda.node.conf.p2pAddress }}:{{ .Values.corda.node.conf.p2pPort }}" 4 | {{- if .Values.corda.node.conf.compatibilityZoneEnabled }} 5 | compatibilityZoneURL: "{{ .Values.corda.node.conf.compatibilityZoneURL }}" 6 | {{- else }} 7 | networkServices: { 8 | doormanURL: "{{ .Values.corda.node.conf.identityManagerAddress }}", 9 | networkMapURL: "{{ .Values.corda.node.conf.networkmapAddress }}" 10 | } 11 | {{- end }} 12 | crlCheckSoftFail: {{ .Values.corda.node.conf.crlCheckSoftFail }} 13 | {{- if ne .Values.corda.node.conf.tlsCertCrlDistPoint "" }} 14 | tlsCertCrlDistPoint: "{{ .Values.corda.node.conf.tlsCertCrlDistPoint }}", 15 | tlsCertCrlIssuer: "{{ .Values.corda.node.conf.tlsCertCrlIssuer }}" 16 | {{- end }} 17 | devMode: {{ .Values.corda.node.conf.devMode }} 18 | {{- if .Values.corda.node.conf.ssh.enabled }} 19 | sshd: { 20 | port: {{ .Values.corda.node.conf.ssh.sshdPort }} 21 | } 22 | {{- end }} 23 | rpcSettings: { 24 | address: "0.0.0.0:{{ .Values.corda.node.conf.rpc.port }}", 25 | adminAddress: "0.0.0.0:{{ .Values.corda.node.conf.rpc.adminPort }}" 26 | } 27 | rpcUsers: [ 28 | {{- range $user := .Values.corda.node.conf.rpc.users }} 29 | { 30 | user: "{{ $user.name }}", 31 | password: "{{ $user.password }}", 32 | permissions: [ 33 | "{{ $user.permissions }}" 34 | ] 35 | } 36 | {{- end }} 37 | ] 38 | {{- if .Values.corda.node.conf.monitoring.enabled }} 39 | jmxMonitoringHttpPort: {{ .Values.corda.node.conf.monitoring.port }} 40 | {{- end }} 41 | 42 | dataSourceProperties: { 43 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 44 | dataSourceClassName: "{{ .Values.corda.node.conf.dataSource.className }}", 45 | dataSource.url: "{{ .Values.corda.node.conf.dataSource.url }}", 46 | {{- end}} 47 | dataSource.user: "{{ .Values.corda.node.conf.dataSource.user }}", 48 | dataSource.password: "{{ .Values.corda.node.conf.dataSource.password }}" 49 | } 50 | {{- if ne .Values.corda.node.conf.dataSource.className "" }} 51 | database = { 52 | {{- if eq .Values.corda.node.conf.dataSource.className "oracle.jdbc.pool.OracleDataSource" }} 53 | transactionIsolationLevel = READ_COMMITTED 54 | schema = xe 55 | {{- end}} 56 | runMigration = true 57 | } 58 | {{- end}} 59 | 60 | trustStorePassword: "{{ .Values.corda.node.conf.truststorePassword }}" 61 | keyStorePassword : "{{ .Values.corda.node.conf.keystorePassword }}" 62 | detectPublicIp: false 63 | messagingServerAddress: "0.0.0.0:{{ .Values.corda.node.conf.p2pPort }}" 64 | messagingServerExternal: false 65 | enterpriseConfiguration: { 66 | externalBridge: true 67 | } 68 | {{- if .Values.corda.node.conf.allowDevCorDapps.enabled }} 69 | cordappSignerKeyFingerprintBlacklist: [ 70 | ] 71 | {{- end }} -------------------------------------------------------------------------------- /helm/files/cordapps/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /helm/files/network/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /helm/files/ping.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | IP=$1 3 | PORT=$2 4 | (echo > /dev/tcp/$IP/$PORT) > /dev/null 2>&1 && echo "UP" || echo "DOWN" 5 | #Alternatives https://superuser.com/questions/621870/test-if-a-port-on-a-remote-system-is-reachable-without-telnet: 6 | #curl http://$IP:$PORT 7 | #nc -zv $IP $PORT &> /dev/null; echo $? 8 | #cat < /dev/tcp/$IP/$PORT 9 | -------------------------------------------------------------------------------- /helm/helm_compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | 46 | HelmCompilePrerequisites () { 47 | helm version | grep "v2." > /dev/null 2>&1 48 | if [ "$?" -ne "0" ] ; then 49 | echo -e "${RED}ERROR${NC}" 50 | echo "Helm version 2 has to be used for compiling these scripts. Please install it from https://github.com/helm/helm/releases" 51 | exit 1 52 | fi 53 | 54 | kubectl cluster-info > /dev/null 2>&1 55 | if [ "$?" -ne "0" ] ; then 56 | echo -e "${RED}ERROR${NC}" 57 | echo "kubectl must be connected to the Kubernetes cluster in order to continue. Please see https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/" 58 | exit 1 59 | fi 60 | 61 | set -eu 62 | 63 | TEMPLATE_NAMESPACE="" 64 | TEMPLATE_NAMESPACE=$(grep -A 3 'config:' $DIR/values.yaml | grep 'namespace: "' | cut -d '"' -f 2) 65 | 66 | if [ "$TEMPLATE_NAMESPACE" = "" ]; then 67 | echo -e "${RED}ERROR${NC}" 68 | echo "Kubernetes requires a namespace to deploy resources to, no namespace is defined in values.yaml, please define one." 69 | exit 1 70 | fi 71 | 72 | if [ ! -f $DIR/files/network/networkRootTrustStore.jks ]; then 73 | echo -e "${RED}ERROR${NC}" 74 | echo "$DIR/files/networkRootTrustStore.jks missing, this should have been copied to this folder before running one-time-setup.sh script." 75 | exit 1 76 | fi 77 | 78 | if [ ! -f $DIR/files/network/network-parameters.file ]; then 79 | echo -e "${RED}ERROR${NC}" 80 | echo "$DIR/files/network-parameters.file missing, this should have been created by one-time-setup.sh script." 81 | exit 1 82 | fi 83 | 84 | if [ ! -f $DIR/files/certificates/node/nodekeystore.jks -o ! -f $DIR/files/certificates/node/sslkeystore.jks -o ! -f $DIR/files/certificates/node/truststore.jks ]; then 85 | echo -e "${RED}ERROR${NC}" 86 | echo "$DIR/files/certificates/node/ missing certificates, expecting to see nodekeystore.jks, sslkeystore.jks and truststore.jks, these files should have been created by one-time-setup.sh script." 87 | echo "Files in folder $DIR/files/certificates/node:" 88 | ls -al $DIR/files/certificates/node 89 | exit 1 90 | fi 91 | 92 | if [ ! -f $DIR/files/certificates/firewall_tunnel/bridge.jks -o ! -f $DIR/files/certificates/firewall_tunnel/float.jks -o ! -f $DIR/files/certificates/firewall_tunnel/trust.jks ]; then 93 | echo -e "${RED}ERROR${NC}" 94 | echo "$DIR/files/certificates/firewall_tunnel/ missing certificates, expecting to see bridge.jks, float.jks and trust.jks, these files should have been created by one-time-setup.sh script." 95 | echo "Files in folder $DIR/files/certificates/firewall_tunnel:" 96 | ls -al $DIR/files/certificates/firewall_tunnel 97 | exit 1 98 | fi 99 | } 100 | HelmCompilePrerequisites 101 | 102 | HelmCompile () { 103 | echo "====== Deploying to Kubernetes cluster next ... ====== " 104 | echo "Compiling Helm templates..." 105 | helm template $DIR --name $TEMPLATE_NAMESPACE --namespace $TEMPLATE_NAMESPACE --output-dir $DIR/output 106 | 107 | # copy-files script 108 | SCRIPT="$DIR/output/corda/templates/copy-files.sh" 109 | mv $SCRIPT.yml $SCRIPT 110 | # Helm always adds a few extra lines, which we want to remove from shell scripts 111 | tail -n +3 "$SCRIPT" > "$SCRIPT.tmp" && mv "$SCRIPT.tmp" "$SCRIPT" 112 | chmod +x $SCRIPT 113 | 114 | echo "Creating Docker Container Registry Pull Secret..." 115 | # docker secret script 116 | SCRIPT="$DIR/output/corda/templates/create-docker-secret.sh" 117 | mv $SCRIPT.yml $SCRIPT 118 | # Helm always adds a few extra lines, which we want to remove from shell scripts 119 | tail -n +3 "$SCRIPT" > "$SCRIPT.tmp" && mv "$SCRIPT.tmp" "$SCRIPT" 120 | chmod +x $SCRIPT 121 | $SCRIPT 122 | 123 | echo "Applying templates to Kubernetes cluster:" 124 | kubectl apply -f $DIR/output/corda/templates/ --namespace=$TEMPLATE_NAMESPACE 125 | 126 | # Copy CorDapps, Database drivers etc. 127 | #$DIR/output/corda/templates/copy-files.sh 128 | echo "====== Deploying to Kubernetes cluster completed. ====== " 129 | } 130 | HelmCompile 131 | -------------------------------------------------------------------------------- /helm/initial_registration/Chart.yaml: -------------------------------------------------------------------------------- 1 | description: Corda Deployment Initial Registration Chart 2 | name: corda 3 | version: 0.0.1 4 | -------------------------------------------------------------------------------- /helm/initial_registration/initial_registration.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | set -eu 46 | 47 | InitialRegistration () { 48 | echo "====== Performing Corda node Initial Registration next ... ====== " 49 | VERSION=$(grep 'cordaVersion:' $DIR/../values.yaml | cut -d '"' -f 2) 50 | 51 | OUTPUT_DIR=$DIR/output 52 | SCRIPT=$OUTPUT_DIR/corda/templates/initial_registration.sh 53 | OUTPUT_NODE_CONF=$OUTPUT_DIR/corda/templates/node.conf 54 | NODE_CONF=$DIR/../files/conf/init-node-$VERSION.conf 55 | NODE_CONF=$DIR/../files/conf/init-node.conf 56 | 57 | if [ ! -f "$NODE_CONF" ]; then 58 | set +x 59 | echo -e "${RED}ERROR${NC}" 60 | echo "The init-node.conf file could not be read, file path: $NODE_CONF" 61 | echo "This most likely means you are targeting a cordaVersion in the helm/values.yaml file which does not have a corresponding init-node.conf file in the helm/files subfolder." 62 | echo "This can in most cases easily be fixed by copying an existing init-node.conf file and naming it according to the version you want to use." 63 | echo "Please follow this guide: If you are deploying a version 4.3, and there is only a conf file for 4.2, copy that one. If you are deploying a version for 4.2.20190221, you should also copy the 4.2 init-node.conf file." 64 | echo "To avoid using a too new file, never copy a newer init-node.conf file as base, because it might contain new settings that your targeted Corda version does not know about." 65 | echo "Should you run into any issues while starting up the Corda node with this init-node.conf file, just check the node workspace logs folder, there you will find the exact details of what the init-node.conf should look like in the case of errors." 66 | echo "" 67 | exit 1 68 | fi 69 | 70 | echo "Compiling Helm Initial Registration templates:" 71 | helm template $DIR -f $DIR/../values.yaml --output-dir $OUTPUT_DIR --set-file node_conf=$NODE_CONF 72 | mv $OUTPUT_DIR/corda/templates/initial_registration.sh.yml $SCRIPT 73 | mv $OUTPUT_DIR/corda/templates/node.conf.yml $OUTPUT_NODE_CONF 74 | 75 | # Helm always adds a few extra lines, which we want to remove from shell scripts 76 | tail -n +3 "$SCRIPT" > "$SCRIPT.tmp" && mv "$SCRIPT.tmp" "$SCRIPT" 77 | # And from compiled node.conf 78 | tail -n +3 "$OUTPUT_NODE_CONF" > "$OUTPUT_NODE_CONF.tmp" && mv "$OUTPUT_NODE_CONF.tmp" "$OUTPUT_NODE_CONF" 79 | 80 | # Make the script executable 81 | chmod +x $SCRIPT 82 | 83 | # Call script: 84 | echo "Executing Initial Registration step:" 85 | $SCRIPT 86 | 87 | echo "====== Corda node Initial Registration completed. ====== " 88 | } 89 | InitialRegistration 90 | -------------------------------------------------------------------------------- /helm/initial_registration/output/corda/templates/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /helm/initial_registration/templates/initial_registration.sh.yml: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | GREEN='\033[0;32m' # Success color 5 | YELLOW='\033[0;33m' # Warning color 6 | NC='\033[0m' # No Color 7 | 8 | set -u 9 | DIR="." 10 | GetPathToCurrentlyExecutingScript () { 11 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 12 | set +e 13 | ABS_PATH=$(readlink -f "$0" 2>&1) 14 | if [ "$?" -ne "0" ]; then 15 | echo "Using macOS alternative to readlink -f command..." 16 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 17 | TARGET_FILE=$0 18 | 19 | cd $(dirname $TARGET_FILE) 20 | TARGET_FILE=$(basename $TARGET_FILE) 21 | ITERATIONS=0 22 | 23 | # Iterate down a (possible) chain of symlinks 24 | while [ -L "$TARGET_FILE" ] 25 | do 26 | TARGET_FILE=$(readlink $TARGET_FILE) 27 | cd $(dirname $TARGET_FILE) 28 | TARGET_FILE=$(basename $TARGET_FILE) 29 | ITERATIONS=$((ITERATIONS + 1)) 30 | if [ "$ITERATIONS" -gt 1000 ]; then 31 | echo "symlink loop. Critical exit." 32 | exit 1 33 | fi 34 | done 35 | 36 | # Compute the canonicalized name by finding the physical path 37 | # for the directory we're in and appending the target file. 38 | PHYS_DIR=$(pwd -P) 39 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 40 | fi 41 | 42 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 43 | DIR=$(dirname "$ABS_PATH") 44 | } 45 | GetPathToCurrentlyExecutingScript 46 | set -eu 47 | 48 | ROOT_FOLDER=$DIR/../../../../.. 49 | # Store DIR in another variable because including docker_config.sh will overwrite it 50 | THIS_PATH=$DIR 51 | 52 | checkStatus () { 53 | status=$1 54 | if [ $status -eq 0 ] 55 | then 56 | echo "The Corda Node initial registration was completed successfully. The certificates will now be copied to the correct folders." 57 | else 58 | echo -e "${RED}ERROR${NC}" 59 | echo "The Corda Node initial registration has failed unexpectedly. MANUAL intervention is required!" 60 | echo "You may have to clean out the workspace folder and start over with a new X500 name for your node. (depends on the error)" 61 | exit 1 62 | fi 63 | return 0 64 | } 65 | 66 | ensureFileExistsAndCopy () { 67 | FROM=$1 68 | TO=$2 69 | if [ -f "$FROM" ] 70 | then 71 | if [ ! -f "$TO" ] 72 | then 73 | cp -f $FROM $TO 74 | else 75 | echo -e "${RED}ERROR${NC}" 76 | echo "Existing certificate already existed, skipping copying as a safe-guard: $TO" 77 | exit 1 78 | fi 79 | else 80 | echo -e "${RED}ERROR${NC}" 81 | echo "File did not exist, probably an issue with initial-registration: $FROM" 82 | exit 1 83 | fi 84 | } 85 | 86 | copyCertificates () { 87 | CERTS_GENERATION_FOLDER=$ROOT_FOLDER/helm/initial_registration/output/corda/templates/workspace/certificates 88 | TO_FOLDER=$ROOT_FOLDER/helm/files/certificates/node 89 | ensureFileExistsAndCopy $CERTS_GENERATION_FOLDER/nodekeystore.jks $TO_FOLDER/nodekeystore.jks 90 | ensureFileExistsAndCopy $CERTS_GENERATION_FOLDER/sslkeystore.jks $TO_FOLDER/sslkeystore.jks 91 | ensureFileExistsAndCopy $CERTS_GENERATION_FOLDER/truststore.jks $TO_FOLDER/truststore.jks 92 | } 93 | 94 | waitTillNetworkParametersIsAvailable () { 95 | NETWORK_PARAMETERS_EXISTS=0 96 | while [ $NETWORK_PARAMETERS_EXISTS -eq 0 ] 97 | do 98 | sleep 2 99 | echo "Checking for network-parameters file..." 100 | if [ -f $THIS_PATH/workspace/network-parameters ] 101 | then 102 | echo "Found network-parameters file!" 103 | NETWORK_PARAMETERS_EXISTS=1 104 | fi 105 | done 106 | echo "waitTillNetworkParametersIsAvailable finished." 107 | } 108 | 109 | copyNetworkParameters () { 110 | waitTillNetworkParametersIsAvailable 111 | 112 | echo "Copying network-parameters to helm/files/network (for Corda Firewall use)." 113 | cp -f $THIS_PATH/workspace/network-parameters $ROOT_FOLDER/helm/files/network/network-parameters.file 114 | } 115 | 116 | waitForNetworkParametersOrTimeout () { 117 | NP_PID=$1 118 | CORDA_PID=$2 119 | LOOPING=1 120 | while [ $LOOPING -eq 1 ]; do 121 | sleep 10 # seconds 122 | #NP_PROCESS_RESULT=$(kill -0 "$NP_PID" > /dev/null 2>&1) 123 | #CORDA_PROCESS_RESULT=$(kill -0 "$CORDA_PID" > /dev/null 2>&1) 124 | if ! kill -0 "$NP_PID" > /dev/null 2>&1; then 125 | echo "network-parameters download has completed, time to ensure Corda Node process terminates as well" 126 | 127 | if kill -0 "$CORDA_PID" > /dev/null 2>&1; then 128 | if kill "$CORDA_PID" > /dev/null 2>&1; then echo "Killed Corda Node process."; fi 129 | else 130 | # All background processes terminated, continue 131 | LOOPING=0 132 | fi 133 | else 134 | # network-parameters download is still ongoing, but we should check to see if Corda Node process is still active 135 | if kill -0 "$CORDA_PID" > /dev/null 2>&1; then 136 | echo "." 137 | else 138 | echo -e "${RED}ERROR${NC}" 139 | echo "Corda Node process terminated before network-parameters was completed. MANUAL investigation required." 140 | LOOPING=0 141 | fi 142 | fi 143 | done 144 | 145 | # Ensure no running background processes gets left behind: 146 | if kill $CORDA_PID > /dev/null 2>&1; then echo "!"; fi 147 | if kill $NP_PID > /dev/null 2>&1; then echo "!"; fi 148 | 149 | if [ -f $ROOT_FOLDER/helm/files/network/network-parameters.file ]; then 150 | echo "network-parameters file was downloaded successfully and we are ready to continue deployment." 151 | else 152 | echo -e "${RED}ERROR${NC}" 153 | echo "Unfortunately the network-parameters file was not downloaded/copied to the correct folder, MANUAL intervention is required." 154 | exit 1 155 | fi 156 | } 157 | 158 | downloadNetworkParameters () { 159 | CORDA_BIN=$1 160 | NODE_CONF=$2 161 | 162 | if [ -f $ROOT_FOLDER/helm/files/network/network-parameters.file ]; then 163 | echo -e "${YELLOW}Warning${NC}" 164 | echo "network-parameters file already existed in the correct folder $ROOT_FOLDER/helm/files/network/, skipping new download." 165 | else 166 | echo "Next we will launch the Corda Node just in order to download network-parameters file. Please wait..." 167 | # Launching the network-parameters copy function async to Corda Node execution: 168 | copyNetworkParameters & NP_PID=$! 169 | java -jar $CORDA_BIN --base-directory=$THIS_PATH/workspace --config-file=$NODE_CONF & CORDA_PID=$! 170 | waitForNetworkParametersOrTimeout $NP_PID $CORDA_PID 171 | fi 172 | } 173 | 174 | initialRegistration () { 175 | CORDA_BIN=$1 176 | NODE_CONF=$2 177 | TRUST_STORE=$3 178 | TRUST_STORE_PASSWORD=$4 179 | #echo "Cleaning any previous initial-registration runs..." 180 | #rm -rf $THIS_PATH/workspace 181 | 182 | TRUSTSTORE_JKS=$ROOT_FOLDER/helm/files/certificates/node/truststore.jks 183 | NODEKEYSTORE_JKS=$ROOT_FOLDER/helm/files/certificates/node/nodekeystore.jks 184 | SSLKEYSTORE_JKS=$ROOT_FOLDER/helm/files/certificates/node/sslkeystore.jks 185 | 186 | echo "Checking if certificates already exist..." 187 | if [ ! -f $TRUSTSTORE_JKS -a ! -f $NODEKEYSTORE_JKS -a ! -f $SSLKEYSTORE_JKS ]; then 188 | echo "Launching Corda Node with option initial_registration to download certificates..." 189 | java -jar $CORDA_BIN initial-registration --network-root-truststore=$TRUST_STORE --network-root-truststore-password=$TRUST_STORE_PASSWORD --base-directory=$THIS_PATH/workspace --config-file=$NODE_CONF || checkStatus $? 190 | checkStatus $? 191 | 192 | echo "Copying certificates from initial-registration step to the helm/files/certificates/node folder" 193 | copyCertificates 194 | else 195 | echo -e "${YELLOW}Warning${NC}" 196 | echo "Skipping initial-registration step because $ROOT_FOLDER/helm/files/certificates/node/ already contains the certificates." 197 | fi 198 | } 199 | 200 | main () { 201 | DOCKER_IMAGES_FOLDER=$ROOT_FOLDER/docker-images 202 | 203 | BIN_DIR=$DOCKER_IMAGES_FOLDER/bin 204 | NODE_CONF=$THIS_PATH/node.conf 205 | TRUST_STORE=$ROOT_FOLDER/helm/files/network/networkRootTrustStore.jks 206 | TRUST_STORE_PASSWORD={{ .Values.corda.node.conf.networkRootTruststorePassword }} 207 | 208 | # Load version numbers from docker_config.sh 209 | . $DOCKER_IMAGES_FOLDER/docker_config.sh 210 | 211 | CORDA_BIN=$BIN_DIR/$CORDA_VERSION.jar 212 | 213 | echo "Starting Corda Node initial registration..." 214 | 215 | if [ -d "$BIN_DIR" -a -f "$CORDA_BIN" ] 216 | then 217 | echo "Corda Enterprise binaries found $CORDA_BIN" 218 | echo "Checking for $TRUST_STORE" 219 | if [ -f "$TRUST_STORE" ] 220 | then 221 | echo "Corda Network root trust store file found." 222 | echo "Checking that node.conf file exists in $NODE_CONF" 223 | if [ -f "$NODE_CONF" ] 224 | then 225 | echo "Corda Node initial-registration step" 226 | initialRegistration $CORDA_BIN $NODE_CONF $TRUST_STORE $TRUST_STORE_PASSWORD 227 | 228 | echo "Corda Node network-parameters step" 229 | downloadNetworkParameters $CORDA_BIN $NODE_CONF 230 | 231 | echo -e "${GREEN}Initial registration completed successfully! You can now deploy to Kubernetes cluster.${NC}" 232 | else 233 | echo -e "${RED}ERROR${NC}" 234 | echo "node.conf not found as $NODE_CONF" 235 | exit 1 236 | fi 237 | else 238 | echo -e "${RED}ERROR${NC}" 239 | echo "Corda Network root trust store file not found, expected: $TRUST_STORE" 240 | exit 1 241 | fi 242 | else 243 | echo -e "${RED}ERROR${NC}" 244 | echo "Corda Enterprise binaries not found in folder $BIN_DIR" 245 | exit 1 246 | fi 247 | } 248 | 249 | main -------------------------------------------------------------------------------- /helm/initial_registration/templates/node.conf.yml: -------------------------------------------------------------------------------- 1 | {{ tpl (.Values.node_conf) . }} -------------------------------------------------------------------------------- /helm/output/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /helm/requirements.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/corda/corda-kubernetes-deployment/f0016325af7b002cf626a87fa355e258e5b2556d/helm/requirements.yaml -------------------------------------------------------------------------------- /helm/templates/ConfigMap.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ .Values.config.resourceName }}-corda-configmap 5 | data: 6 | node.conf: |+ 7 | {{- $filename := (printf "%s-%s%s" "files/conf/node" .Values.setup.cordaVersion ".conf") }} 8 | {{- $file := .Files.Get $filename }} 9 | {{- if $file }} 10 | {{ tpl ($file) . | indent 4 }} 11 | {{- else }} 12 | {{ printf "ERROR: File not found %s, this probably means you are targetting a version of Corda that does not have an assigned node-.conf file, you can in most cases just copy another version (the closest version you can find, eg for 4.4, choose 4.3, for 4.4.2, choose 4.4) of the node.conf file and name it accordingly." $filename }} 13 | {{- end }} 14 | bridge.conf: |+ 15 | {{- $filename := (printf "%s-%s%s" "files/conf/bridge" .Values.setup.cordaVersion ".conf") }} 16 | {{- $file := .Files.Get $filename }} 17 | {{- if $file }} 18 | {{ tpl ($file) . | indent 4 }} 19 | {{- else }} 20 | {{ printf "ERROR: File not found %s, this probably means you are targetting a version of Corda that does not have an assigned bridge-.conf file, you can in most cases just copy another version (the closest version you can find, eg for 4.4, choose 4.3, for 4.4.2, choose 4.4) of the bridge.conf file and name it accordingly." $filename }} 21 | {{- end }} 22 | float.conf: |+ 23 | {{- $filename := (printf "%s-%s%s" "files/conf/float" .Values.setup.cordaVersion ".conf") }} 24 | {{- $file := .Files.Get $filename }} 25 | {{- if $file }} 26 | {{ tpl ($file) . | indent 4 }} 27 | {{- else }} 28 | {{ printf "ERROR: File not found %s, this probably means you are targetting a version of Corda that does not have an assigned float-.conf file, you can in most cases just copy another version (the closest version you can find, eg for 4.4, choose 4.3, for 4.4.2, choose 4.4) of the float.conf file and name it accordingly." $filename }} 29 | {{- end }} 30 | ping.sh: |+ 31 | {{ tpl (.Files.Get "files/ping.sh") . | indent 4 }} 32 | binaryData: 33 | networkRootTrustStore.jks: 34 | {{ .Files.Get "files/network/networkRootTrustStore.jks" | b64enc | quote | indent 4 }} 35 | network-parameters.file: 36 | {{ .Files.Get "files/network/network-parameters.file" | b64enc | quote | indent 4 }} 37 | {{- $root := .}} 38 | {{- range $path, $bytes := .Files.Glob "files/certificates/firewall_tunnel/**.jks" }} 39 | {{ $path | base | indent 2 }}: 40 | {{ $root.Files.Get $path | b64enc | quote | indent 4 }} 41 | {{- end }} 42 | {{- range $path, $bytes := .Files.Glob "files/certificates/node/**.jks" }} 43 | {{ $path | base | indent 2 }}: 44 | {{ $root.Files.Get $path | b64enc | quote | indent 4 }} 45 | {{- end }} 46 | -------------------------------------------------------------------------------- /helm/templates/StorageClass.yml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: {{ .Values.config.storage.resourceName }} 5 | {{- if .Values.config.storage.local.enabled }} 6 | provisioner: kubernetes.io/{{ .Values.config.storage.local.provisioner }} 7 | volumeBindingMode: WaitForFirstConsumer 8 | {{- else if .Values.config.storage.azureFile.enabled }} 9 | provisioner: kubernetes.io/{{ .Values.config.storage.azureFile.provisioner }} 10 | parameters: 11 | skuName: {{ .Values.config.storage.azureFile.skuName }} 12 | storageAccount: {{ .Values.config.storage.azureFile.azureStorageAccountName }} 13 | location: {{ .Values.config.storage.azureFile.location }} 14 | {{- else if .Values.config.storage.gcpPD.enabled }} 15 | provisioner: kubernetes.io/{{ .Values.config.storage.gcpPD.provisioner }} 16 | parameters: 17 | type: {{ .Values.config.storage.gcpPD.type }} 18 | fstype: {{ .Values.config.storage.gcpPD.fsType }} 19 | replication-type: none 20 | {{- else if .Values.config.storage.awsEBS.enabled }} 21 | provisioner: kubernetes.io/{{ .Values.config.storage.awsEBS.provisioner }} 22 | parameters: 23 | type: {{ .Values.config.storage.awsEBS.type }} 24 | fstype: {{ .Values.config.storage.awsEBS.fsType }} 25 | encrypted: "{{ .Values.config.storage.awsEBS.encrypted }}" 26 | {{- if and .Values.config.storage.awsEBS.encrypted (ne .Values.config.storage.awsEBS.kmsKeyId "") }} 27 | kmsKeyId: {{ .Values.config.storage.awsEBS.kmsKeyId }} 28 | {{- end }} 29 | {{- if eq .Values.config.storage.awsEBS.type "io1" }} 30 | iopsPerGB: {{ .Values.config.storage.awsEBS.iopsPerGB }} 31 | {{- end }} 32 | volumeBindingMode: WaitForFirstConsumer 33 | allowedTopologies: 34 | - matchLabelExpressions: 35 | - key: failure-domain.beta.kubernetes.io/zone 36 | values: 37 | {{- range $zone := .Values.config.storage.awsEBS.zones }} 38 | - {{ $zone.name }} 39 | {{- end }} 40 | {{- end }} 41 | -------------------------------------------------------------------------------- /helm/templates/copy-files.sh.yml: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | 46 | CopyDatabaseDrivers () { 47 | POD=$1 48 | DB_DRIVERS_PATH=$2 49 | 50 | CUR_PATH=$(pwd) 51 | cd $DB_DRIVERS_PATH 52 | 53 | set +e 54 | ALL_DRIVER_JARS=(*.jar) 55 | NUM_DRIVERS=${#ALL_DRIVER_JARS[@]} 56 | echo "Copying $NUM_DRIVERS database driver(s) to persistent storage" 57 | echo "" 58 | 59 | echo "Ensuring persistent storage has the drivers folder..." 60 | kubectl exec $POD -- mkdir -p workspace/drivers/ 61 | echo "" 62 | 63 | DRIVERS_IN_PERSISTENT_STORAGE=$(kubectl exec $POD -- ls -al workspace/drivers/) 64 | 65 | for f in "${ALL_DRIVER_JARS[@]}" 66 | do 67 | echo "Driver jar: $f" 68 | echo "$DRIVERS_IN_PERSISTENT_STORAGE" | grep $(basename $f) &> /dev/null 69 | if [ $? -eq 0 ]; then 70 | echo "The driver already exists in persistent storage as:" 71 | echo $(echo "$DRIVERS_IN_PERSISTENT_STORAGE" | grep $(basename $f)) 72 | else 73 | echo "Copying driver to persistent storage..." 74 | kubectl cp "$f" "$POD:/opt/corda/workspace/drivers/" 75 | fi 76 | echo "" 77 | done 78 | cd $CUR_PATH 79 | set -e 80 | echo "Database drivers copy complete." 81 | echo "" 82 | #kubectl exec $POD -- ls workspace/drivers/ | grep postgres 83 | #kubectl exec $POD -- ls workspace/drivers/ | grep ojdbc 84 | #kubectl exec $POD -- ls workspace/drivers/ | grep mssql 85 | } 86 | 87 | CopyCorDapps () { 88 | APP=$1 89 | CORDAPPS_PATH=$2 90 | 91 | # Can run into issues if CorDapps locked by Corda process. TODO: refactor into a new manner of deploying CorDapps. 92 | echo "Copying $CORDAPPS_PATH to $POD:/opt/corda/workspace/" 93 | echo "Contents of cordapps folder:" 94 | ls $CORDAPPS_PATH 95 | set +e 96 | kubectl cp "$CORDAPPS_PATH" "$POD:/opt/corda/workspace/" 97 | result=$? 98 | set -e 99 | if [ $result -eq 0 ]; then 100 | echo "Copy operation completed successfully." 101 | else 102 | echo -e "${RED}ERROR${NC}" 103 | echo "Copy operation failed! Perhaps the files are currently in use?" 104 | fi 105 | 106 | echo "CorDapps copy complete." 107 | echo "" 108 | } 109 | 110 | CopyFilesToPersistentStorage () { 111 | set -eu 112 | APP={{ .Values.config.resourceName }}-node 113 | POD=$(kubectl get pod -l app=$APP -o jsonpath="{.items[0].metadata.name}") 114 | 115 | echo "Copy files to $APP with POD: $POD" 116 | 117 | CopyDatabaseDrivers $POD $(echo "$DIR/../../../../docker-images/bin/db_drivers") 118 | 119 | CopyCorDapps $POD $(echo "$DIR/../../../files/cordapps") 120 | } 121 | CopyFilesToPersistentStorage 122 | -------------------------------------------------------------------------------- /helm/templates/create-docker-secret.sh.yml: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -u 4 | DIR="." 5 | GetPathToCurrentlyExecutingScript () { 6 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 7 | set +e 8 | ABS_PATH=$(readlink -f "$0" 2>&1) 9 | if [ "$?" -ne "0" ]; then 10 | echo "Using macOS alternative to readlink -f command..." 11 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 12 | TARGET_FILE=$0 13 | 14 | cd $(dirname $TARGET_FILE) 15 | TARGET_FILE=$(basename $TARGET_FILE) 16 | ITERATIONS=0 17 | 18 | # Iterate down a (possible) chain of symlinks 19 | while [ -L "$TARGET_FILE" ] 20 | do 21 | TARGET_FILE=$(readlink $TARGET_FILE) 22 | cd $(dirname $TARGET_FILE) 23 | TARGET_FILE=$(basename $TARGET_FILE) 24 | ITERATIONS=$((ITERATIONS + 1)) 25 | if [ "$ITERATIONS" -gt 1000 ]; then 26 | echo "symlink loop. Critical exit." 27 | exit 1 28 | fi 29 | done 30 | 31 | # Compute the canonicalized name by finding the physical path 32 | # for the directory we're in and appending the target file. 33 | PHYS_DIR=$(pwd -P) 34 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 35 | fi 36 | 37 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 38 | DIR=$(dirname "$ABS_PATH") 39 | } 40 | GetPathToCurrentlyExecutingScript 41 | 42 | set -eu 43 | function main() { 44 | SERVER="{{.Values.config.containerRegistry.serverAddress}}" 45 | USERNAME="{{ .Values.config.containerRegistry.username }}" 46 | PASSWORD="{{ .Values.config.containerRegistry.password }}" 47 | EMAIL="{{ .Values.config.containerRegistry.email }}" 48 | 49 | {{- if eq .Values.config.containerRegistry.username "AWS" }} 50 | PASSWORD=$(aws ecr get-login-password) 51 | {{- end }} 52 | 53 | kubectl create secret docker-registry --dry-run=true container-registry-secret \ 54 | --docker-server=$SERVER \ 55 | --docker-username=$USERNAME \ 56 | --docker-password=$PASSWORD \ 57 | --docker-email=$EMAIL \ 58 | -o yaml > $DIR/docker-secret.yml 59 | } 60 | main 61 | -------------------------------------------------------------------------------- /helm/templates/deployment-CordaBridge.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ .Values.config.resourceName }}-bridge-deployment 5 | labels: 6 | app: {{ .Values.config.resourceName }}-bridge 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: {{ .Values.config.resourceName }}-bridge 12 | template: 13 | metadata: 14 | labels: 15 | app: {{ .Values.config.resourceName }}-bridge 16 | spec: 17 | {{- if .Values.config.storage.awsEBS.enabled }} 18 | affinity: 19 | nodeAffinity: 20 | requiredDuringSchedulingIgnoredDuringExecution: 21 | nodeSelectorTerms: 22 | - matchExpressions: 23 | - key: kubernetes.io/hostname 24 | operator: In 25 | values: 26 | - {{ .Values.config.storage.node.volumeHost }} 27 | {{- end }} 28 | securityContext: 29 | runAsNonRoot: true 30 | runAsUser: 1000 31 | runAsGroup: 1000 32 | fsGroup: 1000 33 | volumes: 34 | - name: {{ .Values.config.resourceName }}-bridge-pv 35 | persistentVolumeClaim: 36 | claimName: {{ .Values.config.resourceName }}-bridge-pvc 37 | - name: bridge-config-volume 38 | configMap: 39 | name: {{ .Values.config.resourceName }}-corda-configmap 40 | imagePullSecrets: 41 | - name: container-registry-secret 42 | containers: 43 | - name: {{ .Values.config.resourceName }}-bridge 44 | image: {{ .Values.config.containerRegistry.serverAddress }}/{{ printf .Values.config.dockerImageFirewall (.Values.setup.cordaVersion | lower) }} 45 | imagePullPolicy: Always 46 | resources: 47 | requests: 48 | memory: "500Mi" 49 | cpu: "500m" 50 | limits: 51 | memory: "1Gi" 52 | cpu: "1000m" 53 | ports: 54 | - containerPort: {{ .Values.corda.node.conf.p2pPort }} 55 | volumeMounts: 56 | - mountPath: "/opt/corda/workspace" 57 | name: {{ .Values.config.resourceName }}-bridge-pv 58 | - mountPath: /opt/corda/workspace/network-parameters 59 | name: bridge-config-volume 60 | subPath: network-parameters.file 61 | readOnly: true 62 | - mountPath: /opt/corda/workspace/ping.sh 63 | name: bridge-config-volume 64 | subPath: ping.sh 65 | readOnly: true 66 | - mountPath: /opt/corda/workspace/firewall.conf 67 | name: bridge-config-volume 68 | subPath: bridge.conf 69 | readOnly: true 70 | - mountPath: /opt/corda/workspace/certificates/bridge.jks 71 | name: bridge-config-volume 72 | subPath: bridge.jks 73 | readOnly: true 74 | - mountPath: /opt/corda/workspace/certificates/sslkeystore.jks 75 | name: bridge-config-volume 76 | subPath: sslkeystore.jks 77 | readOnly: true 78 | - mountPath: /opt/corda/workspace/certificates/trust.jks 79 | name: bridge-config-volume 80 | subPath: trust.jks 81 | readOnly: true 82 | - mountPath: /opt/corda/workspace/certificates/truststore.jks 83 | name: bridge-config-volume 84 | subPath: truststore.jks 85 | readOnly: true 86 | -------------------------------------------------------------------------------- /helm/templates/deployment-CordaFloat.yml: -------------------------------------------------------------------------------- 1 | {{- if .Values.setup.cordaFirewall.destination.internalKubernetesCluster.enabled }} 2 | {{- if .Values.setup.cordaFirewall.enabled }} 3 | kind: Service 4 | apiVersion: v1 5 | metadata: 6 | name: {{ .Values.config.resourceName }}-float-p2p-service 7 | spec: 8 | loadBalancerIP: "{{ .Values.config.floatLoadBalancerIP }}" 9 | type: LoadBalancer 10 | selector: 11 | app: {{ .Values.config.resourceName }}-float 12 | ports: 13 | - name: p2p 14 | protocol: TCP 15 | port: {{ .Values.corda.node.conf.p2pPort }} 16 | targetPort: {{ .Values.corda.node.conf.p2pPort }} 17 | --- 18 | {{- end }} 19 | kind: Service 20 | apiVersion: v1 21 | metadata: 22 | name: {{ .Values.config.resourceName }}-float-internal 23 | spec: 24 | selector: 25 | app: {{ .Values.config.resourceName }}-float 26 | ports: 27 | - name: bridge-tunnel 28 | protocol: TCP 29 | port: {{ .Values.corda.node.conf.bridgeTunnelPort }} 30 | targetPort: {{ .Values.corda.node.conf.bridgeTunnelPort }} 31 | --- 32 | apiVersion: apps/v1 33 | kind: Deployment 34 | metadata: 35 | name: {{ .Values.config.resourceName }}-float-deployment 36 | labels: 37 | app: {{ .Values.config.resourceName }}-float 38 | spec: 39 | replicas: 1 40 | selector: 41 | matchLabels: 42 | app: {{ .Values.config.resourceName }}-float 43 | template: 44 | metadata: 45 | labels: 46 | app: {{ .Values.config.resourceName }}-float 47 | spec: 48 | {{- if .Values.config.storage.awsEBS.enabled }} 49 | affinity: 50 | nodeAffinity: 51 | requiredDuringSchedulingIgnoredDuringExecution: 52 | nodeSelectorTerms: 53 | - matchExpressions: 54 | - key: kubernetes.io/hostname 55 | operator: In 56 | values: 57 | - {{ .Values.config.storage.node.volumeHost }} 58 | {{- end }} 59 | securityContext: 60 | runAsNonRoot: true 61 | runAsUser: 1000 62 | runAsGroup: 1000 63 | fsGroup: 1000 64 | volumes: 65 | - name: {{ .Values.config.resourceName }}-float-pv 66 | persistentVolumeClaim: 67 | claimName: {{ .Values.config.resourceName }}-float-pvc 68 | - name: float-config-volume 69 | configMap: 70 | name: {{ .Values.config.resourceName }}-corda-configmap 71 | imagePullSecrets: 72 | - name: container-registry-secret 73 | containers: 74 | - name: {{ .Values.config.resourceName }}-float 75 | image: {{ .Values.config.containerRegistry.serverAddress }}/{{ printf .Values.config.dockerImageFirewall (.Values.setup.cordaVersion | lower) }} 76 | imagePullPolicy: Always 77 | resources: 78 | requests: 79 | memory: "500Mi" 80 | cpu: "500m" 81 | limits: 82 | memory: "1Gi" 83 | cpu: "1000m" 84 | ports: 85 | - containerPort: {{ .Values.corda.node.conf.p2pPort }} 86 | - containerPort: {{ .Values.corda.node.conf.bridgeTunnelPort }} 87 | volumeMounts: 88 | - mountPath: /opt/corda/workspace 89 | name: {{ .Values.config.resourceName }}-float-pv 90 | - mountPath: /opt/corda/workspace/network-parameters 91 | name: float-config-volume 92 | subPath: network-parameters.file 93 | readOnly: true 94 | - mountPath: /opt/corda/workspace/ping.sh 95 | name: float-config-volume 96 | subPath: ping.sh 97 | readOnly: true 98 | - mountPath: /opt/corda/workspace/firewall.conf 99 | name: float-config-volume 100 | subPath: float.conf 101 | readOnly: true 102 | - mountPath: /opt/corda/workspace/certificates/float.jks 103 | name: float-config-volume 104 | subPath: float.jks 105 | readOnly: true 106 | - mountPath: /opt/corda/workspace/certificates/sslkeystore.jks 107 | name: float-config-volume 108 | subPath: sslkeystore.jks 109 | readOnly: true 110 | - mountPath: /opt/corda/workspace/certificates/trust.jks 111 | name: float-config-volume 112 | subPath: trust.jks 113 | readOnly: true 114 | - mountPath: /opt/corda/workspace/certificates/truststore.jks 115 | name: float-config-volume 116 | subPath: truststore.jks 117 | readOnly: true 118 | 119 | {{- end }} -------------------------------------------------------------------------------- /helm/templates/deployment-CordaNode.yml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: {{ .Values.config.resourceName }}-service 5 | spec: 6 | loadBalancerIP: "{{ .Values.config.nodeLoadBalancerIP }}" 7 | type: LoadBalancer 8 | selector: 9 | app: {{ .Values.config.resourceName }}-node 10 | ports: 11 | {{- if not .Values.setup.cordaFirewall.enabled }} 12 | - name: p2p 13 | protocol: TCP 14 | port: {{ .Values.corda.node.conf.p2pPort }} 15 | targetPort: {{ .Values.corda.node.conf.p2pPort }} 16 | {{- end }} 17 | - name: rpc 18 | protocol: TCP 19 | port: {{ .Values.corda.node.conf.rpc.port }} 20 | targetPort: {{ .Values.corda.node.conf.rpc.port }} 21 | {{- if .Values.corda.node.conf.ssh.enabled }} 22 | - name: ssh 23 | protocol: TCP 24 | port: {{ .Values.corda.node.conf.ssh.sshdPort }} 25 | targetPort: {{ .Values.corda.node.conf.ssh.sshdPort }} 26 | {{- end }} 27 | --- 28 | {{- if .Values.setup.cordaFirewall.enabled }} 29 | kind: Service 30 | apiVersion: v1 31 | metadata: 32 | name: {{ .Values.config.resourceName }}-node-internal 33 | spec: 34 | selector: 35 | app: {{ .Values.config.resourceName }}-node 36 | ports: 37 | - name: p2p 38 | protocol: TCP 39 | port: {{ .Values.corda.node.conf.p2pPort }} 40 | targetPort: {{ .Values.corda.node.conf.p2pPort }} 41 | --- 42 | {{- end }} 43 | apiVersion: apps/v1 44 | kind: Deployment 45 | metadata: 46 | name: {{ .Values.config.resourceName }}-deployment 47 | labels: 48 | app: {{ .Values.config.resourceName }}-node 49 | spec: 50 | replicas: 1 51 | selector: 52 | matchLabels: 53 | app: {{ .Values.config.resourceName }}-node 54 | template: 55 | metadata: 56 | labels: 57 | app: {{ .Values.config.resourceName }}-node 58 | spec: 59 | {{- if .Values.config.storage.awsEBS.enabled }} 60 | affinity: 61 | nodeAffinity: 62 | requiredDuringSchedulingIgnoredDuringExecution: 63 | nodeSelectorTerms: 64 | - matchExpressions: 65 | - key: kubernetes.io/hostname 66 | operator: In 67 | values: 68 | - {{ .Values.config.storage.node.volumeHost }} 69 | {{- end }} 70 | securityContext: 71 | runAsNonRoot: true 72 | runAsUser: 1000 73 | runAsGroup: 1000 74 | fsGroup: 1000 75 | volumes: 76 | - name: {{ .Values.config.resourceName }}-pv 77 | persistentVolumeClaim: 78 | claimName: {{ .Values.config.resourceName }}-pvc 79 | - name: node-config-volume 80 | configMap: 81 | name: {{ .Values.config.resourceName }}-corda-configmap 82 | imagePullSecrets: 83 | - name: container-registry-secret 84 | containers: 85 | - name: {{ .Values.config.resourceName }} 86 | image: {{ .Values.config.containerRegistry.serverAddress }}/{{ printf .Values.config.dockerImageNode (.Values.setup.cordaVersion | lower) }} 87 | imagePullPolicy: Always 88 | resources: 89 | requests: 90 | memory: "1Gi" 91 | cpu: "500m" 92 | limits: 93 | memory: "2Gi" 94 | cpu: "1000m" 95 | ports: 96 | - containerPort: {{ .Values.corda.node.conf.p2pPort }} 97 | - containerPort: {{ .Values.corda.node.conf.rpc.port }} 98 | {{- if .Values.corda.node.conf.ssh.enabled }} 99 | - containerPort: {{ .Values.corda.node.conf.ssh.sshdPort }} 100 | {{- end }} 101 | volumeMounts: 102 | - mountPath: "/opt/corda/workspace" 103 | name: {{ .Values.config.resourceName }}-pv 104 | - mountPath: /opt/corda/workspace/ping.sh 105 | name: node-config-volume 106 | subPath: ping.sh 107 | readOnly: true 108 | - mountPath: /opt/corda/workspace/node.conf 109 | name: node-config-volume 110 | subPath: node.conf 111 | readOnly: true 112 | - mountPath: /opt/corda/workspace/bridge.conf 113 | name: node-config-volume 114 | subPath: bridge.conf 115 | readOnly: true 116 | - mountPath: /opt/corda/workspace/float.conf 117 | name: node-config-volume 118 | subPath: float.conf 119 | readOnly: true 120 | - mountPath: /opt/corda/workspace/networkRootTrustStore.jks 121 | name: node-config-volume 122 | subPath: networkRootTrustStore.jks 123 | readOnly: true 124 | - mountPath: /opt/corda/workspace/certificates/nodekeystore.jks 125 | name: node-config-volume 126 | subPath: nodekeystore.jks 127 | readOnly: true 128 | - mountPath: /opt/corda/workspace/certificates/sslkeystore.jks 129 | name: node-config-volume 130 | subPath: sslkeystore.jks 131 | readOnly: true 132 | - mountPath: /opt/corda/workspace/certificates/truststore.jks 133 | name: node-config-volume 134 | subPath: truststore.jks 135 | readOnly: true 136 | env: 137 | - name: IDENTITY_MANAGER_ADDRESS 138 | value: "{{ .Values.corda.node.conf.identityManagerAddress }}" 139 | - name: NETMAP_ADDRESS 140 | value: "{{ .Values.corda.node.conf.networkmapAddress }}" 141 | - name: TRUSTSTORE_PASSWORD 142 | value: "{{ .Values.corda.node.conf.truststorePassword }}" 143 | -------------------------------------------------------------------------------- /helm/templates/secret-CordaNodeAzureFile.yml: -------------------------------------------------------------------------------- 1 | kind: Secret 2 | apiVersion: v1 3 | metadata: 4 | name: {{ .Values.config.storage.resourceName }}-secret 5 | type: Opaque 6 | data: 7 | azurestorageaccountname: "{{ .Values.config.storage.azureFile.azureStorageAccountName | b64enc }}" 8 | azurestorageaccountkey: "{{ .Values.config.storage.azureFile.azureStorageAccountKey | b64enc }}" 9 | -------------------------------------------------------------------------------- /helm/templates/volume-CordaBridge.yml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: {{ .Values.config.resourceName }}-bridge-pvc 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce 8 | storageClassName: {{ .Values.config.storage.resourceName }} 9 | volumeName: {{ .Values.config.resourceName }}-bridge-pv-volume 10 | resources: 11 | requests: 12 | storage: {{ .Values.config.storage.bridge.size }} 13 | --- 14 | kind: PersistentVolume 15 | apiVersion: v1 16 | metadata: 17 | name: {{ .Values.config.resourceName }}-bridge-pv-volume 18 | spec: 19 | storageClassName: {{ .Values.config.storage.resourceName }} 20 | capacity: 21 | storage: {{ .Values.config.storage.bridge.size }} 22 | accessModes: 23 | - ReadWriteOnce 24 | {{- if .Values.config.storage.azureFile.enabled }} 25 | azureFile: 26 | secretName: {{ .Values.config.storage.resourceName }}-secret 27 | shareName: {{ .Values.config.storage.bridge.fileShareName }} 28 | readOnly: false 29 | mountOptions: 30 | - dir_mode=0777 31 | - file_mode=0777 32 | - uid=1000 33 | - gid=1000 34 | {{- else if .Values.config.storage.gcpPD.enabled }} 35 | gcePersistentDisk: 36 | pdName: "{{ .Values.config.storage.bridge.volumeId }}" 37 | fsType: "{{ .Values.config.storage.gcpPD.fsType }}" 38 | {{- else if .Values.config.storage.awsEBS.enabled }} 39 | awsElasticBlockStore: 40 | volumeID: "{{ .Values.config.storage.bridge.volumeId }}" 41 | fsType: "{{ .Values.config.storage.awsEBS.fsType }}" 42 | nodeAffinity: 43 | required: 44 | nodeSelectorTerms: 45 | - matchExpressions: 46 | - key: kubernetes.io/hostname 47 | operator: In 48 | values: 49 | - {{ .Values.config.storage.node.volumeHost }} 50 | {{- end }} 51 | -------------------------------------------------------------------------------- /helm/templates/volume-CordaFloat.yml: -------------------------------------------------------------------------------- 1 | {{- if .Values.setup.cordaFirewall.destination.internalKubernetesCluster.enabled }} 2 | kind: PersistentVolumeClaim 3 | apiVersion: v1 4 | metadata: 5 | name: {{ .Values.config.resourceName }}-float-pvc 6 | spec: 7 | accessModes: 8 | - ReadWriteOnce 9 | storageClassName: {{ .Values.config.storage.resourceName }} 10 | volumeName: {{ .Values.config.resourceName }}-float-pv-volume 11 | resources: 12 | requests: 13 | storage: {{ .Values.config.storage.float.size }} 14 | --- 15 | kind: PersistentVolume 16 | apiVersion: v1 17 | metadata: 18 | name: {{ .Values.config.resourceName }}-float-pv-volume 19 | spec: 20 | storageClassName: {{ .Values.config.storage.resourceName }} 21 | capacity: 22 | storage: {{ .Values.config.storage.float.size }} 23 | accessModes: 24 | - ReadWriteOnce 25 | {{- if .Values.config.storage.azureFile.enabled }} 26 | azureFile: 27 | secretName: {{ .Values.config.storage.resourceName }}-secret 28 | shareName: {{ .Values.config.storage.float.fileShareName }} 29 | readOnly: false 30 | mountOptions: 31 | - dir_mode=0777 32 | - file_mode=0777 33 | - uid=1000 34 | - gid=1000 35 | {{- else if .Values.config.storage.gcpPD.enabled }} 36 | gcePersistentDisk: 37 | pdName: "{{ .Values.config.storage.float.volumeId }}" 38 | fsType: "{{ .Values.config.storage.gcpPD.fsType }}" 39 | {{- else if .Values.config.storage.awsEBS.enabled }} 40 | awsElasticBlockStore: 41 | volumeID: "{{ .Values.config.storage.float.volumeId }}" 42 | fsType: "{{ .Values.config.storage.awsEBS.fsType }}" 43 | nodeAffinity: 44 | required: 45 | nodeSelectorTerms: 46 | - matchExpressions: 47 | - key: kubernetes.io/hostname 48 | operator: In 49 | values: 50 | - {{ .Values.config.storage.node.volumeHost }} 51 | {{- end }} 52 | {{- end }} 53 | -------------------------------------------------------------------------------- /helm/templates/volume-CordaNode.yml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: {{ .Values.config.resourceName }}-pvc 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce 8 | storageClassName: {{ .Values.config.storage.resourceName }} 9 | volumeName: {{ .Values.config.resourceName }}-pv-volume 10 | resources: 11 | requests: 12 | storage: {{ .Values.config.storage.node.size }} 13 | --- 14 | kind: PersistentVolume 15 | apiVersion: v1 16 | metadata: 17 | name: {{ .Values.config.resourceName }}-pv-volume 18 | spec: 19 | storageClassName: {{ .Values.config.storage.resourceName }} 20 | capacity: 21 | storage: {{ .Values.config.storage.node.size }} 22 | accessModes: 23 | - ReadWriteOnce 24 | {{- if .Values.config.storage.azureFile.enabled }} 25 | azureFile: 26 | secretName: {{ .Values.config.storage.resourceName }}-secret 27 | shareName: {{ .Values.config.storage.node.fileShareName }} 28 | readOnly: false 29 | mountOptions: 30 | - dir_mode=0777 31 | - file_mode=0777 32 | - uid=1000 33 | - gid=1000 34 | {{- else if .Values.config.storage.gcpPD.enabled }} 35 | gcePersistentDisk: 36 | pdName: "{{ .Values.config.storage.node.volumeId }}" 37 | fsType: "{{ .Values.config.storage.gcpPD.fsType }}" 38 | {{- else if .Values.config.storage.awsEBS.enabled }} 39 | awsElasticBlockStore: 40 | volumeID: "{{ .Values.config.storage.node.volumeId }}" 41 | fsType: "{{ .Values.config.storage.awsEBS.fsType }}" 42 | nodeAffinity: 43 | required: 44 | nodeSelectorTerms: 45 | - matchExpressions: 46 | - key: kubernetes.io/hostname 47 | operator: In 48 | values: 49 | - {{ .Values.config.storage.node.volumeHost }} 50 | {{- end }} 51 | -------------------------------------------------------------------------------- /one-time-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | set -eu 46 | 47 | checkStatus () { 48 | status=$1 49 | if [ $status -eq 0 ] 50 | then 51 | echo "." 52 | else 53 | echo -e "${RED}ERROR${NC}" 54 | echo "The previous step failed" 55 | exit 1 56 | fi 57 | return 0 58 | } 59 | 60 | OneTimeSetup () { 61 | echo "====== One Time Setup Script ====== " 62 | $DIR/docker-images/build_docker_images.sh 63 | checkStatus $? 64 | $DIR/docker-images/push_docker_images.sh 65 | checkStatus $? 66 | $DIR/corda-pki-generator/generate_firewall_pki.sh 67 | checkStatus $? 68 | 69 | INITIAL_REGISTRATION="" 70 | INITIAL_REGISTRATION=$(grep -A 3 'initialRegistration:' $DIR/helm/values.yaml | grep 'enabled: ' | cut -d ':' -f 2 | xargs) 71 | 72 | if [ "$INITIAL_REGISTRATION" = "true" ]; then 73 | $DIR/helm/initial_registration/initial_registration.sh 74 | checkStatus $? 75 | else 76 | echo -e "${YELLOW}Warning${NC}" 77 | echo "Skipping initial registration step. (disabled in values.yaml)" 78 | fi 79 | 80 | echo "====== One Time Setup Script completed. ====== " 81 | } 82 | OneTimeSetup 83 | -------------------------------------------------------------------------------- /reset_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RED='\033[0;31m' # Error color 4 | YELLOW='\033[0;33m' # Warning color 5 | NC='\033[0m' # No Color 6 | 7 | set -u 8 | DIR="." 9 | GetPathToCurrentlyExecutingScript () { 10 | # Absolute path of this script, e.g. /opt/corda/node/foo.sh 11 | set +e 12 | ABS_PATH=$(readlink -f "$0" 2>&1) 13 | if [ "$?" -ne "0" ]; then 14 | echo "Using macOS alternative to readlink -f command..." 15 | # Unfortunate MacOs issue with readlink functionality, see https://github.com/corda/corda-kubernetes-deployment/issues/4 16 | TARGET_FILE=$0 17 | 18 | cd $(dirname $TARGET_FILE) 19 | TARGET_FILE=$(basename $TARGET_FILE) 20 | ITERATIONS=0 21 | 22 | # Iterate down a (possible) chain of symlinks 23 | while [ -L "$TARGET_FILE" ] 24 | do 25 | TARGET_FILE=$(readlink $TARGET_FILE) 26 | cd $(dirname $TARGET_FILE) 27 | TARGET_FILE=$(basename $TARGET_FILE) 28 | ITERATIONS=$((ITERATIONS + 1)) 29 | if [ "$ITERATIONS" -gt 1000 ]; then 30 | echo "symlink loop. Critical exit." 31 | exit 1 32 | fi 33 | done 34 | 35 | # Compute the canonicalized name by finding the physical path 36 | # for the directory we're in and appending the target file. 37 | PHYS_DIR=$(pwd -P) 38 | ABS_PATH=$PHYS_DIR/$TARGET_FILE 39 | fi 40 | 41 | # Absolute path of the directory this script is in, thus /opt/corda/node/ 42 | DIR=$(dirname "$ABS_PATH") 43 | } 44 | GetPathToCurrentlyExecutingScript 45 | set -eu 46 | 47 | checkStatus () { 48 | status=$1 49 | if [ $status -eq 0 ] 50 | then 51 | echo "." 52 | else 53 | echo -e "${RED}ERROR${NC}" 54 | echo "The previous step failed" 55 | exit 1 56 | fi 57 | return 0 58 | } 59 | 60 | ResetEnvironment () { 61 | echo "====== Resetting deployment environment next ... ====== " 62 | echo -e "${YELLOW}Warning${NC}" 63 | echo "This will remove certificates from your local file system." 64 | echo "If you are sure this is what you want to do, please type 'yes' and press enter." 65 | read -p "Enter 'yes' to continue: " confirm 66 | echo $confirm 67 | if [ "$confirm" = "yes" ]; then 68 | echo "Resetting environment..." 69 | rm -rf $DIR/corda-pki-generator/pki-firewall/certs/ 70 | checkStatus $? 71 | mkdir -p $DIR/corda-pki-generator/pki-firewall/certs/ 72 | rm -rf $DIR/helm/files/certificates/node/ 73 | checkStatus $? 74 | mkdir -p $DIR/helm/files/certificates/node/ 75 | rm -rf $DIR/helm/files/certificates/firewall_tunnel/ 76 | checkStatus $? 77 | mkdir -p $DIR/helm/files/certificates/firewall_tunnel/ 78 | rm -rf $DIR/helm/files/network/*.file 79 | checkStatus $? 80 | rm -rf $DIR/helm/initial_registration/output/corda/templates/workspace/ 81 | checkStatus $? 82 | mkdir -p $DIR/helm/initial_registration/output/corda/templates/workspace/ 83 | echo "Environment now reset, you can execute one-time-setup.sh again." 84 | fi 85 | echo "====== Resetting deployment environment completed. ====== " 86 | } 87 | ResetEnvironment 88 | --------------------------------------------------------------------------------