KNOX-1257 - WebAppSec provider configuration wizard
Project: http://git-wip-us.apache.org/repos/asf/knox/repo Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/9925a637 Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/9925a637 Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/9925a637 Branch: refs/heads/master Commit: 9925a6372cb46bee9a4e40bdf0eac914b54b2717 Parents: f36f659 Author: Phil Zampino <[email protected]> Authored: Tue Apr 24 20:24:50 2018 -0400 Committer: Phil Zampino <[email protected]> Committed: Wed Apr 25 11:17:26 2018 -0400 ---------------------------------------------------------------------- .../cors-provider-config.ts | 116 +++++++++++++++++++ .../csrf-provider-config.ts | 74 ++++++++++++ .../ha-provider-config.ts | 8 +- .../src/app/provider-config-wizard/ha-wizard.ts | 9 +- .../provider-config-wizard.component.ts | 4 + .../sts-provider-config.ts | 64 ++++++++++ .../webappsec-contributor.ts | 28 +++++ .../webappsec-provider-config.ts | 41 +++++++ .../provider-config-wizard/webappsec-wizard.ts | 108 +++++++++++++++++ .../xframeoptions-provider-config.ts | 66 +++++++++++ .../src/app/utils/validation-utils.ts | 11 ++ .../applications/admin-ui/app/index.html | 2 +- .../app/inline.45a383ca05ad5b8aeba5.bundle.js | 1 - .../app/inline.9b86d6e943bbedc3c3a9.bundle.js | 1 + .../app/main.5a33727bde77ca75fd8c.bundle.js | 1 - .../app/main.e16062311693b0626855.bundle.js | 1 + 16 files changed, 521 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/provider-config-wizard/cors-provider-config.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/provider-config-wizard/cors-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/cors-provider-config.ts new file mode 100644 index 0000000..f3e160b --- /dev/null +++ b/gateway-admin-ui/src/app/provider-config-wizard/cors-provider-config.ts @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 {ValidationUtils} from "../utils/validation-utils"; +import {WebAppSecurityContributor} from "./webappsec-contributor"; + +export class CORSProviderConfig extends WebAppSecurityContributor { + + public static TYPE: string = 'cors'; + + public static ALLOW_GENERIC_REQUESTS: string = 'Allow generic requests'; + public static ALLOWED_ORIGINS: string = 'Allowed origins'; + public static ALLOW_SUBDOMAINS: string = 'Allow sub-domains'; + public static SUPPORTED_METHODS: string = 'Supported HTTP methods'; + public static SUPPORTED_HEADERS: string = 'Supported HTTP headers'; + public static EXPOSED_HEADERS: string = 'Exposed HTTP headers'; + public static SUPPORTS_CREDS: string = 'Supports credentials'; + public static MAX_AGE: string = 'Access control max age'; + public static TAG_REQUESTS: string = 'Request tagging'; + + private static displayPropertyNames = [ CORSProviderConfig.ALLOW_GENERIC_REQUESTS, + CORSProviderConfig.ALLOWED_ORIGINS, + CORSProviderConfig.ALLOW_SUBDOMAINS, + CORSProviderConfig.SUPPORTED_METHODS, + CORSProviderConfig.SUPPORTED_HEADERS, + CORSProviderConfig.EXPOSED_HEADERS, + CORSProviderConfig.SUPPORTS_CREDS, + CORSProviderConfig.MAX_AGE, + CORSProviderConfig.TAG_REQUESTS + ]; + + private static displayPropertyNameBindings: Map<string, string> = + new Map([ + [CORSProviderConfig.ALLOW_GENERIC_REQUESTS, 'cors.allowGenericHttpRequests'], + [CORSProviderConfig.ALLOWED_ORIGINS, 'cors.allowOrigin'], + [CORSProviderConfig.ALLOW_SUBDOMAINS, 'cors.allowSubdomains'], + [CORSProviderConfig.SUPPORTED_METHODS, 'cors.supportedMethods'], + [CORSProviderConfig.SUPPORTED_HEADERS, 'cors.supportedHeaders'], + [CORSProviderConfig.EXPOSED_HEADERS, 'cors.exposedHeaders'], + [CORSProviderConfig.SUPPORTS_CREDS, 'cors.supportsCredentials'], + [CORSProviderConfig.MAX_AGE, 'cors.maxAge'], + [CORSProviderConfig.TAG_REQUESTS, 'cors.tagRequests'] + ] as [string, string][]); + + + constructor() { + super(); + // Set default values + this.setParam('cors.enabled', 'true'); + this.setParam(CORSProviderConfig.displayPropertyNameBindings.get(CORSProviderConfig.ALLOW_GENERIC_REQUESTS), 'true'); + this.setParam(CORSProviderConfig.displayPropertyNameBindings.get(CORSProviderConfig.ALLOWED_ORIGINS), '*'); + this.setParam(CORSProviderConfig.displayPropertyNameBindings.get(CORSProviderConfig.ALLOW_SUBDOMAINS), 'false'); + this.setParam(CORSProviderConfig.displayPropertyNameBindings.get(CORSProviderConfig.SUPPORTED_METHODS), 'GET,POST,HEAD,OPTIONS'); + this.setParam(CORSProviderConfig.displayPropertyNameBindings.get(CORSProviderConfig.SUPPORTED_HEADERS), '*'); + this.setParam(CORSProviderConfig.displayPropertyNameBindings.get(CORSProviderConfig.SUPPORTS_CREDS), 'true'); + this.setParam(CORSProviderConfig.displayPropertyNameBindings.get(CORSProviderConfig.MAX_AGE), '-1'); + this.setParam(CORSProviderConfig.displayPropertyNameBindings.get(CORSProviderConfig.TAG_REQUESTS), 'false'); + } + + getDisplayPropertyNames(): string[] { + return CORSProviderConfig.displayPropertyNames; + } + + getDisplayNamePropertyBinding(name: string): string { + return CORSProviderConfig.displayPropertyNameBindings.get(name); + } + + isValidParamValue(paramName: string): boolean { + let isValid: boolean = true; + + let value = this.getParam(this.getDisplayNamePropertyBinding(paramName)); + switch (paramName) { + case CORSProviderConfig.SUPPORTED_METHODS: + if (value) { + let methodList: string[] = value.split(','); + for (let method of methodList) { + isValid = isValid && ValidationUtils.isValidHTTPMethod(method.trim().toUpperCase()); + } + } + break; + case CORSProviderConfig.ALLOW_GENERIC_REQUESTS: + case CORSProviderConfig.ALLOW_SUBDOMAINS: + case CORSProviderConfig.SUPPORTS_CREDS: + case CORSProviderConfig.TAG_REQUESTS: + if (value) { + isValid = ValidationUtils.isValidBoolean(value); + } + break; + case CORSProviderConfig.MAX_AGE: + isValid = ValidationUtils.isValidSignedNumber(value); + break; + default: + if (value) { + isValid = ValidationUtils.isValidString(value); + } + } + + return isValid; + } + +} + http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/provider-config-wizard/csrf-provider-config.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/provider-config-wizard/csrf-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/csrf-provider-config.ts new file mode 100644 index 0000000..7bef2c9 --- /dev/null +++ b/gateway-admin-ui/src/app/provider-config-wizard/csrf-provider-config.ts @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 {ValidationUtils} from "../utils/validation-utils"; +import {WebAppSecurityContributor} from "./webappsec-contributor"; + +export class CSRFProviderConfig extends WebAppSecurityContributor { + + public static CUSTOM_HEADER: string = 'Custom Header'; + public static METHODS_TO_IGNORE: string = 'Methods to Ignore'; + + private static displayPropertyNames = [ CSRFProviderConfig.CUSTOM_HEADER, + CSRFProviderConfig.METHODS_TO_IGNORE + ]; + + private static displayPropertyNameBindings: Map<string, string> = + new Map([ + [CSRFProviderConfig.CUSTOM_HEADER, 'csrf.customHeader'], + [CSRFProviderConfig.METHODS_TO_IGNORE, 'csrf.methodsToIgnore'] + ] as [string, string][]); + + + constructor() { + super(); + this.setParam('csrf.enabled', 'true'); + this.setParam(CSRFProviderConfig.displayPropertyNameBindings.get(CSRFProviderConfig.CUSTOM_HEADER), 'X-XSRF-Header'); + this.setParam(CSRFProviderConfig.displayPropertyNameBindings.get(CSRFProviderConfig.METHODS_TO_IGNORE), 'GET,OPTIONS,HEAD'); + } + + getDisplayPropertyNames(): string[] { + return CSRFProviderConfig.displayPropertyNames; + } + + getDisplayNamePropertyBinding(name: string): string { + return CSRFProviderConfig.displayPropertyNameBindings.get(name); + } + + isValidParamValue(paramName: string): boolean { + let isValid: boolean = true; + + let value = this.getParam(this.getDisplayNamePropertyBinding(paramName)); + if (value) { + switch (paramName) { + case CSRFProviderConfig.CUSTOM_HEADER: + isValid = ValidationUtils.isValidString(value); + break; + case CSRFProviderConfig.METHODS_TO_IGNORE: + let methodList: string[] = value.split(','); + for (let method of methodList) { + isValid = isValid && ValidationUtils.isValidHTTPMethod(method.trim().toUpperCase()); + } + break; + default: + } + } + return isValid; + } + +} + http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/provider-config-wizard/ha-provider-config.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/provider-config-wizard/ha-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/ha-provider-config.ts index 3ae31d9..52ebc45 100644 --- a/gateway-admin-ui/src/app/provider-config-wizard/ha-provider-config.ts +++ b/gateway-admin-ui/src/app/provider-config-wizard/ha-provider-config.ts @@ -46,7 +46,11 @@ export class HaProviderConfig extends DisplayBindingProviderConfig { constructor() { super(); + this.setType(HaProviderConfig.TYPE); + this.enabled = 'true'; this.name = HaProviderConfig.TYPE; + this.role = 'ha'; + this.params = new Map<string, string>(); } getDisplayPropertyNames(): string[] { @@ -57,10 +61,6 @@ export class HaProviderConfig extends DisplayBindingProviderConfig { return HaProviderConfig.displayPropertyNameBindings.get(name); } - getType(): string { - return HaProviderConfig.TYPE; - } - isValidParamValue(paramName: string): boolean { let isValid: boolean = true; http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/provider-config-wizard/ha-wizard.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/provider-config-wizard/ha-wizard.ts b/gateway-admin-ui/src/app/provider-config-wizard/ha-wizard.ts index e2afbf7..af4cba4 100644 --- a/gateway-admin-ui/src/app/provider-config-wizard/ha-wizard.ts +++ b/gateway-admin-ui/src/app/provider-config-wizard/ha-wizard.ts @@ -23,7 +23,7 @@ import {DisplayBindingProviderConfig} from "./display-binding-provider-config"; export class HaWizard extends CategoryWizard implements ProviderContributorWizard { - private static DEFAULT_TYPE: string = HaProviderConfig.TYPE; + private static DEFAULT_TYPE: string = 'Add service'; private stepCount: number = 4; @@ -48,12 +48,7 @@ export class HaWizard extends CategoryWizard implements ProviderContributorWizar } createNewProviderConfig(): ProviderConfig { - let pc = new HaProviderConfig(); - pc.role = 'ha'; -// pc.name = HaProviderConfig.TYPE; // TODO: PJZ: DELETE ME - pc.enabled = 'true'; - pc.params = new Map<string, string>(); - return (pc as HaProviderConfig); + return new HaProviderConfig(); } contribute(target: ProviderConfig) { http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts b/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts index 0504707..6fe3e7b 100644 --- a/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts +++ b/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts @@ -30,6 +30,7 @@ import {DisplayBindingProviderConfig} from "./display-binding-provider-config"; import {OrderedParamContainer} from "./ordered-param-container"; import {HostMapProviderWizard} from "./hostmap-provider-wizard"; import {ProviderContributorWizard} from "./ProviderContributorWizard"; +import {WebAppSecurityWizard} from "./webappsec-wizard"; @Component({ @@ -48,10 +49,12 @@ export class ProviderConfigWizardComponent implements OnInit { private static CATEGORY_AUTHORIZATION: string = 'Authorization'; private static CATEGORY_ID_ASSERTION: string = 'Identity Assertion'; private static CATEGORY_HA: string = 'HA'; + private static CATEGORY_WEBAPPSEC: string = 'Web Application Security'; private static CATEGORY_HOSTMAP: string = 'Host Mapping'; private static providerCategories: string[] = [ ProviderConfigWizardComponent.CATEGORY_AUTHENTICATION, ProviderConfigWizardComponent.CATEGORY_AUTHORIZATION, ProviderConfigWizardComponent.CATEGORY_ID_ASSERTION, + ProviderConfigWizardComponent.CATEGORY_WEBAPPSEC, ProviderConfigWizardComponent.CATEGORY_HA, ProviderConfigWizardComponent.CATEGORY_HOSTMAP ]; @@ -62,6 +65,7 @@ export class ProviderConfigWizardComponent implements OnInit { [ProviderConfigWizardComponent.CATEGORY_AUTHORIZATION, new AuthorizationWizard() as CategoryWizard], [ProviderConfigWizardComponent.CATEGORY_ID_ASSERTION, new IdentityAssertionWizard() as CategoryWizard], [ProviderConfigWizardComponent.CATEGORY_HA, new HaWizard() as CategoryWizard], + [ProviderConfigWizardComponent.CATEGORY_WEBAPPSEC, new WebAppSecurityWizard() as CategoryWizard], [ProviderConfigWizardComponent.CATEGORY_HOSTMAP, new HostMapProviderWizard() as CategoryWizard] ]); http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/provider-config-wizard/sts-provider-config.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/provider-config-wizard/sts-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/sts-provider-config.ts new file mode 100644 index 0000000..e52db77 --- /dev/null +++ b/gateway-admin-ui/src/app/provider-config-wizard/sts-provider-config.ts @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 {ValidationUtils} from "../utils/validation-utils"; +import {WebAppSecurityContributor} from "./webappsec-contributor"; + +export class STSProviderConfig extends WebAppSecurityContributor { + + public static TYPE: string = 'cors'; + + public static STS: string = 'Strict-Transport-Security Header'; + + private static displayPropertyNames = [ STSProviderConfig.STS ]; + + private static displayPropertyNameBindings: Map<string, string> = + new Map([ [STSProviderConfig.STS, 'strict.transport'] ] as [string, string][]); + + constructor() { + super(); + // Set the default values + this.setParam('strict.transport.enabled', 'true'); + this.setParam(STSProviderConfig.displayPropertyNameBindings.get(STSProviderConfig.STS), 'max-age=31536000'); + } + + getDisplayPropertyNames(): string[] { + return STSProviderConfig.displayPropertyNames; + } + + getDisplayNamePropertyBinding(name: string): string { + return STSProviderConfig.displayPropertyNameBindings.get(name); + } + + isValidParamValue(paramName: string): boolean { + let isValid: boolean = true; + + let value = this.getParam(this.getDisplayNamePropertyBinding(paramName)); + if (value) { + switch (paramName) { + case STSProviderConfig.STS: + isValid = ValidationUtils.isValidString(value); + break; + default: + } + } + + return isValid; + } + + +} http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/provider-config-wizard/webappsec-contributor.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/provider-config-wizard/webappsec-contributor.ts b/gateway-admin-ui/src/app/provider-config-wizard/webappsec-contributor.ts new file mode 100644 index 0000000..04233ba --- /dev/null +++ b/gateway-admin-ui/src/app/provider-config-wizard/webappsec-contributor.ts @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 {DisplayBindingProviderConfig} from "./display-binding-provider-config"; + +export abstract class WebAppSecurityContributor extends DisplayBindingProviderConfig { + + constructor() { + super(); + this.params = new Map<string, string>(); + } + +} + http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/provider-config-wizard/webappsec-provider-config.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/provider-config-wizard/webappsec-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/webappsec-provider-config.ts new file mode 100644 index 0000000..3b7cc6e --- /dev/null +++ b/gateway-admin-ui/src/app/provider-config-wizard/webappsec-provider-config.ts @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 {DisplayBindingProviderConfig} from "./display-binding-provider-config"; + +export class WebAppSecurityProviderConfig extends DisplayBindingProviderConfig { + + public static TYPE: string = 'WebAppSec'; + + constructor() { + super(); + this.setType(WebAppSecurityProviderConfig.TYPE); + this.enabled = 'true'; + this.name = WebAppSecurityProviderConfig.TYPE; + this.role = 'webappsec'; + this.params = new Map<string, string>(); + } + + getDisplayPropertyNames(): string[] { + return []; + } + + getDisplayNamePropertyBinding(name: string): string { + return null; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/provider-config-wizard/webappsec-wizard.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/provider-config-wizard/webappsec-wizard.ts b/gateway-admin-ui/src/app/provider-config-wizard/webappsec-wizard.ts new file mode 100644 index 0000000..3f7bca3 --- /dev/null +++ b/gateway-admin-ui/src/app/provider-config-wizard/webappsec-wizard.ts @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 {CategoryWizard} from "./category-wizard"; +import {ProviderConfig} from "../resource-detail/provider-config"; +import {ProviderContributorWizard} from "./ProviderContributorWizard"; +import {HaProviderConfig} from "./ha-provider-config"; +import {DisplayBindingProviderConfig} from "./display-binding-provider-config"; +import {HaWizard} from "./ha-wizard"; +import {WebAppSecurityProviderConfig} from "./webappsec-provider-config"; +import {OIDCProviderConfig} from "./oidc-provider-config"; +import {JWTProviderConfig} from "./jwt-provider-config"; +import {SAMLProviderConfig} from "./saml-provider-config"; +import {OAUTHProviderConfig} from "./oauth-provider-config"; +import {PreAuthSSOProviderConfig} from "./preauth-sso-provider-config"; +import {AuthenticationProviderConfig} from "./authentication-provider-config"; +import {AuthenticationWizard} from "./authentication-wizard"; +import {CASProviderConfig} from "./cas-provider-config"; +import {SSOCookieProviderConfig} from "./sso-cookie-provider-config"; +import {LDAPProviderConfig} from "./ldap-provider-config"; +import {PAMProviderConfig} from "./pam-provider-config"; +import {AnonymousProviderConfig} from "./AnonymousProviderConfig"; +import {KerberosProviderConfig} from "./kerberos-provider-config"; +import {CSRFProviderConfig} from "./csrf-provider-config"; +import {CORSProviderConfig} from "./cors-provider-config"; +import {WebAppSecurityContributor} from "./webappsec-contributor"; +import {STSProviderConfig} from "./sts-provider-config"; +import {XFrameOptionsProviderConfig} from "./xframeoptions-provider-config"; + +export class WebAppSecurityWizard extends CategoryWizard implements ProviderContributorWizard { + + private stepCount: number = 4; + + // WebAppSec provider types + private static CSRF: string = 'Cross-Site Request Forgery'; + private static CORS: string = 'Cross-Origin Resource Sharing'; + private static XFRAME: string = 'X-Frame-Options'; + private static STS: string = 'Strict Transport Security'; + + private static webAppSecTypes: string[] = [ WebAppSecurityWizard.CSRF, + WebAppSecurityWizard.CORS, + WebAppSecurityWizard.XFRAME, + WebAppSecurityWizard.STS + ] + + private static typeConfigMap: Map<string, typeof WebAppSecurityContributor> = + new Map([ + [WebAppSecurityWizard.CSRF, CSRFProviderConfig], + [WebAppSecurityWizard.CORS, CORSProviderConfig], + [WebAppSecurityWizard.XFRAME, XFrameOptionsProviderConfig], + [WebAppSecurityWizard.STS, STSProviderConfig] + ] as [string, typeof WebAppSecurityContributor][]); + + + getTypes(): string[] { + return WebAppSecurityWizard.webAppSecTypes; + } + + getSteps(): number { + return this.stepCount; + } + + onChange() { + let configType = WebAppSecurityWizard.typeConfigMap.get(this.selectedType); + if (configType) { + this.providerConfig = Object.create(configType.prototype) as WebAppSecurityContributor; + this.providerConfig.constructor.apply(this.providerConfig); + (this.providerConfig as WebAppSecurityContributor).setType(this.selectedType); + } else { + console.debug('WebAppSecurityWizard --> No provider configuration type mapped for ' + this.selectedType); + this.providerConfig = null; + } + } + + getProviderConfig(): ProviderConfig { + return (this.providerConfig as WebAppSecurityProviderConfig); + } + + getProviderRole(): string { + return 'webappsec'; + } + + createNewProviderConfig(): ProviderConfig { + return new WebAppSecurityProviderConfig(); + } + + contribute(target: ProviderConfig) { + for (let paramName in this.providerConfig.params) { + (target as DisplayBindingProviderConfig).setParam(paramName, + (this.providerConfig as DisplayBindingProviderConfig).getParam(paramName)); + } + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/provider-config-wizard/xframeoptions-provider-config.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/provider-config-wizard/xframeoptions-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/xframeoptions-provider-config.ts new file mode 100644 index 0000000..900e4d4 --- /dev/null +++ b/gateway-admin-ui/src/app/provider-config-wizard/xframeoptions-provider-config.ts @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 {WebAppSecurityContributor} from "./webappsec-contributor"; + +export class XFrameOptionsProviderConfig extends WebAppSecurityContributor { + + public static TYPE: string = 'cors'; + + public static VALUE: string = 'X-Frame-Options Header'; // DENY, SAMEORIGIN, ALLOW-FROM + + private static SUPPORTED_VALUES: string[] = ['DENY', 'SAMEORIGIN', 'ALLOW-FROM']; + + private static displayPropertyNames = [ XFrameOptionsProviderConfig.VALUE ]; + + private static displayPropertyNameBindings: Map<string, string> = + new Map([ [XFrameOptionsProviderConfig.VALUE, 'xframe-options.value'] ] as [string, string][]); + + constructor() { + super(); + // Set the default values + this.setParam('xframe-options.enabled', 'true'); + this.setParam(XFrameOptionsProviderConfig.displayPropertyNameBindings.get(XFrameOptionsProviderConfig.VALUE), 'DENY'); + } + + getDisplayPropertyNames(): string[] { + return XFrameOptionsProviderConfig.displayPropertyNames; + } + + getDisplayNamePropertyBinding(name: string): string { + return XFrameOptionsProviderConfig.displayPropertyNameBindings.get(name); + } + + isValidParamValue(paramName: string): boolean { + let isValid: boolean = true; + + let value = this.getParam(this.getDisplayNamePropertyBinding(paramName)); + if (value) { + switch (paramName) { + case XFrameOptionsProviderConfig.VALUE: + value = value.trim().toUpperCase(); + isValid = XFrameOptionsProviderConfig.SUPPORTED_VALUES.includes(value); + break; + default: + } + } + + return isValid; + } + +} + http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-admin-ui/src/app/utils/validation-utils.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/utils/validation-utils.ts b/gateway-admin-ui/src/app/utils/validation-utils.ts index a3f1707..0239b72 100644 --- a/gateway-admin-ui/src/app/utils/validation-utils.ts +++ b/gateway-admin-ui/src/app/utils/validation-utils.ts @@ -63,12 +63,15 @@ export class ValidationUtils { private static PRINCIPAL_MAPPING_REGEXP = new RegExp('^(?:(?:[a-zA-Z\\*]+[\\,]?)+=[a-zA-Z]+[;]?)*$'); + private static SIGNED_NUMBER_REGEP = new RegExp('^-?\\d+$'); + static LDAP_URL_SCHEMES: string[] = [ 'ldap', 'ldaps' ]; static HTTP_URL_SCHEMES: string[] = [ 'http', 'https' ]; static CAS_PROTOCOLS: string[] = [ 'CAS10', 'CAS20', 'CAS20_PROXY', 'CAS30', 'CAS30_PROXY', 'SAML' ]; + static HTTP_METHODS: string[] = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'CONNECT']; static parseBoolean(value: string): boolean { let parsed: boolean; @@ -92,6 +95,9 @@ export class ValidationUtils { return (value && !isNaN(Number(value))); } + static isValidSignedNumber(value: string): boolean { + return ValidationUtils.SIGNED_NUMBER_REGEP.test(value); + } static isValidBoolean(value: string): boolean { return (ValidationUtils.parseBoolean(value) !== undefined); @@ -184,4 +190,9 @@ export class ValidationUtils { return isValid; } + + static isValidHTTPMethod(method: string): boolean { + return ValidationUtils.HTTP_METHODS.includes(method); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-applications/src/main/resources/applications/admin-ui/app/index.html ---------------------------------------------------------------------- diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/index.html b/gateway-applications/src/main/resources/applications/admin-ui/app/index.html index 368348e..eec4cb7 100644 --- a/gateway-applications/src/main/resources/applications/admin-ui/app/index.html +++ b/gateway-applications/src/main/resources/applications/admin-ui/app/index.html @@ -11,4 +11,4 @@ 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. ---><!doctype html><html><head><meta charset="utf-8"><title>Apache Knox Manager</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1"><!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><!-- Custom styles for this template --><link href="assets/sticky-footer.css" rel="stylesheet"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script><!-- Latest compiled and minified JavaScript --><scr ipt src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><script src="assets/vkbeautify.js"></script><link href="styles.2ee5b7f4cd59a6cf015e.bundle.css" rel="stylesheet"/></head><body><div class="navbar-wrapper"><div class="container-fluid"><nav class="navbar navbar-inverse navbar-static-top"><div class="container-fluid"><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span></button> <a class="navbar-brand" href="#"><img style="max-width:200px; margin-top: -9px;" src="assets/knox-logo-transparent.gif" alt="Apache Knox Manager"></a></div></div></nav></div><!-- Content --><resource-management></res ource-management><footer class="footer"><div class="container-fluid"><div>Knox Manager Version 1.0.0</div><gateway-version></gateway-version></div></footer><script type="text/javascript" src="inline.45a383ca05ad5b8aeba5.bundle.js"></script><script type="text/javascript" src="scripts.c50bb762c438ae0f8842.bundle.js"></script><script type="text/javascript" src="main.5a33727bde77ca75fd8c.bundle.js"></script></div></body></html> \ No newline at end of file +--><!doctype html><html><head><meta charset="utf-8"><title>Apache Knox Manager</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1"><!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><!-- Custom styles for this template --><link href="assets/sticky-footer.css" rel="stylesheet"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script><!-- Latest compiled and minified JavaScript --><scr ipt src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><script src="assets/vkbeautify.js"></script><link href="styles.2ee5b7f4cd59a6cf015e.bundle.css" rel="stylesheet"/></head><body><div class="navbar-wrapper"><div class="container-fluid"><nav class="navbar navbar-inverse navbar-static-top"><div class="container-fluid"><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span></button> <a class="navbar-brand" href="#"><img style="max-width:200px; margin-top: -9px;" src="assets/knox-logo-transparent.gif" alt="Apache Knox Manager"></a></div></div></nav></div><!-- Content --><resource-management></res ource-management><footer class="footer"><div class="container-fluid"><div>Knox Manager Version 1.0.0</div><gateway-version></gateway-version></div></footer><script type="text/javascript" src="inline.9b86d6e943bbedc3c3a9.bundle.js"></script><script type="text/javascript" src="scripts.c50bb762c438ae0f8842.bundle.js"></script><script type="text/javascript" src="main.e16062311693b0626855.bundle.js"></script></div></body></html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-applications/src/main/resources/applications/admin-ui/app/inline.45a383ca05ad5b8aeba5.bundle.js ---------------------------------------------------------------------- diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.45a383ca05ad5b8aeba5.bundle.js b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.45a383ca05ad5b8aeba5.bundle.js deleted file mode 100644 index a42746c..0000000 --- a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.45a383ca05ad5b8aeba5.bundle.js +++ /dev/null @@ -1 +0,0 @@ -!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,a){for(var u,i,f,l=0,s=[];l<r.length;l++)t[i=r[l]]&&s.push(t[i][0]),t[i]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(n&&n(r,c,a);s.length;)s.shift()();if(a)for(l=0;l<a.length;l++)f=o(o.s=a[l]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName("head")[0],a=document.createElement("script");a.type="text/javascript",a.charset="utf-8",a.async=!0,a.timeout=12e4,o.nc&&a.setAttribute("nonce",o.nc),a.src=o.p+""+e+"."+{0:"5a33727bde77ca75fd8c",1:"aed76669724804835353"}[e]+".chunk.js";var u=setTimeout(i,12e4);function i(){a.onerror=a.onload=null,clearTimeout(u);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chu nk "+e+" failed.")),t[e]=void 0)}return a.onerror=a.onload=i,c.appendChild(a),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw console.error(e),e}}([]); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/knox/blob/9925a637/gateway-applications/src/main/resources/applications/admin-ui/app/inline.9b86d6e943bbedc3c3a9.bundle.js ---------------------------------------------------------------------- diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.9b86d6e943bbedc3c3a9.bundle.js b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.9b86d6e943bbedc3c3a9.bundle.js new file mode 100644 index 0000000..d489f1e --- /dev/null +++ b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.9b86d6e943bbedc3c3a9.bundle.js @@ -0,0 +1 @@ +!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,l=0,s=[];l<r.length;l++)t[i=r[l]]&&s.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=o(o.s=u[l]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute("nonce",o.nc),u.src=o.p+""+e+"."+{0:"e16062311693b0626855",1:"aed76669724804835353"}[e]+".chunk.js";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chu nk "+e+" failed.")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw console.error(e),e}}([]); \ No newline at end of file
