WIP janus secrets
This commit is contained in:
@@ -5,6 +5,13 @@ Generate passwords:
|
||||
mkdir -p /tmp/janus-step-ca-bootstrap && chmod 700 /tmp/janus-step-ca-bootstrap && cd /tmp/janus-step-ca-bootstrap && umask 077 && openssl rand -base64 48 > ca_password.txt && openssl rand -base64 48 > admin_jwk_password.txt
|
||||
```
|
||||
|
||||
Generate the Janus OpenSSH host key that Nix will materialize from SOPS at
|
||||
`/etc/ssh/ssh_host_ed25519_key`:
|
||||
|
||||
```shell
|
||||
ssh-keygen -t ed25519 -N '' -C [email protected] -f /tmp/janus-step-ca-bootstrap/ssh_host_ed25519_key
|
||||
```
|
||||
|
||||
Bootstrap CA materials with SSH enabled:
|
||||
```shell
|
||||
STEPPATH=/tmp/janus-step-ca-bootstrap/step step ca init --name Janus --dns janus.john-stream.com --dns 192.168.1.244 --address :443 --provisioner admin --password-file /tmp/janus-step-ca-bootstrap/ca_password.txt --provisioner-password-file /tmp/janus-step-ca-bootstrap/admin_jwk_password.txt --ssh --deployment-type standalone --with-ca-url https://janus.john-stream.com
|
||||
@@ -17,9 +24,24 @@ Insert generated runtime CA material into `modules/hosts/janus/secrets.yaml` und
|
||||
- `/tmp/janus-step-ca-bootstrap/step/secrets/ssh_host_ca_key` -> `ssh_host_ca_key`
|
||||
- `/tmp/janus-step-ca-bootstrap/step/secrets/ssh_user_ca_key` -> `ssh_user_ca_key`
|
||||
- `/tmp/janus-step-ca-bootstrap/step/config/ca.json` -> `admin_provisioner_encrypted_key` (copy `authority.provisioners[].encryptedKey` for the `admin` JWK provisioner)
|
||||
- `/tmp/janus-step-ca-bootstrap/ssh_host_ed25519_key` -> `ssh_host_ed25519_key`
|
||||
|
||||
If you are only validating wiring first, `admin_provisioner_encrypted_key` can be an encrypted placeholder and replaced later.
|
||||
|
||||
The checked-in `ssh_host_ed25519_key` value is also only an encrypted placeholder.
|
||||
Replace it before deploying Janus, otherwise OpenSSH and SSH host certificate
|
||||
issuance will fail because the materialized host key is not a valid private key.
|
||||
|
||||
For multiline secret values, avoid putting private key contents in shell history.
|
||||
One safe non-interactive pattern is to JSON-encode the file content and pass that
|
||||
temporary JSON file to `sops set --value-file`:
|
||||
|
||||
```shell
|
||||
jq -Rs . /tmp/janus-step-ca-bootstrap/ssh_host_ed25519_key > /tmp/janus-step-ca-bootstrap/ssh_host_ed25519_key.json
|
||||
sops --config .sops.yaml set --value-file modules/hosts/janus/secrets.yaml '["janus"]["ssh_host_ed25519_key"]' /tmp/janus-step-ca-bootstrap/ssh_host_ed25519_key.json
|
||||
rm -f /tmp/janus-step-ca-bootstrap/ssh_host_ed25519_key.json
|
||||
```
|
||||
|
||||
If rotating provisioner password, also set:
|
||||
|
||||
- `/tmp/janus-step-ca-bootstrap/admin_jwk_password.txt` -> `janus.admin_jwk` in `keys/secrets.yaml`
|
||||
@@ -27,6 +49,7 @@ If rotating provisioner password, also set:
|
||||
Secret source-of-truth after this split:
|
||||
|
||||
- `modules/hosts/janus/secrets.yaml`: Janus runtime CA secrets (`ca_password`, `intermediate_ca_key`, `ssh_host_ca_key`, `ssh_user_ca_key`, `admin_provisioner_encrypted_key`)
|
||||
- `modules/hosts/janus/secrets.yaml`: Janus OpenSSH host private key (`ssh_host_ed25519_key`) materialized to `/etc/ssh/ssh_host_ed25519_key`
|
||||
- `keys/secrets.yaml`: shared Janus provisioner secret (`janus.admin_jwk`) consumed by `step-ssh-host` across hosts
|
||||
|
||||
Then update public artifacts in repo from generated output:
|
||||
@@ -38,6 +61,26 @@ Then update public artifacts in repo from generated output:
|
||||
step certificate fingerprint /tmp/janus-step-ca-bootstrap/step/certs/root_ca.crt
|
||||
```
|
||||
- `modules/hosts/janus/ssh_user_ca_key.pub` from `/tmp/janus-step-ca-bootstrap/step/certs/ssh_user_ca_key.pub`
|
||||
- `modules/hosts/janus/ssh_host_ca_key.pub` from `/tmp/janus-step-ca-bootstrap/step/certs/ssh_host_ca_key.pub`
|
||||
|
||||
## First boot checks
|
||||
|
||||
After switching Janus, verify the declarative bootstrap units instead of running
|
||||
ad hoc issuance commands first:
|
||||
|
||||
```shell
|
||||
systemctl status step-ca.service
|
||||
systemctl status step-ssh-host-renew.service
|
||||
systemctl status step-ssh-host-renew.timer
|
||||
systemctl status mtls-bootstrap.service
|
||||
ssh-host-cert-check
|
||||
mtls-check
|
||||
```
|
||||
|
||||
`step-ssh-host-renew.service` issues the SSH host certificate when it is missing
|
||||
or expiring. `mtls-bootstrap.service` issues the first Janus mTLS bundle
|
||||
only when the configured certificate files are absent or invalid; recurring mTLS
|
||||
renewal remains handled by `mtls-renew.timer`.
|
||||
|
||||
## Back up the root CA key offline
|
||||
|
||||
|
||||
@@ -16,9 +16,20 @@ in
|
||||
nixos.docker
|
||||
nixos.login-text
|
||||
nixos.mtls
|
||||
({ lib, pkgs, ... }: {
|
||||
({ config, lib, pkgs, ... }: {
|
||||
networking.hostName = hostname;
|
||||
loginText.extraServiceStatus = {
|
||||
"Step-CA" = "step-ca";
|
||||
};
|
||||
sops.defaultSopsFile = ./secrets.yaml;
|
||||
sops.secrets."janus/ssh_host_ed25519_key" = {
|
||||
sopsFile = ./secrets.yaml;
|
||||
owner = "root";
|
||||
group = "root";
|
||||
mode = "0600";
|
||||
path = "/etc/ssh/ssh_host_ed25519_key";
|
||||
restartUnits = [ "sshd.service" "step-ssh-host-renew.service" ];
|
||||
};
|
||||
step-ssh-host = {
|
||||
hostname = hostname;
|
||||
extraPrincipals = [
|
||||
@@ -49,6 +60,12 @@ in
|
||||
"${hostname}.john-stream.com"
|
||||
"192.168.1.244"
|
||||
];
|
||||
bootstrap = {
|
||||
enable = true;
|
||||
after = [ "network-online.target" "sops-nix.service" "step-ca.service" ];
|
||||
wants = [ "network-online.target" "step-ca.service" ];
|
||||
provisionerPasswordFile = config.sops.secrets."janus/admin_jwk".path;
|
||||
};
|
||||
};
|
||||
|
||||
users.users."${username}" = {
|
||||
|
||||
@@ -1,31 +1,40 @@
|
||||
janus:
|
||||
ca_password: ENC[AES256_GCM,data:GmuqoePDJd5Cn7+sWbvXPlGoUf3SVgYnHOoq9mnPWNWj,iv:VY/8olA+yu66wW+RbhD58GtA0YUWuAtm1HUXtNIIuLk=,tag:fCz3x6B4UPw+XpJE0F3t/g==,type:str]
|
||||
intermediate_ca_crt: ENC[AES256_GCM,data:9W6QXGlcPdfas1ea6S3w1OYI/SeF6YDIdF5J7Hv4ype3,iv:H8oVfbMLBRvU0ywovVSB84g0q1wPhHEdzfpIVAY0Bkg=,tag:7/pU0N1SlfC1i8H2IgPGVA==,type:str]
|
||||
intermediate_ca_key: ENC[AES256_GCM,data:wrzE8pgSZrtMA2jyLuVhMFxr47ICDBUkqOFyFJex9h3g,iv:I3Sz07e+cFDOUunCu7ZGcAjckRJDy3NmTXoB0vtA0HI=,tag:inANSVzyAzWlX4J5pheY8A==,type:str]
|
||||
ssh_host_ca_key: ENC[AES256_GCM,data:IT3PcnbrexRDvxoVEyyxYBx7+Brm3SzVP3Yr2UGkFjeH,iv:edfMiRR+EVx9veTH+mEAFtEdC/rlW8uU5jMD8UX2Ylo=,tag:KKS/2GQE8V6obbjfMLspug==,type:str]
|
||||
ssh_user_ca_key: ENC[AES256_GCM,data:w3gc97CYUODNxk0gIyghd9PCksDVvrdvl8j/NQe/tCtw,iv:WbWlVCPV7niVHEJ9sVcO9SAcLSfquE/bvcR5KClxszk=,tag:08uj+lv9MflYOtQh28K6pw==,type:str]
|
||||
admin_provisioner_encrypted_key: ENC[AES256_GCM,data:/EdlRiPn/LHpQk5sA9VVYTz/U4i6Ag==,iv:r6Rm38L1R4xsnyR97e3J2FdH4KWYewZdADosv9WLAXw=,tag:MnWq9lI7GAXN0FmGTa9zmQ==,type:str]
|
||||
ca_password: ENC[AES256_GCM,data:z6i0ELrn6XwVbJ7gP1GkpWe0Xw==,iv:3pZs/kzPp6bL8iv8jITZnAHuCycbSjhWswgzuJuLvjE=,tag:3gUftdyVXPVWe5dGxh9dvw==,type:str]
|
||||
intermediate_ca_key: ENC[AES256_GCM,data:0QVk/coqb4xvf2vVhZS9wpo9qrGIcdwPRuHqORyJlUIC0VAwH8AoZNKM54uarwag7Wpb+ltv6vhi4frcp+RzGOCDQET28pSrgXBKw5B31vA4uNI6z8pbZbsUrIbVuQDCw/QAu2v+xuCyMyYK58r4hGaCR6RZu6LCZ9Gx7JgmBZWQcZ3Li5jxG+Cm0HM9AympBhCcIGyWfRXreTZkGlzOhknO/MsBhjTmEwpNi4XZdTlsh1dF2tJ3l9nd7B260yAAwcI8AFyCFSIxAZOxYiYWwqUOQu/tFnDA3Zl7Q2LCwCjrr4UyYd+f33R43BWJPD/8TkPOeoyC4RHGIcB11UyyPXGm6TISJITYd0Ii0t8jPkPPFT3bwx5BEadI+/ICYte8bb5d5uV0gbAZB1EpWmeOcEVOOIt076dr6Q==,iv:1ygRHwQfyAAhG7dmm6aB2b5VVDv6JY0/SJGyVVoVSiM=,tag:GTeWsVEE912GXXNjkK2dHw==,type:str]
|
||||
ssh_host_ca_key: ENC[AES256_GCM,data:SA46pzoWXdCLRWPZEHS+n93rspAZ7OQEZTfGF8zNXtuP//522eEocq0CGmmi8AJdST0oWnwbx1EFTyDlz2T8/1eP6ucfNigY8BicLymfdMb57uqJs7lAqN3xakdiM+SqfQcEuGy+SjJjqTjfHw7eqUcFXAuqFcTu6roF+kbVQwqmJyFDhh844aB+YhwIjphBYStqYu6CXGrE4UZBdHtyTHT514I0C1FRXBB6T8QzHr006hh+F7TCCnjVEd+JFNVD9dbf+zfWSdmi5edVRO8/fOrsP0PlDz7LQLocc3YJO+SiLC0m47ihszJJFhE/rYdVfPiagw9L6OmXi2RfDOF1/w2+r2d7Ki9WcyHItnzNsb1FEOFvVICT304s/KbGkesQLpp2JDzyPV3xOIxo/mmSsrJ3kKCahJpxdQ==,iv:rl/Vms9w/8NzaNkSU8kgk2SRV/Ic0DYhdtgT1YFoeEw=,tag:H1GrRqh0CmPN+EfS7+zb3w==,type:str]
|
||||
ssh_user_ca_key: ENC[AES256_GCM,data:jyMrso0G2KVfvn1/Qdl+A0dcQU9/CIrbj1F6hbPB3KWROiQghe/ytTdIsAgKYb+0xUfH27tVjufLY6zEqviPxczzfN9y0ldk+caxH96VEy7da4UdR9rJa7Rl1bvcobRcVIXUCK7rA1deHtJr2wq0KspK4id2QON3w6ggXvYRCe0IAo16p0eGQUMotHqMO+M0qWRkV8IqMKObmxZePK6SGNUEleUNXfSbL4mbN50MIZt9lVKOxOVNZK1BjETtei6IjeeFhPcitJFRjbQTwFB6+5NYqLhEDEZyO3vMZe3poEFtPw9TFlhtYIwtWlBhl+nbh3mAbDWDsHcTix5AL2VVPuDoNpnwCCE4OFzcXjBlBZr28x40o+ukrCxityCXf8M99K3NJVyqgVMdNzjcmViM6pc6wV20t8t/mQ==,iv:RLv3ltoa8Hl1x5Q5xD8xKvlluGd6VTTwxaiV8KhKJBk=,tag:owD14446JnZWznpY9cG2BA==,type:str]
|
||||
admin_provisioner_encrypted_key: ENC[AES256_GCM,data:lv85vgW77Qiy4UOcHt5SaVvuGmBsDIdjTxbUUaxGeP2H+XghTVuHZ/oLNXaPYqBFKKFqctG7FeL3/Gnm5wD7DXn9z6Cwc9eSZjNHUEiYcQLThBHDUOArk/CHhWvuAhWbuT5yBwVJkUmBpO5ZR3slRAh8RS/EBhb3iOXGW63i2Bj1kFAyf4XucmWY8lkRRpIj11gkWA1gVZqJkQI5AJDf4ikvYI/5p33wtQFpClsKJsJRzaoCee+m3w2Obq8hYMdS1mGnXm1L3tbkAj0130dl4/eOvOZq7le2S5Fo0WAFFyk1nhNz771fRI3WtiA85IHC9Nd3v6jGek+PVclk0D4rfvlQTF1yOpemtcsX2BbAbbB2j7sJ5a5bM9O5lotBoFlGQP/co5EU7Ki0+sTYdQxsHVSQhvsCTv5IhSMSjrzkUVN0RV7EwSkKdLK65Q8bR1pmOdXVDAPsyjB4tUJlwWKisrkAc5oyM+mI0Lalz7nvbTYvgtiS0vcBnGmRwcxDC5q//BTm4RhAB2e/My0MadVxF3aEn6fMaoK+3ef1zAToBRG8bV1vC+trhz3ucPqvMNPxjrSQpOdxzJyqlPgfKFVRI/DEQhO0XWpnU3h7wA1mV/dyjeosFVydfKN5iOLl+xF3VgRpisV2oE0Fgas6JkOGwy/d+MpkgNz/Amr+9phZA/bXl2lpDYIKj6aBduqizI4jV1jpM2FHtv99Jkg24DKIcPSZVvzVYr6j8FMmgaxOsA3Z72GlleLdwBKtuBC0GvU=,iv:kcJEhE1d4vYLHk+W2ay2rid+KCuarAIxUZSl/0wi5W4=,tag:7VARgV4a1nT+beIYWelqyw==,type:str]
|
||||
ssh_host_ed25519_key: ENC[AES256_GCM,data:HUL5aKHKXLet6Z1cZKsEgesjT/MoiF2y1MIIdD5YzvUyBBCUuoeZuEPs5TnQwthVITHFsiQP0CJQARLGX2QM0+GpMsw/C7pZYbkuBgVbo0U8qA9fixga3wqqk/2b8bgage8cwjCxg/WCLnfa97b7eeQabSU451VYk7nClLoR1Vh0BSGde0oaXMv0eYmgGPMJaD0JMCZX9wAgX2+VcW2MNP80vsyOJNp/GvkV+9RWa1h3DUh/bpywk3rFm4ftTCcpHjwXNyhXOXWXkheJtKWHAWkPSVzvygODVy45ZZqXke7mOsPZfANy4O2IILic6MLaU/TDQ7FbrNAKq9RPHLAMR8C7XFq7QV2MoLkpZ3fzJOn6tLzfgaGmvHBIekywsHJMgCv3MH1l1Uvw2LYY31dFN6z41I7Mj/bFZGZ4TWDQchuJSAF56aosXSw9DCiTY7gly13HkXNYbTrdKM3BjA5TNyYtJ+KMipket4hBUDAVVQ+fBbk087RFmcuzBSAuCnpkoRvPv767/ht8Q5YQpTY=,iv:m1ZKNB5Ab7pKywHQvxqElkCHokNZUZYbxfXXRF8bDD0=,tag:NPA7ErsJMMmff9XYHrUqbQ==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCTEFTSy96QTluaWo0bURH
|
||||
YlpFSWx3VnYvSHpDYU1PNmZrb0FuVHVTcG00CmJnT09OZEJad01OZk8zUzlPT1Ft
|
||||
bVpHeW9UMXZYN1JJQVgrTk9OamhZeXcKLS0tIFhXMVNDQjhVcUp2aHhjenlGVW9z
|
||||
cTNPalJOQVJNQWxzMnVMT1lYQS9SNW8KWapdX8dwxEvcqhKI8RJmCWRrV7sRmS72
|
||||
sUt6HaUGpQfUQ97MtS01DYaSZjbAvj8t//mXhLubZddDTtTuhbpjAg==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCdFNwM2JQSVlFZXpJZ0VQ
|
||||
eDFYek1TMnNTM3lLbjh4SG56VDl6MGsvb1drCnpLbGZ1N2FwSmRacitFVDJxaFlD
|
||||
Vk5XeCtxRGM0OGV2UFNwQmlFV1pLS1EKLS0tIHB5bm1iRG9WWmpjTlBKcWkwWktz
|
||||
SWVQOVlJU3RBejdpaGpyTTAzVmh0MFkK6nLey1QwSw5J8WeDdUIjJo62pylqOKmP
|
||||
+GANs3OQkRuwW2+nwG+LJR2pfUS6O6PDOz7ZWGKih90/Bk7EMtjOIQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1n94nkvmzezdj08t4dpwukd7s5k4cx2rldwvx9x5qhx3xhqm48yhq6ejldt
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyeE04L0RvYmlnaWpxUWhm
|
||||
M01vQVc2bFdNZ2k4TjJBOWZDTlV1V2VkVGd3CnhseTlOZWtqbmpldXUrWnRxSWdR
|
||||
dFFPTFZtSlZjZVdKMDdYQkVJeG5wZUUKLS0tIGxRbEE3ZjNrUTlLSDMrVVIzbnJ5
|
||||
cEFnNmErTlhQMEtZM282STVRUGl0dVkKDyyTGVFDm6u+cdGu/PzFUFgj6ewCf0fi
|
||||
vFhmYA8bTGNg6loThbYxm4uN1u+mJgwOKJ3FRR+u9yYEF6xvqrIbdw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1ykcs39e62pz3xu6cedg8ea685kv5d5qsrhgkndygzm8rx30xd5ys5t3qxt
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWcnVWS2lpMDM5VWxLWDIx
|
||||
R0xWQ3ZOaEVFNTR5bXArNTc4MzFOM2xCQWhjCnBZeUtJQ3RvWDdZeVRpRzBPbTl2
|
||||
M3FOTlRnTDhIaGg2VzM3MFVEc1FVUmcKLS0tIDAzeDlaZGt5Q2dJbzNWRVB4Qmwr
|
||||
SWpxcytNdEFBQ2o0Q3lWSHZSNEdCUUEKgHE0j678WIhcQQsZQ5RcQNkQcP++ibvr
|
||||
ZT3ScL4PAYhH+lxciJK4tit53taevbp5o0jFibaup4ByDvgj7HPclw==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjeHQ4aDlSU2M2bzE1ODFY
|
||||
Ym1NNEFFaVhrVlR0WUs1ZUVwTFVGN3QwMFZJCmdJWWFaeHByUlB2U3FLbEpwRkJI
|
||||
ckRTNWx2dVl3Mi9ZNjhwUFNTdjZIaTAKLS0tIDZ0dFpCa2F3aFRCYmh2N3Nwb2dF
|
||||
ZUJxakM3Wnc3U3JwTklPcllydXZBUXcKlf9C2/Gb9H9PdEKHdAd48dsalm43vYIz
|
||||
ODYoLItstmJvT/rZ+XijZFALNsRrIj5435CW6V34OsfCkFkjeHz17w==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1gvplss0ddmyf6vpjy363wu3n057vhm0j6n7tc94cxd8kadapypws5mtaj0
|
||||
lastmodified: "2026-07-04T04:20:22Z"
|
||||
mac: ENC[AES256_GCM,data:N0+lAFghaas9fg9PMcsaMPKJbYmnSrgPIFPsEuC749nzMX1IfQVaTLYm6ziZiq8TpscGR1tBqzw2eXiSZG4XfI44naEzO8CvY87aaZAL19/c/j4XE8eBqv1RLsLMbBIYYs8h6aZXCwhWUa3bwFukjueD0iu2X3md6V4T+4RnYSE=,iv:Xd/DCSDymp+KURHjM3Cht8oqbyN/k5+eybdi3pK5eww=,tag:tmDJoo5RKXQTnVjqkXsZ1w==,type:str]
|
||||
lastmodified: "2026-07-04T16:08:14Z"
|
||||
mac: ENC[AES256_GCM,data:9cWYDRVot45SO79sR6ETDI2zwMW5EVH2k3pOObQ/FWPhkdZYBkox3uf2UXgzCo9An98ta3bmhcZnfv77jAnZOz088s4MWTvl89ViI0SFtPnm94Ml2NopxmKdRndja5Aj5AOD5MUrqofaSXIhOTxekp/goCGknd986zuUa7yVhhw=,iv:38ycphhpGYKHFhWTQeM5QlfzS8cnaC3Y5yAkO/kxfEk=,tag:ILOV+YyP3kA3e9FJmBC5Gw==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.13.1
|
||||
|
||||
Reference in New Issue
Block a user