Skip to content

Commit baaba4e

Browse files
Feature/newapisystem (hestiacp#2535)
* Adds new API system * Each key is composed of an identification hash and a secret hash; * Permission system for keys with command limitation; * API connection by non-admin users; * Added /api/v2/ route to not conflict with the old version; * Option to enable V2 in system settings; * Management of keys by the panel; * New keys are saved in the "data/access-keys" directory; * API settings in "data/api". * Changes to the new API system * Merges API routes; * Renames config index to API_SYSTEM; * Updates locales; * Validation to avoid creating a new key when refreshing the page; * Adds key creation and deletion logs. * Fixes for Shellcheck * API changes and fixes * Changes "disabled" to "readonly" in the fields of list_access_key.html; * Initializes the api directory in the installer; * Initialize api directory in 1.6.0 upgrade; * Changes the API version in the installer; * Change JS to hide the IPs field only when the 2 API versions are disabled; * Removes $v_comment variable from the key creation page; * Keep legacy api enabled for now * Allow for coded disabled api without lookup if disabled * Allow enable / disable legacy / new api seperate * Allow changes to api to enable / disable api for legacy / new api * Return access_key:access_secret_key for use in bash Co-authored-by: Jaap Marcus <9754650+jaapmarcus@users.noreply.github.com>
1 parent 8107573 commit baaba4e

36 files changed

+2070
-331
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ test/node_modules/
1515
npm-debug.log
1616
.phpunit.result.cache
1717
.vs
18-
.nova
18+
.nova
19+
/.idea/

bin/v-add-access-key

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/bin/bash
2+
# info: generate access key
3+
# options: USER [PERMISSIONS] [COMMENT] [FORMAT]
4+
#
5+
# example: v-add-access-key admin v-purge-nginx-cache,v-list-mail-accounts comment json
6+
#
7+
# The "PERMISSIONS" argument is optional for the admin user only.
8+
# This function creates a key file in $HESTIA/data/access-keys/
9+
10+
#----------------------------------------------------------#
11+
# Variables & Functions #
12+
#----------------------------------------------------------#
13+
14+
# Argument definition
15+
user=$1
16+
permissions=$2
17+
comment=$3
18+
format=${4-shell}
19+
20+
# Includes
21+
# shellcheck source=/etc/hestiacp/hestia.conf
22+
source /etc/hestiacp/hestia.conf
23+
# shellcheck source=/usr/local/hestia/func/main.sh
24+
source $HESTIA/func/main.sh
25+
# load config file
26+
source_conf "$HESTIA/conf/hestia.conf"
27+
28+
keygen() {
29+
local LENGTH=${1:-20}
30+
local USE_SPECIAL_CHARACTERS="${2:-no}"
31+
32+
local MATRIX='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
33+
if [[ "$USE_SPECIAL_CHARACTERS" == "yes" ]]; then
34+
MATRIX+='_-+^~=%'
35+
fi
36+
37+
local PASS N
38+
while [ ${N:=1} -le $LENGTH ]; do
39+
PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}"
40+
let N+=1
41+
done
42+
43+
echo "$PASS"
44+
}
45+
46+
access_key_id="$(keygen)"
47+
secret_access_key="$(keygen 40 yes)"
48+
49+
# Perform verification if read-only mode is enabled
50+
check_hestia_demo_mode
51+
52+
# Remove whitespace and bin path from permissions
53+
permissions="$(cleanup_key_permissions "$permissions")"
54+
55+
time_n_date=$(date +'%T %F')
56+
time=$(echo "$time_n_date" |cut -f 1 -d \ )
57+
date=$(echo "$time_n_date" |cut -f 2 -d \ )
58+
59+
#----------------------------------------------------------#
60+
# Verifications #
61+
#----------------------------------------------------------#
62+
63+
check_args '1' "$#" 'USER [PERMISSIONS] [COMMENT] [FORMAT]'
64+
is_format_valid 'user'
65+
is_object_valid 'user' 'USER' "$user"
66+
is_key_permissions_format_valid "$permissions" "$user"
67+
if [ -n "$comment" ]; then
68+
is_format_valid 'comment'
69+
fi
70+
71+
#----------------------------------------------------------#
72+
# Action #
73+
#----------------------------------------------------------#
74+
75+
if [ ! -d "$HESTIA/data/access-keys/" ]; then
76+
mkdir -p $HESTIA/data/access-keys/
77+
chown root:root $HESTIA/data/access-keys/
78+
chmod 750 $HESTIA/data/access-keys/
79+
fi
80+
81+
if [[ -e "$HESTIA/data/access-keys/${access_key_id}" ]]; then
82+
while [[ -e "$HESTIA/data/access-keys/${access_key_id}" ]]; do
83+
access_key_id=$(keygen)
84+
done
85+
fi
86+
87+
echo "SECRET_ACCESS_KEY='$secret_access_key'" >"$HESTIA/data/access-keys/${access_key_id}"
88+
echo "USER='$user'" >>"$HESTIA/data/access-keys/${access_key_id}"
89+
echo "PERMISSIONS='$permissions'" >>"$HESTIA/data/access-keys/${access_key_id}"
90+
echo "COMMENT='$comment'" >>"$HESTIA/data/access-keys/${access_key_id}"
91+
echo "TIME='$time'" >>"$HESTIA/data/access-keys/${access_key_id}"
92+
echo "DATE='$date'" >>"$HESTIA/data/access-keys/${access_key_id}"
93+
# TODO Index reserved for future implementation
94+
echo "EXPIRES_IN=''" >>"$HESTIA/data/access-keys/${access_key_id}"
95+
echo "IP=''" >>"$HESTIA/data/access-keys/${access_key_id}"
96+
97+
chmod 640 "$HESTIA/data/access-keys/${access_key_id}"
98+
99+
$BIN/v-list-access-key "$access_key_id" "$format"
100+
101+
#----------------------------------------------------------#
102+
# Hestia #
103+
#----------------------------------------------------------#
104+
105+
# Logging
106+
log_history "Access key $access_key_id generated" "Warning" "$user" "API"
107+
log_event "$OK" "$ARGUMENTS"
108+
109+
exit

