Commit 1c22a9d8 authored by Julius Goryavsky's avatar Julius Goryavsky

MDEV-28277: Checking for mandatory "/v1/" prefix in the URL

According to the Hashicorp Vault API specifications,
the URL to access the keys must include the "/v1/" prefix
at the beginning of the path. This commit adds this parameter
check, as well as a check for the presence of at least one
letter in the hostname inside the URL and in the secret
store name (after "/v1/").
parent 35989d9c
......@@ -1000,34 +1000,144 @@ static int hashicorp_key_management_plugin_init(void *p)
{
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
"Memory allocation error", 0);
goto Failure2;
Failure2:
if (local_token)
{
free(local_token);
local_token = NULL;
}
return 1;
}
snprintf(token_header, buf_len, "%s%s", x_vault_token, token);
vault_url_len = strlen(vault_url);
/*
Checking the maximum allowable length to protect
against allocating too much memory on the stack:
*/
if (vault_url_len > MAX_URL_SIZE)
/* We need to check that the path inside the URL starts with "/v1/": */
const char *suffix = strchr(vault_url, '/');
if (suffix == NULL)
{
Bad_url:
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
"Maximum allowed vault URL length exceeded",
0);
"According to the Hashicorp Vault API rules, "
"the path inside the URL must start with "
"the \"/v1/\" prefix, while the supplied "
"URL value is: \"%s\"", 0, vault_url);
Failure:
vault_url_len = 0;
free(token_header);
token_header = NULL;
Failure2:
if (local_token)
goto Failure2;
}
size_t prefix_len = (size_t) (suffix - vault_url);
if (prefix_len == 0)
{
No_Host:
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
"Supplied URL does not contain a hostname: \"%s\"",
0, vault_url);
goto Failure;
}
/* Check if the suffix consists only of the slash: */
size_t suffix_len = strlen(suffix + 1) + 1;
if (suffix_len == 1)
{
goto Bad_url;
}
vault_url_len = prefix_len + suffix_len;
/*
The scheme always ends with "://", while the "suffix"
points to the first of the slashes:
*/
if (*(suffix - 1) == ':' && suffix[1] == '/')
{
/* Let's check that only the schema is present: */
if (suffix_len == 2)
{
free(local_token);
local_token = NULL;
goto No_Host;
}
return 1;
/* Save the current position: */
const char *start = suffix + 2;
/* We need to find next slash: */
suffix = strchr(start, '/');
if (suffix == NULL)
{
goto Bad_url;
}
/* Update the prefix and suffix lengths: */
prefix_len = (size_t) (suffix - vault_url);
suffix_len = vault_url_len - prefix_len;
/*
The slash right after the scheme is the absence of a hostname,
this is invalid for all schemes, except for the "file://"
(this allowed for debugging purposes only):
*/
if (suffix == start &&
(prefix_len != 7 || memcmp(vault_url, "file", 4) != 0))
{
goto No_Host;
}
/* Check if the suffix consists only of the slash: */
if (suffix_len == 1)
{
goto Bad_url;
}
}
/* Let's skip all leading slashes: */
while (suffix[1] == '/')
{
suffix++;
suffix_len--;
if (suffix_len == 1)
{
goto Bad_url;
}
}
/*
Checking for "/v1" sequence (the leading slash has
already been checked):
*/
if (suffix_len < 3 || suffix[1] != 'v' || suffix[2] != '1')
{
goto Bad_url;
}
/* Let's skip the "/v1" sequence: */
suffix_len -= 3;
if (suffix_len == 0)
{
No_Secret:
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
"Supplied URL does not contain a secret name: \"%s\"",
0, vault_url);
goto Failure;
}
suffix += 3;
/* Checking for a slash at the end of the "/v1/" sequence: */
if (suffix[0] != '/')
{
goto Bad_url;
}
if (vault_url_len && vault_url[vault_url_len - 1] == '/')
/* Skip slashes after the "/v1" sequence: */
do
{
suffix++;
suffix_len--;
if (suffix_len == 0)
{
goto No_Secret;
}
} while (suffix[0] == '/');
/* Remove trailing slashes at the end of the url: */
while (vault_url[vault_url_len - 1] == '/')
{
vault_url_len--;
}
/*
Checking the maximum allowable length to protect
against allocating too much memory on the stack:
*/
if (vault_url_len > MAX_URL_SIZE)
{
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
"Maximum allowed vault URL length exceeded", 0);
goto Failure;
}
/*
In advance, we create a buffer containing the URL for vault
+ the "/data/" suffix (7 characters):
......
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a hostname: "/"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "abcd"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "abcd/"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "abcd//"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a hostname: "/abcd"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "abcd/v"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a secret name: "a/v1"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "a/v1b"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a secret name: "a/v1/"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a secret name: "a/v1///"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a secret name: "a///v1/"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a hostname: "///v1/a"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a hostname: "http://"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a hostname: "http:///"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "http://a"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "http://abcd"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "http://abcd/"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "http://abcd//"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a hostname: "http:///abcd"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "http://abcd/v"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a secret name: "http://a/v1"
[ERROR] mariadbd: hashicorp: According to the Hashicorp Vault API rules, the path inside the URL must start with the "/v1/" prefix, while the supplied URL value is: "http://a/v1b"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a secret name: "http://a/v1/"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a secret name: "http://a/v1///"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a secret name: "http://a///v1/"
[ERROR] mariadbd: hashicorp: Supplied URL does not contain a hostname: "http://///v1/a"
# restart: with restart_parameters
CREATE TABLE t1 (a VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=1;
INSERT INTO t1 VALUES ('foo'),('bar');
DROP TABLE t1;
# restart
# MDEV-28277: Checking for mandatory "/v1/" prefix in the URL
# The test presumes that the local vault is running at $VAULT_ADDR,
# and the token is configured in $VAULT_TOKEN.
--source include/have_innodb.inc
--source hashicorp_plugin.inc
--exec vault secrets disable bug > /dev/null
--exec vault secrets enable -path /bug -version=2 kv > /dev/null
--exec vault kv put /bug/1 data=01234567890123456789012345678901 > /dev/null
--source include/shutdown_mysqld.inc
--let $LOG_FILE=$MYSQLTEST_VARDIR/log/vault.err
--error 0,1
--remove_file $LOG_FILE
--let $vault_defaults=--plugin-load-add=hashicorp_key_management --hashicorp_key_management=force --hashicorp-key-management-check-kv-version=off --hashicorp-key-management-token="$VAULT_TOKEN"
--let $defaults=--defaults-group-suffix=.1 --defaults-file=$MYSQLTEST_VARDIR/my.cnf $vault_defaults --log-error=$LOG_FILE
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="/"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="abcd"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="abcd/"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="abcd//"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="/abcd"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="abcd/v"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="a/v1"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="a/v1b"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="a/v1/"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="a/v1///"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="a///v1/"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="///v1/a"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http:///"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://a"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://abcd"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://abcd/"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://abcd//"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http:///abcd"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://abcd/v"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://a/v1"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://a/v1b"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://a/v1/"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://a/v1///"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://a///v1/"
--error 1
--exec $MYSQLD $defaults --hashicorp-key-management-vault-url="http://///v1/a"
--exec grep -oE "\[ERROR\] .*: hashicorp: .*" -- $LOG_FILE
--remove_file $LOG_FILE
--let $restart_parameters=$vault_defaults --hashicorp-key-management-vault-url="$VAULT_ADDR/v1/bug///"
--let $restart_noprint=1
--source include/start_mysqld.inc
CREATE TABLE t1 (a VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=1;
INSERT INTO t1 VALUES ('foo'),('bar');
# Cleanup
DROP TABLE t1;
--let $restart_parameters=
--source include/restart_mysqld.inc
--exec vault secrets disable bug > /dev/null
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment