Kubernetes
Multiple RSTUF API instances/replicas can be deployed in a distributed environment to support multiple requests.
This example uses Kubernetes
Note
This deployment guide does not show the Kubernetes cluster configuration.
It requires a Kubernetes cluster running with kubectl
configured.
Note
For this deployment Redis is used as the message queue/broker.
Warning
This deployment does not have Authentication/Authorization for the API.
This API is fully accessible for unauthorized users. Consider using an API Authentication/Authorization service.
Note
See the complete Deployment Configuration for in-depth details.
Requirements
Software and tools
Kubernetes Cluster
kubectl
Python >= 3.10
pip
Online Key
This deployment requires the Online Key. See the chapter Signing Keys
Skip if the online key has been generated.
RSTUF Command Line Interface (CLI) provides a feature for Key Generation (generate)
This command will generate cryptographic keys using the securesystemslib
library.
The user is requested to provide:
the key type, from the supported list of encryption algorithms
the key’s filename, whose path will be the current working directory
a password, to encrypt the private key file
After the above procedure, two files, the private and public key
(e.g., id_ed25519
and id_ed25519.pub
), will be generated in the current
working directory.
The generated keys may be used in the Repository Service for TUF Ceremony
process, for the online key or the TUF roles’ keys (root
, targets
, etc. keys).
❯ rstuf key generate
Choose key type [ed25519/ecdsa/rsa] (ed25519): ed25519
Enter the key's filename: (id_ed25519): id_ed25519
Enter password to encrypt private key file 'id_ed25519':
Confirm:
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Key ID ┃ Key Type ┃ Public Key ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ f2f9f111b4a8dfb3766c8066628c81bd3aef42b34… │ ed25519 │ bb713c55bbf9b13ff7f92193af55b2f65ae15e55… │
└────────────────────────────────────────────┴──────────┴───────────────────────────────────────────┘
Show relevant information about a key.
❯ rstuf key info --help
Usage: rstuf key info [OPTIONS]
Show key information
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮
│ --show-private Show the private key. WARNING: use private key information carefully. │
│ --help -h Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
Artifact Management (artifact
)
Manages artifacts using the RSTUF REST API.
❯ rstuf artifact
Usage: rstuf artifact [OPTIONS] COMMAND [ARGS]...
Artifact Management Commands
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮
│ --help -h Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ───────────────────────────────────────────────────────────────────────────────────────╮
│ add Add artifacts to the TUF metadata. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
Artifact Addition (add
)
This command adds the provided artifact to the TUF Metadata using the RSTUF REST API.
❯ rstuf artifact add --help
Usage: rstuf artifact add [OPTIONS] FILEPATH
Add artifacts to the TUF metadata.
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮
│ --path -p TEXT A custom path (`TARGETPATH`) for the file, defined in the metadata. [required] │
│ --help -h Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
Artifact Download (download
)
This command allows downloading an artifact from a provided repository using the RSTUF REST API.
> rstuf artifact download --help
Usage: rstuf artifact download [OPTIONS] ARTIFACT_NAME
Downloads an artifact using TUF metadata from a given artifacts URL.
Note: all options for this command can be configured.
Read 'rstuf artifact repository' documentation for more information.
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮
│ --root -r TEXT A metadata URL to the initial trusted root or a local file. │
│ --metadata-url -m TEXT TUF Metadata repository URL. │
│ --artifacts-url -a TEXT An artifacts base URL to fetch from. │
│ --hash-prefix -p A flag to prefix an artifact with a hash. │
│ --directory-prefix -P TEXT A prefix for the download dir. │
│ --help -h Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
Artifact Repository (repository
)
This command provides artifact repository management for the RSTUF repository config.
❯ rstuf artifact repository --help
Usage: rstuf artifact repository [OPTIONS] COMMAND [ARGS]...
Repository management.
╭─ Options ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --help -h Show this message and exit. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ delete Delete a repository. │
│ add Add a new repository. │
│ show List configured repositories. │
│ update Update repository. │
│ set Switch current repository. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
❯ rstuf artifact repository delete --help
Usage: rstuf artifact repository delete [OPTIONS] REPOSITORY
Delete a repository.
❯ rstuf artifact repository add --help
Usage: rstuf artifact repository add [OPTIONS]
Add a new repository.
╭─ Options ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --name -n TEXT The repository name. [required] │
│ * --root -r TEXT The metadata URL to the initial trusted root or a local file. [required] │
│ * --metadata-url -m TEXT TUF Metadata repository URL. [required] │
│ * --artifacts-url -a TEXT The artifacts base URL to fetch from. [required] │
│ --hash-prefix -p Whether to add a hash prefix to artifact names. │
│ --help -h Show this message and exit. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
❯ rstuf artifact repository show --help
Usage: rstuf artifact repository show [OPTIONS] [REPOSITORY]
List configured repositories.
❯ rstuf artifact repository update --help
Usage: rstuf artifact repository update [OPTIONS] REPOSITORY
Update repository.
╭─ Options ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --root -r TEXT The metadata URL to the initial trusted root or a local file. │
│ --metadata-url -m TEXT TUF Metadata repository URL. │
│ --artifacts-url -a TEXT The artifacts base URL to fetch from. │
│ --hash-prefix -p Whether to add a hash prefix to artifact names. │
│ --help -h Show this message and exit. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
❯ rstuf artifact repository set --help
Usage: rstuf artifact repository set [OPTIONS] REPOSITORY
Switch current repository.
Task Management (task
)
Manages tasks using the RSTUF REST API.
❯ rstuf task
Usage: rstuf task [OPTIONS] COMMAND [ARGS]...
Task Management Commands
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮
│ --help -h Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ───────────────────────────────────────────────────────────────────────────────────────╮
│ info Retrieve task state. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
Task Information (info
)
This command retrieves the task state of the given task ID using the RSTUF REST API.
❯ rstuf task info --help
Usage: rstuf task info [OPTIONS] TASK_ID
Retrieve task state.
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮
│ --api-server TEXT RSTUF API URL, i.e., http://127.0.0.1 │
│ --help -h Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
Secrets
Caution
Do not use this credential, it is just an example.
onlinekey secret
Generating the secrets for RSTUF Online Key
Get the key content and encode it to base 64
❯ base64 -i tests/files/key_storage/online.key
YWI2ODU0YzE5MjlmNjYxNTc4MTBhNDBjMjQ1ZGU0NGJAQEBAMTAwMDAwQEBAQGUxZTk4MzMyZTZiYmNkM2M2ZjdmMGFiZjczNTdmNDNmZGJhN2QwMTRkYzYwMDk2YzNkODRkZjIyYTc3NDUwYmVAQEBANDgxNWEzNTgxZTBmNGM3MDU2OThmZTczMmE2ZWEwNDRAQEBAMmJmYjEwMmNjZTg4OWE0ZWRmZDA0YjU0NGQ1MTE2M2FjNGU0NTY4OWU3NmU3ZTdlZTNmMDQ3ZmE0MTQwM2ZiNmViYzI3MDdjMjM3NzgyNjJkNTQwMGU3YWZlYmQ4MWQ0NmE2OWEwZGUwOWZmNjk0N2Y0YzlkY2QzMzkwODlhYTkyNDA0NTI2M2ZjODg0Yzg1MDFiN2NjYjU5MDZjZTMzYjcyY2JkMDc1NWYwYjhhMzVlYzc1M2E1MDAyMmNkM2RkZDU5MjcxMGQyNjlhYjk0ZjMzOTBhYjVmOWZjNTRlOGUzZGJmMzBjMGUxNjNmYmRhYWQ3NzViMjE4MzdmMzcwODdkNDAxN2NhYjA2YjU1NjI1NmE5ODQwNjBmYmEwMWQ5ZDQ0MjdiNzQ1OTZiODQ5N2RmYjM3ZWRiMTUwZmE2OThkMmNiNzVmYWVkYjhiNTFiZmRjZjUwZDNhM2JlNDM3MThkM2FkM2E1YTU5MTNlY2YyNTA4NzUzYTAxOGVlM2Y5NTI0MmRhNjhjMmMyZjYxNDlmZGJkMmU4OGQ1OTBmYmY0N2YzYTE0MWJhMDVkMjRhYTA1MDg1Mjg3NDMwZDg0MmQwZmI3NmE0YzBjNjgxN2ZkNmVjYjM1NGM1YmNmZWUyYTk4NTRhNTc4NTMwYTI4ZDkxMDE4MzYxMmZhYzBiMjkwMmM1ZGNmODI3ZTA0YTkwODIwYmRhNGYyNWJkMjYzMWQ2ODlmYWYwMWM4MTMzNWI2OGMzYjkwMjEzYjlhMDRjNWFjZGM5OTdmNTA1YmJkNDA5NzZiNTU2Y2NhNmEzYjU0ZjI3MGE3ZWI2YjBkOWI2ZjE5YmUyOWQ2YWI4ZDRhMzFhZWRmYmI3MmE0YzhjZDk2Y2ExY2JmZmU5MDExOGJh
Create a base 64 entry for the secrets. See
LocalKeyVault
in RSTUF_KEYVAULT_BACKEND
❯ echo -n "base64|YWI2ODU0YzE5MjlmNjYxNTc4MTBhNDBjMjQ1ZGU0NGJAQEBAMTAwMDAwQEBAQGUxZTk4MzMyZTZiYmNkM2M2ZjdmMGFiZjczNTdmNDNmZGJhN2QwMTRkYzYwMDk2YzNkODRkZjIyYTc3NDUwYmVAQEBANDgxNWEzNTgxZTBmNGM3MDU2OThmZTczMmE2ZWEwNDRAQEBAMmJmYjEwMmNjZTg4OWE0ZWRmZDA0YjU0NGQ1MTE2M2FjNGU0NTY4OWU3NmU3ZTdlZTNmMDQ3ZmE0MTQwM2ZiNmViYzI3MDdjMjM3NzgyNjJkNTQwMGU3YWZlYmQ4MWQ0NmE2OWEwZGUwOWZmNjk0N2Y0YzlkY2QzMzkwODlhYTkyNDA0NTI2M2ZjODg0Yzg1MDFiN2NjYjU5MDZjZTMzYjcyY2JkMDc1NWYwYjhhMzVlYzc1M2E1MDAyMmNkM2RkZDU5MjcxMGQyNjlhYjk0ZjMzOTBhYjVmOWZjNTRlOGUzZGJmMzBjMGUxNjNmYmRhYWQ3NzViMjE4MzdmMzcwODdkNDAxN2NhYjA2YjU1NjI1NmE5ODQwNjBmYmEwMWQ5ZDQ0MjdiNzQ1OTZiODQ5N2RmYjM3ZWRiMTUwZmE2OThkMmNiNzVmYWVkYjhiNTFiZmRjZjUwZDNhM2JlNDM3MThkM2FkM2E1YTU5MTNlY2YyNTA4NzUzYTAxOGVlM2Y5NTI0MmRhNjhjMmMyZjYxNDlmZGJkMmU4OGQ1OTBmYmY0N2YzYTE0MWJhMDVkMjRhYTA1MDg1Mjg3NDMwZDg0MmQwZmI3NmE0YzBjNjgxN2ZkNmVjYjM1NGM1YmNmZWUyYTk4NTRhNTc4NTMwYTI4ZDkxMDE4MzYxMmZhYzBiMjkwMmM1ZGNmODI3ZTA0YTkwODIwYmRhNGYyNWJkMjYzMWQ2ODlmYWYwMWM4MTMzNWI2OGMzYjkwMjEzYjlhMDRjNWFjZGM5OTdmNTA1YmJkNDA5NzZiNTU2Y2NhNmEzYjU0ZjI3MGE3ZWI2YjBkOWI2ZjE5YmUyOWQ2YWI4ZDRhMzFhZWRmYmI3MmE0YzhjZDk2Y2ExY2JmZmU5MDExOGJh,strongPassword" | base64
YmFzZTY0fFlXSTJPRFUwWXpFNU1qbG1Oall4TlRjNE1UQmhOREJqTWpRMVpHVTBOR0pBUUVCQU1UQXdNREF3UUVCQVFHVXhaVGs0TXpNeVpUWmlZbU5rTTJNMlpqZG1NR0ZpWmpjek5UZG1ORE5tWkdKaE4yUXdNVFJrWXpZd01EazJZek5rT0RSa1pqSXlZVGMzTkRVd1ltVkFRRUJBTkRneE5XRXpOVGd4WlRCbU5HTTNNRFUyT1RobVpUY3pNbUUyWldFd05EUkFRRUJBTW1KbVlqRXdNbU5qWlRnNE9XRTBaV1JtWkRBMFlqVTBOR1ExTVRFMk0yRmpOR1UwTlRZNE9XVTNObVUzWlRkbFpUTm1NRFEzWm1FME1UUXdNMlppTm1WaVl6STNNRGRqTWpNM056Z3lOakprTlRRd01HVTNZV1psWW1RNE1XUTBObUUyT1dFd1pHVXdPV1ptTmprME4yWTBZemxrWTJRek16a3dPRGxoWVRreU5EQTBOVEkyTTJaak9EZzBZemcxTURGaU4yTmpZalU1TURaalpUTXpZamN5WTJKa01EYzFOV1l3WWpoaE16VmxZemMxTTJFMU1EQXlNbU5rTTJSa1pEVTVNamN4TUdReU5qbGhZamswWmpNek9UQmhZalZtT1daak5UUmxPR1V6WkdKbU16QmpNR1V4TmpObVltUmhZV1EzTnpWaU1qRTRNemRtTXpjd09EZGtOREF4TjJOaFlqQTJZalUxTmpJMU5tRTVPRFF3TmpCbVltRXdNV1E1WkRRME1qZGlOelExT1RaaU9EUTVOMlJtWWpNM1pXUmlNVFV3Wm1FMk9UaGtNbU5pTnpWbVlXVmtZamhpTlRGaVptUmpaalV3WkROaE0ySmxORE0zTVRoa00yRmtNMkUxWVRVNU1UTmxZMll5TlRBNE56VXpZVEF4T0dWbE0yWTVOVEkwTW1SaE5qaGpNbU15WmpZeE5EbG1aR0prTW1VNE9HUTFPVEJtWW1ZME4yWXpZVEUwTVdKaE1EVmtNalJoWVRBMU1EZzFNamczTkRNd1pEZzBNbVF3Wm1JM05tRTBZekJqTmpneE4yWmtObVZqWWpNMU5HTTFZbU5tWldVeVlUazROVFJoTlRjNE5UTXdZVEk0WkRreE1ERTRNell4TW1aaFl6QmlNamt3TW1NMVpHTm1PREkzWlRBMFlUa3dPREl3WW1SaE5HWXlOV0prTWpZek1XUTJPRGxtWVdZd01XTTRNVE16TldJMk9HTXpZamt3TWpFellqbGhNRFJqTldGalpHTTVPVGRtTlRBMVltSmtOREE1TnpaaU5UVTJZMk5oTm1FellqVTBaakkzTUdFM1pXSTJZakJrT1dJMlpqRTVZbVV5T1dRMllXSTRaRFJoTXpGaFpXUm1ZbUkzTW1FMFl6aGpaRGsyWTJFeFkySm1abVU1TURFeE9HSmgsc3Ryb25nUGFzc3dvcmQ=
postgrespassword secret
Generating the secrets for Postgres password
❯ echo -n "PostgreSQLstrongPassword" | base64
UG9zdGdyZVNRTHN0cm9uZ1Bhc3N3b3Jk
Secrets example
k8s/secrets.yml
1##########################################
2# SECRETS
3##########################################
4# RSTUF online key password
5apiVersion: v1
6kind: Secret
7metadata:
8 name: onlinekey
9type: Opaque
10data:
11 keys: YmFzZTY0fFlXSTJPRFUwWXpFNU1qbG1Oall4TlRjNE1UQmhOREJqTWpRMVpHVTBOR0pBUUVCQU1UQXdNREF3UUVCQVFHVXhaVGs0TXpNeVpUWmlZbU5rTTJNMlpqZG1NR0ZpWmpjek5UZG1ORE5tWkdKaE4yUXdNVFJrWXpZd01EazJZek5rT0RSa1pqSXlZVGMzTkRVd1ltVkFRRUJBTkRneE5XRXpOVGd4WlRCbU5HTTNNRFUyT1RobVpUY3pNbUUyWldFd05EUkFRRUJBTW1KbVlqRXdNbU5qWlRnNE9XRTBaV1JtWkRBMFlqVTBOR1ExTVRFMk0yRmpOR1UwTlRZNE9XVTNObVUzWlRkbFpUTm1NRFEzWm1FME1UUXdNMlppTm1WaVl6STNNRGRqTWpNM056Z3lOakprTlRRd01HVTNZV1psWW1RNE1XUTBObUUyT1dFd1pHVXdPV1ptTmprME4yWTBZemxrWTJRek16a3dPRGxoWVRreU5EQTBOVEkyTTJaak9EZzBZemcxTURGaU4yTmpZalU1TURaalpUTXpZamN5WTJKa01EYzFOV1l3WWpoaE16VmxZemMxTTJFMU1EQXlNbU5rTTJSa1pEVTVNamN4TUdReU5qbGhZamswWmpNek9UQmhZalZtT1daak5UUmxPR1V6WkdKbU16QmpNR1V4TmpObVltUmhZV1EzTnpWaU1qRTRNemRtTXpjd09EZGtOREF4TjJOaFlqQTJZalUxTmpJMU5tRTVPRFF3TmpCbVltRXdNV1E1WkRRME1qZGlOelExT1RaaU9EUTVOMlJtWWpNM1pXUmlNVFV3Wm1FMk9UaGtNbU5pTnpWbVlXVmtZamhpTlRGaVptUmpaalV3WkROaE0ySmxORE0zTVRoa00yRmtNMkUxWVRVNU1UTmxZMll5TlRBNE56VXpZVEF4T0dWbE0yWTVOVEkwTW1SaE5qaGpNbU15WmpZeE5EbG1aR0prTW1VNE9HUTFPVEJtWW1ZME4yWXpZVEUwTVdKaE1EVmtNalJoWVRBMU1EZzFNamczTkRNd1pEZzBNbVF3Wm1JM05tRTBZekJqTmpneE4yWmtObVZqWWpNMU5HTTFZbU5tWldVeVlUazROVFJoTlRjNE5UTXdZVEk0WkRreE1ERTRNell4TW1aaFl6QmlNamt3TW1NMVpHTm1PREkzWlRBMFlUa3dPREl3WW1SaE5HWXlOV0prTWpZek1XUTJPRGxtWVdZd01XTTRNVE16TldJMk9HTXpZamt3TWpFellqbGhNRFJqTldGalpHTTVPVGRtTlRBMVltSmtOREE1TnpaaU5UVTJZMk5oTm1FellqVTBaakkzTUdFM1pXSTJZakJrT1dJMlpqRTVZbVV5T1dRMllXSTRaRFJoTXpGaFpXUm1ZbUkzTW1FMFl6aGpaRGsyWTJFeFkySm1abVU1TURFeE9HSmgsc3Ryb25nUGFzc3dvcmQ=
12---
13# POSTGRES password
14apiVersion: v1
15kind: Secret
16metadata:
17 name: postgrespassword
18data:
19 password: UG9zdGdyZVNRTHN0cm9uZ1Bhc3N3b3Jk
Applying secrets
❯ kubectl apply -f secrets.yml
secret/onlinekey created
secret/postgrespassword created
❯ kubectl get secrets
NAME TYPE DATA AGE
default-token-dqt9k kubernetes.io/service-account-token 3 22d
onlinekey Opaque 1 2s
postgrespassword Opaque 1 2s
Volumes
The following volumes will be defined:
rstuf-storage persistent volume
RSTUF Workers will use the Storage Backend Service
type as LocalStorage
which requires a
LocalStorage [Optional]
RSTUF Workers will use the
RSTUF_STORAGE_BACKEND_PATH
as this volumeWebServer will use the same volume the HTTP root document (htdocs) to expose the TUF Metadata at
http://webserver/
rstuf-keystorage persistent volume
RSTUF Workers will use the Key Vault Backend Service
type as LocalKeyVault
which requires a
LocalKeyVault [Optional]
RSTUF Workers will use the
RSTUF_KEYVAULT_BACKEND_PATH
as this volumeThe online keys will be uploaded to this volume
redis-data persistent volume
Redis persistent data volume
postgres-data persistent volume
Postgres persistent data volume
Volumes example
1##########################################
2# VOLUMES
3##########################################
4# RSTUF Storage (backend storage)
5apiVersion: v1
6kind: PersistentVolumeClaim
7metadata:
8 labels:
9 io.kompose.service: rstuf-storage
10 name: rstuf-storage
11spec:
12 accessModes:
13 - ReadWriteOnce
14 resources:
15 requests:
16 storage: 100Mi
17status: {}
18---
19# RSTUF KeyVault (backend keyvault)
20apiVersion: v1
21kind: PersistentVolumeClaim
22metadata:
23 labels:
24 io.kompose.service: rstuf-keystorage
25 name: rstuf-keystorage
26spec:
27 accessModes:
28 - ReadWriteOnce
29 resources:
30 requests:
31 storage: 100Mi
32status: {}
33---
34# Redis persistent data volume
35apiVersion: v1
36kind: PersistentVolumeClaim
37metadata:
38 labels:
39 io.kompose.service: redis-data
40 name: redis-data
41spec:
42 accessModes:
43 - ReadWriteOnce
44 resources:
45 requests:
46 storage: 100Mi
47status: {}
48---
49# Postgres persistent data volume
50apiVersion: v1
51kind: PersistentVolumeClaim
52metadata:
53 labels:
54 io.kompose.service: postgres-data
55 name: postgres-data
56spec:
57 accessModes:
58 - ReadWriteOnce
59 resources:
60 requests:
61 storage: 250Mi
62status: {}
Applying Volumes
❯ kubectl apply -f volumes.yml
persistentvolumeclaim/rstuf-storage created
persistentvolumeclaim/rstuf-keystorage created
persistentvolumeclaim/redis-data created
persistentvolumeclaim/postgres-data created
❯ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM REASON AGE
pvc-5184d98009604a73 10Gi RWO Retain Bound default/redis-data 7s
pvc-70548101b01f440e 10Gi RWO Retain Bound default/rstuf-keystorage 9s
pvc-79aff76456bd433f 10Gi RWO Retain Bound default/rstuf-storage 9s
pvc-c3ee2645d4114816 10Gi RWO Retain Bound default/postgres-data 8s
Services
redis service
Exposes the port 6379 in the deployment network
postgres service
Exposes the port 5432 in the deployment network
web-metadata
Exposes the port 80 externally, using a load balancer
rstuf-api
Exposes the port 80 externally, using a load balancer
Services example
1##########################################
2# SERVICES
3##########################################
4
5# Redis service
6apiVersion: v1
7kind: Service
8metadata:
9 labels:
10 io.kompose.service: redis
11 name: redis
12spec:
13 ports:
14 - name: "6379"
15 port: 6379
16 targetPort: 6379
17 selector:
18 io.kompose.service: redis
19status:
20 loadBalancer: {}
21---
22# Postgres service
23apiVersion: v1
24kind: Service
25metadata:
26 labels:
27 io.kompose.service: postgres
28 name: postgres
29spec:
30 ports:
31 - name: "5432"
32 port: 5432
33 targetPort: 5432
34 selector:
35 io.kompose.service: postgres
36status:
37 loadBalancer: {}
38---
39# http service (exposing TUF metadata plublic)
40apiVersion: v1
41kind: Service
42metadata:
43 labels:
44 io.kompose.service: web-metadata
45 name: web-metadata
46spec:
47 type: LoadBalancer
48 ports:
49 - name: "http"
50 port: 80
51 targetPort: 80
52 selector:
53 io.kompose.service: web-metadata
54---
55# RSTUF API service
56apiVersion: v1
57kind: Service
58metadata:
59 labels:
60 io.kompose.service: rstuf-api
61 name: rstuf-api
62spec:
63 type: LoadBalancer
64 ports:
65 - name: "http"
66 port: 80
67 targetPort: 80
68 selector:
69 io.kompose.service: rstuf-api
70# RSTUF Worker is not a service, only a consumer backend
Applying services
❯ kubectl apply -f services.yml
service/redis created
service/postgres created
service/web-metadata created
service/rstuf-api created
❯ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.128.0.1 <none> 443/TCP 32d
postgres ClusterIP 10.128.54.79 <none> 5432/TCP 30s
redis ClusterIP 10.128.202.49 <none> 6379/TCP 30s
rstuf-api LoadBalancer 10.128.44.53 <PUBLIC_IP> 80:30158/TCP 30s
web-metadata LoadBalancer 10.128.135.249 <PUBLIC_IP> 80:32744/TCP 30s
Deployment
The following deployment will be applied:
redis deployment
Redis will use the redis-data persistent volume mounted on
/data
Redis container will use port as 6379 (default)
postgres deployment
Postgres will use the postgres-data persistent volume mounted on
/var/lib/postgresql/data/rstuf
Postgres will use environment variable
POSTGRES_PASSWORD
set as the secretspostgrespassword
web-metadata deployment
web-metadata is the Web Server is Apache which exposes the TUF Metadata
Web Server will use rstuf-storage persistent volume mounted on
/usr/local/apache2/htdocs
Web Server container will use port 80
rstuf-api deployment
RSTUF API will use environment variables
RSTUF_BROKER_SERVER
andRSTUF_REDIS_SERVER
as redis deployment address (redis://redis
).RSTUF API container will use port 80 to serve the API (internally)
rstuf-worker deployment
RSTUF Worker will use:
rstuf-keystorage persistent volume mounted on
/var/opt/repository-service-tuf/keystorage
rstuf-storage persistent volume mounted on
/var/opt/repository-service-tuf/storage
environment variables
RSTUF_BROKER_SERVER
andRSTUF_REDIS_SERVER
as redis deployment (redis://redis
).environment variables
RSTUF_SQL_SERVER
as the postgres deployment (postgres:5432
),RSTUF_SQL_USER
aspostgres
, andRSTUF_SQL_PASSWORD
as the postgrespassword secret.environment variable
RSTUF_KEYVAULT_BACKEND
asLocalKeyVault
environment variable
RSTUF_LOCAL_KEYVAULT_PATH
as/var/opt/repository-service-tuf/keystorage
environment variable
RSTUF_LOCAL_KEYVAULT_KEYS
as onlinekey secretenvironment variable
RSTUF_STORAGE_BACKEND
asLocalStorage
environment variable
RSTUF_LOCAL_STORAGE_BACKEND_PATH
as/var/opt/repository-service-tuf/storage
Deployment example
1##########################################
2# DEPLOYMENT
3##########################################
4
5# Redis deployment
6apiVersion: apps/v1
7kind: Deployment
8metadata:
9 labels:
10 io.kompose.service: redis
11 name: redis
12spec:
13 replicas: 1
14 selector:
15 matchLabels:
16 io.kompose.service: redis
17 strategy:
18 type: Recreate
19 template:
20 metadata:
21 labels:
22 io.kompose.service: redis
23 spec:
24 containers:
25 - image: redis:4.0
26 livenessProbe:
27 exec:
28 command:
29 - redis-cli
30 - ping
31 name: redis
32 ports:
33 - containerPort: 6379
34 resources: {}
35 tty: true
36 volumeMounts:
37 - mountPath: /data
38 name: redis-data
39 restartPolicy: Always
40 volumes:
41 - name: redis-data
42 persistentVolumeClaim:
43 claimName: redis-data
44status: {}
45---
46# Postgres Deployment
47apiVersion: apps/v1
48kind: Deployment
49metadata:
50 labels:
51 io.kompose.service: postgres
52 name: postgres
53spec:
54 replicas: 1
55 selector:
56 matchLabels:
57 io.kompose.service: postgres
58 strategy:
59 type: Recreate
60 template:
61 metadata:
62 labels:
63 io.kompose.service: postgres
64 spec:
65 containers:
66 - env:
67 - name: POSTGRES_PASSWORD
68 valueFrom:
69 secretKeyRef:
70 name: postgrespassword
71 key: password
72 - name: PGDATA
73 value: /var/lib/postgresql/data/rstuf
74 image: postgres:15.1
75 livenessProbe:
76 exec:
77 command:
78 - pg_isready
79 - -U
80 - postgres
81 - -d
82 - postgres
83 name: postgres
84 resources: {}
85 tty: true
86 volumeMounts:
87 - mountPath: /var/lib/postgresql/data
88 name: postgres-data
89 restartPolicy: Always
90 volumes:
91 - name: postgres-data
92 persistentVolumeClaim:
93 claimName: postgres-data
94status: {}
95---
96# http deployment (Web Server to expose metadata public)
97apiVersion: apps/v1
98kind: Deployment
99metadata:
100 name: web-metadata
101 labels:
102 io.kompose.service: web-metadata
103spec:
104 replicas: 1
105 selector:
106 matchLabels:
107 io.kompose.service: web-metadata
108 template:
109 metadata:
110 labels:
111 io.kompose.service: web-metadata
112 spec:
113 containers:
114 - name: web-metadata
115 image: httpd
116 ports:
117 - containerPort: 80
118 resources: {}
119 volumeMounts:
120 - mountPath: /usr/local/apache2/htdocs
121 name: rstuf-storage
122 restartPolicy: Always
123 volumes:
124 - name: rstuf-storage
125 persistentVolumeClaim:
126 claimName: rstuf-storage
127---
128# RSTUF Worker deployment
129apiVersion: apps/v1
130kind: Deployment
131metadata:
132 labels:
133 io.kompose.service: rstuf-worker
134 name: rstuf-worker
135spec:
136 replicas: 5
137 selector:
138 matchLabels:
139 io.kompose.service: rstuf-worker
140 strategy:
141 type: Recreate
142 template:
143 metadata:
144 labels:
145 io.kompose.service: rstuf-worker
146 spec:
147 containers:
148 - env:
149 - name: RSTUF_BROKER_SERVER
150 value: redis://redis
151 - name: RSTUF_REDIS_SERVER
152 value: redis://redis
153 - name: RSTUF_SQL_SERVER
154 value: postgres:5433
155 - name: RSTUF_SQL_USER
156 value: postgres
157 - name: RSTUF_SQL_PASSWORD
158 valueFrom:
159 secretKeyRef:
160 name: postgrespassword
161 key: password
162 - name: RSTUF_KEYVAULT_BACKEND
163 value: LocalKeyVault
164 - name: RSTUF_LOCAL_KEYVAULT_PATH
165 value: /var/opt/repository-service-tuf/keystorage/
166 - name: RSTUF_LOCAL_KEYVAULT_KEYS
167 valueFrom:
168 secretKeyRef:
169 name: onlinekey
170 key: keys
171 - name: RSTUF_STORAGE_BACKEND
172 value: LocalStorage
173 - name: RSTUF_LOCAL_STORAGE_BACKEND_PATH
174 value: /var/opt/repository-service-tuf/storage
175 image: ghcr.io/repository-service-tuf/repository-service-tuf-worker:latest
176 name: rstuf-worker
177 resources: {}
178 tty: true
179 volumeMounts:
180 - name: onlinekey
181 mountPath: "/run/secrets/onlinekey"
182 readOnly: true
183 - name: postgrespassword
184 mountPath: "/run/secrets/postgrespassword"
185 readOnly: true
186 - mountPath: /var/opt/repository-service-tuf/storage
187 name: rstuf-storage
188 - mountPath: /var/opt/repository-service-tuf/keystorage
189 name: rstuf-keystorage
190 restartPolicy: Always
191 volumes:
192 - name: rstuf-storage
193 persistentVolumeClaim:
194 claimName: rstuf-storage
195 - name: rstuf-keystorage
196 persistentVolumeClaim:
197 claimName: rstuf-keystorage
198 - name: onlinekey
199 secret:
200 secretName: onlinekey
201 - name: postgrespassword
202 secret:
203 secretName: postgrespassword
204status: {}
205---
206# RSTUF API deployment
207apiVersion: apps/v1
208kind: Deployment
209metadata:
210 labels:
211 io.kompose.service: rstuf-api
212 name: rstuf-api
213spec:
214 replicas: 1
215 selector:
216 matchLabels:
217 io.kompose.service: rstuf-api
218 strategy:
219 type: Recreate
220 template:
221 metadata:
222 labels:
223 io.kompose.service: rstuf-api
224 spec:
225 containers:
226 - env:
227 - name: RSTUF_BROKER_SERVER
228 value: redis://redis
229 - name: RSTUF_REDIS_SERVER
230 value: redis://redis
231 image: ghcr.io/repository-service-tuf/repository-service-tuf-api:latest
232 name: rstuf-api
233 ports:
234 - containerPort: 80
235 resources: {}
236 volumes:
237 restartPolicy: Always
238status: {}
Applying deployment
❯ kubectl apply -f deployment.yml
deployment.apps/redis created
deployment.apps/postgres created
deployment.apps/web-metadata created
deployment.apps/rstuf-worker created
deployment.apps/rstuf-api created
❯ kubectl get pods
NAME READY STATUS RESTARTS AGE
postgres-64866cf7f9-p4clt 1/1 Running 0 4m12s
redis-6f6fbbd9ff-ckrrt 1/1 Running 0 4m12s
rstuf-api-7cd78b65f7-sn56n 1/1 Running 0 4m12s
rstuf-worker-5b89554c95-xrlgb 1/1 Running 0 4m12s
web-metadata-75f59886f-h274h 1/1 Running 0 4m12s
RSTUF Ceremony and Bootstrap
Repository Service for TUF (RSTUF) has two specific processes as part of the initial setup: Ceremony and Bootstrap.
Note
The setup and configuration requirements:
Set of root key(s) and online key for signing
RSTUF service deployed
Note
It is a one-time process to setup the RSTUF service. If this process is completed during the deployment do not run it again.
RSTUF Command Line Interface provides a guided process for the Ceremony and Bootstrap.
To make this process easier, the Repository Service for TUF CLI provides an interactive guided process to perform the Ceremony.
Note
Required RSTUF CLI installed (See Installation)
❯ rstuf admin ceremony -hA video demonstrating this process is available.
The Ceremony defines the RSTUF settings/configuration and generates the initial signed TUF root metadata.
It does not activate the RSTUF service. It generates the required JSON payload to bootstrap the RSTUF service.
The Ceremony can be done Connected as a specific step or Disconnected, combined with Bootstrap.
This process generates the initial metadata and defines some settings of the TUF service.
See settings details
Root metadata expiration policy
Defines how long this metadata is valid, for example, 365 days (year). This metadata is invalid when it expires.
Root number of keys
It is the total number of root keys (offline keys) used by the TUF Root metadata. The number of keys implies that the number of identities is the TUF Metadata’s top-level administrator.
Note
Updating the Root metadata with new expiration, changing/updating keys or the number of keys, threshold, or rotating a new online key and sign requires following the Metadata Update process.
Note
RSTUF requires all Root key(s) during the Ceremony.
Note
RSTUF requires at least the threshold number of Root key(s) for Metadata Update.
Root key threshold
The minimum number of keys required to update and sign the TUF Root metadata.
Targets, BINS, Snapshot, and Timestamp metadata expiration policy
Defines how long this metadata is valid. The metadata is invalid when it expires.
Targets number of delegated hash bin roles
The target metadata file might contain a large number of artifacts. The target role delegates trust to the hash bin roles to reduce the metadata overhead for clients.
Targets base URL
The base URL path for downloading all artifacts. Example: https://www.example.com/download/
Signing
This process will also require the Online Key and Root Key(s) (offline) for signing the initial root TUF metadata.
The settings are guided during Ceremony.
The disconnected Ceremony will only generate the required JSON payload (
payload.json
) file. The Bootstrap requires the payload.Note
The payload (
payload.json
) contains only public data, it does not contain private keys.This process is appropriate when performing the Ceremony on a disconnected computer to RSTUF API to perform the Bootstrap later as a separate step.
❯ rstuf admin ceremonyThe connected Ceremony generates the JSON payload file and run the Bootstrap request to RSTUF API.
This process is appropriate when performing the Ceremony on a computer connected to RSTUF API. It does not require a Bootstrap step.
❯ rstuf admin ceremony -bIf a Ceremony Connected is complete, skip this, as the RSTUF service is ready.
If a Ceremony Disconnected is complete, it requires running the Bootstrap from a computer connected to the RSTUF API.
❯ rstuf admin ceremony -b -u