Fix some notes
This commit is contained in:
parent
f3175b9b03
commit
905b1096ac
4 changed files with 211 additions and 165 deletions
|
@ -41,3 +41,7 @@ To transfer the secrets needed for OpenTofu from Bitwarden to OpenBAO/Vault run:
|
||||||
```bash
|
```bash
|
||||||
nix run '.#bitwarden-to-vault'
|
nix run '.#bitwarden-to-vault'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Immediate TODO list:
|
||||||
|
|
||||||
|
1. Make the hetzner-static-ip.service not fail when the IP is already assigned.
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
# Before beginning
|
||||||
|
|
||||||
|
Enable bootstrapping of the instance, by setting `config.khscodes."security.kaareskovgaard.net".bootstrap.enable = true` in `default.nix`.
|
||||||
|
|
||||||
# After creating the instance
|
# After creating the instance
|
||||||
|
|
||||||
Open https://secrets.kaareskovgaard.net and initialize OpenBAO. Remember to get some sort of auto unsealing set up afterwards, currently this is implemented with a cronjob on TrueNAS. Doing it this way allows various certificates to continue getting issued, even as OpenBAO gets sealed (due to auto updates).
|
Open https://secrets.kaareskovgaard.net and initialize OpenBAO. Remember to get some sort of auto unsealing set up afterwards, currently this is implemented with a cronjob on TrueNAS. Doing it this way allows various certificates to continue getting issued, even as OpenBAO gets sealed (due to auto updates).
|
||||||
|
@ -5,7 +9,7 @@ Open https://secrets.kaareskovgaard.net and initialize OpenBAO. Remember to get
|
||||||
After this, configure the OpenBAO instance with:
|
After this, configure the OpenBAO instance with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
nix run '.#configure-instance` -- security.kaareskovgaard.net
|
nix run '.#configure-instance' -- security.kaareskovgaard.net
|
||||||
```
|
```
|
||||||
|
|
||||||
In order for `security.kaareskovgaard.net` to authenticate itself with OpenBAO, the printed credentials needs to be passed to the server with (on the server):
|
In order for `security.kaareskovgaard.net` to authenticate itself with OpenBAO, the printed credentials needs to be passed to the server with (on the server):
|
||||||
|
@ -22,4 +26,18 @@ kanidm-reset-password <user>
|
||||||
|
|
||||||
Open https://login.kaareskovgaard.net - and log into the account, setting up the Yubikey (Passkey) auth, as well as Bitwarden based TOTP/password auth.
|
Open https://login.kaareskovgaard.net - and log into the account, setting up the Yubikey (Passkey) auth, as well as Bitwarden based TOTP/password auth.
|
||||||
|
|
||||||
|
## Disable bootstrapping
|
||||||
|
|
||||||
|
Now remove the previously enabled bootstrapping. Then update the instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix run '.#update-instance' -- security.kaareskovgaard.net
|
||||||
|
```
|
||||||
|
|
||||||
|
And reconfigure it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix run '.#configure-instance' -- security-kaareskovgaard.net
|
||||||
|
```
|
||||||
|
|
||||||
Then `nix run '.#bitwarden-to-vault` can transfer the needed Bitwarden secrets to vault, enabling other instances to not rely on Bitwarden.
|
Then `nix run '.#bitwarden-to-vault` can transfer the needed Bitwarden secrets to vault, enabling other instances to not rely on Bitwarden.
|
||||||
|
|
|
@ -1,32 +1,40 @@
|
||||||
{
|
{
|
||||||
inputs,
|
inputs,
|
||||||
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
|
options.khscodes."security.kaareskovgaard.net" = {
|
||||||
|
bootstrap = {
|
||||||
|
enable = lib.mkEnableOption "Enables bootstrapping mode for security.kaareskovgaard.net. This should be set when first setting up the server. See the README";
|
||||||
|
};
|
||||||
|
};
|
||||||
imports = [
|
imports = [
|
||||||
"${inputs.self}/nix/profiles/nixos/hetzner-server.nix"
|
"${inputs.self}/nix/profiles/nixos/hetzner-server.nix"
|
||||||
./kanidm.nix
|
./kanidm.nix
|
||||||
./openbao.nix
|
./openbao.nix
|
||||||
./post
|
./post
|
||||||
];
|
];
|
||||||
environment.systemPackages = [ pkgs.khscodes.bao-import-secret ];
|
config = {
|
||||||
khscodes.services.nginx.enable = true;
|
environment.systemPackages = [ pkgs.khscodes.bao-import-secret ];
|
||||||
khscodes.infrastructure.hetzner-instance = {
|
khscodes.services.nginx.enable = true;
|
||||||
enable = true;
|
khscodes.infrastructure.hetzner-instance = {
|
||||||
server_type = "cax11";
|
enable = true;
|
||||||
|
server_type = "cax11";
|
||||||
|
};
|
||||||
|
# Cannot use vault for secrets source, as this is the server containing vault.
|
||||||
|
khscodes.infrastructure.provisioning.pre.secretsSource = "bitwarden";
|
||||||
|
khscodes.infrastructure.provisioning.post.secretsSource = "bitwarden";
|
||||||
|
khscodes.infrastructure.vault-server-approle.stage = "post";
|
||||||
|
khscodes.networking.fqdn = "security.kaareskovgaard.net";
|
||||||
|
users.users.khs = {
|
||||||
|
initialPassword = "changeme";
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCqY0FHnWFKfLG2yfgr4qka5sR9CK+EMAhzlHUkaQyWHTKD+G0/vC/fNPyL1VV3Dxc/ajxGuPzVE+mBMoyxazL3EtuCDOVvHJ5CR+MUSEckg/DDwcGHqy6rC8BvVVpTAVL04ByQdwFnpE1qNSBaQLkxaFVdtriGKkgMkc7+UNeYX/bv7yn+APqfP1a3xr6wdkSSdO8x4N2jsSygOIMx10hLyCV4Ueu7Kp8Ww4rGY8j5o7lKJhbgfItBfSOuQHdppHVF/GKYRhdnK6Y2fZVYbhq4KipUtclbZ6O/VYd8/sOO98+LMm7cOX+K35PQjUpYgcoNy5+Sw3CNS/NHn4JvOtTaUEYP7fK6c9LhMULOO3T7Cm6TMdiFjUKHkyG+s2Mu/LXJJoilw571zwuh6chkeitW8+Ht7k0aPV96kNEvTdoXwLhBifVEaChlAsLAzSUjUq+YYCiXVk0VIXCZQWKj8LoVNTmaqDksWwbcT64fw/FpVC0N18WHbKcFUEIW/O4spJMa30CQwf9FeqpoWoaF1oRClCSDPvX0AauCu0JcmRinz1/JmlXljnXWbSfm20/V+WyvktlI0wTD0cdpNuSasT9vS77YfJ8nutcWWZKSkCj4R4uHeCNpDTX5YXzapy7FxpM9ANCXLIvoGX7Yafba2Po+er7SSsUIY1AsnBBr8ZoDVw=="
|
||||||
|
];
|
||||||
|
};
|
||||||
|
khscodes.infrastructure.openbao.domain = "secrets.kaareskovgaard.net";
|
||||||
|
system.stateVersion = "25.05";
|
||||||
};
|
};
|
||||||
# Cannot use vault for secrets source, as this is the server containing vault.
|
|
||||||
khscodes.infrastructure.provisioning.pre.secretsSource = "bitwarden";
|
|
||||||
khscodes.infrastructure.provisioning.post.secretsSource = "bitwarden";
|
|
||||||
khscodes.infrastructure.vault-server-approle.stage = "post";
|
|
||||||
khscodes.networking.fqdn = "security.kaareskovgaard.net";
|
|
||||||
users.users.khs = {
|
|
||||||
initialPassword = "changeme";
|
|
||||||
openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCqY0FHnWFKfLG2yfgr4qka5sR9CK+EMAhzlHUkaQyWHTKD+G0/vC/fNPyL1VV3Dxc/ajxGuPzVE+mBMoyxazL3EtuCDOVvHJ5CR+MUSEckg/DDwcGHqy6rC8BvVVpTAVL04ByQdwFnpE1qNSBaQLkxaFVdtriGKkgMkc7+UNeYX/bv7yn+APqfP1a3xr6wdkSSdO8x4N2jsSygOIMx10hLyCV4Ueu7Kp8Ww4rGY8j5o7lKJhbgfItBfSOuQHdppHVF/GKYRhdnK6Y2fZVYbhq4KipUtclbZ6O/VYd8/sOO98+LMm7cOX+K35PQjUpYgcoNy5+Sw3CNS/NHn4JvOtTaUEYP7fK6c9LhMULOO3T7Cm6TMdiFjUKHkyG+s2Mu/LXJJoilw571zwuh6chkeitW8+Ht7k0aPV96kNEvTdoXwLhBifVEaChlAsLAzSUjUq+YYCiXVk0VIXCZQWKj8LoVNTmaqDksWwbcT64fw/FpVC0N18WHbKcFUEIW/O4spJMa30CQwf9FeqpoWoaF1oRClCSDPvX0AauCu0JcmRinz1/JmlXljnXWbSfm20/V+WyvktlI0wTD0cdpNuSasT9vS77YfJ8nutcWWZKSkCj4R4uHeCNpDTX5YXzapy7FxpM9ANCXLIvoGX7Yafba2Po+er7SSsUIY1AsnBBr8ZoDVw=="
|
|
||||||
];
|
|
||||||
};
|
|
||||||
khscodes.infrastructure.openbao.domain = "secrets.kaareskovgaard.net";
|
|
||||||
system.stateVersion = "25.05";
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
{ config, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
domain = "login.kaareskovgaard.net";
|
domain = "login.kaareskovgaard.net";
|
||||||
|
bootstrapping = config.khscodes."security.kaareskovgaard.net".bootstrap.enable;
|
||||||
openbaoAppBasicSecretFile = "/var/lib/vault-agent/kanidm/openbao_basic_secret";
|
openbaoAppBasicSecretFile = "/var/lib/vault-agent/kanidm/openbao_basic_secret";
|
||||||
openbaoDomain = config.khscodes.infrastructure.openbao.domain;
|
openbaoDomain = config.khscodes.infrastructure.openbao.domain;
|
||||||
openbaoAllowedRedirectUrls = [
|
openbaoAllowedRedirectUrls = [
|
||||||
|
@ -63,35 +69,39 @@ in
|
||||||
present = true;
|
present = true;
|
||||||
members = [ "khs" ];
|
members = [ "khs" ];
|
||||||
};
|
};
|
||||||
systems.oauth2.openbao = {
|
# We cannot add oauth2 apps before the secrets for them are generated.
|
||||||
present = true;
|
systems.oauth2 = lib.mkIf (!bootstrapping) {
|
||||||
public = false;
|
openbao = {
|
||||||
preferShortUsername = true;
|
present = true;
|
||||||
basicSecretFile = openbaoAppBasicSecretFile;
|
public = false;
|
||||||
originUrl = openbaoAllowedRedirectUrls;
|
preferShortUsername = true;
|
||||||
originLanding = "https://${openbaoDomain}";
|
basicSecretFile = openbaoAppBasicSecretFile;
|
||||||
displayName = "OpenBAO";
|
originUrl = openbaoAllowedRedirectUrls;
|
||||||
scopeMaps = {
|
originLanding = "https://${openbaoDomain}";
|
||||||
"openbao_admin" = [
|
displayName = "OpenBAO";
|
||||||
"profile"
|
scopeMaps = {
|
||||||
"email"
|
|
||||||
"openid"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
claimMaps.groups = {
|
|
||||||
joinType = "array";
|
|
||||||
valuesByGroup = {
|
|
||||||
"openbao_admin" = [
|
"openbao_admin" = [
|
||||||
"openbao_reader"
|
"profile"
|
||||||
"openbao_writer"
|
"email"
|
||||||
"openbao_sudo"
|
"openid"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
claimMaps.groups = {
|
||||||
|
joinType = "array";
|
||||||
|
valuesByGroup = {
|
||||||
|
"openbao_admin" = [
|
||||||
|
"openbao_reader"
|
||||||
|
"openbao_writer"
|
||||||
|
"openbao_sudo"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
systemd.services.kanidm = {
|
# Don't add dependencies from bootstrapping when not bootstrapping.
|
||||||
|
systemd.services.kanidm = lib.mkIf (!bootstrapping) {
|
||||||
unitConfig = {
|
unitConfig = {
|
||||||
ConditionPathExists = [
|
ConditionPathExists = [
|
||||||
openbaoAppBasicSecretFile
|
openbaoAppBasicSecretFile
|
||||||
|
@ -142,144 +152,150 @@ in
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# Sets up OIDC authentication within OpenBAO
|
# Sets up OIDC authentication within OpenBAO.
|
||||||
{
|
# OpenBAO queries the openid url for its configuration when adding it, so it is not possible,
|
||||||
resource.vault_jwt_auth_backend.oidc = {
|
# to add this before
|
||||||
description = "Kanidm auth backend";
|
(
|
||||||
path = "oidc";
|
if bootstrapping then
|
||||||
type = "oidc";
|
{ }
|
||||||
oidc_discovery_url = "https://${domain}/oauth2/openid/openbao";
|
else
|
||||||
oidc_client_id = "openbao";
|
{
|
||||||
oidc_client_secret = "\${ resource.random_password.openbao_secret.result }";
|
resource.vault_jwt_auth_backend.oidc = {
|
||||||
jwt_supported_algs = [
|
description = "Kanidm auth backend";
|
||||||
"ES256"
|
path = "oidc";
|
||||||
];
|
type = "oidc";
|
||||||
tune = [
|
oidc_discovery_url = "https://${domain}/oauth2/openid/openbao";
|
||||||
{
|
oidc_client_id = "openbao";
|
||||||
listing_visibility = "unauth";
|
oidc_client_secret = "\${ resource.random_password.openbao_secret.result }";
|
||||||
default_lease_ttl = "2h";
|
jwt_supported_algs = [
|
||||||
max_lease_ttl = "2h";
|
"ES256"
|
||||||
token_type = "default-service";
|
];
|
||||||
passthrough_request_headers = [ ];
|
tune = [
|
||||||
allowed_response_headers = [ ];
|
{
|
||||||
audit_non_hmac_request_keys = [ ];
|
listing_visibility = "unauth";
|
||||||
audit_non_hmac_response_keys = [ ];
|
default_lease_ttl = "2h";
|
||||||
}
|
max_lease_ttl = "2h";
|
||||||
];
|
token_type = "default-service";
|
||||||
};
|
passthrough_request_headers = [ ];
|
||||||
|
allowed_response_headers = [ ];
|
||||||
|
audit_non_hmac_request_keys = [ ];
|
||||||
|
audit_non_hmac_response_keys = [ ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
resource.vault_jwt_auth_backend_role.oidc_reader = {
|
resource.vault_jwt_auth_backend_role.oidc_reader = {
|
||||||
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
||||||
role_name = "reader";
|
role_name = "reader";
|
||||||
bound_audiences = [ "openbao" ];
|
bound_audiences = [ "openbao" ];
|
||||||
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
||||||
user_claim = "sub";
|
user_claim = "sub";
|
||||||
token_policies = [ "reader" ];
|
token_policies = [ "reader" ];
|
||||||
groups_claim = "groups";
|
groups_claim = "groups";
|
||||||
oidc_scopes = [
|
oidc_scopes = [
|
||||||
"openid"
|
"openid"
|
||||||
"profile"
|
"profile"
|
||||||
"email"
|
"email"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_jwt_auth_backend_role.oidc_writer = {
|
resource.vault_jwt_auth_backend_role.oidc_writer = {
|
||||||
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
||||||
role_name = "writer";
|
role_name = "writer";
|
||||||
bound_audiences = [ "openbao" ];
|
bound_audiences = [ "openbao" ];
|
||||||
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
||||||
user_claim = "sub";
|
user_claim = "sub";
|
||||||
token_policies = [ "writer" ];
|
token_policies = [ "writer" ];
|
||||||
groups_claim = "groups";
|
groups_claim = "groups";
|
||||||
oidc_scopes = [
|
oidc_scopes = [
|
||||||
"openid"
|
"openid"
|
||||||
"profile"
|
"profile"
|
||||||
"email"
|
"email"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_jwt_auth_backend_role.oidc_sudo = {
|
resource.vault_jwt_auth_backend_role.oidc_sudo = {
|
||||||
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
||||||
role_name = "sudo";
|
role_name = "sudo";
|
||||||
bound_audiences = [ "openbao" ];
|
bound_audiences = [ "openbao" ];
|
||||||
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
||||||
user_claim = "sub";
|
user_claim = "sub";
|
||||||
token_policies = [ "sudo" ];
|
token_policies = [ "sudo" ];
|
||||||
groups_claim = "groups";
|
groups_claim = "groups";
|
||||||
oidc_scopes = [
|
oidc_scopes = [
|
||||||
"openid"
|
"openid"
|
||||||
"profile"
|
"profile"
|
||||||
"email"
|
"email"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_identity_group.reader = {
|
resource.vault_identity_group.reader = {
|
||||||
name = "reader";
|
name = "reader";
|
||||||
policies = [ "reader" ];
|
policies = [ "reader" ];
|
||||||
type = "external";
|
type = "external";
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_identity_group.writer = {
|
resource.vault_identity_group.writer = {
|
||||||
name = "writer";
|
name = "writer";
|
||||||
policies = [ "writer" ];
|
policies = [ "writer" ];
|
||||||
type = "external";
|
type = "external";
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_identity_group.sudo = {
|
resource.vault_identity_group.sudo = {
|
||||||
name = "sudo";
|
name = "sudo";
|
||||||
policies = [ "sudo" ];
|
policies = [ "sudo" ];
|
||||||
type = "external";
|
type = "external";
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_identity_group_alias.reader = {
|
resource.vault_identity_group_alias.reader = {
|
||||||
name = "openbao_reader";
|
name = "openbao_reader";
|
||||||
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
||||||
canonical_id = "\${ vault_identity_group.reader.id }";
|
canonical_id = "\${ vault_identity_group.reader.id }";
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_identity_group_alias.writer = {
|
resource.vault_identity_group_alias.writer = {
|
||||||
name = "openbao_writer";
|
name = "openbao_writer";
|
||||||
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
||||||
canonical_id = "\${ vault_identity_group.writer.id }";
|
canonical_id = "\${ vault_identity_group.writer.id }";
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_identity_group_alias.sudo = {
|
resource.vault_identity_group_alias.sudo = {
|
||||||
name = "openbao_sudo";
|
name = "openbao_sudo";
|
||||||
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
||||||
canonical_id = "\${ vault_identity_group.writer.id }";
|
canonical_id = "\${ vault_identity_group.writer.id }";
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_policy.reader = {
|
resource.vault_policy.reader = {
|
||||||
name = "reader";
|
name = "reader";
|
||||||
|
|
||||||
policy = ''
|
policy = ''
|
||||||
path "*" {
|
path "*" {
|
||||||
capabilities = ["read", "list"]
|
capabilities = ["read", "list"]
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_policy.writer = {
|
resource.vault_policy.writer = {
|
||||||
name = "writer";
|
name = "writer";
|
||||||
|
|
||||||
policy = ''
|
policy = ''
|
||||||
path "*" {
|
path "*" {
|
||||||
capabilities = ["create", "update", "patch", "read", "delete", "list"]
|
capabilities = ["create", "update", "patch", "read", "delete", "list"]
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
resource.vault_policy.sudo = {
|
resource.vault_policy.sudo = {
|
||||||
name = "sudo";
|
name = "sudo";
|
||||||
|
|
||||||
policy = ''
|
policy = ''
|
||||||
path "auth/token/create" {
|
path "auth/token/create" {
|
||||||
capabilities = ["create", "update", "sudo"]
|
capabilities = ["create", "update", "sudo"]
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
khscodes.services.vault-agent.templates = [
|
khscodes.services.vault-agent.templates = [
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue