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
|
||||
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
|
||||
|
||||
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:
|
||||
|
||||
```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):
|
||||
|
@ -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.
|
||||
|
||||
## 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.
|
||||
|
|
|
@ -1,32 +1,40 @@
|
|||
{
|
||||
inputs,
|
||||
lib,
|
||||
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 = [
|
||||
"${inputs.self}/nix/profiles/nixos/hetzner-server.nix"
|
||||
./kanidm.nix
|
||||
./openbao.nix
|
||||
./post
|
||||
];
|
||||
environment.systemPackages = [ pkgs.khscodes.bao-import-secret ];
|
||||
khscodes.services.nginx.enable = true;
|
||||
khscodes.infrastructure.hetzner-instance = {
|
||||
enable = true;
|
||||
server_type = "cax11";
|
||||
config = {
|
||||
environment.systemPackages = [ pkgs.khscodes.bao-import-secret ];
|
||||
khscodes.services.nginx.enable = true;
|
||||
khscodes.infrastructure.hetzner-instance = {
|
||||
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
|
||||
domain = "login.kaareskovgaard.net";
|
||||
bootstrapping = config.khscodes."security.kaareskovgaard.net".bootstrap.enable;
|
||||
openbaoAppBasicSecretFile = "/var/lib/vault-agent/kanidm/openbao_basic_secret";
|
||||
openbaoDomain = config.khscodes.infrastructure.openbao.domain;
|
||||
openbaoAllowedRedirectUrls = [
|
||||
|
@ -63,35 +69,39 @@ in
|
|||
present = true;
|
||||
members = [ "khs" ];
|
||||
};
|
||||
systems.oauth2.openbao = {
|
||||
present = true;
|
||||
public = false;
|
||||
preferShortUsername = true;
|
||||
basicSecretFile = openbaoAppBasicSecretFile;
|
||||
originUrl = openbaoAllowedRedirectUrls;
|
||||
originLanding = "https://${openbaoDomain}";
|
||||
displayName = "OpenBAO";
|
||||
scopeMaps = {
|
||||
"openbao_admin" = [
|
||||
"profile"
|
||||
"email"
|
||||
"openid"
|
||||
];
|
||||
};
|
||||
claimMaps.groups = {
|
||||
joinType = "array";
|
||||
valuesByGroup = {
|
||||
# We cannot add oauth2 apps before the secrets for them are generated.
|
||||
systems.oauth2 = lib.mkIf (!bootstrapping) {
|
||||
openbao = {
|
||||
present = true;
|
||||
public = false;
|
||||
preferShortUsername = true;
|
||||
basicSecretFile = openbaoAppBasicSecretFile;
|
||||
originUrl = openbaoAllowedRedirectUrls;
|
||||
originLanding = "https://${openbaoDomain}";
|
||||
displayName = "OpenBAO";
|
||||
scopeMaps = {
|
||||
"openbao_admin" = [
|
||||
"openbao_reader"
|
||||
"openbao_writer"
|
||||
"openbao_sudo"
|
||||
"profile"
|
||||
"email"
|
||||
"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 = {
|
||||
ConditionPathExists = [
|
||||
openbaoAppBasicSecretFile
|
||||
|
@ -142,144 +152,150 @@ in
|
|||
};
|
||||
}
|
||||
)
|
||||
# Sets up OIDC authentication within OpenBAO
|
||||
{
|
||||
resource.vault_jwt_auth_backend.oidc = {
|
||||
description = "Kanidm auth backend";
|
||||
path = "oidc";
|
||||
type = "oidc";
|
||||
oidc_discovery_url = "https://${domain}/oauth2/openid/openbao";
|
||||
oidc_client_id = "openbao";
|
||||
oidc_client_secret = "\${ resource.random_password.openbao_secret.result }";
|
||||
jwt_supported_algs = [
|
||||
"ES256"
|
||||
];
|
||||
tune = [
|
||||
{
|
||||
listing_visibility = "unauth";
|
||||
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 = [ ];
|
||||
}
|
||||
];
|
||||
};
|
||||
# Sets up OIDC authentication within OpenBAO.
|
||||
# OpenBAO queries the openid url for its configuration when adding it, so it is not possible,
|
||||
# to add this before
|
||||
(
|
||||
if bootstrapping then
|
||||
{ }
|
||||
else
|
||||
{
|
||||
resource.vault_jwt_auth_backend.oidc = {
|
||||
description = "Kanidm auth backend";
|
||||
path = "oidc";
|
||||
type = "oidc";
|
||||
oidc_discovery_url = "https://${domain}/oauth2/openid/openbao";
|
||||
oidc_client_id = "openbao";
|
||||
oidc_client_secret = "\${ resource.random_password.openbao_secret.result }";
|
||||
jwt_supported_algs = [
|
||||
"ES256"
|
||||
];
|
||||
tune = [
|
||||
{
|
||||
listing_visibility = "unauth";
|
||||
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 = {
|
||||
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
||||
role_name = "reader";
|
||||
bound_audiences = [ "openbao" ];
|
||||
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
||||
user_claim = "sub";
|
||||
token_policies = [ "reader" ];
|
||||
groups_claim = "groups";
|
||||
oidc_scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
];
|
||||
};
|
||||
resource.vault_jwt_auth_backend_role.oidc_reader = {
|
||||
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
||||
role_name = "reader";
|
||||
bound_audiences = [ "openbao" ];
|
||||
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
||||
user_claim = "sub";
|
||||
token_policies = [ "reader" ];
|
||||
groups_claim = "groups";
|
||||
oidc_scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
];
|
||||
};
|
||||
|
||||
resource.vault_jwt_auth_backend_role.oidc_writer = {
|
||||
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
||||
role_name = "writer";
|
||||
bound_audiences = [ "openbao" ];
|
||||
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
||||
user_claim = "sub";
|
||||
token_policies = [ "writer" ];
|
||||
groups_claim = "groups";
|
||||
oidc_scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
];
|
||||
};
|
||||
resource.vault_jwt_auth_backend_role.oidc_writer = {
|
||||
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
||||
role_name = "writer";
|
||||
bound_audiences = [ "openbao" ];
|
||||
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
||||
user_claim = "sub";
|
||||
token_policies = [ "writer" ];
|
||||
groups_claim = "groups";
|
||||
oidc_scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
];
|
||||
};
|
||||
|
||||
resource.vault_jwt_auth_backend_role.oidc_sudo = {
|
||||
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
||||
role_name = "sudo";
|
||||
bound_audiences = [ "openbao" ];
|
||||
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
||||
user_claim = "sub";
|
||||
token_policies = [ "sudo" ];
|
||||
groups_claim = "groups";
|
||||
oidc_scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
];
|
||||
};
|
||||
resource.vault_jwt_auth_backend_role.oidc_sudo = {
|
||||
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
|
||||
role_name = "sudo";
|
||||
bound_audiences = [ "openbao" ];
|
||||
allowed_redirect_uris = openbaoAllowedRedirectUrls;
|
||||
user_claim = "sub";
|
||||
token_policies = [ "sudo" ];
|
||||
groups_claim = "groups";
|
||||
oidc_scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
];
|
||||
};
|
||||
|
||||
resource.vault_identity_group.reader = {
|
||||
name = "reader";
|
||||
policies = [ "reader" ];
|
||||
type = "external";
|
||||
};
|
||||
resource.vault_identity_group.reader = {
|
||||
name = "reader";
|
||||
policies = [ "reader" ];
|
||||
type = "external";
|
||||
};
|
||||
|
||||
resource.vault_identity_group.writer = {
|
||||
name = "writer";
|
||||
policies = [ "writer" ];
|
||||
type = "external";
|
||||
};
|
||||
resource.vault_identity_group.writer = {
|
||||
name = "writer";
|
||||
policies = [ "writer" ];
|
||||
type = "external";
|
||||
};
|
||||
|
||||
resource.vault_identity_group.sudo = {
|
||||
name = "sudo";
|
||||
policies = [ "sudo" ];
|
||||
type = "external";
|
||||
};
|
||||
resource.vault_identity_group.sudo = {
|
||||
name = "sudo";
|
||||
policies = [ "sudo" ];
|
||||
type = "external";
|
||||
};
|
||||
|
||||
resource.vault_identity_group_alias.reader = {
|
||||
name = "openbao_reader";
|
||||
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
||||
canonical_id = "\${ vault_identity_group.reader.id }";
|
||||
};
|
||||
resource.vault_identity_group_alias.reader = {
|
||||
name = "openbao_reader";
|
||||
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
||||
canonical_id = "\${ vault_identity_group.reader.id }";
|
||||
};
|
||||
|
||||
resource.vault_identity_group_alias.writer = {
|
||||
name = "openbao_writer";
|
||||
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
||||
canonical_id = "\${ vault_identity_group.writer.id }";
|
||||
};
|
||||
resource.vault_identity_group_alias.writer = {
|
||||
name = "openbao_writer";
|
||||
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
||||
canonical_id = "\${ vault_identity_group.writer.id }";
|
||||
};
|
||||
|
||||
resource.vault_identity_group_alias.sudo = {
|
||||
name = "openbao_sudo";
|
||||
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
||||
canonical_id = "\${ vault_identity_group.writer.id }";
|
||||
};
|
||||
resource.vault_identity_group_alias.sudo = {
|
||||
name = "openbao_sudo";
|
||||
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
|
||||
canonical_id = "\${ vault_identity_group.writer.id }";
|
||||
};
|
||||
|
||||
resource.vault_policy.reader = {
|
||||
name = "reader";
|
||||
resource.vault_policy.reader = {
|
||||
name = "reader";
|
||||
|
||||
policy = ''
|
||||
path "*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
'';
|
||||
};
|
||||
policy = ''
|
||||
path "*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
resource.vault_policy.writer = {
|
||||
name = "writer";
|
||||
resource.vault_policy.writer = {
|
||||
name = "writer";
|
||||
|
||||
policy = ''
|
||||
path "*" {
|
||||
capabilities = ["create", "update", "patch", "read", "delete", "list"]
|
||||
}
|
||||
'';
|
||||
};
|
||||
policy = ''
|
||||
path "*" {
|
||||
capabilities = ["create", "update", "patch", "read", "delete", "list"]
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
resource.vault_policy.sudo = {
|
||||
name = "sudo";
|
||||
resource.vault_policy.sudo = {
|
||||
name = "sudo";
|
||||
|
||||
policy = ''
|
||||
path "auth/token/create" {
|
||||
capabilities = ["create", "update", "sudo"]
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
||||
policy = ''
|
||||
path "auth/token/create" {
|
||||
capabilities = ["create", "update", "sudo"]
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
||||
)
|
||||
];
|
||||
|
||||
khscodes.services.vault-agent.templates = [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue