Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove signed HTTP request support #5137

Merged
merged 52 commits into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
86d4d4e
Disable member_signature_auth_policy
achamayou Mar 23, 2023
8fb4199
Switch auth
achamayou Mar 23, 2023
4ca5473
Merge branch 'main' into disable_signed_request_support
achamayou Mar 23, 2023
cc678c7
Avoid replay
achamayou Mar 23, 2023
6424433
Merge branch 'main' into disable_signed_request_support
achamayou Mar 24, 2023
2c1e44d
Fix schema test
achamayou Mar 24, 2023
ab70610
Merge branch 'main' into disable_signed_request_support
achamayou Mar 24, 2023
f3dc0b0
fmt
achamayou Mar 24, 2023
717dfab
Fix membership tests
achamayou Mar 24, 2023
025d2da
fmt
achamayou Mar 24, 2023
d3744c3
Fix governance tests
achamayou Mar 24, 2023
2b90f11
Remove un-necessary additional client
achamayou Mar 24, 2023
677c409
Merge branch 'main' into disable_signed_request_support
achamayou Mar 31, 2023
362ee98
Update documentation
achamayou Mar 31, 2023
b73bbe4
disable_support_for_http_sig_in_curl_client
achamayou Mar 31, 2023
0f8550e
Merge branch 'main' into disable_signed_request_support
achamayou Apr 12, 2023
d4cbcb6
Merge branch 'main' into disable_signed_request_support
achamayou Apr 12, 2023
35919bd
Merge branch 'main' into disable_signed_request_support
achamayou Apr 13, 2023
23a83e1
tmp
achamayou Apr 13, 2023
85047f9
Merge branch 'disable_signed_request_support' of https://github.com/a…
achamayou Apr 13, 2023
a243484
Remove tests
achamayou Apr 13, 2023
96c8c4b
Merge branch 'main' into disable_signed_request_support
achamayou Apr 13, 2023
1ce1383
Stop unnecessarily signing the first request with the node key
achamayou Apr 13, 2023
cfaf9fb
Merge branch 'main' into disable_signed_request_support
achamayou Apr 13, 2023
381c8cc
More removal
achamayou Apr 13, 2023
261999d
Merge branch 'main' into disable_signed_request_support
achamayou Apr 13, 2023
d686706
.
achamayou Apr 13, 2023
8acc82d
Merge branch 'disable_signed_request_support' of https://github.com/a…
achamayou Apr 14, 2023
028e61d
.
achamayou Apr 14, 2023
5a37d12
.
achamayou Apr 14, 2023
da1814d
Merge branch 'main' into disable_signed_request_support
achamayou Apr 14, 2023
d4fa6ad
.
achamayou Apr 14, 2023
3a2165e
.
achamayou Apr 14, 2023
e0096ee
Add warning
achamayou Apr 14, 2023
a97b853
.
achamayou Apr 14, 2023
a49bb6c
Update documentation and changelog
achamayou Apr 14, 2023
8f37a2e
Update documentation and changelog
achamayou Apr 14, 2023
d5ab6ae
.
achamayou Apr 14, 2023
1ca5469
Merge branch 'main' into disable_signed_request_support
achamayou Apr 17, 2023
9006d31
Sleep faster
achamayou Apr 17, 2023
7cf4eb7
clock
achamayou Apr 17, 2023
ac6a25e
fmt
achamayou Apr 17, 2023
45c89b0
Merge branch 'main' into disable_signed_request_support
achamayou Apr 17, 2023
6cbdeb0
daily
achamayou Apr 17, 2023
6f6431b
.
achamayou Apr 18, 2023
40ebf64
compat
achamayou Apr 18, 2023
97a9032
.
achamayou Apr 18, 2023
8075b2b
.
achamayou Apr 18, 2023
6007ed0
.
achamayou Apr 18, 2023
14d37d1
.
achamayou Apr 19, 2023
1d7fe30
Merge branch 'main' into disable_signed_request_support
achamayou Apr 19, 2023
099a49d
Merge branch 'main' into disable_signed_request_support
achamayou Apr 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [4.0.0-rc2]

[4.0.0-rc2]: https://github.com/microsoft/CCF/releases/tag/ccf-4.0.0-rc2

### Removed

- Support for HTTP request signing has been removed (#5137). Governance requests must use COSE Sign1 signing instead, see [documentation](https://microsoft.github.io/CCF/main/use_apps/issue_commands.html#cose-sign1) for details.

## [4.0.0-rc1]

[4.0.0-rc1]: https://github.com/microsoft/CCF/releases/tag/ccf-4.0.0-rc1
Expand Down
15 changes: 0 additions & 15 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -512,21 +512,6 @@ if(BUILD_TESTS)
${CMAKE_CURRENT_SOURCE_DIR}/src/node/rpc/test/tx_status_test.cpp
)

add_unit_test(
proposal_id_test ${CMAKE_CURRENT_SOURCE_DIR}/src/js/wrap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/node/rpc/test/proposal_id_test.cpp
)
target_link_libraries(
proposal_id_test
PRIVATE ${CMAKE_THREAD_LIBS_INIT}
http_parser.host
sss.host
ccf_endpoints.host
ccfcrypto.host
quickjs.host
ccf_kv.host
)

add_unit_test(
node_frontend_test ${CMAKE_CURRENT_SOURCE_DIR}/src/js/wrap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/node/rpc/test/node_frontend_test.cpp
Expand Down
1 change: 0 additions & 1 deletion cmake/common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ set(CCF_ENDPOINTS_SOURCES
${CCF_DIR}/src/endpoints/authentication/cert_auth.cpp
${CCF_DIR}/src/endpoints/authentication/empty_auth.cpp
${CCF_DIR}/src/endpoints/authentication/jwt_auth.cpp
${CCF_DIR}/src/endpoints/authentication/sig_auth.cpp
${CCF_DIR}/src/enclave/enclave_time.cpp
${CCF_DIR}/src/indexing/strategies/seqnos_by_key_bucketed.cpp
${CCF_DIR}/src/indexing/strategies/seqnos_by_key_in_memory.cpp
Expand Down
7 changes: 0 additions & 7 deletions doc/build_apps/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ Policies
.. doxygenvariable:: ccf::user_cert_auth_policy
:project: CCF

.. doxygenvariable:: ccf::user_signature_auth_policy
:project: CCF

.. doxygenvariable:: ccf::jwt_auth_policy
:project: CCF

Expand All @@ -77,10 +74,6 @@ Identities
:project: CCF
:members:

.. doxygenstruct:: ccf::UserSignatureAuthnIdentity
:project: CCF
:members:

Supporting Types
----------------

Expand Down
2 changes: 0 additions & 2 deletions doc/build_apps/js_app_bundle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ Each endpoint object contains the following information:
is executed. An empty list indicates an unauthenticated endpoint which can be called by anyone. Possible entries are:

- ``"user_cert"``
- ``"user_signature"``
- ``"member_cert"``
- ``"member_signature"``
- ``"jwt"``
- ``"no_auth"``

Expand Down
28 changes: 0 additions & 28 deletions doc/governance/accept_recovery.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,34 +54,6 @@ A member proposes to recover the network and other members can vote on the propo
"state": "Accepted"
}

Or alternatively, with the old signature method:

.. code-block:: bash

$ scurl.sh https://<ccf-node-address>/gov/proposals --cacert service_cert.pem --signing-key member1_privk.pem --signing-cert member1_cert.pem --data-binary @transition_service_to_open.json -H "content-type: application/json"
{
"ballot_count": 0,
"proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377",
"proposer_id": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1",
"state": "Open"
}

$ scurl.sh https://<ccf-node-address>/gov/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots --cacert service_cert.pem --signing-key member2_privk.pem --signing-cert member2_cert.pem --data-binary @vote_accept.json -H "content-type: application/json"
{
"ballot_count": 1,
"proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377",
"proposer_id": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1",
"state": "Open"
}

$ scurl.sh https://<ccf-node-address>/gov/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots --cacert service_cert.pem --signing-key member3_privk.pem --signing-cert member3_cert.pem --data-binary @vote_accept.json -H "content-type: application/json"
{
"ballot_count": 2,
"proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377",
"proposer_id": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1",
"state": "Accepted"
}

Once the proposal to recover the network has passed under the rules of the :term:`Constitution`, the recovered service is ready for members to submit their recovery shares.

Note that the ``transition_service_to_open`` proposal takes two parameters: the previous and the next service identity (x509 certificates in PEM format). This is to ensure that the correct network is recovered and to facilitate auditing, as well as to avoid forks. The previous service identity is used to validate the snapshot the recovery node is started from; CCF will refuse to start from a snapshot where the signing node certificate is not endorsed by the previous service identity. Since both identities are recorded on the ledger with the proposal, it is always clear at which point the identity changed.
Expand Down
9 changes: 1 addition & 8 deletions doc/governance/adding_member.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,14 @@ First, the new member should update and retrieve the latest state digest via the
}


