Compare commits

...

106 Commits

Author SHA1 Message Date
Christer Warén
3fafb66781 FIx typos part 2 2025-11-10 21:13:56 +02:00
Christer Warén
54409a4197 FIx typos 2025-11-10 19:48:07 +02:00
Christer Warén
77a54ef1f6 Comment debugging args in stop function 2025-11-10 12:41:58 +02:00
Christer Warén
fbaa5780d9 Refactoring Code 2025-11-10 12:40:35 +02:00
Christer Warén
5a666e6f60 VSCode Settings: Update 2025-11-03 02:41:43 +02:00
Christer Warén
1e4f9ed508 Generator Update 2025-11-03 02:40:44 +02:00
Christer Warén
592cd95f42 Replace bin only on successful connection 2025-09-27 00:02:35 +03:00
Christer Warén
bce9c3c4d6 Auto - Create SSH certificates before getting SSH privatekeys 2025-09-24 13:39:33 +03:00
Christer Warén
f91e69ee55 Run clean in Uninstall command 2025-08-21 18:35:09 +03:00
Christer Warén
32e6b83611 Exit after Uninstall finished 2025-08-21 18:32:01 +03:00
Christer Warén
2742d39818 Fix issue with crontab removal in Uninstall 2025-08-21 18:18:30 +03:00
Christer Warén
fe5abf5419 Fix grep to ignore wildcard as regexp 2025-08-21 17:58:38 +03:00
Christer Warén
43192faed1 Fix typos 2025-08-21 17:44:27 +03:00
Christer Warén
a276adb6d2 Remove logout from uninstall 2025-08-21 17:28:23 +03:00
Christer Warén
b5186f0380 Add cronjob removal into uninstall 2025-08-21 17:26:21 +03:00
Christer Warén
86bb04d2ea Add cronjob to installation 2025-08-21 17:21:22 +03:00
Christer Warén
67fabf0ce1 Code Update 2025-06-26 23:07:14 +03:00
Christer Warén
fe56c50bfb Code Update 2025-06-23 09:35:37 +03:00
Christer Warén
eb14aa46ff Code Update 2025-06-22 01:24:09 +03:00
Christer Warén
c59d1b374d Code Update 2025-06-22 01:22:12 +03:00
Christer Warén
1a99d2e2a1 Code Update 2025-06-22 00:44:42 +03:00
Christer Warén
1d03f7be64 Code Update 2025-06-22 00:31:52 +03:00
Christer Warén
994e44d8f1 Code Update 2025-06-22 00:22:15 +03:00
Christer Warén
f016a452cd Remove Hostname variable from login process 2025-06-21 23:46:20 +03:00
Christer Warén
c17b9a0e42 Code Update 2025-05-10 12:09:50 +03:00
Christer Warén
a91d5d6011 Code Update 2025-05-10 11:29:56 +03:00
Christer Warén
3a0902fe8e Code Update 2025-04-27 15:39:50 +03:00
Christer Warén
9baae5bccc Code Update 2025-04-27 15:32:10 +03:00
Christer Warén
7b837fdba7 Code Update 2025-04-27 15:21:27 +03:00
Christer Warén
283b7538e6 Rename build.sh to maintainer.sh 2025-01-04 08:18:12 +02:00
Christer Warén
14ae6e5dad Fix typo in code 2025-01-04 06:22:06 +02:00
Christer Warén
87608f9bfb Code Update 2025-01-04 06:19:35 +02:00
Christer Warén
5903932328 Update copyright year 2025-01-01 18:00:22 +02:00
Christer Warén
96193196cc Fix typo on curl that will get Vault passwords in Infra command 2024-11-23 07:42:02 +02:00
Christer Warén
0186421fc6 Get Ansible vault passwords in Infra command 2024-11-23 07:18:17 +02:00
Christer Warén
714feda225 Hide git command output from stdout in Infra command 2024-11-23 07:06:57 +02:00
Christer Warén
3d834933e7 Fix home directory issue 2024-11-23 07:04:12 +02:00
Christer Warén
dd72a873ab Temporarily disable using jump host when getting Infra repo from Git server 2024-11-23 07:01:33 +02:00
Christer Warén
81cd3a1c1c Create secondary Infra directory and pull changes when using Infra command 2024-11-23 06:57:41 +02:00
Christer Warén
b52f1d4486 Add secondary Infra repo path to Infra command 2024-11-23 06:50:26 +02:00
Christer Warén
42239ef54d Add secondary Ansible Vault to cwchristerw user 2024-11-22 00:16:35 +02:00
Christer Warén
256a79e427 Code Update 2024-06-24 06:32:58 +03:00
Christer Warén
b36f98e5e9 Hide Clean output in logout command 2024-06-19 20:56:27 +03:00
Christer Warén
2f33daaaa7 Code Update 2024-06-16 04:06:43 +03:00
Christer Warén
4e9ae9109e Code Update 2024-06-16 04:03:45 +03:00
Christer Warén
0071b7407d Code Update 2024-06-16 04:01:17 +03:00
Christer Warén
b014dd1990 Code Update 2024-06-16 02:51:29 +03:00
Christer Warén
13e0deb5f5 Code Update 2024-06-03 23:10:36 +03:00
Christer Warén
b5b1b88763 Code Update 2024-06-01 15:27:05 +03:00
Christer Warén
90414af2dc Code Update 2024-06-01 02:09:21 +03:00
Christer Warén
e1b05fbc51 Code Update 2024-06-01 01:53:48 +03:00
Christer Warén
a614d63d1c Code Update 2024-06-01 01:11:20 +03:00
Christer Warén
ca14cb1988 Build Script 2024-06-01 00:28:36 +03:00
Christer Warén
e36265403e Code Update 2024-06-01 00:28:18 +03:00
Christer Warén
0ef3f8d8d6 Code Update 2024-05-31 23:26:44 +03:00
Christer Warén
706a917dbf Code Update 2024-05-30 19:19:35 +03:00
Christer Warén
7f950148e0 Code Update 2024-05-30 19:10:31 +03:00
Christer Warén
a54f68ded0 Code Update 2024-05-30 16:00:50 +03:00
Christer Warén
29be307377 Code Update 2024-05-30 15:56:01 +03:00
Christer Warén
02c84ef45f Code Update 2024-05-30 15:51:49 +03:00
Christer Warén
399372294c README.md Update 2024-05-30 15:34:13 +03:00
Christer Warén
0b0237ede5 Code Update 2024-05-30 15:33:31 +03:00
Christer Warén
2df1590a6d Code Update 2024-05-20 00:30:48 +03:00
Christer Warén
18d3ed8890 Code Update 2024-05-18 02:13:48 +03:00
Christer Warén
25bf1a9ebc Code Update 2024-05-15 17:51:45 +03:00
Christer Warén
1852b1a119 Code Update 2024-05-15 17:48:58 +03:00
Christer Warén
3618a34c41 Code Update 2024-05-09 13:26:22 +03:00
Christer Warén
a6cb4ae626 Code Update 2024-05-04 18:08:46 +03:00
Christer Warén
fb02109d68 Code Update 2024-05-03 01:26:36 +03:00
Christer Warén
b58142a45f Code Update 2024-05-03 00:53:02 +03:00
Christer Warén
26dac6550c Source Update 2024-05-01 03:18:34 +03:00
Christer Warén
6b9afb0ed0 Source Update 2024-05-01 02:55:43 +03:00
Christer Warén
7765af850a Source Update 2024-05-01 02:52:21 +03:00
Christer Warén
cb76cbd190 Update Install instructions in README.md 2024-05-01 01:50:58 +03:00
Christer Warén
7a5c84f5c0 ReadMe Update 2024-05-01 01:37:57 +03:00
Christer Warén
ecaa7e3a73 Source Update 2024-04-29 21:38:01 +03:00
Christer Warén
a2478d0a7a Source Update 2024-04-29 21:35:32 +03:00
Christer Warén
71cf24869a Fix typo 2024-04-29 21:27:50 +03:00
Christer Warén
d1b32a0296 Source Update 2024-04-29 07:57:18 +03:00
Christer Warén
aff9e6d985 Source Update 2024-04-29 07:52:51 +03:00
Christer Warén
7b7c540e12 Source Update 2024-04-29 07:51:17 +03:00
Christer Warén
dc0bdf6755 Source Update 2024-04-29 07:46:45 +03:00
Christer Warén
c5359ed8f5 Source Update 2024-04-29 07:43:45 +03:00
Christer Warén
3d04f2f24c Source Update 2024-04-29 07:39:30 +03:00
Christer Warén
cc1cc6e39f Source Update 2024-04-29 07:22:08 +03:00
Christer Warén
6619193dc6 Source Update 2024-04-29 07:18:35 +03:00
Christer Warén
963770b974 Source Update 2024-04-29 06:00:07 +03:00
Christer Warén
d54100edf8 Source Update 2024-04-29 05:06:21 +03:00
Christer Warén
28aed09fd1 Source Update 2024-04-28 06:08:57 +03:00
Christer Warén
824ca7168c Source Update 2024-04-28 01:26:18 +03:00
Christer Warén
0da7c1ade1 Source Update 2024-04-28 01:19:47 +03:00
Christer Warén
b2d3908d6f Source Update 2024-04-27 23:32:06 +03:00
Christer Warén
91ae087bd4 Generator Update 2024-04-27 21:14:13 +03:00
Christer Warén
ee152b0562 Source Update 2024-04-27 21:13:32 +03:00
Christer Warén
56b6f58f4e Docs Update 2024-04-27 20:09:05 +03:00
Christer Warén
fb3c902d9a Generator Update 2024-04-27 20:08:52 +03:00
Christer Warén
9f0df0dbdf Build Update 2024-04-27 20:08:43 +03:00
Christer Warén
3daa8a84dc Source Update 2024-04-27 20:08:15 +03:00
Christer Warén
a1ff2b40d7 Source Update 2024-04-27 18:25:14 +03:00
Christer Warén
0b8ea6b7bf Config Update 2024-04-26 06:35:00 +03:00
Christer Warén
2c5ddd1280 Source Update 2024-04-26 06:34:52 +03:00
Christer Warén
219aac45e5 Source Update 2024-04-26 06:25:59 +03:00
Christer Warén
8808aa7b93 Source Update 2024-04-26 06:22:52 +03:00
Christer Warén
d3901ba519 Source Update 2024-04-26 06:20:28 +03:00
Christer Warén
d99860148b Source Update 2024-04-26 05:49:45 +03:00
Christer Warén
9a740b9873 Generator Update 2024-04-26 05:49:32 +03:00
45 changed files with 1787 additions and 149 deletions

