Skip to content

Commit

Permalink
(ESPSTUDIO-8275) (#6)
Browse files Browse the repository at this point in the history
Plugin deployment option for different namespaces on Viya

Update readme to reflect that the scripts are now run separate configure-grafana.sh and then the appropriate register-oauth-client-*.sh

no longer need to provide the whole plugin url, just the version
  • Loading branch information
mtlljm authored Dec 5, 2023
1 parent 4d95ab5 commit 4fe8df3
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 37 deletions.
41 changes: 31 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,11 @@ This section is relevant only to internal users at SAS.

### Install a Released Version of the Plug-in

An installation script is provided to install the plug-in and configure Grafana. The installation script performs the following tasks:
* Modifies the Grafana deployment by adding the GF_INSTALL_PLUGINS environment variable to enable Grafana to install the plug-in.
* Configures a new `grafana.ini` file to enable OAuth authentication.
* Configures Grafana as an OAuth client with the chosen OAuth provider. Users of Grafana are directed to use the OAuth login page.
* Optionally installs Grafana for you.

Use the installation script to install the plug-in:
Installation scripts are provided to install the plug-in and configure Grafana. These scripts perform the following tasks:
* Modify the Grafana deployment by adding the GF_INSTALL_PLUGINS environment variable to enable Grafana to install the plug-in.
* Configure a new `grafana.ini` file to enable OAuth authentication.
* Configure Grafana as an OAuth client with the chosen OAuth provider. Users of Grafana are directed to use the OAuth login page.
* Optionally install Grafana for you.

1. Set the correct Kubernetes configuration file for your environment.
```
Expand All @@ -105,16 +103,39 @@ Use the installation script to install the plug-in:
```
export GRAFANA_NAMESPACE=grafana
```
5. Run the installation script, adjusting the command to specify the following variables:
5. Run `configure-grafana.sh`, adjusting the command to specify the following variables:
- The Kubernetes _namespace_ in which SAS Event Stream Processing is installed.
- The _version_ of the plug-in that you want to install. Ensure that you specify a version of the plug-in that is compatible with your version of Grafana.
- The _oauth-provider_ of the environment. Select one of the following options: **uaa**, **keycloak** or **viya**.
- The _oauth-provider_ of the environment. Select one of the following options: `uaa`, `keycloak` or `viya`.
> **Caution**: Running the installation script might overwrite any existing Grafana configuration.
```
cd ./install
bash configure-grafana.sh <namespace> https://github.com/sassoftware/grafana-esp-plugin/download/<version>/sasesp-plugin-<version>.zip <oauth-provider>
bash configure-grafana.sh <namespace> <version> <oauth-provider>
```
6. Run one of the following three scripts, depending on your chosen OAuth provider. Adjust the command to specify the following variables.
- The Kubernetes namespace in which SAS Event Stream Processing is installed, _esp-namespace_.
- (Optional) The Kubernetes namespace in which Grafana is installed, _grafana-namespace_ if this differs from the namespace in which SAS Event Stream Processing is installed.
```
bash register-oauth-client-keycloak.sh <esp-namespace> <grafana-namespace>
```
```
bash register-oauth-client-uaa.sh <esp-namespace> <grafana-namespace>
```
```
bash register-oauth-client-viya.sh <esp-namespace> <grafana-namespace>
```
7. If your OAuth provider is the SAS Viya platform and Grafana is not running in the same namespace as the SAS Viya platform, you must update the Content Security Policy (CSP) for SAS Logon to allow the Grafana host name to be used as a target of form submission.
If you do not update the CSP, the browser blocks the redirect. You can update the CSP in one of the following two ways:
- Use SAS Environment Manager to update the _content-security-policy_ value under the _sas.commons.web.security_ section.
- Update the _sas-logon-app_ deployment to add the _SAS_COMMONS_WEB_SECURITY_CONTENTSECURITYPOLICY_ environment variable.
Update either SAS Environment Manager or the _sas-logon-app_ deployment with the following value, substituting the Grafana host name:
```
default-src 'self'; style-src 'self'; font-src 'self' data:;
frame-ancestors 'self'; form-action 'self' <grafana-host>;
```
### (Optional) Build and Install a Privately Signed Version of the Plug-in
Expand Down
28 changes: 9 additions & 19 deletions install/configure-grafana.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -e -o pipefail -o nounset

#input variables
ESP_NAMESPACE="${1}"; export ESP_NAMESPACE
ESP_PLUGIN_SOURCE="${2}"
ESP_PLUGIN_VERSION="${2}"
OAUTH_TYPE="${3:-uaa}"

#optional environment variables - exported for use in other scripts
Expand All @@ -25,12 +25,12 @@ function check_requirements() {
}

[ -z "${ESP_NAMESPACE}" ] && {
echo "Usage: ${0} <namespace> <plugin-zip-url> <oauth-type>" >&2
echo "Usage: ${0} <namespace> <version> <oauth-type>" >&2
exit 1
}

[ -z "${ESP_PLUGIN_SOURCE}" ] && {
echo "Usage: ${0} <namespace> <plugin-zip-url> <oauth-type>" >&2
[ -z "${ESP_PLUGIN_VERSION}" ] && {
echo "Usage: ${0} <namespace> <version> <oauth-type>" >&2
exit 1
}

Expand Down Expand Up @@ -75,40 +75,29 @@ function generate_manifests() {
check_requirements

echo "Fetching required deployment information..."
ESP_DOMAIN=$(kubectl -n "${ESP_NAMESPACE}" get ingress --output json | jq -r '.items[0].spec.rules[0].host')
export ESP_DOMAIN

#duplicate domain code
ESP_DOMAIN=$(kubectl -n "${ESP_NAMESPACE}" get ingress --output json | jq -r '.items[0].spec.rules[0].host')
GRAFANA_DOMAIN=$(kubectl -n "${GRAFANA_NAMESPACE}" get ingress --output json | jq -r '.items[0].spec.rules[0].host')
ESP_PLUGIN_SOURCE="https://github.com/sassoftware/grafana-esp-plugin/download/$ESP_PLUGIN_VERSION/sasesp-plugin-$ESP_PLUGIN_VERSION.zip"

echo "Adding Grafana to allowed OAuth client redirects..."
if [ "${OAUTH_TYPE}" == "viya" ]; then

if [[ "${DRY_RUN}" == false ]]; then
bash register-oauth-client-viya.sh
fi

TEMPLATE_AUTH_URL="https://${ESP_DOMAIN}/SASLogon/oauth/authorize"
TEMPLATE_TOKEN_URL="https://${ESP_DOMAIN}/SASLogon/oauth/token"
TEMPLATE_API_URL="https://${ESP_DOMAIN}/SASLogon/userinfo"
TEMPLATE_SIGNOUT_REDIRECT_URL="https://${ESP_DOMAIN}/SASLogon/logout.do"

elif [ "${OAUTH_TYPE}" == "keycloak" ]; then

if [[ "${DRY_RUN}" == false ]]; then
bash register-oauth-client-keycloak.sh
fi

TEMPLATE_AUTH_URL="https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/realms/sas-esp/protocol/openid-connect/auth"
TEMPLATE_TOKEN_URL="https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/realms/sas-esp/protocol/openid-connect/token"
TEMPLATE_API_URL="https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/realms/sas-esp/protocol/openid-connect/userinfo"
TEMPLATE_SIGNOUT_REDIRECT_URL="https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/realms/sas-esp/protocol/openid-connect/logout?client_id=${OAUTH_CLIENT_ID}\&post_logout_redirect_uri=https://${ESP_DOMAIN}/grafana/login"

else

if [[ "${DRY_RUN}" == false ]]; then
bash register-oauth-client-uaa.sh
fi

TEMPLATE_AUTH_URL="https://${ESP_DOMAIN}/uaa/oauth/authorize"
TEMPLATE_TOKEN_URL="https://${ESP_DOMAIN}/uaa/oauth/token?token_format=jwt"
TEMPLATE_API_URL="https://${ESP_DOMAIN}/uaa/userinfo"
Expand All @@ -129,12 +118,13 @@ echo "Generating manifests..."
generate_manifests

if [[ "${DRY_RUN}" == true ]]; then
#GF_INSTALL_PLUGINS_VALUE=$(kubectl -n "${ESP_NAMESPACE}" get deployment/grafana --output json | jq -c '.spec.template.spec.containers[0].env[] | select(.name | contains("GF_INSTALL_PLUGINS")) | .value')
exit 0
fi

if [[ "${INSTALL_GRAFANA}" == true ]]; then
echo "Installing grafana"
kubectl -n "${ESP_NAMESPACE}" apply -f ./manifests/grafana.yaml
kubectl -n "${GRAFANA_NAMESPACE}" apply -f ./manifests/grafana.yaml
fi

echo "Applying config-map.yaml"
Expand Down
34 changes: 30 additions & 4 deletions install/register-oauth-client-keycloak.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@

set -e -o pipefail -o nounset

ESP_NAMESPACE="${1}"
KEYCLOAK_SUBPATH="${KEYCLOAK_SUBPATH:-auth}"

function usage () {
echo "Usage: ${0} <esp-namespace> " >&2
exit 1
}

[ -z "$KUBECONFIG" ] && {
echo "KUBECONFIG environment variable unset." >&2
exit 1
}

[ -z "${ESP_NAMESPACE}" ] && {
usage
}

ESP_DOMAIN=$(kubectl -n "${ESP_NAMESPACE}" get ingress --output json | jq -r '.items[0].spec.rules[0].host')

function check_keycloak_deployment() {
if ! kubectl -n "${ESP_NAMESPACE}" get deployment keycloak-deployment 2>/dev/null 1>&2; then
echo >&2 "ERROR: No Keycloak deployment found under namespace ${ESP_NAMESPACE}."
Expand Down Expand Up @@ -40,7 +59,7 @@ function check_requirements() {

# Fetch access token to perform admin tasks:
function fetch_keycloak_admin_token() {
_resp=$(curl "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/realms/master/protocol/openid-connect/token" -s -k -X POST \
_resp=$(curl "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/realms/master/protocol/openid-connect/token" -k -X POST \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Accept: application/json' \
-d "client_id=admin-cli&grant_type=password&username=${KEYCLOAK_ADMIN}&password=${KEYCLOAK_SECRET}")
Expand All @@ -51,7 +70,7 @@ function fetch_keycloak_admin_token() {
function create_role() {
_role_name="${1}"
_role_repr="{\"name\": \"${_role_name}\", \"clientRole\": true}"
curl "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients/${_client_id}/roles" -s -k -X POST \
curl "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients/${_client_id}/roles" -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${_token}" \
-d "${_role_repr}"
Expand All @@ -75,7 +94,7 @@ function add_protocol_mapper() {
}
}")
_mapper_body=$(echo "${_mapper_repr}" | jq -r -c)
curl -s -k -X POST \
curl -k -X POST \
"https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients/${_client_id}/protocol-mappers/models" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${_token}" \
Expand All @@ -85,7 +104,7 @@ function add_protocol_mapper() {
function prepare_keycloak_roles() {
_token="$(fetch_keycloak_admin_token)"
# Get sas-esp realm clients:
_kc_clients=$(curl -s -k -X GET "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients" -H "Authorization: Bearer ${_token}")
_kc_clients=$(curl -k -X GET "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients" -H "Authorization: Bearer ${_token}")
# Get OAuth2 Proxy client ID:
_client_id=$(echo "${_kc_clients}" | jq -r --arg opid "${OAUTH_CLIENT_ID}" '.[] | select(.clientId == $opid) | .id')
# Create Grafana roles:
Expand All @@ -106,4 +125,11 @@ export OAUTH_CLIENT_ID
OAUTH_CLIENT_SECRET=$(echo "${_oauth2_proxy_secret}" | jq -r '.data.OAUTH2_PROXY_CLIENT_SECRET | @base64d')
export OAUTH_CLIENT_SECRET

cat <<EOF
OAuth details:
ESP Domain: ${ESP_DOMAIN}
OAuth client ID: ${OAUTH_CLIENT_ID}
OAuth client secret: ${OAUTH_CLIENT_SECRET}
EOF

prepare_keycloak_roles
40 changes: 36 additions & 4 deletions install/register-oauth-client-uaa.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,31 @@

set -e -o pipefail -o nounset

ESP_NAMESPACE="${1}"
GRAFANA_NAMESPACE="${2:-${ESP_NAMESPACE}}"
OAUTH_CLIENT_ID="${OAUTH_CLIENT_ID:-sv_client}"; export OAUTH_CLIENT_ID
OAUTH_CLIENT_SECRET="${OAUTH_CLIENT_SECRET:-secret}"; export OAUTH_CLIENT_SECRET

function usage () {
echo "Usage: ${0} <esp-namespace> " >&2
exit 1
}

[ -z "$KUBECONFIG" ] && {
echo "KUBECONFIG environment variable unset." >&2
exit 1
}

[ -z "${ESP_NAMESPACE}" ] && {
usage
}

ESP_DOMAIN=$(kubectl -n "${ESP_NAMESPACE}" get ingress --output json | jq -r '.items[0].spec.rules[0].host')
GRAFANA_DOMAIN=$(kubectl -n "${GRAFANA_NAMESPACE}" get ingress --output json | jq -r '.items[0].spec.rules[0].host')

# Fetch access token to perform admin tasks:
function fetch_uaa_admin_token() {
_resp=$(curl "https://${ESP_DOMAIN}/uaa/oauth/token" -s -k -X POST \
_resp=$(curl "https://${ESP_DOMAIN}/uaa/oauth/token" -k -X POST \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Accept: application/json' \
-d "client_id=${UAA_ADMIN}&client_secret=${UAA_SECRET}&grant_type=client_credentials&response_type=token")
Expand All @@ -15,14 +37,14 @@ function fetch_uaa_admin_token() {
# Add Grafana generic OAuth to allowed auth redirects:
function add_grafana_auth_redirect_uaa() {
_token="$(fetch_uaa_admin_token)"
_redirect="https://${ESP_DOMAIN}/grafana/login/generic_oauth"
_redirect="https://${GRAFANA_DOMAIN}/grafana/login/generic_oauth"

_config=$(curl -s -k -X GET "https://${ESP_DOMAIN}/uaa/oauth/clients/${OAUTH_CLIENT_ID}" -H "Authorization: Bearer ${_token}")
_config=$(curl -k -X GET "https://${ESP_DOMAIN}/uaa/oauth/clients/${OAUTH_CLIENT_ID}" -H "Authorization: Bearer ${_token}")

_update_body=$(echo "${_config}" | jq -c -r --arg redirect "${_redirect}" \
'.redirect_uri += [$redirect] | {client_id: .client_id, redirect_uri: .redirect_uri}')

_resp=$(curl "https://${ESP_DOMAIN}/uaa/oauth/clients/${OAUTH_CLIENT_ID}" -s -k -X PUT \
_resp=$(curl "https://${ESP_DOMAIN}/uaa/oauth/clients/${OAUTH_CLIENT_ID}" -k -X PUT \
-o /dev/null -w "%{http_code}" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${_token}" \
Expand All @@ -43,4 +65,14 @@ export UAA_ADMIN
UAA_SECRET=$(echo "${_uaa_secret_data}" | jq -r '.data.password | @base64d')
export UAA_SECRET

cat <<EOF
OAuth details:
ESP Domain: ${ESP_DOMAIN}
Grafana Domain: ${GRAFANA_DOMAIN}
OAuth client ID: ${OAUTH_CLIENT_ID}
OAuth client secret: ${OAUTH_CLIENT_SECRET}
UAA Admin: ${UAA_ADMIN}
UAA secret: ${UAA_SECRET}
EOF

add_grafana_auth_redirect_uaa
30 changes: 30 additions & 0 deletions install/register-oauth-client-viya.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@

set -e -o pipefail -o nounset

ESP_NAMESPACE="${1}"
GRAFANA_NAMESPACE="${2:-${ESP_NAMESPACE}}"
OAUTH_CLIENT_ID="${OAUTH_CLIENT_ID:-sv_client}"; export OAUTH_CLIENT_ID
OAUTH_CLIENT_SECRET="${OAUTH_CLIENT_SECRET:-secret}"; export OAUTH_CLIENT_SECRET

function usage () {
echo "Usage: ${0} <viya-namespace> <grafana-namespace>" >&2
exit 1
}

[ -z "$KUBECONFIG" ] && {
echo "KUBECONFIG environment variable unset." >&2
exit 1
}

[ -z "${ESP_NAMESPACE}" ] && {
usage
}

ESP_DOMAIN=$(kubectl -n "${ESP_NAMESPACE}" get ingress --output json | jq -r '.items[0].spec.rules[0].host')
GRAFANA_DOMAIN=$(kubectl -n "${GRAFANA_NAMESPACE}" get ingress --output json | jq -r '.items[0].spec.rules[0].host')

function fetch_consul_token () {
_token=$(kubectl -n "${ESP_NAMESPACE}" get secret sas-consul-client -o go-template='{{ .data.CONSUL_TOKEN | base64decode}}')

Expand Down Expand Up @@ -48,4 +70,12 @@ function register_oauth_client () {

}

cat <<EOF
OAuth details:
ESP Domain: ${ESP_DOMAIN}
Grafana Domain: ${GRAFANA_DOMAIN}
OAuth client ID: ${OAUTH_CLIENT_ID}
OAuth client secret: ${OAUTH_CLIENT_SECRET}
EOF

register_oauth_client

0 comments on commit 4fe8df3

Please sign in to comment.