bin/v-change-sys-api

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22
# info: Enable / Disable API access
33
# options: STATUS
44
#
5-
# example: v-change-sys-api enable
6-
# # Enable API
5+
# example: v-change-sys-api enable legacy
6+
# # Enable legacy api currently default on most of api based systems
7+
# example: v-change-sys-api enable api
8+
# # Enable api
79
#
810
# example: v-change-sys-api disable
911
# # Disable API
1012
#
1113
# Enabled / Disable API
1214

1315
status=$1
16+
version=$2
1417

1518
# Includes
1619
# shellcheck source=/etc/hestiacp/hestia.conf
@@ -24,9 +27,8 @@ source_conf "$HESTIA/conf/hestia.conf"
2427
# Variables & Functions #
2528
#----------------------------------------------------------#
2629

27-
check_args '1' "$#" "STATUS"
30+
check_args '1' "$#" "STATUS" "VERSION"
2831
is_type_valid "enable,disable,remove" "$status"
29-
3032
# Perform verification if read-only mode is enabled
3133
check_hestia_demo_mode
3234

@@ -51,10 +53,12 @@ if [ "$status" = "enable" ]; then
5153
sed -i 's|die("Error: Disabled");|//die("Error: Disabled");|g' $HESTIA/web/api/index.php
5254
sed -i 's|////|//|g' $HESTIA/web/api/index.php
5355
fi
54-
$HESTIA/bin/v-change-sys-config-value "API" "yes"
56+
if [ "$version" = "legacy" ] || [ "$version" = "all" ]; then $HESTIA/bin/v-change-sys-config-value "API" "yes"; fi
57+
if [ "$version" = "api" ] || [ "$version" = "all" ]; then $HESTIA/bin/v-change-sys-config-value "API_SYSTEM" "1"; fi
5558
else
5659
$HESTIA/bin/v-change-sys-config-value "API" "no"
5760
$HESTIA/bin/v-change-sys-config-value "API_ALLOWED_IP" ""
61+
$HESTIA/bin/v-change-sys-config-value "API_SYSTEM" "0"
5862
if [ "$status" != "remove" ]; then
5963
sed -i 's|//die("Error: Disabled");|die("Error: Disabled");|g' $HESTIA/web/api/index.php
6064
fi