11
.vscode/settings.json vendored
View File

@@ -1,6 +1,9 @@
{ {
"files.trimTrailingWhitespace": true, "files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true, "files.insertFinalNewline": true,
"files.trimFinalNewlines": true, "files.trimFinalNewlines": true,
"editor.renderFinalNewline": false "editor.renderFinalNewline": false,
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.detectIndentation": false
} }

View File

@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2023-2024 Warén Group Copyright (c) 2023-2025 Warén Group
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -1 +1,15 @@
# Warén Group - WX # Warén Group - Warén CLI (wx)
## Install
```
mkdir $HOME/bin &> /dev/null
curl https://git.waren.io/warengroup/wx/raw/branch/master/wx -o $HOME/bin/wx &> /dev/null
chmod +x $HOME/bin/wx &> /dev/null
export PATH=$HOME/bin:$PATH
```
## Schedule
```
# Warén CLI
*/30 * * * * $HOME/bin/wx auto
```

View File

@@ -1,10 +0,0 @@
---
warengroup:
domain: waren.io
folder: warengroup
cwinfo:
domain: cwinfo.net
folder: cwinfo
cwchristerw:
domain: christerwaren.fi
folder: cwchristerw

View File

@@ -6,28 +6,38 @@ $base = file_get_contents(__DIR__."/src/base.sh");
$dirs = [ $dirs = [
__DIR__.'/src/commands/*.sh', __DIR__.'/src/commands/*.sh',
__DIR__.'/src/commands/*/*.sh', __DIR__.'/src/commands/*/*.sh',
__DIR__.'/src/commands/*/*/*.sh' __DIR__.'/src/commands/*/*/*.sh',
__DIR__.'/src/functions/*.sh',
__DIR__.'/src/ui/*.sh'
]; ];
$codes = []; $codes = [];
foreach($dirs as $dir){ foreach($dirs as $dir){
foreach(glob($dir) as $file){ foreach(glob($dir) as $file){
$codes[$file] = file_get_contents($file); if(str_contains($dir, "commands")){
$codes['commands'][$file] = file_get_contents($file);
}
if(str_contains($dir, "functions")){
$codes['functions'][$file] = file_get_contents($file);
}
if(str_contains($dir, "ui")){
$codes['ui'][$file] = file_get_contents($file);
}
} }
} }
$code = str_replace("{{ COMMANDS }}", implode("\n", $codes), $base); $code = str_replace("{{ FUNCTIONS }}", implode("\n", $codes['functions']), $base);
$code = str_replace("{{ UI }}", implode("\n", $codes['ui']), $code);
$code = str_replace("{{ COMMANDS }}", implode("\n", $codes['commands']), $code);
try { try {
$file = __DIR__.'/wx'; $file = __DIR__.'/wx.tmp';
$file = fopen($file, "w"); $file = fopen($file, "w");
fwrite($file, $code); fwrite($file, $code);
fclose($file); fclose($file);
echo "Status: Successful";
} catch (\Error $e) { } catch (\Error $e) {
echo "Status: Failed";
} }
?> ?>

13
maintainer.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
if [ ! "$BASH_VERSION" ] ; then
bash $0
exit 1
fi
if [[ -f "./wx" ]] && [[ -d "./src" ]]
then
podman run -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp docker.io/library/php:8-cli php generator.php &> /dev/null
mv wx.tmp wx &> /dev/null
chmod +x wx &> /dev/null
fi

View File

@@ -1,53 +1,68 @@
#!/bin/bash #!/bin/bash
if [ ! "$BASH_VERSION" ] ; then #if [ ! "$BASH_VERSION" ] ; then
bash $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 # bash $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
exit 1 # exit 1
fi #fi
warencli-syntax-line-douple() { declare -Ax args
echo -n " declare -Ax config
============================== declare -Ax messages
"
}
warencli-syntax-line-single() {
echo -n "
------------------------------
"
}
warencli-start() {
warencli-syntax-line-douple
echo -n "Warén CLI "
warencli-syntax-line-douple
}
warencli-stop () {
echo " "
exit 1
}
warencli-update() {
if [[ -d "./src" ]]; then
echo ">>> Building... <<<"
podman run -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp docker.io/library/php:8-cli php generator.php
else
echo ">>> Updating... <<<"
sudo curl https://git.waren.io/warengroup/wx/raw/branch/master/wx -o /opt/wx &> /dev/null
if [[ -d "/usr/bin" ]]; then
sudo ln -sf /opt/wx /usr/bin/wx &> /dev/null
fi
sudo chmod +x /usr/bin/wx &> /dev/null
fi
}
{{ FUNCTIONS }}
{{ UI }}
{{ COMMANDS }} {{ COMMANDS }}
COMMAND=$1 i=1
while [[ "$1" != "" ]]
do
case $1 in
--*)
key="${1%%=*}"
value="${1#*=}"
warencli-start if [[ "$value" == "$key" ]]
if [[ ! -z $1 ]]; then then
warencli-$1 $2 $3 $4 $5 $6 $7 $8 $9 shift
value="$1"
fi
if [[ -z $value ]]
then
value=true
fi
args["${key#--}"]="$value"
;;
-*)
key="${1%=*}"
value="${1#*=}"
if [[ "$value" == "$key" ]]
then
shift
value="$1"
fi
if [[ -z $value ]]
then
value=true
fi
args["${key#-}"]="$value"
;;
*)
args["$i"]="${1%%=*}"
i=$((i + 1))
;;
esac
shift
done
if [[ ! -z ${args['1']} ]] && [[ $(type -t wx-${args['1']}) == function ]]
then
wx-${args['1']}
else
wx-welcome
fi fi
warencli-stop wxi-stop

View File

