Skip to content

Commit

Permalink
chart(update): remove basic auth credential in grid URL
Browse files Browse the repository at this point in the history
Signed-off-by: Viet Nguyen Duc <[email protected]>
  • Loading branch information
VietND96 committed Sep 20, 2024
1 parent c45f709 commit 0701191
Show file tree
Hide file tree
Showing 12 changed files with 62 additions and 34 deletions.
3 changes: 2 additions & 1 deletion Base/check-grid.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set -e

HOST="localhost"
PORT="4444"
BASIC_AUTH="$(echo -n "${SE_ROUTER_USERNAME}:${SE_ROUTER_PASSWORD}" | base64)"

echoerr() { echo "$@" 1>&2; }

Expand All @@ -26,4 +27,4 @@ while [[ $# -gt 0 ]]; do
esac
done

curl -skSL ${SE_SERVER_PROTOCOL:-"http"}://${HOST}:${PORT}/wd/hub/status | jq -r '.value.ready' | grep -q "true" || exit 1
curl -skSL -H "Authorization: Basic ${BASIC_AUTH}" ${SE_SERVER_PROTOCOL:-"http"}://${HOST}:${PORT}/wd/hub/status | jq -r '.value.ready' | grep -q "true" || exit 1
1 change: 1 addition & 0 deletions charts/selenium-grid/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes
| basicAuth.enabled | bool | `false` | Enable or disable basic auth for the Hub/Router |
| basicAuth.username | string | `"admin"` | Username for basic auth |
| basicAuth.password | string | `"admin"` | Password for basic auth |
| basicAuth.embeddedUrl | bool | `false` | Embed the basic auth "username:password@" in few URLs e.g. SE_NODE_GRID_URL |
| basicAuth.annotations | object | `{}` | Annotations for basic auth secret resource |
| isolateComponents | bool | `false` | Deploy Router, Distributor, EventBus, SessionMap and Nodes separately |
| serviceAccount.create | bool | `true` | Create a service account for all components |
Expand Down
7 changes: 6 additions & 1 deletion charts/selenium-grid/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,13 @@ hub:
```
# Source: selenium-grid/templates/node-configmap.yaml

SE_NODE_GRID_URL: 'http://admin:admin@10.10.10.10/selenium'
SE_NODE_GRID_URL: 'http://10.10.10.10/selenium'
```
For security reasons, it is not recommend to put the credentials in the URL in env variable `SE_NODE_GRID_URL`. For any utilities that need to access the Grid, basic auth should get from env variables `SE_ROUTER_USERNAME` and `SE_ROUTER_PASSWORD`.
If you want to keep basic auth credential is embedded in few URLs (in case Websocket URLs construct in session capabilities), you can set `basicAuth.embeddedUrl` to `true`. By default, it is `false`.
Besides that, from the outside of the cluster, you can access via NodePort `http://10.10.10.10:30444/selenium`
### Configuration of Nodes
Expand Down
11 changes: 6 additions & 5 deletions charts/selenium-grid/configs/distributor/distributorProbe.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,28 @@ ts_format=${SE_LOG_TIMESTAMP_FORMAT:-"+%T.%3N"}
ROUTER_CONFIG_DIRECTORY=${ROUTER_CONFIG_DIRECTORY:-"/opt/bin"}

GRID_GRAPHQL_URL=$(bash ${ROUTER_CONFIG_DIRECTORY}/routerGraphQLUrl.sh)
BASIC_AUTH="$(echo -n "${SE_ROUTER_USERNAME}:${SE_ROUTER_PASSWORD}" | base64)"

if [ -z "${GRID_GRAPHQL_URL}" ]; then
echo "$(date ${ts_format}) DEBUG [${probe_name}] - Could not construct GraphQL endpoint, please provide SE_HUB_HOST (or SE_ROUTER_HOST) and SE_HUB_PORT (or SE_ROUTER_PORT). Bypass the probe checks for now."
exit 0
fi

GRAPHQL_PRE_CHECK=$(curl --noproxy "*" -m ${max_time} -k -X POST -H "Content-Type: application/json" --data '{"query":"{ grid { sessionCount } }"}' -s -o /dev/null -w "%{http_code}" ${GRID_GRAPHQL_URL})
GRAPHQL_PRE_CHECK=$(curl --noproxy "*" -m ${max_time} -k -X POST -H "Authorization: Basic ${BASIC_AUTH}" -H "Content-Type: application/json" --data '{"query":"{ grid { sessionCount } }"}' -s -o /dev/null -w "%{http_code}" ${GRID_GRAPHQL_URL})

if [ ${GRAPHQL_PRE_CHECK} -ne 200 ]; then
echo "$(date ${ts_format}) DEBUG [${probe_name}] - GraphQL endpoint ${GRID_GRAPHQL_URL} is not reachable. Status code: ${GRAPHQL_PRE_CHECK}."
exit 1
fi

SESSION_QUEUE_SIZE=$(curl --noproxy "*" --retry ${retry_time} -m ${max_time} -k -X POST -H "Content-Type: application/json" --data '{"query":"{ grid { sessionQueueSize } }"}' -s ${GRID_GRAPHQL_URL} | jq -r '.data.grid.sessionQueueSize')
SESSION_QUEUE_SIZE=$(curl --noproxy "*" --retry ${retry_time} -m ${max_time} -k -X POST -H "Authorization: Basic ${BASIC_AUTH}" -H "Content-Type: application/json" --data '{"query":"{ grid { sessionQueueSize } }"}' -s ${GRID_GRAPHQL_URL} | jq -r '.data.grid.sessionQueueSize')

SESSION_COUNT=$(curl --noproxy "*" --retry ${retry_time} -m ${max_time} -k -X POST -H "Content-Type: application/json" --data '{"query": "{ grid { sessionCount } }"}' -s ${GRID_GRAPHQL_URL} | jq -r '.data.grid.sessionCount')
SESSION_COUNT=$(curl --noproxy "*" --retry ${retry_time} -m ${max_time} -k -X POST -H "Authorization: Basic ${BASIC_AUTH}" -H "Content-Type: application/json" --data '{"query": "{ grid { sessionCount } }"}' -s ${GRID_GRAPHQL_URL} | jq -r '.data.grid.sessionCount')

MAX_SESSION=$(curl --noproxy "*" --retry ${retry_time} -m ${max_time} -k -X POST -H "Content-Type: application/json" --data '{"query":"{ grid { maxSession } }"}' -s ${GRID_GRAPHQL_URL} | jq -r '.data.grid.maxSession')
MAX_SESSION=$(curl --noproxy "*" --retry ${retry_time} -m ${max_time} -k -X POST -H "Authorization: Basic ${BASIC_AUTH}" -H "Content-Type: application/json" --data '{"query":"{ grid { maxSession } }"}' -s ${GRID_GRAPHQL_URL} | jq -r '.data.grid.maxSession')

if [ "${SE_LOG_LISTEN_GRAPHQL:-"false"}" = "true" ]; then
echo "$(curl --noproxy "*" --retry ${retry_time} -m ${max_time} -k -X POST -H "Content-Type: application/json" --data '{"query":"{ grid { sessionCount, maxSession, totalSlots }, nodesInfo { nodes { id, status, sessionCount, maxSession, slotCount, stereotypes, sessions { id, capabilities, slot { id, stereotype } } } }, sessionsInfo { sessionQueueRequests } }"}' -s ${GRID_GRAPHQL_URL} )"
echo "$(curl --noproxy "*" --retry ${retry_time} -m ${max_time} -k -X POST -H "Authorization: Basic ${BASIC_AUTH}" -H "Content-Type: application/json" --data '{"query":"{ grid { sessionCount, maxSession, totalSlots }, nodesInfo { nodes { id, status, sessionCount, maxSession, slotCount, stereotypes, sessions { id, capabilities, slot { id, stereotype } } } }, sessionsInfo { sessionQueueRequests } }"}' -s ${GRID_GRAPHQL_URL} )"
fi

if [ ${SESSION_QUEUE_SIZE} -gt 0 ] && [ ${SESSION_COUNT} -eq 0 ]; then
Expand Down
22 changes: 9 additions & 13 deletions charts/selenium-grid/configs/node/nodeGridUrl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,29 @@

max_time=3

if [ -n "${SE_ROUTER_USERNAME}" ] && [ -n "${SE_ROUTER_PASSWORD}" ]; then
BASIC_AUTH="${SE_ROUTER_USERNAME}:${SE_ROUTER_PASSWORD}@"
fi
BASIC_AUTH="$(echo -n "${SE_ROUTER_USERNAME}:${SE_ROUTER_PASSWORD}" | base64)"

if [ "${SE_SUB_PATH}" = "/" ]; then
SE_SUB_PATH=""
fi

if [ -z "${SE_HUB_HOST:-$SE_ROUTER_HOST}" ] || [ -z "${SE_HUB_PORT:-$SE_ROUTER_PORT}" ]; then
grid_url=""
else
grid_url=${SE_SERVER_PROTOCOL}://${BASIC_AUTH}${SE_HUB_HOST:-$SE_ROUTER_HOST}:${SE_HUB_PORT:-$SE_ROUTER_PORT}${SE_SUB_PATH}
grid_url=${SE_SERVER_PROTOCOL}://${SE_HUB_HOST:-$SE_ROUTER_HOST}:${SE_HUB_PORT:-$SE_ROUTER_PORT}${SE_SUB_PATH}
fi

if [ -z "${grid_url}" ]; then
grid_url="${SE_NODE_GRID_URL}"
fi

if [ -z "${grid_url}" ]; then
grid_url="${SE_SERVER_PROTOCOL}://${BASIC_AUTH}127.0.0.1:4444${SE_SUB_PATH}" # For standalone mode
grid_url="${SE_SERVER_PROTOCOL}://127.0.0.1:4444${SE_SUB_PATH}" # For standalone mode
fi

grid_url_checks=$(curl --noproxy "*" -m ${max_time} -s -k -o /dev/null -w "%{http_code}" ${grid_url})
if [ "${grid_url_checks}" = "401" ]; then
return ${grid_url_checks}
fi
if [ "${grid_url_checks}" = "404" ]; then
return ${grid_url_checks}
fi
grid_url_checks=$(curl --noproxy "*" -H "Authorization: Basic ${BASIC_AUTH}" -m ${max_time} -s -k -o /dev/null -w "%{http_code}" ${grid_url})

return_array=("${grid_url}" "${grid_url_checks}")

echo "${grid_url}"
# stdout the values for other scripts consuming
echo "${return_array[@]}"
18 changes: 13 additions & 5 deletions charts/selenium-grid/configs/node/nodePreStop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ tmp_node_file="/tmp/nodeProbe${ID}"

function on_exit() {
rm -rf ${tmp_node_file}
echo "$(date +%FT%T%Z) [${probe_name}] - Exiting Node preStop..."
echo "$(date +%FT%T%Z) [${probe_name}] - Exiting Node ${probe_name}..."
exit 0
}
trap on_exit EXIT
Expand All @@ -30,12 +30,20 @@ else
fi

function signal_hub_to_drain_node() {
grid_url=$(bash ${NODE_CONFIG_DIRECTORY}/nodeGridUrl.sh)
return_list=($(bash ${NODE_CONFIG_DIRECTORY}/nodeGridUrl.sh))
grid_url=${return_list[0]}
grid_check=${return_list[1]}
BASIC_AUTH="$(echo -n "${SE_ROUTER_USERNAME}:${SE_ROUTER_PASSWORD}" | base64)"
if [ -n "${grid_url}" ]; then
if [ "${grid_check}" = "401" ]; then
echo "$(date +%FT%T%Z) [${probe_name}] - Hub/Router requires authentication. Please check SE_ROUTER_USERNAME and SE_ROUTER_PASSWORD."
elif [ "${grid_check}" = "404" ]; then
echo "$(date +%FT%T%Z) [${probe_name}] - Hub/Router endpoint could not be found. Please check the endpoint ${grid_url}"
fi
echo "$(date +%FT%T%Z) [${probe_name}] - Signaling Hub/Router to drain node"
curl --noproxy "*" -m ${max_time} -k -X POST ${grid_url}/se/grid/distributor/node/${NODE_ID}/drain --header "${HEADERS}"
curl --noproxy "*" -m ${max_time} -k -X POST -H "Authorization: Basic ${BASIC_AUTH}" ${grid_url}/se/grid/distributor/node/${NODE_ID}/drain --header "${HEADERS}"
else
echo "$(date +%FT%T%Z) [${probe_name}] - There is no configured HUB/ROUTER host or SE_NODE_GRID_URL isn't set. preStop ignores to send drain request to upstream."
echo "$(date +%FT%T%Z) [${probe_name}] - There is no configured HUB/ROUTER host or SE_NODE_GRID_URL isn't set. ${probe_name} ignores to send drain request to upstream."
fi
}

Expand Down Expand Up @@ -66,7 +74,7 @@ if curl --noproxy "*" -m ${max_time} -sfk ${SE_SERVER_PROTOCOL}://127.0.0.1:${SE
echo
exit 0
else
echo "$(date +%FT%T%Z) [${probe_name}] - Node preStop is waiting for current session on slot ${SLOT_HAS_SESSION} to be finished. Node details: message: $(jq -r '.value.message' ${tmp_node_file} || "unknown"), availability: $(jq -r '.value.node.availability' ${tmp_node_file} || "unknown")"
echo "$(date +%FT%T%Z) [${probe_name}] - Node ${probe_name} is waiting for current session on slot ${SLOT_HAS_SESSION} to be finished. Node details: message: $(jq -r '.value.message' ${tmp_node_file} || "unknown"), availability: $(jq -r '.value.node.availability' ${tmp_node_file} || "unknown")"
sleep 2;
fi

Expand Down
17 changes: 15 additions & 2 deletions charts/selenium-grid/configs/node/nodeProbe.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,22 @@ if curl --noproxy "*" -m ${max_time} -sfk ${SE_SERVER_PROTOCOL}://127.0.0.1:${SE
exit 1
fi

grid_url=$(bash ${NODE_CONFIG_DIRECTORY}/nodeGridUrl.sh)
return_list=($(bash ${NODE_CONFIG_DIRECTORY}/nodeGridUrl.sh))
grid_url=${return_list[0]}
grid_check=${return_list[1]}
BASIC_AUTH="$(echo -n "${SE_ROUTER_USERNAME}:${SE_ROUTER_PASSWORD}" | base64)"

curl --noproxy "*" -m ${max_time} -sfk "${grid_url}/status" -o ${tmp_grid_file}
if [ -n "${grid_url}" ]; then
if [ "${grid_check}" = "401" ]; then
echo "$(date +%FT%T%Z) [${probe_name}] - Hub/Router requires authentication. Please check SE_ROUTER_USERNAME and SE_ROUTER_PASSWORD."
elif [ "${grid_check}" = "404" ]; then
echo "$(date +%FT%T%Z) [${probe_name}] - Hub/Router endpoint could not be found. Please check the endpoint ${grid_url}"
fi
else
echo "$(date +%FT%T%Z) [${probe_name}] - There is no configured HUB/ROUTER host or SE_NODE_GRID_URL isn't set. ${probe_name} will not work as expected."
fi

curl --noproxy "*" -m ${max_time} -H "Authorization: Basic ${BASIC_AUTH}" -sfk "${grid_url}/status" -o ${tmp_grid_file}
GRID_NODE_ID=$(jq -e ".value.nodes[].id|select(. == \"${NODE_ID}\")" ${tmp_grid_file} | tr -d '"' || "")
if [ -n "${GRID_NODE_ID}" ]; then
echo "$(date +%FT%T%Z) [${probe_name}] - Grid responds a matched Node ID: ${GRID_NODE_ID}"
Expand Down
5 changes: 1 addition & 4 deletions charts/selenium-grid/configs/router/routerGraphQLUrl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
if [ -z "${SE_HUB_HOST:-$SE_ROUTER_HOST}" ] || [ -z "${SE_HUB_PORT:-$SE_ROUTER_PORT}" ]; then
graphql_url=""
else
if [ -n "${SE_ROUTER_USERNAME}" ] && [ -n "${SE_ROUTER_PASSWORD}" ]; then
BASIC_AUTH="${SE_ROUTER_USERNAME}:${SE_ROUTER_PASSWORD}@"
fi

if [[ ${SE_SUB_PATH} == */ ]]; then
GRAPHQL_ENDPOINT="${SE_SUB_PATH}graphql"
Expand All @@ -19,7 +16,7 @@ else
GRAPHQL_ENDPOINT="/${GRAPHQL_ENDPOINT}"
fi

graphql_url="${SE_SERVER_PROTOCOL}://${BASIC_AUTH}${SE_HUB_HOST:-${SE_ROUTER_HOST}}:${SE_HUB_PORT:-${SE_ROUTER_PORT}}${GRAPHQL_ENDPOINT}"
graphql_url="${SE_SERVER_PROTOCOL}://${SE_HUB_HOST:-${SE_ROUTER_HOST}}:${SE_HUB_PORT:-${SE_ROUTER_PORT}}${GRAPHQL_ENDPOINT}"
fi

echo "${graphql_url}"
3 changes: 2 additions & 1 deletion charts/selenium-grid/configs/router/routerProbe.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ ts_format=${SE_LOG_TIMESTAMP_FORMAT:-"+%T.%3N"}
ROUTER_CONFIG_DIRECTORY=${ROUTER_CONFIG_DIRECTORY:-"/opt/bin"}

GRID_GRAPHQL_URL=$(bash ${ROUTER_CONFIG_DIRECTORY}/routerGraphQLUrl.sh)
BASIC_AUTH="$(echo -n "${SE_ROUTER_USERNAME}:${SE_ROUTER_PASSWORD}" | base64)"

if [ -z "${GRID_GRAPHQL_URL}" ]; then
echo "$(date ${ts_format}) DEBUG [${probe_name}] - Could not construct GraphQL endpoint, please provide SE_HUB_HOST (or SE_ROUTER_HOST) and SE_HUB_PORT (or SE_ROUTER_PORT). Bypass the probe checks for now."
exit 0
fi

GRAPHQL_PRE_CHECK=$(curl --noproxy "*" -m ${max_time} -k -X POST -H "Content-Type: application/json" --data '{"query":"{ grid { sessionCount } }"}' -s -o /dev/null -w "%{http_code}" ${GRID_GRAPHQL_URL})
GRAPHQL_PRE_CHECK=$(curl --noproxy "*" -m ${max_time} -k -X POST -H "Authorization: Basic ${BASIC_AUTH}" -H "Content-Type: application/json" --data '{"query":"{ grid { sessionCount } }"}' -s -o /dev/null -w "%{http_code}" ${GRID_GRAPHQL_URL})

if [ ${GRAPHQL_PRE_CHECK} -ne 200 ]; then
echo "$(date ${ts_format}) DEBUG [${probe_name}] - GraphQL endpoint is not reachable. Status code: ${GRAPHQL_PRE_CHECK}."
Expand Down
3 changes: 3 additions & 0 deletions charts/selenium-grid/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,10 @@ template:
Get the url of the grid. If the external url can be figured out from the ingress use that, otherwise the cluster internal url
*/}}
{{- define "seleniumGrid.url" -}}
{{- $url := printf "%s://%s%s%s" (include "seleniumGrid.url.schema" .) (include "seleniumGrid.url.host" .) (include "seleniumGrid.url.port" .) (include "seleniumGrid.url.subPath" .) -}}
{{- if $.Values.basicAuth.embeddedUrl -}}
{{- $url := printf "%s://%s%s%s%s" (include "seleniumGrid.url.schema" .) (include "seleniumGrid.url.basicAuth" .) (include "seleniumGrid.url.host" .) (include "seleniumGrid.url.port" .) (include "seleniumGrid.url.subPath" .) -}}
{{- end -}}
{{- $url }}
{{- end -}}

