From 8b2ab4105765aad2ab041368a83ea58cb986972c Mon Sep 17 00:00:00 2001 From: Joel Dudley Date: Mon, 5 Nov 2018 15:51:42 +0000 Subject: [PATCH] Updated network docs (#4154) * Renaming and reordering to help users navigate the Networks section. * Split of pages between bootstrapped, existing and dynamic compatibility zones. Reintegrates Mike H content about creating a dynamic zone. * Address review feedback except BNO point. * Documents BNO app. * Better docs of networkServices config option. Better comments of NetworkParameters fields. * Documents additional network map protocol endpoint. * Address review feedback. * Addresses Kostas review feedback. * Update protocol due to bug. * Addresses Kostas's review feedback. * Addresses Kostas's review feedback. --- docs/source/cipher-suites.rst | 4 +- docs/source/compatibility-zones.rst | 65 ++---- docs/source/corda-networks-index.rst | 13 +- docs/source/corda-testnet-intro.rst | 4 +- docs/source/deploy-locally.rst | 4 +- docs/source/deploy-to-testnet-index.rst | 10 + docs/source/joining-a-compatibility-zone.rst | 58 ++++++ docs/source/network-map.rst | 6 +- docs/source/permissioning.rst | 4 +- ...etting-up-a-dynamic-compatibility-zone.rst | 191 ++++++++++++++++++ 10 files changed, 297 insertions(+), 62 deletions(-) create mode 100644 docs/source/deploy-to-testnet-index.rst create mode 100644 docs/source/joining-a-compatibility-zone.rst create mode 100644 docs/source/setting-up-a-dynamic-compatibility-zone.rst diff --git a/docs/source/cipher-suites.rst b/docs/source/cipher-suites.rst index 13a4bf9ae7..8f2d313c45 100644 --- a/docs/source/cipher-suites.rst +++ b/docs/source/cipher-suites.rst @@ -1,5 +1,5 @@ -Supported cipher suites -======================= +Cipher suites supported by Corda +================================ .. contents:: diff --git a/docs/source/compatibility-zones.rst b/docs/source/compatibility-zones.rst index eb3e6680b2..0e94daaaa0 100644 --- a/docs/source/compatibility-zones.rst +++ b/docs/source/compatibility-zones.rst @@ -4,54 +4,29 @@ -Compatibility zones -=================== +What is a compatibility zone? +============================= Every Corda node is part of a "zone" (also sometimes called a Corda network) that is *permissioned*. Production -deployments require a secure certificate authority. Most users will join an existing network such as Corda -Network (the main network) or the Corda Testnet. We use the term "zone" to refer to a set of technically compatible nodes reachable -over a TCP/IP network like the internet. The word "network" is used in Corda but can be ambiguous with the concept -of a "business network", which is usually more like a membership list or subset of nodes in a zone that have agreed -to trade with each other. +deployments require a secure certificate authority. We use the term "zone" to refer to a set of technically compatible +nodes reachable over a TCP/IP network like the internet. The word "network" is used in Corda but can be ambiguous with +the concept of a "business network", which is usually more like a membership list or subset of nodes in a zone that +have agreed to trade with each other. -To connect to a compatibility zone you need to register with its certificate signing authority (doorman) by submitting -a certificate signing request (CSR) to obtain a valid identity for the zone. You could do this out of band, for instance -via email or a web form, but there's also a simple request/response protocol built into Corda. +How do I become part of a compatibility zone? +--------------------------------------------- -Before you can register, you must first have received the trust store file containing the root certificate from the zone -operator. For high security zones this might be delivered physically. Then run the following command: +Bootstrapping a compatibility zone +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +You can easily bootstrap a compatibility zone for testing or pre-production use with either the +:doc:`network-bootstrapper` or the :doc:`network-builder` tools. -``java -jar corda.jar --initial-registration --network-root-truststore-password `` +Joining an existing compatibility zone +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +After the testing and pre-production phases, users are encouraged to join an existing compatibility zone such as Corda +Network (the main compatibility zone) or the Corda Testnet. See :doc:`joining-a-compatibility-zone`. -By default it will expect the trust store file to be in the location ``certificates/network-root-truststore.jks``. -This can be overridden with the additional ``--network-root-truststore`` flag. - -The certificate signing request will be created based on node information obtained from the node configuration. -The following information from the node configuration file is needed to generate the request. - -* **myLegalName** Your company's legal name as an X.500 string. X.500 allows differentiation between entities with the same - name, as the legal name needs to be unique on the network. If another node has already been permissioned with this - name then the permissioning server will automatically reject the request. The request will also be rejected if it - violates legal name rules, see :ref:`node_naming` for more information. You can use the X.500 schema to disambiguate - entities that have the same or similar brand names. - -* **emailAddress** e.g. "admin@company.com" - -* **devMode** must be set to false - -* **networkServices** or **compatibilityZoneURL** The Corda compatibility zone services must be configured. This must be either: - - * **compatibilityZoneURL** The Corda compatibility zone network management service root URL. - * **networkServices** Replaces the ``compatibilityZoneURL`` when the doorman and network map services - are configured to operate on different URL endpoints. The ``doorman`` entry is used for registration. - -A new pair of private and public keys generated by the Corda node will be used to create the request. - -The utility will submit the request to the doorman server and poll for a result periodically to retrieve the -certificates. Once the request has been approved and the certificates downloaded from the server, the node will create -the keystore and trust store using the certificates and the generated private key. - -.. note:: You can exit the utility at any time if the approval process is taking longer than expected. The request - process will resume on restart as long as the ``--initial-registration`` flag is specified. - -This process only is needed when the node connects to the network for the first time, or when the certificate expires. +Setting up a dynamic compatibility zone +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Some users may also be interested in setting up their own dynamic compatibility zone. For instructions and a discussion +of whether this approach is suitable for you, see :doc:`setting-up-a-dynamic-compatibility-zone`. diff --git a/docs/source/corda-networks-index.rst b/docs/source/corda-networks-index.rst index 435beb7981..dce2e2caa1 100644 --- a/docs/source/corda-networks-index.rst +++ b/docs/source/corda-networks-index.rst @@ -5,14 +5,13 @@ Networks :maxdepth: 1 compatibility-zones - corda-testnet-intro - running-a-notary permissioning network-map versioning - azure-vm-explore - aws-vm-explore - gcp-vm - deploy-locally - testnet-explorer-corda cipher-suites + joining-a-compatibility-zone + corda-testnet-intro + deploy-to-testnet-index + testnet-explorer-corda + setting-up-a-dynamic-compatibility-zone + running-a-notary diff --git a/docs/source/corda-testnet-intro.rst b/docs/source/corda-testnet-intro.rst index 0e8a5a34ff..1fe7e89abb 100644 --- a/docs/source/corda-testnet-intro.rst +++ b/docs/source/corda-testnet-intro.rst @@ -1,5 +1,5 @@ -The Corda Testnet -================= +Joining Corda Testnet +===================== .. contents:: diff --git a/docs/source/deploy-locally.rst b/docs/source/deploy-locally.rst index bf2221d3c8..2381420af6 100644 --- a/docs/source/deploy-locally.rst +++ b/docs/source/deploy-locally.rst @@ -1,5 +1,5 @@ -Setting up your local environment to allow the deployment of a Corda node -========================================================================= +Deploying Corda to Corda Testnet from your local environment +============================================================ .. contents:: diff --git a/docs/source/deploy-to-testnet-index.rst b/docs/source/deploy-to-testnet-index.rst new file mode 100644 index 0000000000..c17957b675 --- /dev/null +++ b/docs/source/deploy-to-testnet-index.rst @@ -0,0 +1,10 @@ +Deploying Corda to Testnet +========================== + +.. toctree:: + :maxdepth: 1 + + azure-vm-explore + aws-vm-explore + gcp-vm + deploy-locally diff --git a/docs/source/joining-a-compatibility-zone.rst b/docs/source/joining-a-compatibility-zone.rst new file mode 100644 index 0000000000..72df1ee193 --- /dev/null +++ b/docs/source/joining-a-compatibility-zone.rst @@ -0,0 +1,58 @@ +.. highlight:: kotlin +.. raw:: html + + + + +Joining an existing compatibility zone +====================================== + +To connect to a compatibility zone you need to register with its certificate signing authority (or *doorman*) by +submitting a certificate signing request (CSR) to obtain a valid identity for the zone. This process is only necessary +when the node connects to the network for the first time, or when the certificate expires. You could do this out of +band, for instance via email or a web form, but there's also a simple request/response utility built into the node. + +Before using this utility, you must first have received the trust store file containing the root certificate from the +zone operator. For high security zones, this might be delivered physically. Then run the following command: + +``java -jar corda.jar --initial-registration --network-root-truststore-password `` + +By default, the utility expects the trust store file to be in the location ``certificates/network-root-truststore.jks``. +This can be overridden using the additional ``--network-root-truststore`` flag. + +The utility performs the following steps: + +1. It creates a certificate signing request based on the following information from the node's configuration file (see + :doc:`corda-configuration-file`): + + * **myLegalName** Your company's legal name as an X.500 string. X.500 allows differentiation between entities with the same + name, as the legal name needs to be unique on the network. If another node has already been permissioned with this + name then the permissioning server will automatically reject the request. The request will also be rejected if it + violates legal name rules, see :ref:`node_naming` for more information. You can use the X.500 schema to disambiguate + entities that have the same or similar brand names + + * **emailAddress** e.g. "admin@company.com" + + * **devMode** must be set to false + + * **compatibilityZoneURL** or **networkServices** The address(es) used to register with the compatibility zone and + retrieve the network map. These should be provided to you by the operator of the zone. This must be either: + + * **compatibilityZoneURL** The root address of the network management service. Use this if both the doorman and the + network map service are operating on the same URL endpoint + * **networkServices** The root addresses of the doorman and the network map service. Use this if the doorman and the + network map service are operating on the same URL endpoint, where: + + * **doormanURL** is the root address of the doorman. This is the address used for initial registration + * **networkMapURL** is the root address of the network map service + +2. It generates a new private/public keypair to sign the certificate signing request + +3. It submits the request to the doorman server and polls periodically to retrieve the corresponding certificates + +4. It creates the node's keystore and trust store using the received certificates + +5. It creates and stores the node's TLS keys and legal identity key along with their corresponding certificate-chains + +.. note:: You can exit the utility at any time if the approval process is taking longer than expected. The request + process will resume on restart as long as the ``--initial-registration`` flag is specified. diff --git a/docs/source/network-map.rst b/docs/source/network-map.rst index 2bda2ed9a8..918ba7301a 100644 --- a/docs/source/network-map.rst +++ b/docs/source/network-map.rst @@ -1,5 +1,5 @@ -Network map -=========== +The network map +=============== .. contents:: @@ -45,6 +45,8 @@ The set of REST end-points for the network map service are as follows. +----------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ | GET | /network-map/network-parameters/{hash} | Retrieve the signed network parameters (see below). The entire object is signed with the network map certificate which is also attached. | +----------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| GET | /network-map/my-hostname | Retrieve the IP address of the caller (and **not** of the network map). | ++----------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ HTTP is used for the network map service instead of Corda's own AMQP based peer to peer messaging protocol to enable the server to be placed behind caching content delivery networks like Cloudflare, Akamai, Amazon Cloudfront and so on. diff --git a/docs/source/permissioning.rst b/docs/source/permissioning.rst index c7ca9986cc..2e12ed7524 100644 --- a/docs/source/permissioning.rst +++ b/docs/source/permissioning.rst @@ -4,8 +4,8 @@ -Network permissioning -===================== +Network certificates +==================== .. contents:: diff --git a/docs/source/setting-up-a-dynamic-compatibility-zone.rst b/docs/source/setting-up-a-dynamic-compatibility-zone.rst new file mode 100644 index 0000000000..be5b5f7dc4 --- /dev/null +++ b/docs/source/setting-up-a-dynamic-compatibility-zone.rst @@ -0,0 +1,191 @@ +.. highlight:: kotlin +.. raw:: html + + + + +Setting up a dynamic compatibility zone +======================================= + +.. contents:: + +Do you need to create your own dynamic compatibility zone? +---------------------------------------------------------- + +By *dynamic compatibility zone*, we mean a compatibility zone that relies on a network map server to allow nodes to +join dynamically, instead of requiring each node to be bootstrapped and have the node-infos distributed manually. While +this may sound appealing, think twice before going down this route: + +1. If you need to test a CorDapp, it is easier to create a test network using the network bootstrapper tool (see below) +2. If you need to control who uses your CorDapp, it is easier to apply permissioning by creating a business network + (see below) + +**Testing.** Creating a production-ready zone isn't necessary for testing as you can use the *network bootstrapper* +tool to create all the certificates, keys, and distribute the needed map files to run many nodes. The bootstrapper can +create a network locally on your desktop/laptop but it also knows how to automate cloud providers via their APIs and +using Docker. In this way you can bring up a simulation of a real Corda network with different nodes on different +machines in the cloud for your own testing. Testing this way has several advantages, most obviously that you avoid +race conditions in your tests caused by nodes/tests starting before all map data has propagated to all nodes. +You can read more about the reasons for the creation of the bootstrapper tool +`in a blog post on the design thinking behind Corda's network map infrastructure `__. + +**Permissioning.** And creating a zone is also unnecessary for imposing permissioning requirements beyond that of the +base Corda network. You can control who can use your app by creating a *business network*. A business network is what we +call a coalition of nodes that have chosen to run a particular app within a given commercial context. Business networks +aren't represented in the Corda API at this time, partly because the technical side is so simple. You can create one +via a simple three step process: + +1. Distribute a list of X.500 names that are members of your business network. You can use the + `reference Business Network Membership Service implementation `_. + Alternatively, you could do this is by hosting a text file with one name per line on your website at a fixed HTTPS + URL. You could also write a simple request/response flow that serves the list over the Corda protocol itself, + although this requires the business network to have its own node. +2. Write a bit of code that downloads and caches the contents of this file on disk, and which loads it into memory in + the node. A good place to do this is in a class annotated with ``@CordaService``, because this class can expose + a ``Set`` field representing the membership of your service. +3. In your flows use ``serviceHub.findService`` to get a reference to your ``@CordaService`` class, read the list of + members and at the start of each flow, throw a FlowException if the counterparty isn't in the membership list. + +In this way you can impose a centrally controlled ACL that all members will collectively enforce. + +.. note:: A production-ready Corda network and a new iteration of the testnet will be available soon. + +Why create your own zone? +------------------------- + +The primary reason to create a zone and provide the associated infrastructure is control over *network parameters*. These +are settings that control Corda's operation, and on which all users in a network must agree. Failure to agree would create +the Corda equivalent of a blockchain "hard fork". Parameters control things like the root of identity, +how quickly users should upgrade, how long nodes can be offline before they are evicted from the system and so on. + +Creating a zone involves the following steps: + +1. Create the zone private keys and certificates. This procedure is conventional and no special knowledge is required: + any self-signed set of certificates can be used. A professional quality zone will probably keep the keys inside a + hardware security module (as the main Corda network and test networks do). +2. Write a network map server. +3. Optionally, create a doorman server. +4. Finally, you would select and generate your network parameter file. + +How to create your own compatibility zone +----------------------------------------- + +Using an existing network map implementation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can use an existing network map implementation such as the +`Cordite Network Map Service `_ to create a dynamic compatibility zone. + +Creating your own network map implementation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Writing a network map server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This server implements a simple HTTP based protocol described in the ":doc:`network-map`" page. +The map server is responsible for gathering NodeInfo files from nodes, storing them, and distributing them back to the +nodes in the zone. By doing this it is also responsible for choosing who is in and who is out: having a signed +identity certificate is not enough to be a part of a Corda zone, you also need to be listed in the network map. +It can be thought of as a DNS equivalent. If you want to de-list a user, you would do it here. + +It is very likely that your map server won't be entirely standalone, but rather, integrated with whatever your master +user database is. + +The network map server also distributes signed network parameter files and controls the rollout schedule for when they +become available for download and opt-in, and when they become enforced. This is again a policy decision you will +probably choose to place some simple UI or workflow tooling around, in particular to enforce restrictions on who can +edit the map or the parameters. + +Writing a doorman server +~~~~~~~~~~~~~~~~~~~~~~~~ + +This step is optional because your users can obtain a signed certificate in many different ways. The doorman protocol +is again a very simple HTTP based approach in which a node creates keys and requests a certificate, polling until it +gets back what it expects. However, you could also integrate this process with the rest of your signup process. For example, +by building a tool that's integrated with your payment flow (if payment is required to take part in your zone at all). +Alternatively you may wish to distribute USB smartcard tokens that generate the private key on first use, as is typically +seen in national PKIs. There are many options. + +If you do choose to make a doorman server, the bulk of the code you write will be workflow related. For instance, +related to keeping track of an applicant as they proceed through approval. You should also impose any naming policies +you have in the doorman process. If names are meant to match identities registered in government databases then that +should be enforced here, alternatively, if names can be self-selected or anonymous, you would only bother with a +deduplication check. Again it will likely be integrated with a master user database. + +Corda does not currently provide a doorman or network map service out of the box, partly because when stripped of the +zone specific policy there isn't much to them: just a basic HTTP server that most programmers will have favourite +frameworks for anyway. + +The protocol is: + +* If $URL = ``https://some.server.com/some/path`` +* Node submits a PKCS#10 certificate signing request using HTTP POST to ``$URL/certificate``. It will have a MIME + type of ``application/octet-stream``. The ``Client-Version`` header is set to be "1.0". +* The server returns an opaque string that references this request (let's call it ``$requestid``, or an HTTP error if something went wrong. +* The returned request ID should be persisted to disk, to handle zones where approval may take a long time due to manual + intervention being required. +* The node starts polling ``$URL/$requestid`` using HTTP GET. The poll interval can be controlled by the server returning + a response with a ``Cache-Control`` header. +* If the request is answered with a ``200 OK`` response, the body is expected to be a zip file. Each file is expected to + be a binary X.509 certificate, and the certs are expected to be in order. +* If the request is answered with a ``204 No Content`` response, the node will try again later. +* If the request is answered with a ``403 Not Authorized`` response, the node will treat that as request rejection and give up. +* Other response codes will cause the node to abort with an exception. + +Setting zone parameters +~~~~~~~~~~~~~~~~~~~~~~~ + +Zone parameters are stored in a file containing a Corda AMQP serialised ``SignedDataWithCert`` +object. It is easy to create such a file with a small Java or Kotlin program. The ``NetworkParameters`` object is a +simple data holder that could be read from e.g. a config file, or settings from a database. Signing and saving the +resulting file is just a few lines of code. A full example can be found in ``NetworkParametersCopier.kt`` in the source +tree, but a flavour of it looks like this: + +.. container:: codeset + + .. sourcecode:: java + + NetworkParameters networkParameters = new NetworkParameters( + 4, // minPlatformVersion + Collections.emptyList(), // the `NotaryInfo`s of all the network's notaries + 1024 * 1024 * 20, // maxMessageSize + 1024 * 1024 * 15, // maxTransactionSize + Instant.now(), // modifiedTime + 2, // epoch + Collections.emptyMap() // whitelisted contract code JARs + ); + CertificateAndKeyPair signingCertAndKeyPair = loadNetworkMapCA(); + SerializedBytes> bytes = SerializedBytes.from(netMapCA.sign(networkParameters)); + Files.copy(bytes.open(), Paths.get("params-file")); + + .. sourcecode:: kotlin + + val networkParameters = NetworkParameters( + minimumPlatformVersion = 4, + notaries = listOf(...), + maxMessageSize = 1024 * 1024 * 20 // 20mb, for example. + maxTransactionSize = 1024 * 1024 * 15, + modifiedTime = Instant.now(), + epoch = 2, + ... etc ... + ) + val signingCertAndKeyPair: CertificateAndKeyPair = loadNetworkMapCA() + val signedParams: SerializedBytes = signingCertAndKeyPair.sign(networkParameters).serialize() + signedParams.open().copyTo(Paths.get("/some/path")) + +Each individual parameter is documented in `the JavaDocs/KDocs for the NetworkParameters class +`__. The network map +certificate is usually chained off the root certificate, and can be created according to the instructions above. Each +time the zone parameters are changed, the epoch should be incremented. Epochs are essentially version numbers for the +parameters, and they therefore cannot go backwards. Once saved, the new parameters can be served by the network map server. + +Selecting parameter values +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +How to choose the parameters? This is the most complex question facing you as a new zone operator. Some settings may seem +straightforward and others may involve cost/benefit tradeoffs specific to your business. For example, you could choose +to run a validating notary yourself, in which case you would (in the absence of SGX) see all the users' data. Or you could +run a non-validating notary, with BFT fault tolerance, which implies recruiting others to take part in the cluster. + +New network parameters will be added over time as Corda evolves. You will need to ensure that when your users upgrade, +all the new network parameters are being served. You can ask for advice on the `corda-dev mailing list `__.