@@ -1,3 +1,139 @@
warencli-login() { wx-login(){
echo ">>> Authentication: Login"; wxi-header "Login"
wxi-restricted --user
wxi-restricted --org
wxi-restricted --vault
wxi-header "$ORG_HEADER" h3
if [[ ! -z ${args['login-type']} ]]
then
LOGIN_TYPE=${args['login-type']}
elif [[ ! -z ${args['token']} ]]
then
LOGIN_TYPE=token
elif [[ -f "$HOME/.warengroup/config.json" && $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token) != 'null' && $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token) != '' ]]
then
LOGIN_TYPE=token
elif [[ ! -z ${args['username']} ]]
then
LOGIN_TYPE=ldap
else
LOGIN_TYPE=ldap
fi
if [[ ! -z $LOGIN_TYPE ]]
then
case $LOGIN_TYPE in
ldap)
echo -n "Username: "
if [[ ! -z ${args['username']} ]]
then
USERNAME=${args['username']}
wxi-content text "$USERNAME"
else
read USERNAME
fi
echo -n "Password: "
if [[ ! -z ${args['password']} ]]
then
PASSWORD=${args['password']}
else
read -s PASSWORD
fi
if [[ ! -z $PASSWORD ]]
then
wxi-content text "****************"
else
wxi-content text ""
fi
if [[ -z $USERNAME || -z $PASSWORD ]]
then
wxi-content status "Username & Password" "Required"
wxi-footer
wxi-stop
fi
VAULT_LOGIN=$(curl https://$VAULT_DOMAIN/v1/auth/ldap/login/$USERNAME -X POST -d '{ "password": "'$PASSWORD'" }' -s | jq -r '.auth.client_token')
if [[ -z $VAULT_LOGIN || ${#VAULT_LOGIN} -lt 95 || ${#VAULT_LOGIN} -gt 95 ]]
then
wxi-content status "Login" "Failed"
wxi-stop
fi
wxi-config login
;;
token)
echo -n "Token: "
if [[ ! -z ${args['token']} ]]
then
if [[ ${args['token']} != "true" ]]
then
TOKEN=${args['token']}
fi
elif [[ -f "$HOME/.warengroup/config.json" && $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token) != 'null' && $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token) != '' ]]
then
TOKEN=$(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token)
else
read -s TOKEN
fi
if [[ ! -z $TOKEN ]]
then
wxi-content text "***********************************************************************************************"
fi
if [[ -z $TOKEN ]]
then
wxi-content status "Token" "Required"
wxi-footer
wxi-stop
fi
if [[ ${#TOKEN} -lt 95 || ${#TOKEN} -gt 95 ]]
then
wxi-content status "Token" "Invalid"
wxi-footer
wxi-stop
fi
VAULT_LOGIN=$(curl https://$VAULT_DOMAIN/v1/auth/token/renew-self -X POST --header "X-Vault-Token: $TOKEN" -d '{ "token": "'$TOKEN'" }' -s | jq -r '.auth.client_token')
if [[ -z $VAULT_LOGIN || ${#VAULT_LOGIN} -lt 95 || ${#VAULT_LOGIN} -gt 95 ]]
then
wxi-content status "Login" "Failed"
wxi-stop
fi
TOKEN=$VAULT_LOGIN
wxi-config login
;;
*)
wxi-content status "Login Type" "Unsupported"
wxi-footer
wxi-stop
;;
esac
fi
VAULT_USERNAME=$(curl https://$VAULT_DOMAIN/v1/auth/token/lookup-self -X GET --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.display_name')
if [[ -z $VAULT_USERNAME ]]
then
wxi-content status "Login" "Username Missing"
wxi-stop
elif [[ $VAULT_USERNAME != ldap* && $VAULT_USERNAME != oidc* ]]
then
wxi-content status "Login" "Authentication Method Invalid"
wxi-stop
elif [[ $VAULT_USERNAME == ldap* ]]
then
USERNAME=${VAULT_USERNAME#ldap-}
elif [[ $VAULT_USERNAME == oidc* ]]
then
USERNAME=${VAULT_USERNAME#oidc-}
fi
wxi-footer
} }

View File

@@ -1,3 +1,23 @@
warencli-logout() { wx-logout(){
echo ">>> Authentication: Logout"; wxi-header "Logout"
wxi-restricted --user
wxi-restricted --org
wxi-restricted --vault
if [[ -f "$HOME/.warengroup/config.json" && $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token) != 'null' ]]
then
TOKEN=$(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token)
fi
VAULT_STATUS=$(curl https://$VAULT_DOMAIN/v1/auth/token/revoke-self -X POST --header "X-Vault-Token: $TOKEN" -s -o /dev/null -w "%{http_code}")
if [[ $VAULT_STATUS -eq 204 || $VAULT_STATUS -eq 403 ]]
then
wxi-header "$ORG_HEADER" h3
echo "Logging Out..."
TOKEN=""
wxi-config login
wxi-footer
wxi-stop
fi
} }

View File

@@ -1,22 +1,42 @@
warencli-help() { wx-help(){
echo "
wxi-header "Help"
wxi-content text "
Usage: $0 COMMAND [OPTIONS] Usage: $0 COMMAND [OPTIONS]
Common Commands: Common Commands:
init Init
help Help
ssh SSH ssh SSH
config Config config Config
sign Certificates edit Edit
save Save
sync Sync
clean Clean
keys Keys
generate Generate
sign Sign
retrieve Retrieve
save Save
sync Sync
clean Clean
Authentication Commands: Authentication Commands:
login Login login Login
logout Logout logout Logout
Management Commands: Management Commands:
auto Auto
clean Clean
settings Settings settings Settings
Maintenance Commands: Maintenance Commands:
install Install install Install
update Update update Update
uninstall Uninstall
"; ";
}
wxi-footer
}

77
src/commands/infra.sh Normal file
View File

@@ -0,0 +1,77 @@
wx-infra(){
wx-login &> /dev/null
wx-auto &> /dev/null
wxi-header "Infra"
wxi-restricted
case $USERNAME in
cwchristerw)
if [[ -d "$HOME/.warengroup/infra" ]]
then
INFRA_PATH="$HOME/.warengroup/infra"
else
INFRA_PATH="$HOME/.warengroup/infra"
mkdir -p "$INFRA_PATH" &> /dev/null
git clone ssh://git@git.waren.io:2222/warengroup-private/infra.git --config core.sshCommand="ssh -i $HOME/.ssh/keys/warengroup-legacy -o ProxyJump=none" "$INFRA_PATH" &> /dev/null
fi
if [[ ! -f "$INFRA_PATH/vault/cwchristerw" || ! -f "$INFRA_PATH/vault/warengroup" ]]
then
mkdir -p "$INFRA_PATH/vault" &> /dev/null
curl \
-H "X-Vault-Token: $TOKEN" \
-X GET \
https://$VAULT_DOMAIN/v1/cli/data/cwchristerw/settings/infra -s | jq -r '.data.data.cwchristerw' > "$INFRA_PATH/vault/cwchristerw"
curl \
-H "X-Vault-Token: $TOKEN" \
-X GET \
https://$VAULT_DOMAIN/v1/cli/data/cwchristerw/settings/infra -s | jq -r '.data.data.warengroup' > "$INFRA_PATH/vault/warengroup"
fi
INFRA_VAULT="--vault-id warengroup@vault/warengroup --vault-id cwchristerw@vault/cwchristerw"
;;
*)
wxi-content status "User" "Unsupported"
wxi-footer
wxi-stop
INFRA_PATH="$HOME/.warengroup/infra"
INFRA_VAULT="--vault-id warengroup@vault/warengroup"
;;
esac
if [[ -z ${args['2']} ]]
then
echo "Tag Required"
else
cd "$INFRA_PATH"
#git pull &> /dev/null
#ansible-galaxy collection install -r requirements.yml --upgrade &> /dev/null
if [[ ${args['2']} == "init" ]]
then
wxi-header "Init" h3
if [[ -z ${args['3']} ]]
then
tags=init
else
tags=${args['3']}
fi
ansible-playbook $INFRA_VAULT playbooks/init.yml -t $tags --limit "${args['limit']}"
elif [[ ${args['2']} == "manager" ]]
then
wxi-header "Manager" h3
ansible-playbook $INFRA_VAULT manager.yml --extra-vars "${args['extra-vars']}"
else
wxi-header "Playbooks" h3
tags=${args['2']}
ansible-playbook $INFRA_VAULT playbooks.yml -t $tags --limit "${args['limit']}"
fi
cd "$OLDPWD"
fi
wxi-footer
}

View File

@@ -1,3 +0,0 @@
warencli-install() {
echo ">>> Install";
}

View File

@@ -0,0 +1,25 @@
wx-install(){
wxi-header "Install"
wxi-restricted --user
if [[ -f "./wx" && -f "./maintainer.sh" && -d "./src" ]]
then
./maintainer.sh
fi
mkdir -p $HOME/bin
if [[ $(curl -s -o /dev/null -w "%{http_code}" https://git.waren.io/warengroup/wx/raw/branch/master/wx) -eq 200 ]]
then
curl https://git.waren.io/warengroup/wx/raw/branch/master/wx -o $HOME/bin/wx &> /dev/null
chmod +x $HOME/bin/wx &> /dev/null
fi
CRONJOB_NAME="#Warén CLI: Auto"
CRONJOB_TASK="*/5 * * * * $HOME/bin/wx auto"
if [[ -z $(crontab -l | grep -F "$CRONJOB_NAME") || -z $(crontab -l | grep -F "$CRONJOB_TASK") ]]
then
(crontab -l ; echo "$CRONJOB_NAME" ; echo "$CRONJOB_TASK") | grep -Fv "no crontab" | crontab -
fi
wxi-footer
}

View File

@@ -0,0 +1,26 @@
wx-uninstall(){
wxi-header "Uninstall"
wxi-restricted --user
wx-clean &> /dev/null
if [[ -d "$HOME/.warengroup" ]]
then
rm "$HOME/.warengroup" -rf
fi
CRONJOB_NAME="#Warén CLI: Auto"
CRONJOB_TASK="*/5 * * * * $HOME/bin/wx auto"
if [[ $(crontab -l | grep -F "$CRONJOB_NAME") || $(crontab -l | grep -F "$CRONJOB_TASK") ]]
then
crontab -l | grep -Fv "$CRONJOB_NAME" | grep -Fv "$CRONJOB_TASK" | grep -Fv "no crontab" | crontab -
fi
if [[ -f "$HOME/bin/wx" ]]
then
rm "$HOME/bin/wx" -rf
fi
wxi-footer
wxi-repeat "\n" 3
exit 1
}

View File

@@ -0,0 +1,9 @@
wx-update(){
wxi-header "Update"
wxi-restricted --user
wx-install &> /dev/null
echo "Updates Completed"
wxi-footer
}

View File

@@ -0,0 +1,11 @@
wx-auto(){
wx-login &> /dev/null
wxi-header "Auto"
wxi-restricted
wxi-footer
wxi-ssh-config-sync
wxi-ssh-keys-sign
wxi-ssh-keys-sync
}

View File

@@ -0,0 +1,8 @@
wx-clean(){
wxi-header "Clean"
wxi-restricted --user
wxi-footer
wxi-ssh-config-clean
wxi-ssh-keys-clean
}

View File

@@ -0,0 +1,8 @@
wx-settings(){
wx-login &> /dev/null
wx-auto &> /dev/null
wxi-header "Settings"
wxi-restricted --user
wxi-footer
}

View File

@@ -1,3 +0,0 @@
warencli-settings() {
echo ">>> Settings";
}

View File

@@ -1,3 +1,18 @@
warencli-ssh() { wx-ssh(){
echo ">>> SSH"; wx-login &> /dev/null
wx-auto &> /dev/null
case ${args['2']} in
config)
wxi-ssh-config
;;
keys)
wxi-ssh-keys
;;
*)
wxi-header "SSH"
wxi-restricted
wxi-footer
;;
esac
} }

View File

@@ -1,3 +1,21 @@
warencli-ssh-config(){ wxi-ssh-config(){
echo ">>> SSH: Config" case ${args['3']} in
edit)
wxi-ssh-config-sync
wxi-ssh-config-edit
wxi-ssh-config-save
;;
save)
wxi-ssh-config-save
;;
sync)
wxi-ssh-config-sync
;;
clean)
wxi-ssh-config-clean
;;
*)
wxi-ssh-config-sync
;;
esac
} }

View File

@@ -0,0 +1,11 @@
wxi-ssh-config-clean(){
wxi-header "SSH / Config / Clean"
wxi-restricted
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: $TOKEN")
if [[ -f "$HOME/.ssh/config" && $VAULT_STATUS -eq 200 ]]
then
rm "$HOME/.ssh/config"
fi
wxi-footer
}

View File

@@ -0,0 +1,7 @@
wxi-ssh-config-edit(){
wxi-header "SSH / Config / Edit"
wxi-restricted
nano ~/.ssh/config
wxi-footer
}

View File

@@ -0,0 +1,10 @@
wxi-ssh-config-save(){
wxi-header "SSH / Config / Save"
wxi-restricted
if [[ -f "$HOME/.ssh/config" ]]
then
curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X POST --header "X-Vault-Token: $TOKEN" -d "{ \"data\": { \"data\": \"$(cat ~/.ssh/config | base64 -w 0)\" } }" -s &> /dev/null
fi
wxi-footer
}

View File

@@ -0,0 +1,18 @@
wxi-ssh-config-sync(){
wxi-header "SSH / Config / Sync"
wxi-restricted
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: $TOKEN")
if [[ $VAULT_STATUS -eq 200 ]]
then
touch ~/.ssh/config
SSH1_CONFIG_MD5=$(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.data.data' | base64 -d | md5sum | base64)
SSH2_CONFIG_MD5=$(cat ~/.ssh/config | md5sum | base64)
if [[ $SSH1_CONFIG_MD5 != $SSH2_CONFIG_MD5 ]]
then
echo $(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.data.data') | base64 -d > ~/.ssh/config 2>&1
chmod 700 ~/.ssh/config
fi
fi
wxi-footer
}

28
src/commands/ssh/keys.sh Normal file
View File

@@ -0,0 +1,28 @@
wxi-ssh-keys(){
case ${args['3']} in
generate)
wxi-ssh-keys-retrieve ${args['4']}
wxi-ssh-keys-generate ${args['4']}
wxi-ssh-keys-save ${args['4']}
;;
sign)
wxi-ssh-keys-sign
;;
retrieve)
wxi-ssh-keys-retrieve ${args['4']}
;;
save)
wxi-ssh-keys-save ${args['4']}
;;
sync)
wxi-ssh-keys-sync
;;
clean)
wxi-ssh-keys-clean
;;
*)
wxi-header "SSH / Keys"
wxi-footer
;;
esac
}

