Skip to content

Commit

Permalink
Support for Signer Authorized Keys
Browse files Browse the repository at this point in the history
Authorized key is the tezos native method to authenticate signing
requests, one that we use in the new tezos-kms-signer-lambda.

This adds the required support on tezos-k8s to sign with such a signer.

The way it works in octez is:

* when the baker/client connects to the signer for the first time,
  signer answers with a list of "authorized_keys" that the signature
  request must be signed with. These authorized keys are just tezos
  accounts
* if the baker/client has the secret key for one of these authorized
  keys, they will just sign every request with it. otherwise, there will
  be an error
* this can't be nested. the authorized_key can't be remote

We add support in tezos-k8s by assuming the authorized_keys are just
standard "accounts". Then, you may configure a baker as follows:

```
nodes:
  mybaker:
    bake_using_accounts:
    - mybakeraddy
    authorized_keys:
    - my_authorized_key
```

config-generator then ensures that the private authorized key is
accessible to the baker.

We also add support on octez-signer end:

```
octezSigners:
  mysigner:
    sign_for_accounts:
    - mybakeraddy
    authorized_keys:
    - my_authorized_key
```

When set, the signer mandates requests to be authenticated. Otherwise,
it signs anything.

This way, you can test end-to-end in a private chain.

We modify mkchain to do this by default: mkchain now generates an
authorized key and uses it to sign by default.

Also, mkchain was previously defaulting to using one remote signer, but
this broke when adding support for tacoInfra signer. I fixed it.

I have tested it with 3 bakers and 2 signers, one authorized and one
not. It's all working. I haven't tried zerotier and public chains.

Other changes:

* switch default version to 17.3
* no magic byte restriction from signer - prevents activation
  • Loading branch information
nicolasochem committed Oct 24, 2023
1 parent cc77815 commit 5afa03f
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 21 deletions.
6 changes: 5 additions & 1 deletion charts/tezos/scripts/remote-signer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ CLIENT_DIR="$TEZ_VAR/client"
NODE_DIR="$TEZ_VAR/node"
NODE_DATA_DIR="$TEZ_VAR/node/data"

CMD="$TEZ_BIN/octez-signer -d $CLIENT_DIR launch http signer --magic-bytes 0x11,0x12,0x13 --check-high-watermark -a 0.0.0.0 -p 6732"
extra_args=""
if [ -f ${CLIENT_DIR}/authorized_keys ]; then
extra_args="${extra_args} --require-authentication"
fi
CMD="$TEZ_BIN/octez-signer -d $CLIENT_DIR ${extra_args} launch http signer -a 0.0.0.0 -p 6732"

# ensure we can run tezos-signer commands without specifying client dir
ln -s /var/tezos/client /home/tezos/.tezos-signer
Expand Down
6 changes: 5 additions & 1 deletion charts/tezos/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ is_invitation: false

# Images not part of the tezos-k8s repo go here
images:
octez: tezos/tezos:v17.1
octez: tezos/tezos:v17.3
tacoinfraRemoteSigner: ghcr.io/oxheadalpha/tacoinfra-remote-signer:0.1.0
# Images that are part of the tezos-k8s repo go here with 'dev' tag
tezos_k8s_images:
Expand Down Expand Up @@ -174,6 +174,7 @@ should_generate_unsafe_deterministic_data: false
# Don't also set `bake_using_accounts`.
# - `bake_using_accounts`: List of account names that should be used for baking.
# Don't also set `bake_using_account`.
# - `authorized_keys`: List of account names available to the baker to sign signature requests.
# - `config`: Same as the outer statefulset level `config`. It overrides the
# statefulset level.
# - `is_bootstrap_node`: Boolean for is this node a bootstrap peer.
Expand Down Expand Up @@ -314,6 +315,9 @@ octezSigners: {}
# tezos-signer-0:
# accounts:
# - baker0
# authorized_keys:
# # if set, baker will only sign request authenticated by one of the authorized_keys
# - authorized_key0
# ```
#
# Deploys a signer using AWS KMS to sign operations.
Expand Down
2 changes: 1 addition & 1 deletion mkchain/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ You can explicitly specify some values by:
| | --number-of-nodes | Number of non-baking nodes in the cluster | 0 |
| bootstrap_peers | --bootstrap-peers | Peer ips to connect to | [] |
| expected_proof_of_work | --expected-proof-of-work | Node identity generation difficulty | 0 |
| images.octez | --octez-docker-image | Version of the Octez docker image to run | tezos/tezos:v17.1 |
| images.octez | --octez-docker-image | Version of the Octez docker image to run | tezos/tezos:v17.3 |
| | --use-docker (--no...) | Use (or don't use) docker to generate keys rather than pytezos | autodetect |
| zerotier_config.zerotier_network | --zerotier-network | Zerotier network id for external chain access | |
| zerotier_config.zerotier_token | --zerotier-token | Zerotier token for external chain access | |
Expand Down
14 changes: 8 additions & 6 deletions mkchain/tqchain/mkchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def quoted_scalar(dumper, data): # a representer to force quotations on scalars
},
"octez_docker_image": {
"help": "Version of the Octez docker image",
"default": "tezos/tezos:v17.1",
"default": "tezos/tezos:v17.3",
},
"use_docker": {
"action": "store_true",
Expand Down Expand Up @@ -154,6 +154,7 @@ def node_config(name, n, is_baker):
"shell": {"history_mode": "rolling"},
"metrics_addr": [":9932"],
},
"authorized_keys": ["authorized-key-0"],
}
if is_baker:
ret["bake_using_accounts"] = [f"{name}-{n}"]
Expand Down Expand Up @@ -243,7 +244,7 @@ def main():
baking_accounts = {
f"{ARCHIVE_BAKER_NODE_NAME}-{n}": {} for n in range(args.number_of_bakers)
}
for account in baking_accounts:
for account in [*baking_accounts, *["authorized-key-0"]]:
print(f"Generating keys for account {account}")
keys = gen_key(args.octez_docker_image)
for key_type in keys:
Expand Down Expand Up @@ -275,11 +276,12 @@ def main():
],
}