Then, the new member should sign the state digest returned by the :http:POST:`/gov/ack/update_state_digest` via the :http:POST:`/gov/ack` endpoint, using either the ``ccf_cose_sign1`` or ``scurl.sh`` utilities:
Then, the new member should sign the state digest returned by the :http:POST:`/gov/ack/update_state_digest` via the :http:POST:`/gov/ack` endpoint, using the ``ccf_cose_sign1`` utility:

.. code-block:: bash

$ ccf_cose_sign1 --ccf-gov-msg-type ack --ccf-gov-msg-created_at `date -Is` --signing-key new_member_privk.pem --signing-cert new_member_cert.pem --content request.json | \
curl https://<ccf-node-address>/gov/ack --cacert service_cert.pem --data-binary @- -H "content-type: application/cose"
true

Or alternatively:

.. code-block:: bash

$ scurl.sh https://<ccf-node-address>/gov/ack --cacert service_cert.pem --signing-key new_member_privk.pem --signing-cert new_member_cert.pem --header "Content-Type: application/json" --data-binary @request.json
true

Once the command completes, the new member becomes active and can take part in governance operations (e.g. creating a new proposal or voting for an existing one). You can verify the activation of the member at `/gov/members`.

.. code-block:: bash
Expand Down
56 changes: 0 additions & 56 deletions doc/governance/common_member_operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,34 +80,6 @@ To limit the scope of key compromise, members of the consortium can refresh the
"state": "Accepted"
}

Or alternatively, with the old signature method:

.. code-block:: bash

$ scurl.sh https://<ccf-node-address>/gov/proposals --cacert service_cert.pem --signing-key member1_privk.pem --signing-cert member1_cert.pem --data-binary @trigger_ledger_rekey.json -H "content-type: application/json"
{
"ballot_count": 0,
"proposal_id": "2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e",
"proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0",
"state": "Open"
}

$ scurl.sh https://<ccf-node-address>/gov/proposals/2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e/ballots --cacert service_cert.pem --signing-key member2_privk.pem --signing-cert member2_cert.pem --data-binary @vote_accept_1.json -H "content-type: application/json"
{
"ballot_count": 1,
"proposal_id": "2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e",
"proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0",
"state": "Open"
}

$ scurl.sh https://<ccf-node-address>/gov/proposals/2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e/ballots --cacert service_cert.pem --signing-key member3_privk --signing-cert member3_cert.pem --data-binary @vote_accept_1.json -H "content-type: application/json"
{
"ballot_count": 2,
"proposal_id": "2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e",
"proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0",
"state": "Accepted"
}

Once the proposal is accepted (``"state": "Accepted"``) it is immediately enacted. All subsequent transactions will be encrypted with a fresh new ledger encryption key.

Updating Recovery Threshold
Expand Down Expand Up @@ -162,34 +134,6 @@ The number of member shares required to restore the private ledger (``recovery_t
"state": "Accepted"
}

Or alternatively, with the old signature method:

.. code-block:: bash

