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

2.18 #2154

Open
wants to merge 8 commits into
base: 2.18
Choose a base branch
from
Open

2.18 #2154

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
3 changes: 3 additions & 0 deletions common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export const SAML_AUTH_LOGIN_WITH_FRAGMENT = '/auth/saml/captureUrlFragment';
export const ANONYMOUS_AUTH_LOGIN = '/auth/anonymous';
export const AUTH_TYPE_PARAM = 'auth_type';

export const KERBEROS_AUTH_LOGIN = '/auth/kerberos/login';

export const OPENID_AUTH_LOGOUT = '/auth/openid/logout';
export const SAML_AUTH_LOGOUT = '/auth/saml/logout';
export const ANONYMOUS_AUTH_LOGOUT = '/auth/anonymous/logout';
Expand Down Expand Up @@ -72,6 +74,7 @@ export enum AuthType {
SAML = 'saml',
PROXY = 'proxy',
ANONYMOUS = 'anonymous',
KERBEROS = 'kerberos',
}

export enum ResourceType {
Expand Down
120 changes: 120 additions & 0 deletions kerberos_notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
### Required environment for Kerberos authentication ###
1. Kerberos server
2. DNS server
3. Opensearch Core & Dashboards server
4. Client browser with SPNEGO ( I testing on google-chrome )

---
### KEBEROS SERVER ###
Required
1. User principle to be authenticate
2. Service principle eg. HTTP/<server_host> ( When created with kadmin should get as HTTP/<server_host>@<your_domain>)
3. Keytab for Service principle ( Make sure to give owner to opensearch core )

**NOTE**
1. I only test both core and dashboards on the same host.
2. Dashboards isn't the one authenticate with Kerberos but the core did so keytab doesn't need for dashboards.

---

### DNS SERVER ###
Required
1. DNS Service if using **bind9** should have dns address to opensearch & kerberos like
```
_kerberos._udp.<YOUR DOMAIN>. IN SRV 1 0 88 kdc.<your domain>.
_kerberos._tcp.<YOUR DOMAIN>. IN SRV 1 0 88 kdc.<your domain>.
_kerberos-adm._tcp.<YOUR DOMAIN>. IN SRV 1 0 749 kdc.<your domain>.
_kpasswd._udp.<YOUR DOMAIN>. IN SRV 1 0 464 kdc.<your domain>.

kdc IN A <kerberos kdc server address>
opensearch IN A <opensearch server address>
```

---

### Opensearch core ###
Required
1. set DNS point to your DNS server
2. Add config to opensearch.yml
```
plugins.security.kerberos.krb5_filepath: '/etc/krb5.conf' # this is your kerberos config location
plugins.security.kerberos.acceptor_keytab_filepath: '<path to keytab file>' # keytab file for kerberos ( don't forget to give owner to opensearch )
plugins.security.kerberos.acceptor_principal: 'HTTP/<server_host>' # this is your service principle on your kerberos for opensearch
```

3. Configuration Opensearch-security config file ( don't forget to apply )
```
authc:
kerberos_auth_domain:
http_enabled: true # enable this
transport_enabled: false
order: 6
http_authenticator:
type: kerberos
challenge: false
config:
krb_debug: true
strip_realm_from_principal: true
authentication_backend:
type: noop


jwt_auth_domain:
description: "Authenticate via Json Web Token"
http_enabled: true
transport_enabled: false
order: 0
http_authenticator:
type: jwt
challenge: false
config:
signing_key: "<encoded secret key>" # edit this to your key (encoded by base64)
jwt_header: "Authorization"
jwt_url_parameter: null
# jwt_clock_skew_tolerance_seconds: 30
roles_key: roles
subject_key: user
authentication_backend:
type: noop
```

---

### Opensearch Dashboards ###
Required
Edit config file for dashboards

```
# define auth type
opensearch_security.auth.type: kerberos

# set your secret key
opensearch_security.kerberos.jwt_siging_key: '<your secret key>' #NOTE as plain text not encoded

```

---

### Client Browser ###
Required ( For google chrome )
1. Make sure to that browser have **SPNEGO**
1. Edit policy section for ```AuthServerAllowlist```

For google chrome debian package should locate at ```/etc/opt/chrome/policies/managed/```
create your policy file eg.
```
{
"AuthServerAllowlist" : "<opensearch_hostname>"
}
```

**NOTE**
- When search on browser you must access hostname according to policies your defined.

- Make sure that you already use **kinit** and see your tokens via **klist**

- You can test with curl for checking kerberos by
```curl <opensearch_hostname>:<port> -u ':' --negotiate -v```
( You should see Negotiate token when request to server. If not it may problem with misconfiguration kerberos (usually principle) or DNS )

- **Don't forget** to add permission to user name same as kerberos principle of that user.
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@
"dependencies": {
"@hapi/cryptiles": "5.0.0",
"@hapi/wreck": "^17.1.0",
"@types/jsonwebtoken": "^9.0.7",
"html-entities": "1.3.1",
"jsonwebtoken": "^9.0.2",
"proxy-agent": "^6.4.0",
"zxcvbn": "^4.4.2",
"semver": "^7.5.3"
"semver": "^7.5.3",
"zxcvbn": "^4.4.2"
},
"resolutions": {
"selenium-webdriver": "4.10.0",
Expand All @@ -58,4 +60,4 @@
"body-parser": "^1.20.3",
"micromatch": "^4.0.8"
}
}
}
4 changes: 4 additions & 0 deletions server/auth/auth_handler_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
ProxyAuthentication,
SamlAuthentication,
MultipleAuthentication,
KerberosAuthentication,
} from './types';
import { SecuritySessionCookie } from '../session/security_cookie';
import { IAuthenticationType, IAuthHandlerConstructor } from './types/authentication_type';
Expand Down Expand Up @@ -76,6 +77,9 @@ export async function getAuthenticationHandler(
case AuthType.PROXY:
authHandlerType = ProxyAuthentication;
break;
case AuthType.KERBEROS:
authHandlerType = KerberosAuthentication;
break;
default:
throw new Error(`Unsupported authentication type: ${currType}`);
}
Expand Down
1 change: 1 addition & 0 deletions server/auth/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ export { OpenIdAuthentication } from './openid/openid_auth';
export { ProxyAuthentication } from './proxy/proxy_auth';
export { SamlAuthentication } from './saml/saml_auth';
export { MultipleAuthentication } from './multiple/multi_auth';
export { KerberosAuthentication } from './kerberos/kerberos_auth';
117 changes: 117 additions & 0 deletions server/auth/types/kerberos/kerberos_auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* 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 {
CoreSetup,
SessionStorageFactory,
IRouter,
ILegacyClusterClient,
OpenSearchDashboardsRequest,
Logger,
LifecycleResponseFactory,
AuthToolkit,
} from 'opensearch-dashboards/server';
import { OpenSearchDashboardsResponse } from 'src/core/server/http/router';
import { SecurityPluginConfigType } from '../../..';
import { SecuritySessionCookie } from '../../../session/security_cookie';
import { KerberosAuthRoutes } from './routes';
import { AuthenticationType } from '../authentication_type';
import { composeNextUrlQueryParam } from '../../../utils/next_url';
import { KERBEROS_AUTH_LOGIN } from '../../../../common';