signers = {
octezSigners = {
"tezos-signer-0": {
"sign_for_accounts": [
"accounts": [
f"{ARCHIVE_BAKER_NODE_NAME}-{n}" for n in range(args.number_of_bakers)
]
],
"authorized_keys": ["authorized-key-0"],
}
}

Expand Down Expand Up @@ -308,7 +310,7 @@ def main():
**base_constants,
"bootstrap_peers": bootstrap_peers,
"accounts": accounts["secret"],
"signers": signers,
"octezSigners": octezSigners,
"nodes": creation_nodes,
**activation,
}
Expand Down
10 changes: 5 additions & 5 deletions test/charts/mainnet.expect.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ data:
ARCHIVE_TARBALL_URL: ""
PREFER_TARBALLS: "false"
SNAPSHOT_SOURCE: "https://xtz-shots.io/tezos-snapshots.json"
OCTEZ_VERSION: "tezos/tezos:v17.1"
OCTEZ_VERSION: "tezos/tezos:v17.3"
NODE_GLOBALS: |
{
"config": {},
Expand Down Expand Up @@ -128,7 +128,7 @@ spec:
spec:
containers:
- name: octez-node
image: "tezos/tezos:v17.1"
image: "tezos/tezos:v17.3"
imagePullPolicy: IfNotPresent
command:
- /bin/sh
Expand Down Expand Up @@ -213,7 +213,7 @@ spec:
memory: 80Mi
initContainers:
- name: config-init
image: "tezos/tezos:v17.1"
image: "tezos/tezos:v17.3"
imagePullPolicy: IfNotPresent
command:
- /bin/sh
Expand Down Expand Up @@ -324,7 +324,7 @@ spec:
- mountPath: /var/tezos
name: var-volume
- name: snapshot-importer
image: "tezos/tezos:v17.1"
image: "tezos/tezos:v17.3"
imagePullPolicy: IfNotPresent
command:
- /bin/sh
Expand Down Expand Up @@ -387,7 +387,7 @@ spec:
- mountPath: /var/tezos
name: var-volume
- name: upgrade-storage
image: "tezos/tezos:v17.1"
image: "tezos/tezos:v17.3"
imagePullPolicy: IfNotPresent
command:
- /bin/sh
Expand Down
10 changes: 5 additions & 5 deletions test/charts/mainnet2.expect.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ data:
ARCHIVE_TARBALL_URL: ""
PREFER_TARBALLS: "false"
SNAPSHOT_SOURCE: "https://xtz-shots.io/tezos-snapshots.json"
OCTEZ_VERSION: "tezos/tezos:v17.1"
OCTEZ_VERSION: "tezos/tezos:v17.3"
NODE_GLOBALS: |
{
"config": {},
Expand Down Expand Up @@ -195,7 +195,7 @@ spec:
spec:
containers:
- name: octez-node
image: "tezos/tezos:v17.1"
image: "tezos/tezos:v17.3"
imagePullPolicy: IfNotPresent
command:
- /bin/sh
Expand Down Expand Up @@ -316,7 +316,7 @@ spec:
memory: 80Mi
initContainers:
- name: config-init
image: "tezos/tezos:v17.1"
image: "tezos/tezos:v17.3"
imagePullPolicy: IfNotPresent
command:
- /bin/sh
Expand Down Expand Up @@ -433,7 +433,7 @@ spec:
- mountPath: /var/tezos
name: var-volume
- name: snapshot-importer
image: "tezos/tezos:v17.1"
image: "tezos/tezos:v17.3"
imagePullPolicy: IfNotPresent
command:
- /bin/sh
Expand Down Expand Up @@ -498,7 +498,7 @@ spec:
- mountPath: /var/tezos
name: var-volume
- name: upgrade-storage
image: "tezos/tezos:v17.1"
image: "tezos/tezos:v17.3"
imagePullPolicy: IfNotPresent
command:
- /bin/sh
Expand Down
6 changes: 5 additions & 1 deletion test/charts/private-chain.expect.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1561,7 +1561,11 @@ spec:
NODE_DIR="$TEZ_VAR/node"
NODE_DATA_DIR="$TEZ_VAR/node/data"
CMD="$TEZ_BIN/octez-signer -d $CLIENT_DIR launch http signer --magic-bytes 0x11,0x12,0x13 --check-high-watermark -a 0.0.0.0 -p 6732"
extra_args=""
if [ -f ${CLIENT_DIR}/authorized_keys ]; then
extra_args="${extra_args} --require-authentication"
fi
CMD="$TEZ_BIN/octez-signer -d $CLIENT_DIR ${extra_args} launch http signer -a 0.0.0.0 -p 6732"
# ensure we can run tezos-signer commands without specifying client dir
ln -s /var/tezos/client /home/tezos/.tezos-signer
Expand Down
19 changes: 18 additions & 1 deletion utils/config-generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,11 @@ def expose_secret_key(account_name):
pod. It returns the obvious Boolean.
"""
if MY_POD_TYPE == "activating":
all_authorized_keys = [key for node in NODES.values() for instance in node['instances'] for key in instance.get('authorized_keys', [])]
if account_name in all_authorized_keys:
# populate all known authorized keys in the activation account.
# This avoids annoying edge cases for activating private chains, when security is not critical.
return True
return NETWORK_CONFIG["activation_account_name"] == account_name

if MY_POD_TYPE == "signing":
Expand All @@ -340,6 +345,8 @@ def expose_secret_key(account_name):
if MY_POD_TYPE == "node":
if MY_POD_CONFIG.get("bake_using_account", "") == account_name:
return True
if account_name in MY_POD_CONFIG.get("authorized_keys", {}):
return True
return account_name in MY_POD_CONFIG.get("bake_using_accounts", {})

return False
Expand Down Expand Up @@ -419,6 +426,7 @@ def import_keys(all_accounts):
secret_keys = []
public_keys = []
public_key_hashs = []
authorized_keys = []

for account_name, account_values in all_accounts.items():
print("\n Importing keys for account: " + account_name)
Expand Down Expand Up @@ -453,6 +461,11 @@ def import_keys(all_accounts):
public_key_hashs.append({"name": account_name, "value": pkh_b58})
account_values["pkh"] = pkh_b58

if MY_POD_TYPE == "signing" and \
account_name in MY_POD_CONFIG.get("authorized_keys", {}):
print(f" Appending authorized key: {pk_b58}")
authorized_keys.append({"name": account_name, "value": pk_b58})

print(f" Account key type: {account_values.get('type')}")
print(
f" Account bootstrap balance: "
Expand All @@ -463,17 +476,21 @@ def import_keys(all_accounts):
+ f"{account_values.get('is_bootstrap_baker_account', False)}"
)

sk_path, pk_path, pkh_path = (
sk_path, pk_path, pkh_path, ak_path = (
f"{tezdir}/secret_keys",
f"{tezdir}/public_keys",
f"{tezdir}/public_key_hashs",
f"{tezdir}/authorized_keys",
)
print(f"\n Writing {sk_path}")
json.dump(secret_keys, open(sk_path, "w"), indent=4)
print(f" Writing {pk_path}")
json.dump(public_keys, open(pk_path, "w"), indent=4)
print(f" Writing {pkh_path}")
json.dump(public_key_hashs, open(pkh_path, "w"), indent=4)
if MY_POD_TYPE == "signing" and len(authorized_keys) > 0:
print(f" Writing {ak_path}")
json.dump(authorized_keys, open(ak_path, "w"), indent=4)


def create_node_identity_json():
Expand Down

0 comments on commit 5afa03f

Please sign in to comment.