Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 2.x] Cypress13 testing frame work for OIDC and SAML #1691

Merged
merged 3 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ node_modules
/build
/target
/.eslintrc.js
/cypress.config.js
36 changes: 30 additions & 6 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,35 @@ const LICENSE_HEADER = `
*/
`

module.exports = {
root: true,
module.exports = {
root: true,
extends: ['@elastic/eslint-config-kibana', 'plugin:@elastic/eui/recommended'],
env: {
'cypress/globals': true,
},
plugins: [
'cypress',
],
rules: {
// "@osd/eslint/require-license-header": "off"
'@osd/eslint/no-restricted-paths': [
'error',
{
basePath: __dirname,
zones: [
{
target: ['(public|server)/**/*'],
from: ['../../packages/**/*','packages/**/*'],
},
],
},
],
// Add cypress specific rules here
'cypress/no-assigning-return-values': 'error',
'cypress/no-unnecessary-waiting': 'error',
'cypress/assertion-before-screenshot': 'warn',
'cypress/no-force': 'warn',
'cypress/no-async-tests': 'error',
},
overrides: [
{
Expand All @@ -31,8 +55,8 @@ module.exports = {
licenses: [ LICENSE_HEADER ],
},
],
"no-console": 0
}
}
'no-console': 0,
},
},
],
};
};
256 changes: 256 additions & 0 deletions .github/workflows/cypress-test-oidc-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
name: Snapshot based E2E OIDC tests workflow
on:
pull_request:
branches: [ '**' ]
env:
OPENSEARCH_VERSION: '2.12.0'
KEYCLOAK_VERSION: '21.0.1'
TEST_KEYCLOAK_CLIENT_SECRET: 'oacHfNaXyy81r2uHq1A9RY4ASryre4rZ'
CI: 1
# avoid warnings like "tput: No value for $TERM and no -T specified"
TERM: xterm
PLUGIN_NAME: opensearch-security
# This is the SHA256 checksum of the known good kc.sh script for Keycloak version 21.0.1.
KNOWN_CHECKSUM_OF_KEYCLOAK_SCRIPT: 'f825ea1a9ffa5ad91673737c06857ababbb69b6b8f09e0c637b4c998517f9608'

jobs:
tests:
name: Run Cypress E2E OIDC tests
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
runs-on: ${{ matrix.os }}

steps:
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: 11

- name: Checkout Branch
uses: actions/checkout@v3

- name: Set env
run: |
opensearch_version=$(node -p "require('./package.json').opensearchDashboards.version")
plugin_version=$(node -p "require('./package.json').version")
echo "OPENSEARCH_VERSION=$opensearch_version" >> $GITHUB_ENV
echo "PLUGIN_VERSION=$plugin_version" >> $GITHUB_ENV
shell: bash

# Download and Check Keycloak Version
- name: Download and Check Keyloak Version on Linux
if: ${{ runner.os == 'Linux' }}
run: |
echo "Downloading Keycloak ${{ env.KEYCLOAK_VERSION }}"
wget https://github.com/keycloak/keycloak/releases/download/${{ env.KEYCLOAK_VERSION }}/keycloak-${{ env.KEYCLOAK_VERSION }}.tar.gz
echo "Unpacking Keycloak"
tar -xzf keycloak-${{ env.KEYCLOAK_VERSION }}.tar.gz
cd keycloak-${{ env.KEYCLOAK_VERSION }}/bin
chmod +x ./kc.sh
echo "Generating checksum for the downloaded kc.sh script..."
DOWNLOADED_CHECKSUM=$(sha256sum kc.sh | awk '{print $1}')
echo "Downloaded kc.sh checksum: $DOWNLOADED_CHECKSUM"
echo "Known good kc.sh checksum: ${{ env.KNOWN_CHECKSUM_OF_KEYCLOAK_SCRIPT }}"
KNOWN_GOOD_CHECKSUM="${{ env.KNOWN_CHECKSUM_OF_KEYCLOAK_SCRIPT }}"
if [ "$DOWNLOADED_CHECKSUM" != "$KNOWN_GOOD_CHECKSUM" ]; then
echo "Checksum mismatch. The kc.sh script does not match the known good version. Please check https://github.com/keycloak/keycloak and verify the updates."
exit 1
else
echo "Checksum match confirmed. Proceeding with setup."
fi
chmod +x ./kc.sh

