Vault Implementation Reference Architecture
Vault and Consul
Vault with Consul Storage Reference Architecture
Vault with Consul Storage Reference Architecture
In previous setup, root token is used all the time, which should not be the case in real situation.
The steps can follow Signed SSH Certificates using Hashicorp Vault
export VAULT_TOKEN=<root_token>
export VAULT_ADDR='http://host:8200'
$ vault policy write my-policy - << EOF
path "ssh-client-signer/sign/my-role" {
capabilities = ["create", "update", "read"]
}
EOF
$ vault token create -field token -policy=my-policy
$ 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 -i signed-cert.pub -i ~/.ssh/id_rsa ubuntu@host
vault auth enable approle
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
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
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
...
vault token lookup | grep policies
policies [default my-policy]
$ 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 -i signed-cert.pub -i ~/.ssh/id_rsa ubuntu@host
If tested finished, password authentication can be set to no:
PasswordAuthentication no
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.
The root token should not be used as recommended. Will try admin token later.
Download following packages, install first two packages.
Xcode_10.1.xip
Command_Line_Tools_macOS_10.13_for_Xcode_10.1.dmg
Kernel_Debug_Kit_10.13.6_build_17G10017.dmg
Swift_5_Runtime_Support_for_Command_Line_Tools.dmg
Swift_Playgrounds_Author_Template_for_Xcode_10.xip
Font_Tools_for_Xcode_11.dmg
Additional_Tools_for_Xcode_10.1.dmg
Run following command to install
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
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.
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.
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.
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN="<token>"
$ vault secrets enable -path=ssh-client-signer ssh
Successfully mounted 'ssh' at 'ssh-client-signer'!
$ vault write ssh-client-signer/config/ca generate_signing_key=true
Key Value
--- -----
public_key ssh-rsa AAAAB3NzaC1yc2EA...
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
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN="<token>"
# vault read -field=public_key ssh-client-signer/config/ca > /etc/ssh/trusted-user-ca-keys.pem
Add following lines in /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
# systemctl restart sshd
$ ssh-keygen -t rsa -C "user@example.com"
This will generate a pair of files, .ssh/id_rsa
and .ssh/id_rsa.pub
.
$ vault write -field=signed_key ssh-client-signer/sign/my-role \
public_key=@$HOME/.ssh/id_rsa.pub > signed-cert.pub
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
...
$ 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
Signed SSH Certificates
Leveraging Signed SSH for Remote Access with Vault
mkdir -p vault/{config,file,logs}
Create vault/config/vault.json
{
"backend": {
"file": {
"path": "/vault/file"
}
},
"listener": {
"tcp":{
"address": "0.0.0.0:8200",
"tls_disable": 1
}
},
"ui": true
}
Create file vault/docker-compose.yml
version: '3.7'
services:
vault:
image: vault:latest
container_name: vault
ports:
- "8200:8200"
restart: unless-stopped
volumes:
- ./logs:/vault/logs
- ./file:/vault/file
- ./config:/vault/config
cap_add:
- IPC_LOCK
entrypoint: vault server -config=/vault/config/vault.json
Run docker-compose command in vault
folder
cd vault
docker-compose up -d
Access http://localhost:8200/ from browser
# curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add -
# apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
# apt-get install vault
# vault
$ export VAULT_ADDR='http://127.0.0.1:8200'
$ export VAULT_TOKEN="<token>"
$ vault status
...
Sealed false
...
Subcommand | kv v1 | kv v2 | Description |
---|---|---|---|
delete | x | x | Delete versions of secrets stored in K/V |
destroy | x | Permanently remove one or more versions of secrets | |
enable-versioning | x | Turns on versioning for an existing K/V v1 store | |
get | x | x | Retrieve data |
list | x | x | List data or secrets |
metadata | x | Interact with Vault\'s Key-Value storage | |
patch | x | Update secrets without overwriting existing secrets | |
put | x | x | Sets or update secrets (this replaces existing secrets) |
rollback | x | Rolls back to a previous version of secrets | |
undelete | x | Restore the deleted version of secrets |
Example:
vault-getting-started:~# vault login root
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token root
token_accessor rSn3h08ikdez4zch5ghr4wYY
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
vault-getting-started:~# vault kv put secret/hello foo=world
Key Value
--- -----
created_time 2021-11-25T06:15:45.332182013Z
deletion_time n/a
destroyed false
version 1
vault-getting-started:~# vault kv put secret/hello foo=world excited=yes
Key Value
--- -----
created_time 2021-11-25T06:15:48.808651794Z
deletion_time n/a
destroyed false
version 2
vault-getting-started:~# vault kv get secret/hello
====== Metadata ======
Key Value
--- -----
created_time 2021-11-25T06:15:48.808651794Z
deletion_time n/a
destroyed false
version 2
===== Data =====
Key Value
--- -----
excited yes
foo world
vault-getting-started:~# vault kv get -field=excited secret/hello
yes
vault-getting-started:~# vault kv get -format=json secret/hello | jq -r .data.data.excited
yes
vault-getting-started:~# vault kv delete secret/hello
Success! Data deleted (if it existed) at: secret/hello
vault-getting-started:~#
The driver to save secret in different way, type of secret.
Every path has it's own secret type
$ vault secrets list
Path Type Accessor Description
---- ---- -------- -----------
cubbyhole/ cubbyhole cubbyhole_78189996 per-token private secret storage
identity/ identity identity_ac07951e identity store
kv/ kv kv_15087625 n/a
secret/ kv kv_4b990c45 key/value secret storage
sys/ system system_adff0898 system endpoints used for control, policy and debugging
Set one path to specific secret type
$ vault secrets enable -path=kv kv
Success! Enabled the kv secrets engine at: kv/
or
$ vault secrets enable kv
$ vault kv put kv/hello target=world
Success! Data written to: kv/hello
$ vault kv get kv/hello
===== Data =====
Key Value
--- -----
target world
$ vault kv delete kv/hello
Success! Data deleted (if it existed) at: kv/hello
$ vault kv list kv/
Keys
----
hello
$ vault secrets disable kv/
Success! Disabled the secrets engine (if it existed) at: kv/
When using secret engine such as aws engine.
$ vault secrets enable -path=aws aws
Success! Enabled the aws secrets engine at: aws/
More Info: Dynamic Secrets
$ vault token create
Key Value
--- -----
token s.iyNUhq8Ov4hIAx6snw5mB2nL
token_accessor maMfHsZfwLB6fi18Zenj3qh6
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
$ vault login s.iyNUhq8Ov4hIAx6snw5mB2nL
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token s.iyNUhq8Ov4hIAx6snw5mB2nL
token_accessor maMfHsZfwLB6fi18Zenj3qh6
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
$ vault token revoke s.iyNUhq8Ov4hIAx6snw5mB2nL
Success! Revoked token (if it existed)
$ vault auth enable github
Success! Enabled github auth method at: github/
$ vault write auth/github/config organization=hashicorp
Success! Data written to: auth/github/config
$ vault write auth/github/map/teams/engineering value=default,applications
Success! Data written to: auth/github/map/teams/engineering
$ vault auth list
Path Type Description
---- ---- -----------
github/ github n/a
token/ token token based credentials
$ vault login -method=github
GitHub Personal Access Token (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token s.DNtKCjVQ1TxAzgMqtDuwjjC2
token_accessor e7zLJuPg2tLpav66ZSu5AyDC
token_duration 768h
token_renewable true
token_policies [default applications]
token_meta_org hashicorp
token_meta_username my-user
$ vault login root
$ vault token revoke -mode path auth/github
$ vault auth disable github
Success! Disabled the auth method (if it existed) at: github/
The policy path secret/data/*
is related to all secret path secret/*
.
The policy path secret/data/foo
is related to secret path secret/foo
.
The policy path secret/approle/*
is related to role_id + secret_id authentication.
$ vault policy write my-policy - << EOF
# Dev servers have version 2 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "secret/data/*" {
capabilities = ["create", "update"]
}
path "secret/data/foo" {
capabilities = ["read"]
}
EOF
$ vault policy list
default
my-policy
root
$ vault policy read my-policy
# Dev servers have version 2 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "secret/data/*" {
capabilities = ["create", "update"]
}
path "secret/data/foo" {
capabilities = ["read"]
}
$ export VAULT_TOKEN="$(vault token create -field token -policy=my-policy)"
$ vault token lookup | grep policies
policies [default my-policy]
$ vault kv put secret/creds password="my-long-password"
Key Value
--- -----
created_time 2018-05-22T18:05:42.537496856Z
deletion_time n/a
destroyed false
version 1
$ vault kv put secret/foo robot=beepboop
Error writing data to secret/data/foo: Error making API request.
URL: PUT http://localhost:8200/v1/secret/data/foo
Code: 403. Errors:
* 1 error occurred:
* permission denied
$ vault auth enable approle
Success! Enabled approle auth method at: approle/
my-role
link to my-policy
$ 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
Success! Data written to: auth/approle/role/my-role
role_id
$ export ROLE_ID="$(vault read -field=role_id auth/approle/role/my-role/role-id)"
secret_id
$ export SECRET_ID="$(vault write -f -field=secret_id auth/approle/role/my-role/secret-id)"
$ vault write auth/approle/login role_id="$ROLE_ID" secret_id="$SECRET_ID"
Key Value
--- -----
token s.Sh9h1wZ9ycATeSaASoOQvovr
token_accessor xCgUIu6WWLM9opkEkAiNLsRc
token_duration 20m
token_renewable true
token_policies ["default" "my-policy"]
identity_policies []
policies ["default" "my-policy"]
token_meta_role_name my-role
A strange error happens in some browsers, NextCloud menu become a big page vertically, and one password textbox there requesting password, but the password is not working.
In my iMac, Safari is not working. In my one Windows machine, Firefox is not working. By the way, the Firefox has sync enabled and it is working in another PC. Google Chrome and Microsoft Edge have no issue.
There is programming error, the contents were downloaded from following website directly, not the NextCloud server. Browser blocked them.
https://raw.githubusercontent.com
Disable "Theming App" in NextCloud Apps screen.
sed
command uncommon behaviorsThe sed
command is used in Unix, some strange behaviors can let time waste.
Normally, the \
is escape character, but it wasn't in some cases.
For example, .
is to match any character, it needs to have \
as escape character if need it to be a dot character.
$ echo "test (111) help . 1" | sed -e "s/.//"
est (111) help . 1
$ echo "test (111) help . 1" | sed -e "s/\.//"
test (111) help 1
But this is not for ()
, without \
, they are ()
, with \
, they are indicating subpattern.
$ echo "test (111) help . 1" | sed -e 's/(111)//'
test help . 1
$ echo "test (111) help . 1" | sed -e 's/\(111\)//'
test () help . 1
$
Same for {}
echo "test (111) help . 1" | sed -e 's/hel{1}p//'
test (111) help . 1
$ echo "test (111) help . 1" | sed -e 's/hel\{1\}p//'
test (111) . 1
and ?
$ echo "test (111) help . 1" | sed -e 's/he?lp//'
test (111) help . 1
$ echo "test (111) help . 1" | sed -e 's/h?lp//'
test (111) help . 1
$ echo "test (111) help . 1" | sed -e 's/he\?lp//'
test (111) . 1
*
and +
The sed
understands the meaning of *
, but not for +
.
$ echo "test (111) help . 1" | sed -e 's/hel*p//'
test (111) . 1
$ echo "test (111) help . 1" | sed -e 's/hel+p//'
test (111) help . 1
\*
and \+
The sed
understands the meaning of \+
, but not for \*
.
$ echo "test (111) help . 1" | sed -e 's/hel\*p//'
test (111) help . 1
$ echo "test (111) help . 1" | sed -e 's/hel\+p//'
test (111) . 1
Got issue to see AppStore in NextCloud, could not fix it.
appstore
in config.php
Updated config.php
with following options, but failed.
'appstoreenabled' => true,
'appstoreurl' => 'https://apps.nextcloud.com/api/v1',
But successfully using curl
tested access to https://apps.nextcloud.com/api/v1.
occ
php occ app:list
Can not see Apps in AppStore
Download App from app.nextcloud.com, extract to nextcloud/apps
folder.
Change owner to www-data:www-data
Go to GUI Apps => Disabled apps, refresh page
Then the app should be listed.
Click on install to install it.
As CIS requirements, ICMPv6 Redirect Messages should be disabled in Solaris.
cis_netconfig.sh
cis_netconfig.xml
Following commands are copied from CIS document, which is not clean. Just for reference.
cat > cis_netconfig.sh << END
#!/sbin/sh
ndd -set /dev/ip ip_forward_src_routed 0
ndd -set /dev/ip ip6_forward_src_routed 0
ndd -set /dev/tcp tcp_rev_src_routes 0
ndd -set /dev/ip ip_forward_directed_broadcasts 0
ndd -set /dev/tcp tcp_conn_req_max_q0 4096
ndd -set /dev/tcp tcp_conn_req_max_q 1024
ndd -set /dev/ip ip_respond_to_timestamp 0
ndd -set /dev/ip ip_respond_to_timestamp_broadcast 0
ndd -set /dev/ip ip_respond_to_address_mask_broadcast 0
ndd -set /dev/ip ip_respond_to_echo_multicast 0
ndd -set /dev/ip ip6_respond_to_echo_multicast 0
ndd -set /dev/ip ip_respond_to_echo_broadcast 0
ndd -set /dev/arp arp_cleanup_interval 60000
ndd -set /dev/ip ip_ire_arp_interval 60000
ndd -set /dev/ip ip_ignore_redirect 1
ndd -set /dev/ip ip6_ignore_redirect 1
ndd -set /dev/tcp tcp_extra_priv_ports_add 6112
ndd -set /dev/ip ip_strict_dst_multihoming 1
ndd -set /dev/ip ip6_strict_dst_multihoming 1
ndd -set /dev/ip ip_send_redirects 0
ndd -set /dev/ip ip6_send_redirects 0
END
chmod +x cis_netconfig.sh
cat > cis_netconfig.xml << END
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='CIS:cis_netconfig'>
<service name='site/cis_netconfig' type='service' version='1'>
<create_default_instance enabled='true' />
<single_instance />
<dependency name='usr' type='service' grouping='require_all' restart_on='none'>
<service_fmri value='svc:/system/filesystem/minimal' />
</dependency>
<!-- Run ndd commands after network/physical is plumbed. -->
<dependency name='network-physical' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/network/physical' />
</dependency>
<!-- but run the commands before network/initial -->
<dependent name='ndd_network- initial' grouping='optional_all' restart_on='none'>
<service_fmri value='svc:/network/initial' />
</dependent>
<exec_method type='method' name='start' exec='/lib/svc/method/cis_netconfig.sh' timeout_seconds='60' />
<exec_method type='method' name='stop' exec=':true' timeout_seconds='60' />
<property_group name='startd' type='framework'>
<propval name='duration' type='astring' value='transient' />
</property_group>
<stability value='Unstable' />
<template>
<common_name>
<loctext xml:lang='C'> CIS IP Network Parameter Set </loctext>
</common_name>
</template>
</service>
</service_bundle>
END
cp cis_netconfig.sh /lib/svc/method
chmod 750 /lib/svc/method/cis_netconfig.sh
svccfg import cis_netconfig.xml
# cp cis_netconfig.sh /lib/svc/method
# chmod 750 /lib/svc/method/cis_netconfig.sh
# svccfg import cis_netconfig.xml
CIS Oracle Solaris 10 Benchmark v5.2.0 - 09-02-2015 - Local Cache
To split NGINX configuration file into multiple conf.d/*.conf
files.
This is defined in /etc/nginx/nginx.conf
file as below
http {
...
include /etc/nginx/conf.d/*.conf;
}
Avoid large configuration file and manage easiler.
NGINX will read all files in conf.d directory, which has extension name as .conf
and use them all as final configuration.
Only definitions in http { ... }
directive can be defined in conf.d/*.conf
.
Which file to be loaded first is unclear.
One server definition should not be defined in mulitipe files.