Expand Down
2 changes: 2 additions & 0 deletions charts/selenium-grid/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ basicAuth:
username: admin
# -- Password for basic auth
password: admin
# -- Embed the basic auth "username:password@" in few URLs e.g. SE_NODE_GRID_URL
embeddedUrl: false
# -- Annotations for basic auth secret resource
annotations: {}

Expand Down
4 changes: 2 additions & 2 deletions tests/charts/templates/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ def test_ingress_nginx_annotations(self):
count += 1
self.assertEqual(count, len(resources_name), "No ingress resources found")

def test_sub_path_append_to_node_grid_url(self):
def test_sub_path_append_to_node_grid_url_and_basic_auth_should_not_include(self):
resources_name = ['{0}selenium-secrets'.format(RELEASE_NAME),]
for doc in LIST_OF_DOCUMENTS:
if doc['metadata']['name'] in resources_name and doc['kind'] == 'Secret':
logger.info(f"Assert graphql url is constructed without basic auth in url")
base64_url = doc['data']['SE_NODE_GRID_URL']
decoded_url = base64.b64decode(base64_url).decode('utf-8')
self.assertTrue(decoded_url == 'https://sysadmin:strongPassword@10.10.10.10:8443/selenium', decoded_url)
self.assertTrue(decoded_url == 'https://10.10.10.10:8443/selenium', decoded_url)

def test_sub_path_set_to_grid_env_var(self):
resources_name = ['{0}selenium-router'.format(RELEASE_NAME)]
Expand Down

0 comments on commit 0701191

Please sign in to comment.