Access Control & Permissioning¶
Dune Network provides several access control features:
- to control access to the services of the node (RPCs)
- to control access to the the network (for private/permissioned networks).
- to control access to the accounts (KYC)
Access Control to RPCs¶
Dune nodes provide a large set of RPCs to allow clients to interact with them. Some of these RPCs can expose the node to attackers, as they allow to change the settings of the node, or require expensive computations leading to possible D-DOS attacks.
Server-side Parameters¶
To protect nodes from such attacks, Dune provides two parameters that
can be set in the node configuration file, in the rpc
section:
- The
allow_public_access
parameter can be used to decide whether anybody should have access to the node ; - The
users
parameter can be used to define a list of login+password pairs that can have full access to the node;
Both parameters work together:
- If
allow_public_access
isfalse
(default), andusers
is empty (default), the node RPCs can only be accessed from the local host. This setting has become the default mode for the node; - If
allow_public_access
isfalse
, andusers
is not empty, the node RPCs can only be accessed by the users in users ; - If
allow_public_access
istrue
, andusers
is empty, all the node RPCs are available from anywhere and anybody. This was the former default setting for the node; - If
allow_public_access
istrue
, andusers
is not empty, only the users specified in users can access all the node RPCs, but a subset of the node RPCs is made available for public access. This subset has been chosen to include only computation-friendly requests, and non-sensible information. The public RPCs includes most of the ones needed for dune-client and dune-baker.
For now, authentication for the users parameter is done using the
Basic HTTP Authentication, supported by all browsers and web
clients. Since it sends the password in clear in the request, it is
advised to use https://
to encrypt the communication to the node.
Client-side Settings¶
On the client side, dune-client
provides a new parameter
users
in its configuration file. This parameter is a list of
associations between hosts and user-password pairs. Each pair is written
as one string with a :
between the user and password.
The argument --user LOGIN:PASSWORD
can also be used directly on
the command-line.
Full Example¶
The first thing we will do for this example is create a self-signed TLS certificate to encrypt RPCs. It’s not mandatory, and can make the requests slower, but it’s an additional level of security. For that, we use the OpenSSL library and tools:
openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem
This command will ask you many questions to generate a self-signed
certificate for your node. The most important one is the Common Name,
which should be your computer name or IP address. It generates two
files key.pem
and certificate.pem
.
Now, let’s write the configuration of our server in
~/.dune-node/config.json
:
{ "rpc":
{ "listen-addrs": [ "127.0.0.1:8733" ],
"cors-origin": [ "*" ],
"cors-headers": [ "content-type" ],
"key":"key.pem",
"crt": "certificate.pem",
"allow_public_access": false,
"users": [ [ "admin", "admXrpcX" ] ] },
"p2p": { "listen-addr": "[::]:9733" },
"shell":
{ "chain_validator": { "bootstrap_threshold": 1 },
"history_mode": "archive" }
}
In the rpc
section, the parameters key
and crt
have been
set to point to the TLS certificate files (in a real setting, these
should be absolute paths). We set allow_public_access
to
false
, and we define one user "admin"
with his password
"admXrpcX"
.
We can now run the server: dune-node run
We can then test a simple RPC:
wget --no-check-certificate https://localhost:8733/network/version
--2020-01-21 17:02:02-- https://localhost:8733/network/version
Resolving localhost (localhost)... ::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:8733... failed: Connection refused.
Connecting to localhost (localhost)|127.0.0.1|:8733... connected.
WARNING: The certificate of 'localhost' is not trusted.
WARNING: The certificate of 'localhost' hasn't got a known issuer.
HTTP request sent, awaiting response... 401 Unauthorized
Username/Password Authentication Failed.
The request complained about the self-signed certificate, of course
(we added --no-check-certificate
to avoid an immediate exit), but
finally, it fails because of the lack of authentication. Note that
this particular RPC would have succeeded if allow_public_access was
true, because it’s not a sensible one.
We can now test again with a user/password:
wget --user admin:admXrpcX --no-check-certificate https://localhost:8733/network/version
--2020-01-21 17:06:04-- https://localhost:8733/network/version
Resolving localhost (localhost)... ::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:8733... failed: Connection refused.
Connecting to localhost (localhost)|127.0.0.1|:8733... connected.
WARNING: The certificate of 'localhost' is not trusted.
WARNING: The certificate of 'localhost' hasn't got a known issuer.
HTTP request sent, awaiting response... 401 Unauthorized
Authentication selected: Basic realm="Dune"
Reusing existing connection to localhost:8733.
HTTP request sent, awaiting response... 200 OK
Length: 102 [application/json]
Saving to: 'version'
This time, the request succeeded.
Let’s try now with dune-client
. We can first try directly, using
command line arguments for TLS (-S
) and user (--user
):
dune-client -S --user admin:admXrpcX get balance for baker
Config: Testnet. Revision: 3
User config: "$HOME/.dune-client/config"
Node: https://localhost:8733 (user:admin)
470137.151878 đ
We can also modify the client configuration file ~/.dune-client/config
:
{ "base_dir": "$HOME/.dune-client",
"node_addr": "localhost", "node_port": 8733,
"web_port": 8080, "confirmations": 0,
"tls": true,
"users": [ [ "localhost:8733", "admin:admXrpcX" ] ]
}
We have set the tls
option to true to force https://
, and
added a user to be used for host localhost:8733 with the users
parameter.
We can now use a much simpler version on the command line:
dune-client get balance for baker
Config: Testnet. Revision: 3
User config: "$HOME/.dune-client/config"
Node: https://localhost:8733 (user:admin)
470137.151878 đ
Private/Permissioned Networks¶
Dune provides several ways to create a private network. The former way was to use the Private Mode that forced to statically specify the IP+port addresses of all the nodes in the network.
The following 3 new ways to create a private network have been added. They give more flexibility and expressiveness than the former mode:
- Shared Secret: a node can only connect to another one if it knows a shared secret with the other node;
- Closed Network: each node reads a configuration with the list of node identifiers allowed in the network;
- On-chain Access Control: the list of node identifiers is maintained on-chain. Any node can connect to another node, but not read data from the chain if its identifier is not in the list of allowed identifiers for that chain.
Note that the 3 mechanisms can be used separately or together. For all these mechanisms, a node will reject any node that is not using the same mechanisms, i.e. an open node will reject any connection from a closed-network node, and vice-versa. This prevents badly-configured nodes from entering a private network.
As an exception to the previous rule, it is possible to specify a list of node identifiers without being in a closed network. This mechanism can be used to limit a specific node to connect to a restricted set of other nodes. If used in combination with the Private Mode, all the node identifiers are marked as trusted.
Privacy by Closed Network¶
The second form of access control is more dynamic: when a network is configured as a Closed Network, the identity (node identifier) of every node must be known beforehand and listed in a configuration file. Revoking a node only requires to remove, on every other node, its identifier from the list and restarting the other node. Such an operation can be done without any risk of forking the network.
To configure a private network to become a Closed Network, the option
closed_network
must be set to true
in the network
configuration (the JSON file pointed to by DUNE_CONFIG
).
A file must contain the identifiers of all the nodes that can be
connected to a node of the network. The name of that file must be put
in the nodes_list
option of the p2p
section of the node
configuration. The filename can also be set in the nodes_list
option of the network configuration, but it’s probably less
convenient.
The nodes_list
file must contain a list of JSON nodes objects,
corresponding to the nodes, with two fields:
- A mandatory
peer_id
field associated to a string containing the identifier of the node (itself starting withid...
, and found in thepeer_id
field of theidentity.json
file of the node). - An optional
addr
field, associated to a string containing the address (IP or hostname, plus port) of the corresponding node.
Note that the addr
field is only used to find the node on the
network, it will not allow any node at this address to connect if
their identifier is not known.
A node in a Closed Network will only accept connections to and from nodes that are also in Closed Network mode, and with matching identifiers. However, there is no guarrantee that the list of nodes is the same one on all the nodes.
It is also possible to use the nodes_list
option to secure a node
in a public network (i.e. closed_network
is false
). In that
case, the node will only accept connections from the nodes list. All
nodes in the nodes list will be added to the set of trusted peers (and
trusted addresses if their addresses are provided).
Privacy by On-Chain Access Control¶
The last way to create a private network is to use the on-chain access control feature. The main benefit of on-chain access control is that the list of nodes is automatically maintained on-chain, so that all nodes have the same configuration, for any given block of the chain. Also, this feature does not prevent unauthorized nodes from connecting to nodes in the network. Instead, it prevents them from downloading the chain data and from sending data to the chain.
To use this feature, one of the two following options must be set to
true
:
- The
access_control
option in the network configuration file (file pointed to byDUNE_CONFIG
). - The
access_control
field of thep2p
section of the node configuration file.
Once the access_control
field is set to true
, the node will
only accept connections from other nodes with also the
access_control
field set. This feature can be combined with the
Shared Secret mode to keep the network cleaner.
Once in On-Chain Access Control mode, the node will only send any chain data to a node if it belongs to a list of identifiers. This list of identifiers being updated on-chain, the access to data depends on the list value at the level when a message is received or sent. In particular, a node that has been revoked might still have access to the chain state before the time when it was revoked, if the node has not yet received the blocks where it was revoked.
To change the list of peer identifiers (empty at the beginning),
Manage_accounts
operations must be used (by superadmin accounts),
with two different fields:
- The peer identifiers in the
allow_peer_ids
field will be added to the list - The peer identifiers in the
revoke_peer_ids
field will be removed from the list
It is also possible to control the list of allowed peer identifiers from a smart contract.
In Michelson, the two instructions
ALLOW_PEERS
andREVOKE_PEERS
have the following type:ALLOW_PEERS: string list : S -> operation : S REVOKE_PEERS: string list : S -> operation : S
They take a list of peer identifiers as argument, and return an operation to return that will add or revoke these peers.
The list of allowed peers at any given block can be retrieved from the node using the following RPC:
dune-client rpc get /chains/main/blocks/head/allowed_peer_ids
Access-Control for Accounts¶
In a private network, it is sometimes required to control precisely which accounts can send operations or receive tokens. A typical example is the need for the user to fill a KYC before accessing his account. Other examples are the superadmin role or the baker role in a private network.
Superadmin Account (Network Administration)¶
Dune Network can be administered using superadmin accounts. The superadmin accounts are the only ones authorized to perform the following operations:
- The
Activate_protocol
operation to change the protocol or the protocol constants - The
Manage_accounts
operation to change accounts’ rights
Initially, the superadmin account is specified in the network
configuration, in the genesis_key
field.
It is possible to add/revoke superadmin accounts, especially smart
contracts (for multisig validation for example). For that, the
current superadmin must use the actions
field of the
Manage_accounts
operation, with actions add_superadmin
or
remove_superadmin
:
{
"actions": [
[ "add_superadmin", "0", [ "dn1X1..", "dn1X2.." ] ],
[ "remove_superadmin", "0", [ "dn1X3..", "dn1X4.." ] ]
]
}
Baker Authorization (Proof-of-Authority)¶
It is possible to restrict which accounts can validate blocks in a private network, to get a Proof-of-Authority consensus (PoA).
For that, the option only_allowed_bakers
must be set to true
in
the network configuration (the file pointed to by DUNE_CONFIG
).
When this option is set:
- Bakers in the bootstrap accounts (accounts created when activating the protocol after the genesis block) are automatically added to the list of allowed bakers
- The
Manage_accounts
operation can be used to trigger actionsadd_allowed_bakers
andremove_allowed_bakers
to add or revoke allowed bakers.
Note that, to properly remove a baker, the maxrolls
parameter of
the baker should first be set to 0, 7 cycles before removing it from
the allowed bakers set. Otherwise, the baker will still have baking
rights, but will be prevented from baking.
In PoA, a baker can only register itself as a baker after being added to the allowed bakers.
In PoA, allowed bakers do not receive rewards for baking, and they don’t have to deposit.
Account Authorization (KYC)¶
To enable this feature, the kyc_level
option must be set to one of
these values in the network configuration file:
open
means that there is no KYC on the network. It is the default on the public network;source
means that the source account (dn1/2/3) of any signed operation must be authorized for the operation to succeed;both
means that the source account of any signed operation, and the destination (dn1/2/3) of any transfer, must be authorized for the operation to succeed.
To authorize or revoke authorized accounts, Manage_accounts operations must be used by superadmin accounts with the following fields:
- The
actions
field can contain several actionskyc_accounts
, the KYC level to authorize, and a list of accounts whose KYC should be changed
For example:
{
"actions": [
[ "kyc_accounts", "1", [ "dn1X1..", "dn1X2.." ] ],
[ "kyc_accounts", "0", [ "dn1X3..", "dn1X4.." ] ],
[ "kyc_accounts", "255", [ "dn1X5..", "dn1X6.." ] ]
]
}
The KYC level can be:
- 0 means that the account is not authorized
- 255 means that the account is authorized to do everything
It is possible to set the KYC using a binary-or between the following values:
- 1 means that the account is authorized to reveal its public key
- 2 means that the account is authorized to receive tokens (only checked
in
both
mode) - 4 means that the account is authorized to transfer or call
- 8 means that the account is authorized to delegate
- 16 means that the account is authorized to originate contracts
- 32 means that the account is authorized to manage its parameters
- 64 and 128 are not yet used
A smart contract can use the following instructions to manage KYC:
In Michelson, the instruction
ADMIN_ACCOUNTS
has the type:ADMIN_ACCOUNTS: string : mudun : address list : S -> operation : S
and can be called with the string
"kyc_accounts"
and an amount corresponding to the value of the KYC.