Tag: ssh

Commands for Signed SSH Certificates using Hashicorp Vault

Commands for Signed SSH Certificates using Hashicorp Vault

List down the commands required.

Client

Generate SSH Admin token (One time)

export VAULT_ADDR='https://vault.bx.net:8200'
export VAULT_TOKEN="<ROOT_TOKEN>"

vault token create -field token -policy=ssh-admin-policy

Renew Admin token

export VAULT_TOKEN="<SSH_ADMIN_TOKEN>"
vault token renew

Generate signed certificate

export VAULT_TOKEN="<SSH_ADMIN_TOKEN>"
vault token lookup
vault write -field=signed_key ssh-client-signer/sign/my-role public_key=@$HOME/.ssh/id_rsa.pub > ~/.ssh/signed-cert.pub

SSH using signed certificate

ssh -i ~/.ssh/signed-cert.pub -i ~/.ssh/id_rsa <host>

Server

Save CA key

export VAULT_ADDR='https://vault.bx.net:8200'
export VAULT_TOKEN="<ROOT_TOKEN>"

vault read -field=public_key ssh-client-signer/config/ca > /etc/ssh/trusted-user-ca-keys.pem

Configure /etc/ssh/sshd_config

Add following lines in /etc/ssh/sshd_config

TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
CASignatureAlgorithms ^ssh-rsa

Note: Comment out last line if SSH got error

Troubleshooting

Server SSL cert

The SSL cert in vault server needs to be trusted by local client, otherwise, following server occurred.

Error writing data to ssh-client-signer/sign/my-role: Put "<role_name>": x509: certificate signed by unknown authority

References

SSH Proxy

SSH Proxy

When access remote servers, proxy server/jump host could be a good choice.

Two servers definition

jump_host

This is the proxy server, normally can be in the form of user@proxy_host.

target

This is the target server, has the form of target_user@target_host.

Jump host

This is the most simplest method which uses remote ssh command to login to target server. If just wants to use one SSH server to access another SSH server, run following command

ssh -t <jump_host> ssh <target>

Here -t is to create a pseudo-terminal, otherwise, the remote server could not display message because no tty can be used.

Proxy Jump

This is using SSH building proxy function.

ssh -o "ProxyJump <jump_host>" <target>

Proxy Command

This is to run an external command to build communication. For example, use nc command, and pass two parameters, %h is the target host, %p is the port.

ssh -o "ProxyCommand ssh <jump_host> nc %h %p" <target>

Use ssh client configuration

./ssh/cofig

Instead of using command, ProxyJump and ProxyCommand can be set in ssh client configuration file.

Host <connection_name>
  HostName <target_host>
  User <target_user>
  ProxyCommand ssh <jump_host> nc %h %p

For one server

Host target
  HostName 192.168.1.2
  User user1
  ProxyCommand ssh user2@proxy nc %h %p

For all servers

Host * !proxy
  HostName %h
  User target_user
  # ProxyCommand ssh proxy_user@proxy nc %h %p

/etc/ssh/ssh_config

This is the same as previous example, except it is a global setting.

References

4 ways to SSH & SCP via proxy (jump) server in Linux

More secure but easy ways to access SSH server

More secure but easy ways to access SSH server

Except User name and Password, which is hard to remember if you don't want others guess it easily, there are other easy ways to protect SSH server.

Public Key

Steps

This is most a simple way, just generate a pair of key,

ssh-keygen

If need more secure, generate 4096 bit RSA key

ssh-keygen  -t rsa -b 4096

Then inject public key in .ssh/id_rsa.pub into remote .ssh/authorized_keys

Cons

  • Needs to perform for every user
  • Needs to inject public keys of clients into all target servers
  • No expiration

Signed Certificate

Steps

Refer to Signed SSH Certificates using Hashicorp Vault in Practice

  • Use free software, hashicorp vault to manage signed certificate.

  • Inject trusted CA key retrieved from vault into target SSH server configure,

  • Use authorized token and client private key to generate short life signed certificate

  • Use signed certificate and client private key login to target server

Note: Only need normal token to generate signed certificate

  • Authorized token can be renewed (replaced) after used