# Setup and Run Keycloak
- name: Get and run Keycloak on Linux
if: ${{ runner.os == 'Linux' }}
run: |
export KEYCLOAK_ADMIN=admin
export KEYCLOAK_ADMIN_PASSWORD=admin
cd keycloak-${{ env.KEYCLOAK_VERSION }}/bin
echo "Starting keycloak"
./kc.sh start-dev --http-enabled=true --hostname-strict-https=false --http-host=localhost --http-relative-path /auth --health-enabled=true &
timeout 300 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8080/auth/health)" != "200" ]]; do sleep 5; done'
chmod +x kcadm.sh
echo "Creating client"
./kcadm.sh config credentials --server http://localhost:8080/auth --realm master --user admin --password admin
CID=$(./kcadm.sh create clients -r master -s clientId=opensearch -s secret="${{ env.TEST_KEYCLOAK_CLIENT_SECRET }}" -s 'attributes."access.token.lifespan"=60' -s 'redirectUris=["http://localhost:5603/auth/openid/login", "http://localhost:5601", "http://localhost:5601/auth/openid/login"]' -i)
./kcadm.sh get clients/$CID/installation/providers/keycloak-oidc-keycloak-json > tmp
echo "Getting client secret for dashboards configuration purpose"
CLIENT_SECRET=$(grep -o '"secret" : "[^"]*' tmp | grep -o '[^"]*$')
echo "KEYCLOAK_CLIENT_SECRET=$CLIENT_SECRET" >> $GITHUB_ENV
echo "The client secret is: $CLIENT_SECRET"
echo "Creating client mapper"
./kcadm.sh create clients/$CID/protocol-mappers/models -r master -s 'config."id.token.claim"=true' -s 'config."multivalued"=true' -s 'config."claim.name"="roles"' -s 'config."userinfo.token.claim"=true' -s 'config."access.token.claim"=true' -s 'name=rolemapper' -s 'protocolMapper=oidc-usermodel-realm-role-mapper' -s "protocol=openid-connect"

- name: Download security plugin and create setup scripts
uses: ./.github/actions/download-plugin
with:
opensearch-version: ${{ env.OPENSEARCH_VERSION }}
plugin-name: ${{ env.PLUGIN_NAME }}
plugin-version: ${{ env.PLUGIN_VERSION }}

# Download OpenSearch
- name: Download OpenSearch for Linux
uses: peternied/download-file@v2
if: ${{ runner.os == 'Linux' }}
with:
url: https://artifacts.opensearch.org/snapshots/core/opensearch/${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/opensearch-min-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT-linux-x64-latest.tar.gz

# Extract downloaded tar/zip
- name: Extract downloaded tar
if: ${{ runner.os == 'Linux' }}
run: |
tar -xzf opensearch-*.tar.gz
rm -f opensearch-*.tar.gz
shell: bash

# Install the security plugin
- name: Install Plugin into OpenSearch for Linux
if: ${{ runner.os == 'Linux'}}
run: |
chmod +x ./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/bin/opensearch-plugin
/bin/bash -c "yes | ./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/bin/opensearch-plugin install file:$(pwd)/opensearch-security.zip"
shell: bash

# Add OIDC Configuration
- name: Injecting OIDC Configuration for Linux
if: ${{ runner.os == 'Linux'}}
run: |
echo "Creating new SAML configuration"
cd ./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/config/opensearch-security/
rm -rf config.yml
cat << 'EOT' > config.yml
---
_meta:
type: "config"
config_version: 2
config:
dynamic:
http:
anonymous_auth_enabled: false
authc:
basic_internal_auth_domain:
description: "Authenticate via HTTP Basic against internal users database"
http_enabled: true
transport_enabled: true
order: 0
http_authenticator:
type: basic
challenge: false
authentication_backend:
type: intern
openid_auth_domain:
http_enabled: true
transport_enabled: true
order: 1
http_authenticator:
type: openid
challenge: false
config:
subject_key: preferred_username
roles_key: roles
openid_connect_url: http://localhost:8080/auth/realms/master/.well-known/openid-configuration
authentication_backend:
type: noop
EOT
echo "THIS IS THE SECURITY CONFIG FILE: "
cat config.yml