View File

@@ -0,0 +1,32 @@
wxi-ssh-keys-clean(){
wxi-header "SSH / Keys / Clean"
wxi-restricted
if [[ ! -z $1 ]]
then
if [[ -f "$HOME/.ssh/keys/$1" ]]
then
rm "$HOME/.ssh/keys/$1" &> /dev/null
rm "$HOME/.ssh/keys/$1.pub" &> /dev/null
rm "$HOME/.ssh/keys/$1.sig" &> /dev/null
fi
else
wxi-ssh-keys-clean $ORG
if [[ $USERNAME == "cwchristerw" ]]
then
wxi-ssh-keys-clean warengroup
fi
for file in ~/.ssh/keys/*
do
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$(basename "$file" .pub) -X GET --header "X-Vault-Token: $TOKEN")
if [[ $VAULT_STATUS -eq 200 ]]
then
rm "$file" &> /dev/null
fi
done
fi
wxi-footer
}

View File

@@ -0,0 +1,13 @@
wxi-ssh-keys-generate(){
wxi-header "SSH / Keys / Generate"
wxi-restricted
if [[ ! -z $1 ]]
then
if [[ ! -f "$HOME/.ssh/keys/$1" ]]
then
ssh-keygen -t ed25519 -f $HOME/.ssh/keys/$1 -q -N "" -C "$USERNAME" &> /dev/null
fi
fi
wxi-footer
}

View File

@@ -0,0 +1,18 @@
wxi-ssh-keys-retrieve(){
wxi-header "SSH / Keys / Retrieve"
wxi-restricted
if [[ ! -z $1 ]]
then
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X GET --header "X-Vault-Token: $TOKEN")
if [[ $VAULT_STATUS -eq 200 ]]
then
echo $(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X GET --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.data.private') | base64 -d > ~/.ssh/keys/$1 2>&1
chmod 700 ~/.ssh/keys/$1
echo $(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X GET --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.data.public') | base64 -d > ~/.ssh/keys/$1.pub 2>&1
chmod 700 ~/.ssh/keys/$1.pub
fi
fi
wxi-footer
}

View File

@@ -0,0 +1,13 @@
wxi-ssh-keys-save(){
wxi-header "SSH / Keys / Save"
wxi-restricted
if [[ ! -z $1 ]]
then
if [[ -f "$HOME/.ssh/keys/$1" ]]
then
curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X POST --header "X-Vault-Token: $TOKEN" -d "{ \"data\": { \"private\": \"$(cat ~/.ssh/keys/$1 | base64 -w 0)\", \"public\": \"$(cat ~/.ssh/keys/$1.pub | base64 -w 0)\" } }" -s &> /dev/null
fi
fi
wxi-footer
}

View File

@@ -0,0 +1,27 @@
wxi-ssh-keys-sign(){
wxi-header "SSH / Keys / Sign"
wxi-restricted
wxi-ssh-keys-sign-create $ORG sysadmin 3600
if [[ $USERNAME == "cwchristerw" ]]
then
wxi-ssh-keys-sign-create warengroup sysadmin 3600
fi
wxi-footer
}
wxi-ssh-keys-sign-create(){
NAME=$1
ROLE=$2
PRINCIPALS=$2
TTL=$3
wxi-ssh-keys-generate $NAME &> /dev/null
if [[ -f "$HOME/.ssh/keys/$NAME" ]]
then
wxi-content text "$NAME/$ROLE"
echo $(curl https://$VAULT_DOMAIN/v1/ssh/sign/$ROLE -X POST --header "X-Vault-Token: $TOKEN" -d "{ \"public_key\": \"$(cat $HOME/.ssh/keys/$NAME.pub)\", \"valid_principals\": \"$PRINCIPALS,$USERNAME\", \"ttl\": \"$TTL\" }" -s | jq -r '.data.signed_key') > ~/.ssh/keys/$NAME.sig 2>&1
fi
}

View File

@@ -0,0 +1,14 @@
wxi-ssh-keys-sync(){
wxi-header "SSH / Keys / Sync"
wxi-restricted
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/metadata/$USERNAME/settings/ssh/keys -X LIST --header "X-Vault-Token: $TOKEN")
if [[ $VAULT_STATUS -eq 200 ]]
then
for name in $(curl https://$VAULT_DOMAIN/v1/cli/metadata/$USERNAME/settings/ssh/keys -X LIST --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.keys | @sh' | tr -d \')
do
wxi-content text $name
wxi-ssh-keys-retrieve $name &> /dev/null
done
fi
wxi-footer
}

View File

@@ -1,3 +0,0 @@
warencli-ssh-sign(){
echo ">>> SSH: Certificates"
}

14
src/commands/welcome.sh Normal file
View File

@@ -0,0 +1,14 @@
wx-welcome(){
wxi-header "Welcome"
wxi-header "Help" h3
wxi-content text "Use \"wx help\" command"
echo ""
wxi-header "Useful Links" h3
wxi-content link "Infra" "https://infra.waren.io"
wxi-content link "Status" "https://status.waren.io"
wxi-footer
}

12
src/functions/config.sh Normal file
View File

@@ -0,0 +1,12 @@
wxi-config(){
case $1 in
login)
jq '.login.'$ORG'.token = "'$TOKEN'"' $HOME/.warengroup/config.json &> $HOME/.warengroup/config.json.tmp
;;
*)
echo -n ""
;;
esac
mv $HOME/.warengroup/config.json.tmp $HOME/.warengroup/config.json &> /dev/null
}

View File

@@ -0,0 +1,84 @@
wxi-restricted(){
if [[ -z $1 || $1 == "--user" ]]
then
if [[ $USER == "root" || $USER == "local" ]]
then
wxi-content status "Command" "Restricted"
wxi-content text "It's not permitted to execute this command with root or local user."
wxi-footer
wxi-repeat "\n" 3
exit 1
fi
fi
if [[ $1 == "--org" ]]
then
if [[ ! -z ${args['org']} ]]
then
case ${args['org']} in
warengroup)
ORG=warengroup
;;
cwchristerw)
ORG=cwchristerw
;;
*)
wxi-content status "Organization" "Unsupported"
wxi-footer
wxi-stop
;;
esac
elif [[ $(hostname -d) == "devices.waren.io" ]]
then
ORG=warengroup
elif [[ $(hostname -d) == "devices.christerwaren.fi" ]]
then
ORG=cwchristerw
fi
if [[ ! -z $ORG ]]
then
case $ORG in
warengroup)
DOMAIN=waren.io
VAULT_DOMAIN=vault.cwinfo.net
ORG_HEADER="Warén Group"
;;
cwchristerw)
DOMAIN=christerwaren.fi
VAULT_DOMAIN=vault.cwinfo.net
ORG_HEADER="Christer Warén"
;;
*)
wxi-content status "Organization" "Unsupported"
wxi-footer
wxi-stop
;;
esac
else
wxi-content status "Organization" "Required"
wxi-footer
wxi-stop
fi
fi
if [[ -z $1 || $1 == "--vault" ]]
then
if [[ -z $VAULT_DOMAIN ]]
then
wxi-content status "Vault" "Unavailable"
wxi-footer
wxi-repeat "\n" 3
exit 1
fi
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/sys/health)
if [[ ! $VAULT_STATUS -eq 200 ]]
then
wxi-content status "Vault" "Offline"
wxi-footer
wxi-repeat "\n" 3
exit 1
fi
fi
}

13
src/functions/start.sh Normal file
View File

@@ -0,0 +1,13 @@
wxi-start(){
wxi-header "Warén CLI" h1
mkdir -p $HOME/.warengroup
if [[ ! -f $HOME/.warengroup/config.json || $(jq -e . < $HOME/.warengroup/config.json &>/dev/null; echo $?) -gt 0 ]]
then
echo '{}' | jq > $HOME/.warengroup/config.json
fi
mkdir -p $HOME/.ssh/keys
chmod 700 -R $HOME/.ssh/keys
mkdir -p $HOME/.ssh/multiplex
chmod 700 -R $HOME/.ssh/multiplex
}

18
src/functions/stop.sh Normal file
View File

@@ -0,0 +1,18 @@
wxi-stop(){
if [[ ! -f $HOME/bin/wx ]]
then
wx-install &> /dev/null
else
wx-update &> /dev/null
fi
# wxi-repeat "\n" 3
# for key in "${!args[@]}"
# do
# echo "$key: ${args[$key]}"
# done
wxi-repeat "\n" 3
exit 1
}

16
src/ui/content.sh Normal file
View File

@@ -0,0 +1,16 @@
wxi-content(){
if [[ $1 == "text" ]]
then
echo "$2"
elif [[ $1 == "status" ]]
then
wxi-repeat "\n" 2
echo -n "$wxiBold"
echo "Status"
echo -n "$wxiNormal"
echo "$2 - $3"
elif [[ $1 == "link" ]]
then
echo "$2 - $3"
fi
}

11
src/ui/footer.sh Normal file
View File

@@ -0,0 +1,11 @@
wxi-footer(){
echo ""
echo "------------------------------"
wxi-repeat " " $((30/2-12/2))
echo -n "$wxiBold"
echo "Warén Group™"
echo -n "$wxiNormal"
wxi-repeat " " $((30/2-17/2))
echo "https://waren.io"
echo "=============================="
}

11
src/ui/formatting.sh Normal file
View File

@@ -0,0 +1,11 @@
wxiRed=$(tput setaf 196)
wxiGreen=$(tput setaf 46)
wxiYellow=$(tput setaf 226)
wxiBlue=$(tput setaf 21)
wxiPurple=$(tput setaf 165)
wxiTurquoise=$(tput setaf 14)
wxiPink=$(tput setaf 198)
wxiOrange=$(tput setaf 202)
wxiUnderline=$(tput smul)
wxiBold=$(tput bold)
wxiNormal=$(tput sgr0)

30
src/ui/header.sh Normal file
View File

@@ -0,0 +1,30 @@
wxi-header(){
if [[ $2 == "h1" ]]
then
wxi-repeat "\n" 3
echo "=============================="
wxi-repeat " " $((30/2-${#1}/2))
echo -n "$wxiBold"
echo "$1"
echo -n "$wxiNormal"
echo "=============================="
fi
if [[ $2 == "h2" || -z $2 ]]
then
wxi-start
wxi-repeat " " $((30/2-6/2-${#1}/2))
echo -n "$wxiBold"
echo ">> $1 <<"
echo -n "$wxiNormal"
echo "------------------------------"
echo ""
fi
if [[ $2 == "h3" ]]
then
echo -n "$wxiBold"
echo "$1"
echo -n "$wxiNormal"
fi
}

0
src/ui/messages.sh Normal file
View File

13
src/ui/repeat.sh Normal file
View File

@@ -0,0 +1,13 @@
wxi-repeat() {
if [[ $1 == " " ]]
then
local str=$1 n=$2 spaces
printf -v spaces "%*s" $n " "
printf "%s" "${spaces// /$str}"
else
for i in $(seq 1 $2);
do
echo -en $1
done
fi
}

936
wx
View File

@@ -1,103 +1,919 @@
#!/bin/bash #!/bin/bash
if [ ! "$BASH_VERSION" ] ; then #if [ ! "$BASH_VERSION" ] ; then
bash $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 # bash $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
exit 1 # exit 1
fi #fi
warencli-syntax-line-douple() { declare -Ax args
echo -n " declare -Ax config
============================== declare -Ax messages
"
wxi-config(){
case $1 in
login)
jq '.login.'$ORG'.token = "'$TOKEN'"' $HOME/.warengroup/config.json &> $HOME/.warengroup/config.json.tmp
;;
*)
echo -n ""
;;
esac
mv $HOME/.warengroup/config.json.tmp $HOME/.warengroup/config.json &> /dev/null
} }
warencli-syntax-line-single() { wxi-restricted(){
echo -n " if [[ -z $1 || $1 == "--user" ]]
------------------------------ then
" if [[ $USER == "root" || $USER == "local" ]]
then
wxi-content status "Command" "Restricted"
wxi-content text "It's not permitted to execute this command with root or local user."
wxi-footer
wxi-repeat "\n" 3
exit 1
fi
fi
if [[ $1 == "--org" ]]
then
if [[ ! -z ${args['org']} ]]
then
case ${args['org']} in
warengroup)
ORG=warengroup
;;
cwchristerw)
ORG=cwchristerw
;;
*)
wxi-content status "Organization" "Unsupported"
wxi-footer
wxi-stop
;;
esac
elif [[ $(hostname -d) == "devices.waren.io" ]]
then
ORG=warengroup
elif [[ $(hostname -d) == "devices.christerwaren.fi" ]]
then
ORG=cwchristerw
fi
if [[ ! -z $ORG ]]
then
case $ORG in
warengroup)
DOMAIN=waren.io
VAULT_DOMAIN=vault.cwinfo.net
ORG_HEADER="Warén Group"
;;
cwchristerw)
DOMAIN=christerwaren.fi
VAULT_DOMAIN=vault.cwinfo.net
ORG_HEADER="Christer Warén"
;;
*)
wxi-content status "Organization" "Unsupported"
wxi-footer
wxi-stop
;;
esac
else
wxi-content status "Organization" "Required"
wxi-footer
wxi-stop
fi
fi
if [[ -z $1 || $1 == "--vault" ]]
then
if [[ -z $VAULT_DOMAIN ]]
then
wxi-content status "Vault" "Unavailable"
wxi-footer
wxi-repeat "\n" 3
exit 1
fi
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/sys/health)
if [[ ! $VAULT_STATUS -eq 200 ]]
then
wxi-content status "Vault" "Offline"
wxi-footer
wxi-repeat "\n" 3
exit 1
fi
fi
} }
warencli-start() { wxi-start(){
warencli-syntax-line-douple wxi-header "Warén CLI" h1
echo -n "Warén CLI "
warencli-syntax-line-douple mkdir -p $HOME/.warengroup
if [[ ! -f $HOME/.warengroup/config.json || $(jq -e . < $HOME/.warengroup/config.json &>/dev/null; echo $?) -gt 0 ]]
then
echo '{}' | jq > $HOME/.warengroup/config.json
fi
mkdir -p $HOME/.ssh/keys
chmod 700 -R $HOME/.ssh/keys
mkdir -p $HOME/.ssh/multiplex
chmod 700 -R $HOME/.ssh/multiplex
} }
warencli-stop () { wxi-stop(){
echo " " if [[ ! -f $HOME/bin/wx ]]
then
wx-install &> /dev/null
else
wx-update &> /dev/null
fi
# wxi-repeat "\n" 3
# for key in "${!args[@]}"
# do
# echo "$key: ${args[$key]}"
# done
wxi-repeat "\n" 3
exit 1 exit 1
} }
warencli-update() { wxi-content(){
if [[ -d "./src" ]]; then if [[ $1 == "text" ]]
echo ">>> Building... <<<" then
podman run -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp docker.io/library/php:8-cli php generator.php echo "$2"
else elif [[ $1 == "status" ]]
echo ">>> Updating... <<<" then
sudo curl https://git.waren.io/warengroup/wx/raw/branch/master/wx -o /opt/wx &> /dev/null wxi-repeat "\n" 2
if [[ -d "/usr/bin" ]]; then echo -n "$wxiBold"
sudo ln -sf /opt/wx /usr/bin/wx &> /dev/null echo "Status"
echo -n "$wxiNormal"
echo "$2 - $3"
elif [[ $1 == "link" ]]
then
echo "$2 - $3"
fi fi
sudo chmod +x /usr/bin/wx &> /dev/null
fi
} }
warencli-help() { wxi-footer(){
echo " echo ""
echo "------------------------------"
wxi-repeat " " $((30/2-12/2))
echo -n "$wxiBold"
echo "Warén Group™"
echo -n "$wxiNormal"
wxi-repeat " " $((30/2-17/2))
echo "https://waren.io"
echo "=============================="
}
wxiRed=$(tput setaf 196)
wxiGreen=$(tput setaf 46)
wxiYellow=$(tput setaf 226)
wxiBlue=$(tput setaf 21)
wxiPurple=$(tput setaf 165)
wxiTurquoise=$(tput setaf 14)
wxiPink=$(tput setaf 198)
wxiOrange=$(tput setaf 202)
wxiUnderline=$(tput smul)
wxiBold=$(tput bold)
wxiNormal=$(tput sgr0)
wxi-header(){
if [[ $2 == "h1" ]]
then
wxi-repeat "\n" 3
echo "=============================="
wxi-repeat " " $((30/2-${#1}/2))
echo -n "$wxiBold"
echo "$1"
echo -n "$wxiNormal"
echo "=============================="
fi
if [[ $2 == "h2" || -z $2 ]]
then
wxi-start
wxi-repeat " " $((30/2-6/2-${#1}/2))
echo -n "$wxiBold"
echo ">> $1 <<"
echo -n "$wxiNormal"
echo "------------------------------"
echo ""
fi
if [[ $2 == "h3" ]]
then
echo -n "$wxiBold"
echo "$1"
echo -n "$wxiNormal"
fi
}
wxi-repeat() {
if [[ $1 == " " ]]
then
local str=$1 n=$2 spaces
printf -v spaces "%*s" $n " "
printf "%s" "${spaces// /$str}"
else
for i in $(seq 1 $2);
do
echo -en $1
done
fi
}
wx-help(){
wxi-header "Help"
wxi-content text "
Usage: $0 COMMAND [OPTIONS] Usage: $0 COMMAND [OPTIONS]
Common Commands: Common Commands:
init Init
help Help
ssh SSH ssh SSH
config Config config Config
sign Certificates edit Edit
save Save
sync Sync
clean Clean
keys Keys
generate Generate
sign Sign
retrieve Retrieve
save Save
sync Sync
clean Clean
Authentication Commands: Authentication Commands:
login Login login Login
logout Logout logout Logout
Management Commands: Management Commands:
auto Auto
clean Clean
settings Settings settings Settings
Maintenance Commands: Maintenance Commands:
install Install install Install
update Update update Update
uninstall Uninstall
"; ";
wxi-footer
}
wx-infra(){
wx-login &> /dev/null
wx-auto &> /dev/null
wxi-header "Infra"
wxi-restricted
case $USERNAME in
cwchristerw)
if [[ -d "$HOME/.warengroup/infra" ]]
then
INFRA_PATH="$HOME/.warengroup/infra"
else
INFRA_PATH="$HOME/.warengroup/infra"
mkdir -p "$INFRA_PATH" &> /dev/null
git clone ssh://git@git.waren.io:2222/warengroup-private/infra.git --config core.sshCommand="ssh -i $HOME/.ssh/keys/warengroup-legacy -o ProxyJump=none" "$INFRA_PATH" &> /dev/null
fi
if [[ ! -f "$INFRA_PATH/vault/cwchristerw" || ! -f "$INFRA_PATH/vault/warengroup" ]]
then
mkdir -p "$INFRA_PATH/vault" &> /dev/null
curl \
-H "X-Vault-Token: $TOKEN" \
-X GET \
https://$VAULT_DOMAIN/v1/cli/data/cwchristerw/settings/infra -s | jq -r '.data.data.cwchristerw' > "$INFRA_PATH/vault/cwchristerw"
curl \
-H "X-Vault-Token: $TOKEN" \
-X GET \
https://$VAULT_DOMAIN/v1/cli/data/cwchristerw/settings/infra -s | jq -r '.data.data.warengroup' > "$INFRA_PATH/vault/warengroup"
fi
INFRA_VAULT="--vault-id warengroup@vault/warengroup --vault-id cwchristerw@vault/cwchristerw"
;;
*)
wxi-content status "User" "Unsupported"
wxi-footer
wxi-stop
INFRA_PATH="$HOME/.warengroup/infra"
INFRA_VAULT="--vault-id warengroup@vault/warengroup"
;;
esac
if [[ -z ${args['2']} ]]
then
echo "Tag Required"
else
cd "$INFRA_PATH"
#git pull &> /dev/null
#ansible-galaxy collection install -r requirements.yml --upgrade &> /dev/null
if [[ ${args['2']} == "init" ]]
then
wxi-header "Init" h3
if [[ -z ${args['3']} ]]
then
tags=init
else
tags=${args['3']}
fi
ansible-playbook $INFRA_VAULT playbooks/init.yml -t $tags --limit "${args['limit']}"
elif [[ ${args['2']} == "manager" ]]
then
wxi-header "Manager" h3
ansible-playbook $INFRA_VAULT manager.yml --extra-vars "${args['extra-vars']}"
else
wxi-header "Playbooks" h3
tags=${args['2']}
ansible-playbook $INFRA_VAULT playbooks.yml -t $tags --limit "${args['limit']}"
fi
cd "$OLDPWD"
fi
wxi-footer
}
wx-ssh(){
wx-login &> /dev/null
wx-auto &> /dev/null
case ${args['2']} in
config)
wxi-ssh-config
;;
keys)
wxi-ssh-keys
;;
*)
wxi-header "SSH"
wxi-restricted
wxi-footer
;;
esac
}
wx-welcome(){
wxi-header "Welcome"
wxi-header "Help" h3
wxi-content text "Use \"wx help\" command"
echo ""
wxi-header "Useful Links" h3
wxi-content link "Infra" "https://infra.waren.io"
wxi-content link "Status" "https://status.waren.io"
wxi-footer
}
wx-login(){
wxi-header "Login"
wxi-restricted --user
wxi-restricted --org
wxi-restricted --vault
wxi-header "$ORG_HEADER" h3
if [[ ! -z ${args['login-type']} ]]
then
LOGIN_TYPE=${args['login-type']}
elif [[ ! -z ${args['token']} ]]
then
LOGIN_TYPE=token
elif [[ -f "$HOME/.warengroup/config.json" && $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token) != 'null' && $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token) != '' ]]
then
LOGIN_TYPE=token
elif [[ ! -z ${args['username']} ]]
then
LOGIN_TYPE=ldap
else
LOGIN_TYPE=ldap
fi
if [[ ! -z $LOGIN_TYPE ]]
then
case $LOGIN_TYPE in
ldap)
echo -n "Username: "
if [[ ! -z ${args['username']} ]]
then
USERNAME=${args['username']}
wxi-content text "$USERNAME"
else
read USERNAME
fi
echo -n "Password: "
if [[ ! -z ${args['password']} ]]
then
PASSWORD=${args['password']}
else
read -s PASSWORD
fi
if [[ ! -z $PASSWORD ]]
then
wxi-content text "****************"
else
wxi-content text ""
fi
if [[ -z $USERNAME || -z $PASSWORD ]]
then
wxi-content status "Username & Password" "Required"
wxi-footer
wxi-stop
fi
VAULT_LOGIN=$(curl https://$VAULT_DOMAIN/v1/auth/ldap/login/$USERNAME -X POST -d '{ "password": "'$PASSWORD'" }' -s | jq -r '.auth.client_token')
if [[ -z $VAULT_LOGIN || ${#VAULT_LOGIN} -lt 95 || ${#VAULT_LOGIN} -gt 95 ]]
then
wxi-content status "Login" "Failed"
wxi-stop
fi
wxi-config login
;;
token)
echo -n "Token: "
if [[ ! -z ${args['token']} ]]
then
if [[ ${args['token']} != "true" ]]
then
TOKEN=${args['token']}
fi
elif [[ -f "$HOME/.warengroup/config.json" && $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token) != 'null' && $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token) != '' ]]
then
TOKEN=$(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token)
else
read -s TOKEN
fi
if [[ ! -z $TOKEN ]]
then
wxi-content text "***********************************************************************************************"
fi
if [[ -z $TOKEN ]]
then
wxi-content status "Token" "Required"
wxi-footer
wxi-stop
fi
if [[ ${#TOKEN} -lt 95 || ${#TOKEN} -gt 95 ]]
then
wxi-content status "Token" "Invalid"
wxi-footer
wxi-stop
fi
VAULT_LOGIN=$(curl https://$VAULT_DOMAIN/v1/auth/token/renew-self -X POST --header "X-Vault-Token: $TOKEN" -d '{ "token": "'$TOKEN'" }' -s | jq -r '.auth.client_token')
if [[ -z $VAULT_LOGIN || ${#VAULT_LOGIN} -lt 95 || ${#VAULT_LOGIN} -gt 95 ]]
then
wxi-content status "Login" "Failed"
wxi-stop
fi
TOKEN=$VAULT_LOGIN
wxi-config login
;;
*)
wxi-content status "Login Type" "Unsupported"
wxi-footer
wxi-stop
;;
esac
fi
VAULT_USERNAME=$(curl https://$VAULT_DOMAIN/v1/auth/token/lookup-self -X GET --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.display_name')
if [[ -z $VAULT_USERNAME ]]
then
wxi-content status "Login" "Username Missing"
wxi-stop
elif [[ $VAULT_USERNAME != ldap* && $VAULT_USERNAME != oidc* ]]
then
wxi-content status "Login" "Authentication Method Invalid"
wxi-stop
elif [[ $VAULT_USERNAME == ldap* ]]
then
USERNAME=${VAULT_USERNAME#ldap-}
elif [[ $VAULT_USERNAME == oidc* ]]
then
USERNAME=${VAULT_USERNAME#oidc-}
fi
wxi-footer
}
wx-logout(){
wxi-header "Logout"
wxi-restricted --user
wxi-restricted --org
wxi-restricted --vault
if [[ -f "$HOME/.warengroup/config.json" && $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token) != 'null' ]]
then
TOKEN=$(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token)
fi
VAULT_STATUS=$(curl https://$VAULT_DOMAIN/v1/auth/token/revoke-self -X POST --header "X-Vault-Token: $TOKEN" -s -o /dev/null -w "%{http_code}")
if [[ $VAULT_STATUS -eq 204 || $VAULT_STATUS -eq 403 ]]
then
wxi-header "$ORG_HEADER" h3
echo "Logging Out..."
TOKEN=""
wxi-config login
wxi-footer
wxi-stop
fi
}
wx-install(){
wxi-header "Install"
wxi-restricted --user
if [[ -f "./wx" && -f "./maintainer.sh" && -d "./src" ]]
then
./maintainer.sh
fi
mkdir -p $HOME/bin
if [[ $(curl -s -o /dev/null -w "%{http_code}" https://git.waren.io/warengroup/wx/raw/branch/master/wx) -eq 200 ]]
then
curl https://git.waren.io/warengroup/wx/raw/branch/master/wx -o $HOME/bin/wx &> /dev/null
chmod +x $HOME/bin/wx &> /dev/null
fi
CRONJOB_NAME="#Warén CLI: Auto"
CRONJOB_TASK="*/5 * * * * $HOME/bin/wx auto"
if [[ -z $(crontab -l | grep -F "$CRONJOB_NAME") || -z $(crontab -l | grep -F "$CRONJOB_TASK") ]]
then
(crontab -l ; echo "$CRONJOB_NAME" ; echo "$CRONJOB_TASK") | grep -Fv "no crontab" | crontab -
fi
wxi-footer
}
wx-uninstall(){
wxi-header "Uninstall"
wxi-restricted --user
wx-clean &> /dev/null
if [[ -d "$HOME/.warengroup" ]]
then
rm "$HOME/.warengroup" -rf
fi
CRONJOB_NAME="#Warén CLI: Auto"
CRONJOB_TASK="*/5 * * * * $HOME/bin/wx auto"
if [[ $(crontab -l | grep -F "$CRONJOB_NAME") || $(crontab -l | grep -F "$CRONJOB_TASK") ]]
then
crontab -l | grep -Fv "$CRONJOB_NAME" | grep -Fv "$CRONJOB_TASK" | grep -Fv "no crontab" | crontab -
fi
if [[ -f "$HOME/bin/wx" ]]
then
rm "$HOME/bin/wx" -rf
fi
wxi-footer
wxi-repeat "\n" 3
exit 1
}
wx-update(){
wxi-header "Update"
wxi-restricted --user
wx-install &> /dev/null
echo "Updates Completed"
wxi-footer
}
wx-auto(){
wx-login &> /dev/null
wxi-header "Auto"
wxi-restricted
wxi-footer
wxi-ssh-config-sync
wxi-ssh-keys-sign
wxi-ssh-keys-sync
}
wx-clean(){
wxi-header "Clean"
wxi-restricted --user
wxi-footer
wxi-ssh-config-clean
wxi-ssh-keys-clean
}
wx-settings(){
wx-login &> /dev/null
wx-auto &> /dev/null
wxi-header "Settings"
wxi-restricted --user
wxi-footer
}
wxi-ssh-config(){
case ${args['3']} in
edit)
wxi-ssh-config-sync
wxi-ssh-config-edit
wxi-ssh-config-save
;;
save)
wxi-ssh-config-save
;;
sync)
wxi-ssh-config-sync
;;
clean)
wxi-ssh-config-clean
;;
*)
wxi-ssh-config-sync
;;
esac
}
wxi-ssh-keys(){
case ${args['3']} in
generate)
wxi-ssh-keys-retrieve ${args['4']}
wxi-ssh-keys-generate ${args['4']}
wxi-ssh-keys-save ${args['4']}
;;
sign)
wxi-ssh-keys-sign
;;
retrieve)
wxi-ssh-keys-retrieve ${args['4']}
;;
save)
wxi-ssh-keys-save ${args['4']}
;;
sync)
wxi-ssh-keys-sync
;;
clean)
wxi-ssh-keys-clean
;;
*)
wxi-header "SSH / Keys"
wxi-footer
;;
esac
}
wxi-ssh-config-clean(){
wxi-header "SSH / Config / Clean"
wxi-restricted
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: $TOKEN")
if [[ -f "$HOME/.ssh/config" && $VAULT_STATUS -eq 200 ]]
then
rm "$HOME/.ssh/config"
fi
wxi-footer
}
wxi-ssh-config-edit(){
wxi-header "SSH / Config / Edit"
wxi-restricted
nano ~/.ssh/config
wxi-footer
}
wxi-ssh-config-save(){
wxi-header "SSH / Config / Save"
wxi-restricted
if [[ -f "$HOME/.ssh/config" ]]
then
curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X POST --header "X-Vault-Token: $TOKEN" -d "{ \"data\": { \"data\": \"$(cat ~/.ssh/config | base64 -w 0)\" } }" -s &> /dev/null
fi
wxi-footer
}
wxi-ssh-config-sync(){
wxi-header "SSH / Config / Sync"
wxi-restricted
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: $TOKEN")
if [[ $VAULT_STATUS -eq 200 ]]
then
touch ~/.ssh/config
SSH1_CONFIG_MD5=$(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.data.data' | base64 -d | md5sum | base64)
SSH2_CONFIG_MD5=$(cat ~/.ssh/config | md5sum | base64)
if [[ $SSH1_CONFIG_MD5 != $SSH2_CONFIG_MD5 ]]
then
echo $(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.data.data') | base64 -d > ~/.ssh/config 2>&1
chmod 700 ~/.ssh/config
fi
fi
wxi-footer
}
wxi-ssh-keys-clean(){
wxi-header "SSH / Keys / Clean"
wxi-restricted
if [[ ! -z $1 ]]
then
if [[ -f "$HOME/.ssh/keys/$1" ]]
then
rm "$HOME/.ssh/keys/$1" &> /dev/null
rm "$HOME/.ssh/keys/$1.pub" &> /dev/null
rm "$HOME/.ssh/keys/$1.sig" &> /dev/null
fi
else
wxi-ssh-keys-clean $ORG
if [[ $USERNAME == "cwchristerw" ]]
then
wxi-ssh-keys-clean warengroup
fi
for file in ~/.ssh/keys/*
do
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$(basename "$file" .pub) -X GET --header "X-Vault-Token: $TOKEN")
if [[ $VAULT_STATUS -eq 200 ]]
then
rm "$file" &> /dev/null
fi
done
fi
wxi-footer
}
wxi-ssh-keys-generate(){
wxi-header "SSH / Keys / Generate"
wxi-restricted
if [[ ! -z $1 ]]
then
if [[ ! -f "$HOME/.ssh/keys/$1" ]]
then
ssh-keygen -t ed25519 -f $HOME/.ssh/keys/$1 -q -N "" -C "$USERNAME" &> /dev/null
fi
fi
wxi-footer
}
wxi-ssh-keys-retrieve(){
wxi-header "SSH / Keys / Retrieve"
wxi-restricted
if [[ ! -z $1 ]]
then
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X GET --header "X-Vault-Token: $TOKEN")
if [[ $VAULT_STATUS -eq 200 ]]
then
echo $(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X GET --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.data.private') | base64 -d > ~/.ssh/keys/$1 2>&1
chmod 700 ~/.ssh/keys/$1
echo $(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X GET --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.data.public') | base64 -d > ~/.ssh/keys/$1.pub 2>&1
chmod 700 ~/.ssh/keys/$1.pub
fi
fi
wxi-footer
}
wxi-ssh-keys-save(){
wxi-header "SSH / Keys / Save"
wxi-restricted
if [[ ! -z $1 ]]
then
if [[ -f "$HOME/.ssh/keys/$1" ]]
then
curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X POST --header "X-Vault-Token: $TOKEN" -d "{ \"data\": { \"private\": \"$(cat ~/.ssh/keys/$1 | base64 -w 0)\", \"public\": \"$(cat ~/.ssh/keys/$1.pub | base64 -w 0)\" } }" -s &> /dev/null
fi
fi
wxi-footer
}
wxi-ssh-keys-sign(){
wxi-header "SSH / Keys / Sign"
wxi-restricted
wxi-ssh-keys-sign-create $ORG sysadmin 3600
if [[ $USERNAME == "cwchristerw" ]]
then
wxi-ssh-keys-sign-create warengroup sysadmin 3600
fi
wxi-footer
}
wxi-ssh-keys-sign-create(){
NAME=$1
ROLE=$2
PRINCIPALS=$2
TTL=$3
wxi-ssh-keys-generate $NAME &> /dev/null
if [[ -f "$HOME/.ssh/keys/$NAME" ]]
then
wxi-content text "$NAME/$ROLE"
echo $(curl https://$VAULT_DOMAIN/v1/ssh/sign/$ROLE -X POST --header "X-Vault-Token: $TOKEN" -d "{ \"public_key\": \"$(cat $HOME/.ssh/keys/$NAME.pub)\", \"valid_principals\": \"$PRINCIPALS,$USERNAME\", \"ttl\": \"$TTL\" }" -s | jq -r '.data.signed_key') > ~/.ssh/keys/$NAME.sig 2>&1
fi
}
wxi-ssh-keys-sync(){
wxi-header "SSH / Keys / Sync"
wxi-restricted
VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/metadata/$USERNAME/settings/ssh/keys -X LIST --header "X-Vault-Token: $TOKEN")
if [[ $VAULT_STATUS -eq 200 ]]
then
for name in $(curl https://$VAULT_DOMAIN/v1/cli/metadata/$USERNAME/settings/ssh/keys -X LIST --header "X-Vault-Token: $TOKEN" -s | jq -r '.data.keys | @sh' | tr -d \')
do
wxi-content text $name
wxi-ssh-keys-retrieve $name &> /dev/null
done
fi
wxi-footer
} }
warencli-install() { i=1
echo ">>> Install"; while [[ "$1" != "" ]]
} do
case $1 in
--*)
key="${1%%=*}"
value="${1#*=}"
warencli-settings() { if [[ "$value" == "$key" ]]
echo ">>> Settings"; then
} shift
value="$1"
fi
warencli-ssh() { if [[ -z $value ]]
echo ">>> SSH"; then
} value=true
fi
warencli-login() { args["${key#--}"]="$value"
echo ">>> Authentication: Login"; ;;
} -*)
key="${1%=*}"
value="${1#*=}"
warencli-logout() { if [[ "$value" == "$key" ]]
echo ">>> Authentication: Logout"; then
} shift
value="$1"
fi
warencli-ssh-config(){ if [[ -z $value ]]
echo ">>> SSH: Config" then
} value=true
fi
warencli-ssh-sign(){ args["${key#-}"]="$value"
echo ">>> SSH: Certificates" ;;
} *)
args["$i"]="${1%%=*}"
i=$((i + 1))
;;
esac
shift
done
if [[ ! -z ${args['1']} ]] && [[ $(type -t wx-${args['1']}) == function ]]
COMMAND=$1 then
wx-${args['1']}
warencli-start else
if [[ ! -z $1 ]]; then wx-welcome
warencli-$1 $2 $3 $4 $5 $6 $7 $8 $9
fi fi
warencli-stop wxi-stop