bin/v-check-access-key

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/bin/bash
2+
# info: check access key
3+
# options: ACCESS_KEY_ID SECRET_ACCESS_KEY COMMAND [IP] [FORMAT]
4+
#
5+
# example: v-check-access-key key_id secret v-purge-nginx-cache 127.0.0.1 json
6+
#
7+
# * Checks if the key exists;
8+
# * Checks if the secret belongs to the key;
9+
# * Checks if the key user is suspended;
10+
# * Checks if the key has permission to run the command.
11+
12+
#----------------------------------------------------------#
13+
# Variables & Functions #
14+
#----------------------------------------------------------#
15+
16+
access_key_id="$(basename "$1")"
17+
secret_access_key=$2
18+
hst_command=$3
19+
ip=${4-127.0.0.1}
20+
format=${5-shell}
21+
22+
# Includes
23+
# shellcheck source=/etc/hestiacp/hestia.conf
24+
source /etc/hestiacp/hestia.conf
25+
# shellcheck source=/usr/local/hestia/func/main.sh
26+
source $HESTIA/func/main.sh
27+
# load config file
28+
source_conf "$HESTIA/conf/hestia.conf"
29+
30+
# Perform verification if read-only mode is enabled
31+
check_hestia_demo_mode
32+
33+
time_n_date=$(date +'%T %F')
34+
time=$(echo "$time_n_date" |cut -f 1 -d \ )
35+
date=$(echo "$time_n_date" |cut -f 2 -d \ )
36+
37+
# JSON list function
38+
json_list() {
39+
echo -n '{"USER": "'$user'"';
40+
41+
if [[ -n "$user_arg_pos" ]]; then
42+
echo -n ', "USER_ARG_POSITION": '$user_arg_pos''
43+
fi
44+
45+
echo '}'
46+
}
47+
48+
# SHELL list function
49+
shell_list() {
50+
echo "USER: $user"
51+
if [[ -n "$user_arg_pos" ]]; then
52+
echo "USER_ARG_POSITION: $user_arg_pos"
53+
fi
54+
}
55+
56+
# Callback to intercept invalid result validation
57+
abort_missmatch() {
58+
echo "Error: $2"
59+
echo "$date $time ${access_key_id:-api} $ip failed to login" >> $HESTIA/log/auth.log
60+
61+
# Add a log for user
62+
if [[ "$1" == "$E_PASSWORD" && -n "$user" ]]; then
63+
log_history "[$ip] $access_key_id $2" "Error" "$user" "API"
64+
fi
65+
66+
if [[ "$1" == "$E_FORBIDEN" ]]; then
67+
exit "$1"
68+
fi
69+
70+
exit "$E_PASSWORD"
71+
}
72+
73+
#----------------------------------------------------------#
74+
# Verifications #
75+
#----------------------------------------------------------#
76+
77+
# Add a callback to intercept invalid "check_result" results
78+
CHECK_RESULT_CALLBACK="abort_missmatch"
79+
80+
check_args '3' "$#" 'ACCESS_KEY_ID SECRET_ACCESS_KEY COMMAND [IP] [FORMAT]'
81+
is_format_valid 'access_key_id'
82+
is_object_valid 'key' 'KEY' "$access_key_id"
83+
is_format_valid 'secret_access_key'
84+
check_access_key_secret "$access_key_id" "$secret_access_key" user
85+
check_access_key_cmd "$access_key_id" "$hst_command" user_arg_pos
86+
87+
# Check if key owner is active
88+
is_format_valid 'user'
89+
is_object_valid 'user' 'USER' "$user"
90+
export USER_DATA=$HESTIA/data/users/$user
91+
is_object_unsuspended 'user' 'USER' "$user"
92+
93+
# Remove the check_result callback
94+
CHECK_RESULT_CALLBACK=""
95+
96+
#----------------------------------------------------------#
97+
# Action #
98+
#----------------------------------------------------------#
99+
100+
# Listing data
101+
case $format in
102+
json) json_list ;;
103+
shell) shell_list ;;
104+
esac
105+
106+
#----------------------------------------------------------#
107+
# Hestia #
108+
#----------------------------------------------------------#
109+
110+
# Logging
111+
log_history "[$ip] Access key $access_key_id successfully launched with command $hst_command" "Info" "$user" "API"
112+
echo "$date $time $access_key_id $ip $hst_command successfully launched" >> $HESTIA/log/auth.log
113+
114+
exit

bin/v-delete-access-key

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/bash
2+
# info: delete access key
3+
# options: ACCESS_KEY_ID
4+
#
5+
# example: v-delete-access-key mykey
6+
#
7+
# This function removes a key from in $HESTIA/data/access-keys/
8+
9+
#----------------------------------------------------------#
10+
# Variables & Functions #
11+
#----------------------------------------------------------#
12+
13+
# Includes
14+
# shellcheck source=/etc/hestiacp/hestia.conf
15+
source /etc/hestiacp/hestia.conf
16+
# shellcheck source=/usr/local/hestia/func/main.sh
17+
source $HESTIA/func/main.sh
18+
# load config file
19+
source_conf "$HESTIA/conf/hestia.conf"
20+
21+
#----------------------------------------------------------#
22+
# Variables & Functions #
23+
#----------------------------------------------------------#
24+
25+
access_key_id=$1
26+
27+
check_args '1' "$#" "ACCESS_KEY_ID"
28+
is_format_valid 'access_key_id'
29+
is_object_valid 'key' 'KEY' "$access_key_id"
30+
31+
# Perform verification if read-only mode is enabled
32+
check_hestia_demo_mode
33+
34+
#----------------------------------------------------------#
35+
# Action #
36+
#----------------------------------------------------------#
37+
38+
if [ ! -d "$HESTIA/data/access-keys/" ]; then
39+
exit "$E_NOTEXIST"
40+
fi
41+
42+
if [[ -e "${HESTIA}/data/access-keys/${access_key_id}" ]]; then
43+
source_conf "${HESTIA}/data/access-keys/${access_key_id}"
44+
rm "${HESTIA}/data/access-keys/${access_key_id}"
45+
else
46+
exit "$E_NOTEXIST"
47+
fi
48+
49+
#----------------------------------------------------------#
50+
# Hestia #
51+
#----------------------------------------------------------#
52+
53+
# Logging
54+
log_history "Access key $access_key_id deleted" "Info" "$USER" "API"
55+
log_event "$OK" "$ARGUMENTS"
56+
57+
exit

0 commit comments

Comments
 (0)