Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b018096
Adds resource access management dashboard
DarshitChanpura Aug 29, 2025
a26401f
Updates share button to only be displayed when user can actually share
DarshitChanpura Sep 3, 2025
f8cf74e
Adds UI unit tests
DarshitChanpura Sep 9, 2025
a795e9d
Adds cypress e2e test for resource-access-management dashboard
DarshitChanpura Sep 9, 2025
1f9af51
Updates cypress workflow
DarshitChanpura Sep 10, 2025
87844c5
Set action version to v8
DarshitChanpura Sep 10, 2025
6b346d9
Adds changelog entry
DarshitChanpura Sep 10, 2025
cda24bf
Adds AD plugin to setup and creates sample detector
DarshitChanpura Sep 10, 2025
67fc297
Fix AD dashboard installation
DarshitChanpura Sep 10, 2025
8d5f10b
Adds sample plugin and removes AD completely
DarshitChanpura Sep 10, 2025
4ac3ec4
Fix cypress workflow for resource-access-management
DarshitChanpura Sep 11, 2025
c4eb516
Adds explicit dashboard config in workflow
DarshitChanpura Sep 12, 2025
66f7fcd
Corrects file name in cypress workflow
DarshitChanpura Sep 12, 2025
de27d12
Merge remote-tracking branch 'upstream/main' into resource-access-man…
DarshitChanpura Sep 12, 2025
e6d15df
Addresses fixes to backend api
DarshitChanpura Sep 24, 2025
abf6365
Merge branch 'main' into resource-access-management-dashboard
DarshitChanpura Sep 25, 2025
5016034
Fix unit test failure to address backend change for resource-type
DarshitChanpura Sep 25, 2025
0d4dfde
Uses library for normalization of resource types and changes subtitle…
DarshitChanpura Sep 26, 2025
34dc0cd
Adds EuiEmptyPrompt and update api usage
DarshitChanpura Sep 26, 2025
cb6d600
Merge remote-tracking branch 'upstream/main' into resource-access-man…
DarshitChanpura Sep 26, 2025
a7a91f7
Fix tests
DarshitChanpura Sep 27, 2025
79fbdfa
Change to lodash
DarshitChanpura Sep 29, 2025
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
180 changes: 180 additions & 0 deletions .github/workflows/cypress-test-resource-sharing-enabled-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
name: E2E Resource Access Management Cypress Tests

on: [ push, pull_request ]

env:
CI: 1
# avoid warnings like "tput: No value for $TERM and no -T specified"
TERM: xterm
PLUGIN_NAME: opensearch-security
OPENSEARCH_INITIAL_ADMIN_PASSWORD: myStrongPassword123!

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

steps:
- name: Checkout Branch
uses: actions/checkout@v5

- name: Set up JDK 21 for build
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'

- 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

- 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-location: ${{env.PLUGIN_NAME}}

# build sample-resource-plugin from source (Linux runner)
- name: Build sample-resource-plugin (server)
shell: bash
run: |
set -euo pipefail
OSV="${OPENSEARCH_VERSION}"
# Map 3.2.0[-anything] -> 3.2
SEC_REF="$(echo "$OSV" | sed -E 's/^([0-9]+)\.([0-9]+).*/\1.\2/')"
echo "Derived security repo ref: $SEC_REF (from $OSV)"

# Prefer branch/tag = X.Y; fall back to main if not found
if git ls-remote --exit-code --heads https://github.com/opensearch-project/security.git "$SEC_REF" >/dev/null 2>&1 \
|| git ls-remote --exit-code --tags https://github.com/opensearch-project/security.git "$SEC_REF" >/dev/null 2>&1; then
REF="$SEC_REF"
else
echo "Ref $SEC_REF not found; falling back to main"
REF="main"
fi

git clone --depth 1 --branch "$REF" https://github.com/opensearch-project/security.git security-src

pushd security-src
chmod +x ./gradlew
# Build the sample resource plugin
./gradlew :opensearch-sample-resource-plugin:assemble
ZIP_PATH=$(ls -t sample-resource-plugin/build/distributions/*.zip | head -n1)
echo "Built sample plugin: $ZIP_PATH"
cp "$ZIP_PATH" "$GITHUB_WORKSPACE/sample-resource-plugin.zip"
popd

echo "SAMPLE_PLUGIN_ZIP=$GITHUB_WORKSPACE/sample-resource-plugin.zip" >> "$GITHUB_ENV"


- name: Run Opensearch with security + sample resource plugin
uses: derek-ho/start-opensearch@v8
with:
opensearch-version: ${{ env.OPENSEARCH_VERSION }}
plugins: "file:$(pwd)/opensearch-security.zip,file:${{ env.SAMPLE_PLUGIN_ZIP }}"
security-enabled: true
admin-password: ${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }}
jdk-version: 21
resource-sharing-enabled: true

- name: Check OpenSearch is running
run: |
curl https://localhost:9200/_cat/plugins -v -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k
shell: bash

# OSD bootstrap
- name: Setup Dashboard with Security Dashboards Plugin
uses: derek-ho/setup-opensearch-dashboards@v1
with:
plugin_name: security-dashboards-plugin

- name: Compile OpenSearch Dashboards
run: |
node scripts/build_opensearch_dashboards_platform_plugins --no-examples --workers=10 --verbose
shell: bash
working-directory: OpenSearch-Dashboards

- name: Create OpenSearch Dashboards Config
if: ${{ runner.os == 'Linux' }}
run: |
cat << 'EOT' > resource_sharing_config.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
home.disableWelcomeScreen: true
EOT
shell: bash

- name: Replace opensearch_dashboards.yml
run: |
mv resource_sharing_config.yml $GITHUB_WORKSPACE/OpenSearch-Dashboards/config/opensearch_dashboards.yml
shell: bash

- name: Run OpenSearch Dashboards
run: |
nohup yarn start --no-base-path --no-watch --csp.warnLegacyBrowsers=false | tee dashboard.log &
shell: bash
working-directory: OpenSearch-Dashboards

# Check if OSD is ready with a max timeout of 300 seconds
- name: Wait for OpenSearch Dashboards (status API)
shell: bash
working-directory: OpenSearch-Dashboards
env:
OSD_URL: http://localhost:5601
OSD_USER: admin
OSD_PASS: ${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }}
run: |
set -euo pipefail
TIMEOUT=300
INTERVAL=5
end=$((SECONDS + TIMEOUT))

echo "Waiting up to ${TIMEOUT}s for ${OSD_URL}/api/status ..."
while (( SECONDS < end )); do
out="$(curl -s -k -u "${OSD_USER}:${OSD_PASS}" -H 'kbn-xsrf: true' \
-w 'HTTPSTATUS:%{http_code}' "${OSD_URL}/api/status" || true)"
code="${out##*HTTPSTATUS:}"
body="${out%HTTPSTATUS:*}"

# Ready when HTTP 200 AND overall.state === "green"
if [ "${code:-}" = "200" ] && printf '%s' "${body:-}" | grep -Eiq '"state"[[:space:]]*:[[:space:]]*"green"'; then
echo "OpenSearch Dashboards status is green (HTTP ${code})."
exit 0
fi
sleep "${INTERVAL}"
done

echo "Timed out after ${TIMEOUT}s waiting for OpenSearch Dashboards status."
echo "Last 200 lines of dashboard.log:"
tail -n 200 dashboard.log || true
exit 1


- name: Run Cypress Tests with retry
uses: Wandalen/wretry.action@v3.3.0
with:
attempt_limit: 5
attempt_delay: 2000
command: |
cd ./OpenSearch-Dashboards/plugins/security-dashboards-plugin
yarn add cypress --save-dev
eval 'CYPRESS_VERIFY_TIMEOUT=60000 yarn cypress:run --browser chrome --headless --env LOGIN_AS_ADMIN=true --spec "test/cypress/e2e/resource-sharing/resource_access_management.spec.ts"'

1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Features

* [Resource Sharing] Adds resource access management dashboard ([#2304](https://github.com/opensearch-project/security-dashboards-plugin/pull/2304))

### Enhancements
- Add experimental direct query permissions ([#2315](https://github.com/opensearch-project/security-dashboards-plugin/pull/2315))
Expand Down
3 changes: 3 additions & 0 deletions common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ export const PLUGIN_USERS_APP_ID = `${PLUGIN_NAME}_users`;
export const PLUGIN_PERMISSIONS_APP_ID = `${PLUGIN_NAME}_permissions`;
export const PLUGIN_TENANTS_APP_ID = `${PLUGIN_NAME}_tenants`;
export const PLUGIN_AUDITLOG_APP_ID = `${PLUGIN_NAME}_auditlog`;
export const PLUGIN_RESOURCE_ACCESS_MANAGEMENT_APP_ID = `${PLUGIN_NAME}_resource_access_management`;

export const APP_ID_LOGIN = 'login';
export const APP_ID_CUSTOMERROR = 'customerror';
export const APP_ID_RESOURCE_ACCESS_MANAGEMENT = 'resource_access_management';
export const OPENDISTRO_SECURITY_ANONYMOUS = 'opendistro_security_anonymous';

export const API_PREFIX = '/api/v1';
Expand All @@ -34,6 +36,7 @@ export const API_ENDPOINT_DASHBOARDSINFO = API_PREFIX + '/auth/dashboardsinfo';
export const API_ENDPOINT_AUTHTYPE = API_PREFIX + '/auth/type';
export const LOGIN_PAGE_URI = '/app/' + APP_ID_LOGIN;
export const CUSTOM_ERROR_PAGE_URI = '/app/' + APP_ID_CUSTOMERROR;
export const RESOURCE_ACCESS_MANAGEMENT_URI = '/app/' + APP_ID_RESOURCE_ACCESS_MANAGEMENT;
export const API_AUTH_LOGIN = '/auth/login';
export const API_AUTH_LOGOUT = '/auth/logout';
export const OPENID_AUTH_LOGIN = '/auth/openid/login';
Expand Down
2 changes: 1 addition & 1 deletion cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module.exports = defineConfig({
setupNodeEvents(on, config) {},
supportFile: 'test/cypress/support/e2e.js',
baseUrl: 'http://localhost:5601',
specPattern: 'test/cypress/e2e/**/*.spec.js',
specPattern: ['test/cypress/e2e/**/*.spec.js', 'test/cypress/e2e/**/*.spec.ts'],
},
env: {
openSearchUrl: 'https://localhost:9200',
Expand Down
6 changes: 6 additions & 0 deletions public/apps/resource-sharing/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

// stylelint-disable-next-line @osd/stylelint/no_modifying_global_selectors
112 changes: 112 additions & 0 deletions public/apps/resource-sharing/resource-access-management-app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright OpenSearch Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

import './_index.scss';

import React from 'react';
import ReactDOM from 'react-dom';
import { I18nProvider } from '@osd/i18n/react';

import {
EuiPage,
EuiPageBody,
EuiFlexGroup,
EuiFlexItem,
EuiPageHeader,
EuiTitle,
EuiText,
EuiSpacer,
} from '@elastic/eui';

import { AppMountParameters, CoreStart } from '../../../../../src/core/public';
import { DataSourceManagementPluginSetup } from '../../../../../src/plugins/data_source_management/public';
import { SecurityPluginStartDependencies, ClientConfigType } from '../../types';

import { ResourceSharingPanel } from './resource-sharing-panel';
import { buildResourceApi } from '../../utils/resource-sharing-utils';

interface Props {
coreStart: CoreStart;
depsStart: SecurityPluginStartDependencies;
params: AppMountParameters;
config: ClientConfigType;
redirect: string;
dataSourceManagement?: DataSourceManagementPluginSetup;
}

const ResourceAccessManagementApp: React.FC<Props> = ({ coreStart, depsStart }) => {
const {
http,
notifications: { toasts },
} = coreStart;
const TopNav = depsStart?.navigation?.ui?.TopNavMenu;

return (
<>
{TopNav ? (
<TopNav appName="resource-access" showSearchBar={false} useDefaultBehaviors={true} />
) : null}
<EuiPage restrictWidth="2000px">
<EuiPageBody component="main">
<EuiPageHeader>
<EuiFlexGroup direction="column" gutterSize="xs">
<EuiFlexItem grow={false}>
<EuiTitle size="l">
<h1>Resource Access Management</h1>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText color="subdued" size="s">
Manage sharing for detectors, forecasters, and more.
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageHeader>

<EuiSpacer size="m" />

<ResourceSharingPanel api={buildResourceApi(http)} toasts={toasts} />
</EuiPageBody>
</EuiPage>
</>
);
};

export function renderApp(
coreStart: CoreStart,
depsStart: SecurityPluginStartDependencies,
params: AppMountParameters,
config: ClientConfigType,
redirect: string,
dataSourceManagement?: DataSourceManagementPluginSetup
) {
const deps: Props = {
coreStart,
depsStart,
params,
config,
dataSourceManagement,
redirect,
};

ReactDOM.render(
<I18nProvider>
<ResourceAccessManagementApp {...deps} />
</I18nProvider>,
params.element
);

return () => ReactDOM.unmountComponentAtNode(params.element);
}
Loading
Loading