Skip to content

Commit ee9ead0

Browse files
committed
Merge branch 'register-namespaces' of https://github.com/cwperks/security-dashboards-plugin into register-namespaces
2 parents 92cf494 + 91c999e commit ee9ead0

34 files changed

+1419
-215
lines changed

common/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,37 @@ export const PLUGIN_NAME = 'security-dashboards-plugin';
1818

1919
export const APP_ID_LOGIN = 'login';
2020
export const APP_ID_CUSTOMERROR = 'customerror';
21+
export const OPENDISTRO_SECURITY_ANONYMOUS = 'opendistro_security_anonymous';
2122

2223
export const API_PREFIX = '/api/v1';
2324
export const CONFIGURATION_API_PREFIX = 'configuration';
2425
export const API_ENDPOINT_AUTHINFO = API_PREFIX + '/auth/authinfo';
26+
export const API_ENDPOINT_AUTHTYPE = API_PREFIX + '/auth/type';
2527
export const LOGIN_PAGE_URI = '/app/' + APP_ID_LOGIN;
2628
export const CUSTOM_ERROR_PAGE_URI = '/app/' + APP_ID_CUSTOMERROR;
2729
export const API_AUTH_LOGIN = '/auth/login';
2830
export const API_AUTH_LOGOUT = '/auth/logout';
31+
export const OPENID_AUTH_LOGIN = '/auth/openid/login';
32+
export const SAML_AUTH_LOGIN = '/auth/saml/login';
33+
export const ANONYMOUS_AUTH_LOGIN = '/auth/anonymous';
34+
export const SAML_AUTH_LOGIN_WITH_FRAGMENT = '/auth/saml/captureUrlFragment?nextUrl=%2F';
35+
36+
export const OPENID_AUTH_LOGOUT = '/auth/openid/logout';
37+
export const SAML_AUTH_LOGOUT = '/auth/saml/logout';
38+
export const ANONYMOUS_AUTH_LOGOUT = '/auth/anonymous/logout';
2939

3040
export const ERROR_MISSING_ROLE_PATH = '/missing-role';
41+
export const AUTH_HEADER_NAME = 'authorization';
42+
export const AUTH_GRANT_TYPE = 'authorization_code';
43+
export const AUTH_RESPONSE_TYPE = 'code';
3144

3245
export enum AuthType {
3346
BASIC = 'basicauth',
3447
OPEN_ID = 'openid',
3548
JWT = 'jwt',
3649
SAML = 'saml',
3750
PROXY = 'proxy',
51+
ANONYMOUS = 'anonymous',
3852
}
3953

4054
/**

public/apps/account/account-app.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ import { CoreStart } from 'opensearch-dashboards/public';
1919
import { AccountNavButton } from './account-nav-button';
2020
import { fetchAccountInfoSafe } from './utils';
2121
import { ClientConfigType } from '../../types';
22-
import { CUSTOM_ERROR_PAGE_URI, ERROR_MISSING_ROLE_PATH } from '../../../common';
22+
import { AuthType, CUSTOM_ERROR_PAGE_URI, ERROR_MISSING_ROLE_PATH } from '../../../common';
2323
import { fetchCurrentTenant, selectTenant } from '../configuration/utils/tenant-utils';
2424
import {
2525
getSavedTenant,
2626
getShouldShowTenantPopup,
2727
setShouldShowTenantPopup,
2828
} from '../../utils/storage-utils';
2929
import { constructErrorMessageAndLog } from '../error-utils';
30+
import { fetchCurrentAuthType } from '../../utils/logout-utils';
3031

3132
function tenantSpecifiedInUrl() {
3233
return (
@@ -36,6 +37,20 @@ function tenantSpecifiedInUrl() {
3637
}
3738

3839
export async function setupTopNavButton(coreStart: CoreStart, config: ClientConfigType) {
40+
const authType = config.auth?.type;
41+
let currAuthType = '';
42+
if (typeof authType === 'string') {
43+
currAuthType = authType;
44+
} else if (Array.isArray(authType) && authType.length === 1) {
45+
currAuthType = authType[0];
46+
} else {
47+
try {
48+
currAuthType = (await fetchCurrentAuthType(coreStart.http))?.currentAuthType;
49+
} catch (e) {
50+
currAuthType = AuthType.BASIC;
51+
}
52+
}
53+
3954
const accountInfo = (await fetchAccountInfoSafe(coreStart.http))?.data;
4055
if (accountInfo) {
4156
// Missing role error
@@ -94,6 +109,7 @@ export async function setupTopNavButton(coreStart: CoreStart, config: ClientConf
94109
username={accountInfo.user_name}
95110
tenant={tenant}
96111
config={config}
112+
currAuthType={currAuthType.toLowerCase()}
97113
/>,
98114
element
99115
);

public/apps/account/account-nav-button.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export function AccountNavButton(props: {
4242
username: string;
4343
tenant?: string;
4444
config: ClientConfigType;
45+
currAuthType: string;
4546
}) {
4647
const [isPopoverOpen, setPopoverOpen] = React.useState<boolean>(false);
4748
const [modal, setModal] = React.useState<React.ReactNode>(null);
@@ -137,7 +138,7 @@ export function AccountNavButton(props: {
137138
</>
138139
)}
139140
<LogoutButton
140-
authType={props.config.auth.type}
141+
authType={props.currAuthType}
141142
http={props.coreStart.http}
142143
divider={horizontalRule}
143144
logoutUrl={props.config.auth.logout_url}

public/apps/account/log-out-button.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,46 @@
1616
import React from 'react';
1717
import { EuiButtonEmpty } from '@elastic/eui';
1818
import { HttpStart } from 'opensearch-dashboards/public';
19-
import { logout, samlLogout } from './utils';
19+
import { externalLogout, logout } from './utils';
20+
import { AuthType, OPENID_AUTH_LOGOUT, SAML_AUTH_LOGOUT } from '../../../common';
21+
import { setShouldShowTenantPopup } from '../../utils/storage-utils';
2022

2123
export function LogoutButton(props: {
2224
authType: string;
2325
http: HttpStart;
2426
divider: JSX.Element;
2527
logoutUrl?: string;
2628
}) {
27-
if (props.authType === 'openid') {
29+
if (props.authType === AuthType.OPEN_ID) {
2830
return (
2931
<div>
3032
{props.divider}
3133
<EuiButtonEmpty
3234
data-test-subj="log-out-2"
3335
color="danger"
3436
size="xs"
35-
href={`${props.http.basePath.serverBasePath}/auth/logout`}
37+
onClick={() => externalLogout(props.http, OPENID_AUTH_LOGOUT)}
3638
>
3739
Log out
3840
</EuiButtonEmpty>
3941
</div>
4042
);
41-
} else if (props.authType === 'saml') {
43+
} else if (props.authType === AuthType.SAML) {
4244
return (
4345
<div>
4446
{props.divider}
4547
<EuiButtonEmpty
4648
data-test-subj="log-out-1"
4749
color="danger"
4850
size="xs"
49-
onClick={() => samlLogout(props.http)}
51+
onClick={() => externalLogout(props.http, SAML_AUTH_LOGOUT)}
5052
>
5153
Log out
5254
</EuiButtonEmpty>
5355
</div>
5456
);
55-
} else if (props.authType === 'proxy') {
57+
} else if (props.authType === AuthType.PROXY) {
58+
setShouldShowTenantPopup(null);
5659
return <div />;
5760
} else {
5861
return (

public/apps/account/test/__snapshots__/log-out-button.test.tsx.snap

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,50 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`Account menu - Log out button renders renders when auth type is MultiAuth: basicauth 1`] = `
4+
<div>
5+
<EuiButtonEmpty
6+
color="danger"
7+
data-test-subj="log-out-3"
8+
onClick={[Function]}
9+
size="xs"
10+
>
11+
Log out
12+
</EuiButtonEmpty>
13+
</div>
14+
`;
15+
16+
exports[`Account menu - Log out button renders renders when auth type is MultiAuth: openid 1`] = `
17+
<div>
18+
<EuiButtonEmpty
19+
color="danger"
20+
data-test-subj="log-out-2"
21+
onClick={[Function]}
22+
size="xs"
23+
>
24+
Log out
25+
</EuiButtonEmpty>
26+
</div>
27+
`;
28+
29+
exports[`Account menu - Log out button renders renders when auth type is MultiAuth: saml 1`] = `
30+
<div>
31+
<EuiButtonEmpty
32+
color="danger"
33+
data-test-subj="log-out-1"
34+
onClick={[Function]}
35+
size="xs"
36+
>
37+
Log out
38+
</EuiButtonEmpty>
39+
</div>
40+
`;
41+
342
exports[`Account menu - Log out button renders renders when auth type is OpenId 1`] = `
443
<div>
544
<EuiButtonEmpty
645
color="danger"
746
data-test-subj="log-out-2"
8-
href="/auth/logout"
47+
onClick={[Function]}
948
size="xs"
1049
>
1150
Log out

public/apps/account/test/account-app.test.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
getSavedTenant,
2323
} from '../../../utils/storage-utils';
2424
import { fetchAccountInfoSafe } from '../utils';
25+
import { fetchCurrentAuthType } from '../../../utils/logout-utils';
2526
import { fetchCurrentTenant, selectTenant } from '../../configuration/utils/tenant-utils';
2627

2728
jest.mock('../../../utils/storage-utils', () => ({
@@ -34,6 +35,10 @@ jest.mock('../utils', () => ({
3435
fetchAccountInfoSafe: jest.fn(),
3536
}));
3637

38+
jest.mock('../../../utils/logout-utils', () => ({
39+
fetchCurrentAuthType: jest.fn(),
40+
}));
41+
3742
jest.mock('../../configuration/utils/tenant-utils', () => ({
3843
selectTenant: jest.fn(),
3944
fetchCurrentTenant: jest.fn(),
@@ -66,6 +71,7 @@ describe('Account app', () => {
6671

6772
beforeAll(() => {
6873
(fetchAccountInfoSafe as jest.Mock).mockResolvedValue(mockAccountInfo);
74+
(fetchCurrentAuthType as jest.Mock).mockResolvedValue('dummy');
6975
(fetchCurrentTenant as jest.Mock).mockResolvedValue(mockTenant);
7076
});
7177

public/apps/account/test/account-nav-button.test.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ describe('Account navigation button', () => {
5656
username={userName}
5757
tenant="tenant1"
5858
config={config as any}
59+
currAuthType={'dummy'}
5960
/>
6061
);
6162
});
@@ -77,6 +78,7 @@ describe('Account navigation button', () => {
7778
username={userName}
7879
tenant="tenant1"
7980
config={config as any}
81+
currAuthType={'dummy'}
8082
/>
8183
);
8284
expect(setState).toBeCalledTimes(1);
@@ -137,6 +139,7 @@ describe('Account navigation button, multitenancy disabled', () => {
137139
isInternalUser={true}
138140
username={userName}
139141
config={config as any}
142+
currAuthType={'dummy'}
140143
/>
141144
);
142145
expect(setState).toBeCalledTimes(0);

public/apps/account/test/log-out-button.test.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,37 @@ describe('Account menu - Log out button', () => {
2727
OpenId = 'openid',
2828
SAML = 'saml',
2929
Proxy = 'proxy',
30+
Basic = 'basicauth',
3031
}
32+
3133
const mockHttpStart = {
3234
basePath: {
3335
serverBasePath: '',
3436
},
3537
};
3638
const mockDivider = <></>;
3739
describe('renders', () => {
40+
it('renders when auth type is MultiAuth: openid', () => {
41+
const component = shallow(
42+
<LogoutButton authType={authType.OpenId} http={mockHttpStart} divider={mockDivider} />
43+
);
44+
expect(component).toMatchSnapshot();
45+
});
46+
47+
it('renders when auth type is MultiAuth: saml', () => {
48+
const component = shallow(
49+
<LogoutButton authType={authType.SAML} http={mockHttpStart} divider={mockDivider} />
50+
);
51+
expect(component).toMatchSnapshot();
52+
});
53+
54+
it('renders when auth type is MultiAuth: basicauth', () => {
55+
const component = shallow(
56+
<LogoutButton authType={authType.Basic} http={mockHttpStart} divider={mockDivider} />
57+
);
58+
expect(component).toMatchSnapshot();
59+
});
60+
3861
it('renders when auth type is OpenId', () => {
3962
const component = shallow(
4063
<LogoutButton authType={authType.OpenId} http={mockHttpStart} divider={mockDivider} />

public/apps/account/utils.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
*/
1515

1616
import { HttpStart } from 'opensearch-dashboards/public';
17-
import { API_AUTH_LOGOUT, LOGIN_PAGE_URI } from '../../../common';
17+
import {
18+
API_AUTH_LOGOUT,
19+
LOGIN_PAGE_URI,
20+
OPENID_AUTH_LOGOUT,
21+
SAML_AUTH_LOGOUT,
22+
} from '../../../common';
1823
import { API_ENDPOINT_ACCOUNT_INFO } from './constants';
1924
import { AccountInfo } from './types';
2025
import { httpGet, httpGetWithIgnores, httpPost } from '../configuration/utils/request-utils';
@@ -43,7 +48,21 @@ export async function logout(http: HttpStart, logoutUrl?: string): Promise<void>
4348
export async function samlLogout(http: HttpStart): Promise<void> {
4449
// This will ensure tenancy is picked up from local storage in the next login.
4550
setShouldShowTenantPopup(null);
46-
window.location.href = `${http.basePath.serverBasePath}${API_AUTH_LOGOUT}`;
51+
window.location.href = `${http.basePath.serverBasePath}${SAML_AUTH_LOGOUT}`;
52+
}
53+
54+
export async function openidLogout(http: HttpStart): Promise<void> {
55+
// This will ensure tenancy is picked up from local storage in the next login.
56+
setShouldShowTenantPopup(null);
57+
sessionStorage.clear();
58+
window.location.href = `${http.basePath.serverBasePath}${OPENID_AUTH_LOGOUT}`;
59+
}
60+
61+
export async function externalLogout(http: HttpStart, logoutEndpoint: string): Promise<void> {
62+
// This will ensure tenancy is picked up from local storage in the next login.
63+
setShouldShowTenantPopup(null);
64+
sessionStorage.clear();
65+
window.location.href = `${http.basePath.serverBasePath}${logoutEndpoint}`;
4766
}
4867

4968
export async function updateNewPassword(

public/apps/login/login-app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { ClientConfigType } from '../../types';
2424
export function renderApp(
2525
coreStart: CoreStart,
2626
params: AppMountParameters,
27-
config: ClientConfigType['ui']['basicauth']['login']
27+
config: ClientConfigType
2828
) {
2929
ReactDOM.render(<LoginPage http={coreStart.http} config={config} />, params.element);
3030
return () => ReactDOM.unmountComponentAtNode(params.element);

0 commit comments

Comments
 (0)