$ scurl.sh https://<ccf-node-address>/gov/proposals --cacert service_cert.pem --signing-key member1_privk.pem --signing-cert member1_cert.pem --data-binary @set_recovery_threshold.json -H "content-type: application/json"
{
"ballot_count": 0,
"proposal_id": "b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8",
"proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0",
"state": "Open"
}

$ scurl.sh https://<ccf-node-address>/gov/proposals/b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8/ballots --cacert service_cert.pem --signing-key member2_privk.pem --signing-cert member2_cert.pem --data-binary @vote_accept_1.json -H "content-type: application/json"
{
"ballot_count": 1,
"proposal_id": "b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8",
"proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0",
"state": "Open"
}

$ scurl.sh https://<ccf-node-address>/gov/proposals/b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8/ballots --cacert service_cert.pem --signing-key member3_privk.pem --signing-cert member3_cert.pem --data-binary @vote_accept_1.json -H "content-type: application/json"
{
"ballot_count": 2,
"proposal_id": "b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8",
"proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0",
"state": "Accepted"
}

.. note:: The new recovery threshold has to be in the range between 1 and the current number of active recovery members.

Renewing Node Certificate
Expand Down
43 changes: 3 additions & 40 deletions doc/governance/hsm_keys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,45 +117,6 @@ Like ``ccf_cose_sign1``, the output can be sent directly to the service via curl
"state": "Open"
}

HTTP Signing
achamayou marked this conversation as resolved.
Show resolved Hide resolved
~~~~~~~~~~~~

The ``scurl.sh`` script can be used with the ``--print-digest-to-sign`` option to print the SHA384 to be signed as well as the required headers for HTTP signatures (following the `draft-cavage-http-signatures-12 <https://tools.ietf.org/html/draft-cavage-http-signatures-12>`_ scheme):

.. code-block:: bash

# First, retrieve the hash to be signed
$ scurl.sh https://<ccf-node-address>/gov/<endpoint> -X [GET|POST] --signing-cert $IDENTITY_CERT_NAME.pem --print-digest-to-sign
Hash to sign: <hash_to_sign> # To be signed by AKV
Request headers:
-H 'Digest: SHA-256=...'
-H 'Authorization: Signature keyId="...",algorithm="hs2019",headers="(request-target) digest content-length",signature="<insert_base64_signature_here>"' # Replace signature with AKV signature here
-H 'content-length: 0'

# Then, retrieve the kid url for the identity key
$ export IDENTITY_AKV_KID=$(az keyvault key show --vault-name $VAULT_NAME --name $IDENTITY_CERT_NAME --query key.kid --output tsv)

# Then, sign the request hash to be signed (as output by scurl.sh --print-digest-to-sign)
$ export base64url_signature=$(curl -s -X POST $IDENTITY_AKV_KID/sign?api-version=7.1 --data '{alg: "ES384", "value": "<hash_to_sign>"}' -H "Authorization: Bearer ${AZ_TOKEN}" -H "Content-Type: application/json" | jq -r .value)

.. note:: The signatures returned by AKV are returned as a `JWS signature <https://tools.ietf.org/html/rfc7518#section-3.4>`_ and encoded in `base64url <https://tools.ietf.org/html/rfc4648#section-5>`_ format and are not directly compatible with the signatures supported by CCF.

The :ccf_repo:`jws_to_der.py </doc/governance/jws_to_der.py>` Python script can be used to convert a JWS signature generated by AKV to a DER signature compatible with CCF:

.. code-block:: bash

$ pip install pyasn1
$ export ccf_signature=$(python3.8 jws_to_der.py $base64url_signature)

Finally, the signed HTTP request can be issued, using the request headers printed by ``scurl.sh --print-digest-to-sign``:

.. code-block:: bash

$ curl https://<ccf-node-address>/gov/<endpoint> -X [GET|POST] --cert $IDENTITY_CERT_NAME.pem \
-H 'Digest: SHA-256=...' \
-H 'Authorization: Signature keyId="...",algorithm="hs2019",headers="(request-target) digest content-length",signature="$ccf_signature"' \
-H 'content-length: <content-length>'

Recovery Share Decryption
-------------------------

Expand All @@ -168,4 +129,6 @@ The retrieved encrypted recovery share can be decrypted with the encryption key
$ az keyvault key decrypt --vault-name $VAULT_NAME --name $ENCRYPTION_KEY_NAME --algorithm RSA-OAEP-256 --value <base64_encrypted_share>
# Outputs base64 decrypted share

The decrypted recovery share can then be submitted to the CCF recovered service (see :ref:`governance/accept_recovery:Submitting Recovery Shares`).
The decrypted recovery share can then be submitted to the CCF recovered service (see :ref:`governance/accept_recovery:Submitting Recovery Shares`).

.. warning:: HTTP request signing could be used in previous versions of CCF, but has been removed as of 4.0, in favour of COSE Sign1.
53 changes: 0 additions & 53 deletions doc/governance/open_network.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,6 @@ Then, the certificates of trusted users should be registered in CCF via the memb
"state": "Open"
}

Or alternatively, with the old signature method:

.. code-block:: bash

$ scurl.sh https://<ccf-node-address>/gov/proposals --cacert service_cert.pem --signing-key member0_privk.pem --signing-cert member0_cert.pem --data-binary @set_user.json -H "content-type: application/json"
{
"ballot_count": 0,
"proposal_id": "f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253",
"proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0",
"state": "Open"
}

Other members are then allowed to vote for the proposal, using the proposal id returned to the proposer member. They may submit an unconditional approval, or their vote may query the current state and the proposed actions. These votes `must` be signed.

.. code-block:: bash
Expand All @@ -68,23 +56,6 @@ Other members are then allowed to vote for the proposal, using the proposal id r
"state": "Open"
}

Or alternatively, with the old signature method:

.. code-block:: bash

$ scurl.sh https://<ccf-node-address>/gov/proposals/f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253/ballots --cacert service_cert.pem --signing-key member1_privk.pem --signing-cert member1_cert.pem --data-binary @vote_accept.json -H "content-type: application/json"
{
"ballot_count": 1,
"proposal_id": "f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253",
"proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0",
"state": "Open"
}

$ cat vote_conditional.json
{
"ballot": "export function vote (proposal, proposerId) { return proposerId == \"2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0\" }"
}

.. code-block:: bash

$ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -Is` --ccf-gov-msg-proposal_id f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253 --signing-key member0_privk.pem --signing-cert member0_cert.pem --content vote_conditional.json | \
Expand All @@ -96,18 +67,6 @@ Or alternatively, with the old signature method:
"state": "Accepted"
}

Or alternatively, with the old signature method:

.. code-block:: bash

$ scurl.sh https://<ccf-node-address>/gov/proposals/f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253/ballots --cacert service_cert.pem --signing-key member2_privk.pem --signing-cert member2_cert.pem --data-binary @vote_conditional.json -H "content-type: application/json"
{
"ballot_count": 2,
"proposal_id": "f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253",
"proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0",
"state": "Accepted"
}

The user is successfully added once the proposal has received enough votes under the rules of the :term:`Constitution` (indicated by the response body showing a transition to state ``Accepted``).

The user can then make user RPCs.
Expand Down Expand Up @@ -193,18 +152,6 @@ Once users are added to the opening network, members should create a proposal to
"state": "Open"
}

Or alternatively, with the old signature method:

.. code-block:: bash

$ scurl.sh https://<ccf-node-address>/gov/proposals --cacert service_cert.pem --signing-key member0_privk.pem --signing-cert member0_cert.pem --data-binary @transition_service_to_open.json -H "content-type: application/json"
{
"ballot_count": 0,
"proposal_id": "77374e16de0b2d61f58aec84d01e6218205d19c9401d2df127d893ce62576b81",
"proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0",
"state": "Open"
}

Other members are then able to vote for the proposal using the returned proposal id.

Once the proposal has received enough votes under the rules of the :term:`Constitution` (ie. ballots which evaluate to ``true``), the network is opened to users. It is only then that users are able to execute transactions on the business logic defined by the enclave file (``enclave.file`` configuration entry).
Loading