# TODO: REMOVE THIS ONCE ADMIN JAVA TOOL SUPPORT IT
- name: Write password to initialAdminPassword location
if: ${{ runner.os == 'Linux'}}
run:
echo admin >> ./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/config/initialAdminPassword.txt
shell: bash

# Run any configuration scripts
- name: Run Setup Script for Linux
if: ${{ runner.os == 'Linux' }}
run: |
echo "running linux setup"
chmod +x ./setup.sh
./setup.sh
shell: bash

# Run OpenSearch
- name: Run OpenSearch with plugin on Linux
if: ${{ runner.os == 'Linux'}}
run: |
/bin/bash -c "./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/bin/opensearch &"
shell: bash

# Give the OpenSearch process some time to boot up before sending any requires, might need to increase the default time!
- name: Sleep while OpenSearch starts
uses: peternied/action-sleep@v1
with:
seconds: 30

# Verify that the server is operational
- name: Check OpenSearch Running on Linux
if: ${{ runner.os != 'Windows'}}
run: curl https://localhost:9200/_cat/plugins -u 'admin:admin' -k -v
shell: bash

- if: always()
run: cat ./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/logs/opensearch.log
shell: bash

# OSD bootstrap
- name: Run Dashboard with Security Dashboards Plugin
uses: ./.github/actions/install-dashboards
with:
plugin_name: security-dashboards-plugin

# Configure the Dashboard for OIDC setup
- name: Configure and Run OpenSearch Dashboards with Cypress Test Cases
if: ${{ runner.os == 'Linux' }}
run: |
cd ./OpenSearch-Dashboards
rm -rf ./config/opensearch_dashboards.yml
cat << 'EOT' > ./config/opensearch_dashboards.yml
server.host: "localhost"
opensearch.hosts: ["https://localhost:9200"]
opensearch.ssl.verificationMode: none
opensearch.username: "kibanaserver"
opensearch.password: "kibanaserver"
opensearch.requestHeadersWhitelist: [ authorization,securitytenant ]
opensearch_security.multitenancy.enabled: true
opensearch_security.multitenancy.tenants.preferred: ["Private", "Global"]
opensearch_security.readonly_mode.roles: ["kibana_read_only"]
opensearch_security.cookie.secure: false
opensearch_security.openid.connect_url: "http://127.0.0.1:8080/auth/realms/master/.well-known/openid-configuration"
opensearch_security.openid.client_id: "opensearch"
opensearch_security.openid.client_secret: "${{ env.TEST_KEYCLOAK_CLIENT_SECRET }}"
opensearch_security.auth.type: ["openid"]
opensearch_security.auth.multiple_auth_enabled: true
opensearch_security.ui.openid.login.buttonname: "OIDC"
home.disableWelcomeScreen: true
EOT
echo 'HERE IS THE DASHBOARD CONFIG FILE: '
cat ./config/opensearch_dashboards.yml
nohup yarn start --no-base-path --no-watch | tee dashboard.log &

# Check if OSD is ready with a max timeout of 600 seconds
- name : Check If OpenSearch Dashboards Is Ready
if: ${{ runner.os == 'Linux' }}
run: |
cd ./OpenSearch-Dashboards
echo "Start checking OpenSearch Dashboards."
for i in {1..60}; do
if grep -q "bundles compiled successfully after" "dashboard.log"; then
echo "OpenSearch Dashboards compiled successfully."
break
fi
if [ $i -eq 60 ]; then
echo "Timeout for 600 seconds reached. OpenSearch Dashboards did not finish compiling."
exit 1
fi
sleep 10
done

- name: Run Cypress
run : |
yarn add cypress --save-dev
yarn cypress:run --browser chrome --headless --spec 'test/cypress/e2e/oidc/*.js'
Loading
Loading