Skip to main content
Version: 0.8.1

Running a command

The binary is the service and its commands. A command runs as the service - its image, configuration, store, KEK rights and identity - as a job, never in a shell.

The commands​

tresor-server [rewrap | refs | mac | reseal] [flags] [-config <file>]
CommandDoes
(none)serves
rewrapwraps every data key under the KEK's current version, and off a keys.previous KEK (The KEK)
rewrap -tag-untaggedonce, at the upgrade to authenticated data keys: tags the data keys that have none (Upgrading)
refslists the stored references the configuration would not admit; -resolve reads each one too (Operations)
macSQL stores: gives every row with no MAC, or a stale one, a MAC - once, for a database from before 0.2 (Upgrading)
resealmoves every row to the active data key; -rotate makes a new active one first; -retire then deletes the data keys nothing uses (Data keys)
  • The configuration comes from -config <file>, then TRESOR_CONFIG, then the TRESOR_* variables, as the service's (Configuration). The command comes first: tresor-server -config x rewrap is a usage error.
  • The service's own version. rewrap, mac and reseal open the store as the service does: a newer binary would migrate the database. refs never migrates: an older or newer schema is refused.
  • Beside a serving replica: every change is compare-and-set. On SQLite, stop the service first: mac and reseal need the database's lease (and refuse while a replica holds it); refs takes none, but on a cluster its volume is the serving pod's.
  • The log: names and counts, never a value. refs prints its findings on stdout.
Exit
0done; for refs, nothing to report
1an error: the log says what (a row or data key named, the store or the KEK unreachable)
2a usage error: an unknown command or flag
3refs: findings

Kubernetes (the chart)​

The chart makes a suspended CronJob per command, with the service's image, ServiceAccount, configuration, volumes and environment (Kubernetes). <fullname> is the one the chart's NOTES print.

CronJobRuns
<fullname>-resealreseal -retire
<fullname>-reseal-rotatereseal -rotate -retire
<fullname>-rewraprewrap
<fullname>-refsrefs -resolve
<fullname>-macmac (SQL stores only)
kubectl -n tresor create job --from=cronjob/<fullname>-reseal reseal-$(date +%Y%m%d%H%M)
kubectl -n tresor logs -f job/reseal-…
kubectl -n tresor get job reseal-… # Complete, or Failed
kubectl -n tresor get pods -l job-name=reseal-… \
-o jsonpath='{.items[0].status.containerStatuses[0].state.terminated.exitCode}'
  • A job is not retried (backoffLimit: 0), ends at maintenance.activeDeadlineSeconds (an hour), and is kept a week.

  • rewrap -tag-untagged and refs without -resolve have no CronJob. To run one, render a job from the nearest CronJob, change its args, and create it - a manual step:

    kubectl -n tresor create job --from=cronjob/<fullname>-rewrap tag-untagged --dry-run=client -o yaml > job.yaml
    # args: ["rewrap", "-tag-untagged", "-config", "/etc/tresor/server.yaml"]
    kubectl -n tresor create -f job.yaml

SQLite​

SQLite on a cluster is not recommended. Its volume is ReadWriteOnce and the serving pod's, and mac and reseal need its lease: every command needs the service scaled to 0 first, and no schedule runs.

kubectl -n tresor scale deploy/<fullname> --replicas=0
kubectl -n tresor create job --from=cronjob/<fullname>-reseal reseal-$(date +%Y%m%d%H%M)
kubectl -n tresor logs -f job/reseal-…
kubectl -n tresor scale deploy/<fullname> --replicas=1

The service is down meanwhile. A command started with the service up stops with "the SQLite database is held by a serving replica".

kubectl exec: a fallback​

refs takes no lease and writes nothing: it can run beside a serving replica.

kubectl -n tresor exec deploy/<fullname> -- /tresor-server refs -config /etc/tresor/server.yaml

A fallback only: pods/exec is a broader right than a job's (the pod's files), and the job platforms have no exec.

Azure Container Apps (the recipe)​

The recipe makes a manual job per command, with the app's image, managed identity and settings (Azure Container Apps):

JobRuns
<prefix>-resealreseal -retire
<prefix>-reseal-rotatereseal -rotate -retire
<prefix>-rewraprewrap
<prefix>-refsrefs -resolve
<prefix>-macmac
az containerapp job start -g <rg> -n <prefix>-reseal
az containerapp job execution list -g <rg> -n <prefix>-reseal -o table # Succeeded, or Failed
  • The logs go to the environment's Log Analytics.
  • Start a job with no arguments of your own: a start's arguments replace the container's template, its settings with it.
  • No retry, an hour's timeout.
  • rewrap -tag-untagged and refs without -resolve have no job: not supported by the recipe.

Cloud Run (the GCP recipe)​

The recipe makes a job per command, with the service's image, account, settings and egress (spec 020): <prefix>-reseal (reseal -retire), -reseal-rotate, -rewrap, -refs (refs -resolve), -mac.

gcloud run jobs execute tresor-reseal --region europe-west1 --wait
gcloud run jobs executions list --job tresor-reseal --region europe-west1

Their logs go to Cloud Logging. No retry, an hour's timeout.

ECS (the AWS recipe)​

One task definition, <prefix>-command, with the service's image, role, settings and network; the command is given at the run:

aws ecs run-task --region <region> --cluster tresor --launch-type FARGATE --task-definition tresor-command \
--network-configuration "awsvpcConfiguration={subnets=[<private subnets>],securityGroups=[<task security group>],assignPublicIp=DISABLED}" \
--overrides '{"containerOverrides":[{"name":"tresor","command":["reseal","-retire"]}]}'

The recipe's outputs name the subnets and the security group. Its log goes to CloudWatch Logs, /ecs/<prefix>.

Docker​

The service's image, tag and settings: the same environment, the same mounted configuration and volumes, the same identity.

docker run --rm --env-file <the service's env file> ghcr.io/hugr-lab/tresor-server:<the service's tag> reseal -retire
docker run --rm -v <the configuration's dir>:/etc/tresor:ro -v <the data volume>:<its path> \
ghcr.io/hugr-lab/tresor-server:<the service's tag> refs -resolve -config /etc/tresor/server.yaml

On SQLite, stop the service's container first for rewrap, mac and reseal (mac and reseal refuse otherwise).

A VM​

The binary, as the service's user, with its configuration file and its environment (a local KEK's variable, a password's) - sudo -u alone drops the environment; take the service's own env file:

sudo -u <the service's user> env $(cat /etc/tresor/env) tresor-server reseal -retire -config /etc/tresor/server.yaml

On SQLite, stop the service first for rewrap, mac and reseal, and start it after.