Pros

  • Token never reach Internet, and it can be renewed (replaced) any time
  • Signed certificate has short life

Cons

Need to save a token

2FA

Steps

Refer to Enable 2FA for Ubuntu

Pros

  • Only need a 2FA software, and adding digits after key in password
  • Short life of digits

LDAP or Kerberos

Instead of all servers maintain their own password, passwords are centrally managed by authentication server.

Cons

  • Every server needs connection to authentication server
  • Cannot login if lost connection to authentication server
  • All servers are using same password

One time password

Retrieve password from authentication server, then use it to login to remote server.

Remote server will use it to verify against authentication server.

Cons

  • Every server needs connection to password server
  • Cannot login if lost connection to password server

Admin Token for AppRole in Hashicorp Vault

Admin Token for AppRole in Hashicorp Vault

As suggested, root token should not be used, and it should be revoked immediately after used.

Root token

Follow the steps in page below to create a new root token and revoke it after used.

Generate a new root token for Hashicorp Vault

Admin token

For example, SSH secret engine, following admin policy can be created

vault policy write ssh-admin-policy - << EOF
# SSH secret engine
path "ssh-client-signer/sign/*" {
  capabilities = ["create", "read", "update", "delete", "sudo", "list" ]
}

# Mount the AppRole auth method
path "sys/auth/approle" {
  capabilities = [ "create", "read", "update", "delete", "sudo" ]
}

# Configure the AppRole auth method
path "sys/auth/approle/*" {
  capabilities = [ "create", "read", "update", "delete" ]
}

# Create and manage roles
path "auth/approle/*" {
  capabilities = [ "create", "read", "update", "delete", "list" ]
}

# Write ACL policies
path "sys/policies/acl/*" {
  capabilities = [ "create", "read", "update", "delete", "list" ]
}

##### Add other requirement if required. For example
# Write test data
# Set the path to "secret/data/mysql/*" if you are running `kv-v2`
path "secret/mysql/*" {
  capabilities = [ "create", "read", "update", "delete", "list" ]
}
EOF

Then create token under this policy

vault token create -field token -policy=ssh-admin-policy

The using this token follow the steps in page below:

Signed SSH Certificates using Hashicorp Vault in Practice

  • Generate role_id and secret_id
  • Login using role_id and secret_id
  • Generate SSH policy token
  • Use SSH policy token to generate signed public key
  • Use the signed public key and private key to login to remote system

Renew token itself

To get renew token before expired, run following command

vault token renew

The expire time can be view using following command

vault token lookup

References

Tokens
AppRole Pull Authentication

Signed SSH Certificates using Hashicorp Vault in Practice

Signed SSH Certificates using Hashicorp Vault in Practice

In previous setup, root token is used all the time, which should not be the case in real situation.

Steps

Preparation of Vault and SSH Server

The steps can follow Signed SSH Certificates using Hashicorp Vault

Using root token

export VAULT_TOKEN=<root_token>
export VAULT_ADDR='http://host:8200'

Create Policy

$ vault policy write my-policy - << EOF
path "ssh-client-signer/sign/my-role" {
  capabilities = ["create", "update", "read"]
}
EOF

Get Policy token

$ vault token create -field token -policy=my-policy

Test Policy in SSH client machine

  • Using token in SSH client
$ export VAULT_TOKEN="<policy_token>"
$ vault write -field=signed_key ssh-client-signer/sign/my-role public_key=@$HOME/.ssh/id_rsa.pub > signed-cert.pub
  • SSH into target system using signed public key and private key in SSH client
ssh -i signed-cert.pub -i ~/.ssh/id_rsa ubuntu@host

Enable approle

vault auth enable approle

Create role

vault write auth/approle/role/my-role \
    secret_id_ttl=10m \
    token_num_uses=10 \
    token_ttl=20m \
    token_max_ttl=30m \
    secret_id_num_uses=40 \
    token_policies=my-policy

Get role_id and secret_id

vault read -field=role_id auth/approle/role/my-role/role-id
vault write -f -field=secret_id auth/approle/role/my-role/secret-id

Login from SSH client machine

