From 86be17956697fd65366e028f85c304c0f6e1f7cd Mon Sep 17 00:00:00 2001 From: fxkk Date: Fri, 12 Jan 2024 12:16:01 +0100 Subject: [PATCH] feat(ssh): add signed ssh certificates lab --- docs/assets/ssh_sign.png | Bin 0 -> 30314 bytes docs/ssh.md | 105 ++++++++++++++++++++++++++++++++ main.tf | 8 +++ terraform.tfvars | 5 ++ variables.tf | 6 ++ vault-ssh/files/init.sh | 14 +++++ vault-ssh/terraform/main.tf | 55 +++++++++++++++++ vault-ssh/terraform/versions.tf | 15 +++++ 8 files changed, 208 insertions(+) create mode 100644 docs/assets/ssh_sign.png create mode 100644 docs/ssh.md create mode 100644 vault-ssh/files/init.sh create mode 100644 vault-ssh/terraform/main.tf create mode 100644 vault-ssh/terraform/versions.tf diff --git a/docs/assets/ssh_sign.png b/docs/assets/ssh_sign.png new file mode 100644 index 0000000000000000000000000000000000000000..cd77113775a0ba2241fb548d8ac8cb83062714f9 GIT binary patch literal 30314 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 literal 0 HcmV?d00001 diff --git a/docs/ssh.md b/docs/ssh.md new file mode 100644 index 0000000..54a59eb --- /dev/null +++ b/docs/ssh.md @@ -0,0 +1,105 @@ +# SSH secrets engine + +![img](assets/shh_sign.png) +> https://www.hashicorp.com/blog/managing-ssh-access-at-scale-with-hashicorp-vault + + +The idea of the ssh secret engine is to supplement the classic ssh public key authentication with a signing workflow. + +This means that public keys are no longer entered in the authorized keys files on individual hosts. Instead, all hosts trust the vault ssh ca and therefore keys signed by it. The contexts in which the signed key are valid is specified in the signature. + +To log on to a server, not only the private key but also the corresponding public key signed by the vault ca must be provided. + +The numbers in the diagram represent the following steps: + +- User creates a personal SSH key pair. +- User authenticates to Vault with their Identity Provider (IDP) credentials. +- Once authenticated, the user sends their SSH public key to Vault for signing. +- Vault signs the SSH key and return the SSH certificate to the user. +- User initiates SSH connection using the SSH certificate. +- Host verifies the client SSH certificate is signed by the trusted SSH CA and allows connection. + +[HashiCorp Blog](https://www.hashicorp.com/blog/managing-ssh-access-at-scale-with-hashicorp-vault) + + +## Requirements +You can enable this lab by setting: + +```yaml +# terraform.tfvars +ssh = { + enabled = true +} +``` + +You then can bootstrap the cluster using `make bootstrap` + +## Overview +The following resources will be created: + +1. A Ubuntu Container will be deployed +2. The ssh secret engine will be enabled +3. A ssh signing ca will be created +4. A ssh secret backend role that will allow you to login as the ubuntu user + +## Walkthrough + +The SSH signing ca has been configured under the `ssh-client-signer` path. + +```bash +$ vault secrets list +Path Type Accessor Description +---- ---- -------- ----------- +ssh-client-signer/ ssh ssh_002866eb n/a + +$ vault read ssh-client-signer/config/ca +Key Value +--- ----- +public_key ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDjcpfjEV7fqCj6I14a6oGrfy6M9Fgi5ZQj7brbocNXG4w4GkZkrO5g93fec+5vcn6eoJYG4n== +``` + +A ssh signer role has been created. + +```bash +$vault read ssh-client-signer/roles/ubuntu +Key Value +--- ----- +algorithm_signer default +allow_bare_domains false +allow_host_certificates false +allow_subdomains false +allow_user_certificates true +allow_user_key_ids false +allowed_critical_options n/a +allowed_domains n/a +allowed_domains_template false +allowed_extensions n/a +allowed_user_key_lengths map[] +allowed_users ubuntu +allowed_users_template false +default_critical_options map[] +default_extensions map[permit-pty:] +default_extensions_template false +default_user ubuntu +default_user_template false +key_id_format n/a +key_type ca +max_ttl 0s +not_before_duration 30s +ttl +``` + +To log in to the ubuntu container you need to sign you public key. + +```bash +$ vault write -field=signed_key ssh-client-signer/sign/ubuntu public_key=@$HOME/.ssh/id_rsa.pub >| signed-cert.pub +``` + +Query the ip of the ubuntu container and use the signed public key and your private key to connect. + +```bash +export UBUNTU_IP=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ubuntu + +ssh -i signed-cert.pub -i ~/.ssh/id_rsa ubuntu@$UBUNTU_IP +``` + diff --git a/main.tf b/main.tf index 926169f..3f9f886 100644 --- a/main.tf +++ b/main.tf @@ -102,3 +102,11 @@ module "cm" { depends_on = [module.vault_k8s] } + +module "ssh" { + count = var.ssh.enabled ? 1 : 0 + + source = "./vault-ssh/terraform" + + depends_on = [module.vault] +} diff --git a/terraform.tfvars b/terraform.tfvars index 5f4efe8..ff13d3d 100644 --- a/terraform.tfvars +++ b/terraform.tfvars @@ -43,3 +43,8 @@ kubernetes = { # enable vault agent injector vault_agent_injector = true } + + +ssh = { + enabled = false +} \ No newline at end of file diff --git a/variables.tf b/variables.tf index 15d2dea..61d658f 100644 --- a/variables.tf +++ b/variables.tf @@ -30,3 +30,9 @@ variable "kubernetes" { cert_manager = optional(bool, true) }) } + +variable "ssh" { + type = object({ + enabled = optional(bool, true) + }) +} diff --git a/vault-ssh/files/init.sh b/vault-ssh/files/init.sh new file mode 100644 index 0000000..119bf43 --- /dev/null +++ b/vault-ssh/files/init.sh @@ -0,0 +1,14 @@ +#/usr/bin/sh + +apt-get update +apt install -y openssh-server curl + +mkdir /var/run/sshd +sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config +curl -k -o /etc/ssh/trusted-user-ca-keys.pem https://haproxy/v1/ssh-client-signer/public_key +echo "TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem" >> /etc/ssh/sshd_config + +useradd -m ubuntu -s /bin/bash + + +/usr/sbin/sshd -D \ No newline at end of file diff --git a/vault-ssh/terraform/main.tf b/vault-ssh/terraform/main.tf new file mode 100644 index 0000000..bddccaf --- /dev/null +++ b/vault-ssh/terraform/main.tf @@ -0,0 +1,55 @@ + +data "docker_network" "vault" { + name = "vault" +} + +resource "docker_container" "ubuntu" { + name = "ubuntu" + image = "ubuntu:latest" + + command = ["/usr/bin/sh", "/files/init.sh"] + + volumes { + host_path = abspath("${path.root}/vault-tls/output") + container_path = "/opt/tls/" + read_only = true + } + + volumes { + host_path = abspath("${path.root}/vault-ssh/files") + container_path = "/files" + read_only = true + } + + networks_advanced { + name = data.docker_network.vault.name + } + + lifecycle { + ignore_changes = all + } + + depends_on = [vault_ssh_secret_backend_ca.this] +} + +resource "vault_mount" "ssh" { + type = "ssh" + path = "ssh-client-signer" +} + +resource "vault_ssh_secret_backend_ca" "this" { + backend = vault_mount.ssh.path + generate_signing_key = true +} + +resource "vault_ssh_secret_backend_role" "ubuntu" { + name = "ubuntu" + backend = vault_mount.ssh.path + key_type = "ca" + allow_user_certificates = true + allowed_users = "ubuntu" + default_user = "ubuntu" + default_extensions = { + "permit-pty" : "" + } +} \ No newline at end of file diff --git a/vault-ssh/terraform/versions.tf b/vault-ssh/terraform/versions.tf new file mode 100644 index 0000000..677b2f3 --- /dev/null +++ b/vault-ssh/terraform/versions.tf @@ -0,0 +1,15 @@ +terraform { + required_version = ">= 1.6.0" + + required_providers { + vault = { + source = "hashicorp/vault" + version = "3.20.1" + } + docker = { + source = "kreuzwerker/docker" + version = "3.0.2" + } + } +} +