export class KerberosAuthentication extends AuthenticationType {
public readonly jwtCookie: string = 'jwt';
public readonly kerberosHeader: string = 'Negotiate';

constructor(
config: SecurityPluginConfigType,
sessionStorageFactory: SessionStorageFactory<SecuritySessionCookie>,
router: IRouter,
esClient: ILegacyClusterClient,
coreSetup: CoreSetup,
logger: Logger
) {
super(config, sessionStorageFactory, router, esClient, coreSetup, logger);
}

public async init() {
const routes = new KerberosAuthRoutes(
this.router,
this.config,
this.sessionStorageFactory,
this.securityClient,
this.coreSetup
);
routes.setupRoutes();
}

// Since kerberos authen always attached by SPENGO prevent authentication every request
requestIncludesAuthInfo(
request: OpenSearchDashboardsRequest<unknown, unknown, unknown, any>
): boolean {
return false;
}

async getAdditionalAuthHeader(
request: OpenSearchDashboardsRequest<unknown, unknown, unknown, any>
): Promise<any> {
return {};
}

getCookie(request: OpenSearchDashboardsRequest, authInfo: any): SecuritySessionCookie {
return {};
}

async isValidCookie(cookie: SecuritySessionCookie): Promise<boolean> {
return (
cookie.authType === this.jwtCookie &&
cookie.expiryTime &&
((cookie.username && cookie.credentials?.authHeaderValue) ||
(this.config.auth.anonymous_auth_enabled && cookie.isAnonymousAuth))
);
}

handleUnauthedRequest(
request: OpenSearchDashboardsRequest,
response: LifecycleResponseFactory,
toolkit: AuthToolkit
): OpenSearchDashboardsResponse {
if (this.isPageRequest(request)) {
const nextUrlParam = composeNextUrlQueryParam(
request,
this.coreSetup.http.basePath.serverBasePath
);
const redirectLocation = `${this.coreSetup.http.basePath.serverBasePath}${KERBEROS_AUTH_LOGIN}?${nextUrlParam}`;
return response.redirected({
headers: {
location: `${redirectLocation}`,
},
});
} else {
return response.unauthorized({
body: `Authentication required`,
});
}
}

buildAuthHeaderFromCookie(
cookie: SecuritySessionCookie,
request: OpenSearchDashboardsRequest
): any {
const headers: any = {};
Object.assign(headers, { authorization: cookie.credentials?.authHeaderValue });
return headers;
}
}
Loading
Loading