export VAULT_ADDR='http://host:8200'
export ROLE_ID=<role_id>
export SECRET_ID=<secret_id>
vault write auth/approle/login role_id="$ROLE_ID" secret_id="$SECRET_ID"

Result contains token

Key                     Value
---                     -----
token                   s.Sh9h1wZ9ycATeSaASoOQvovr
...

Check the token info

vault token lookup | grep policies
policies            [default my-policy]

Test Policy in SSH client machine

  • Using token in SSH client
$ export VAULT_TOKEN="<policy_token>"
$ vault write -field=signed_key ssh-client-signer/sign/my-role public_key=@$HOME/.ssh/id_rsa.pub > signed-cert.pub
  • SSH into target system using signed public key and private key in SSH client
ssh -i signed-cert.pub -i ~/.ssh/id_rsa ubuntu@host

Consideration

Disable password authentication

If tested finished, password authentication can be set to no:

PasswordAuthentication no

Time valid for SECRET_ID

If the secret_id expires so fast, then needs to have master token to generate secret_id again, because the policy token is generated using role_id and secret_id pair.

If don't use approle, then all SSH clients can use policy token. Still thinking the advantage of using role_id and secret_id.

Use admin token instead

The root token should not be used as recommended. Will try admin token later.

References

Policies

Signed SSH Certificates using Hashicorp Vault

Signed SSH Certificates using Hashicorp Vault

The idear of signed SSH certificates verification is to use valid (signed) SSH certificate to be verified by SSH server or by SSH client, or by both.

Mechanism

Vaildated by SSH server

Client retrieves signed public key which issued by the CA key in Vault. This key has short expiry date.

Server uses the CA public key configured in SSH configuration, validates the client public key issued by Vault.

Validated by SSH client

This is to validate server public whether signed by Vault by place public key in .ssh/known_hosts file. This key should have long expiry date.

Steps

Vault Server preparation

  • Login into Vault
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN="<token>"
  • Enable SSH secret engine
$ vault secrets enable -path=ssh-client-signer ssh
Successfully mounted 'ssh' at 'ssh-client-signer'!
  • Configure CA
$ vault write ssh-client-signer/config/ca generate_signing_key=true
Key             Value
---             -----
public_key      ssh-rsa AAAAB3NzaC1yc2EA...
  • Create Role

Beware of *allowed_users" and "default_user", they must be set correctly.

$ vault write ssh-client-signer/roles/my-role -<<"EOH"
{
  "allow_user_certificates": true,
  "allowed_users": "*",
  "allowed_extensions": "permit-pty,permit-port-forwarding",
  "default_extensions": [
    {
      "permit-pty": ""
    }
  ],
  "key_type": "ca",
  "default_user": "ubuntu",
  "ttl": "30m0s"
}
EOH

SSH Server Setup

  • Login to Vault
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN="<token>"
  • Save CA key
# vault read -field=public_key ssh-client-signer/config/ca > /etc/ssh/trusted-user-ca-keys.pem
  • Configure SSHD

Add following lines in /etc/ssh/sshd_config

TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
  • Restart SSHD
# systemctl restart sshd

SSH Client

  • Generate SSH key pair if haven't done
$ ssh-keygen -t rsa -C "user@example.com"

This will generate a pair of files, .ssh/id_rsa and .ssh/id_rsa.pub.

  • Generate and save signed public key using client public key
$ vault write -field=signed_key ssh-client-signer/sign/my-role \
    public_key=@$HOME/.ssh/id_rsa.pub > signed-cert.pub
  • Verify signed key (optional)

This can verify the valid period and user

$ ssh-keygen -Lf ~/.ssh/signed-cert.pub
...
        Valid: from 2021-11-27T17:51:29 to 2021-11-27T18:21:59
        Principals: 
                ubuntu
...
  • Login to server using both signed key and private key
$ ssh -i signed-cert.pub -i ~/.ssh/id_rsa username@10.0.23.5

Note: Add following configure in /etc/ssh/sshd_config if got error __userauth_pubkey: certificate signature algorithm ssh-rsa: signature algorithm not supported [preauth]__

CASignatureAlgorithms ^ssh-rsa

References

Signed SSH Certificates
Leveraging Signed SSH for Remote Access with Vault