```
STEPS FOR SETUP/TEST
1) Get the VESCollector image from Nexus
- docker pull nexus.onap.org:10001/onap/org.onap.dcaegen2.collectors.ves.vescollector:1.1
+ docker pull nexus.onap.org:10001/onap/org.onap.dcaegen2.collectors.ves.vescollector:latest
2) Start the container (change the DMAAPHOST environment value to running DMAAP instance host)
docker run -d -p 8080:8080/tcp -p 8443:8443/tcp -P -e DMAAPHOST='10.0.0.174' nexus.onap.org:10001/onap/org.onap.dcaegen2.collectors.ves.vescollector:1.1
3) Login into container and tail /opt/app/VESCollector/logs/collector.log
6) When test is done – do ensure to remove the container (docker rm -f <containerid>) to avoid port conflict
```
-Authentication is disabled on the container by default; below are the steps for enabling HTTPS/authentication for VESCollector.
+Authentication is set by default to "noauth" (via auth.method property) on the container; below are the steps for enabling HTTPS/authentication for VESCollector.
```
1) Login to the container
2) Open /opt/app/VESCollector/etc/collector.properties and edit below properties
a) Comment below property (with authentication enabled, standard http should be disabled)
collector.service.port=8080
- b) Enable basic-authentication
- header.authflag=1
+ b) Enable basic-authentication
+ auth.method=basicAuth
Note: The actual credentials is stored part of header.authlist parameter. This is list of userid,password values. Default configuration has below set
sample1,$2a$10$pgjaxDzSuc6XVFEeqvxQ5u90DKJnM/u7TJTcinAlFJVaavXMWf/Zi|vdnsagg,$2a$10$C45JhiRSY.qXTBfzWST3Q.AmwKlPRMc67c33O0U9hOH8KSGaweN4m
where password maps to same value as username.
3) Restart the collector
cd /opt/app/VESCollector
./bin/appController.sh stop
- ./bin/appController.sh start
+ ./bin/appController.sh start
4) Exit from container and ensure tcp port on VM is not hanging on finwait – you can execute “netstat -an | grep 8443” . If under FIN_WAIT2, wait for server to release.
-5) Simulate via curl (Note - username/pwd will be required)
- Example of successfull POST:
+5) Simulate via curl (Note - username/pwd will be required)
+ Example of successfull POST:
vv770d@osdcae-dev-16:~$ curl -i -u 'sample1:sample1' -X POST -d @volte.txt --header "Content-Type: application/json" https://localhost:8443/eventListener/v5 -k
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
2) Open /opt/app/VESCollector/etc/collector.properties and edit below properties
a) Comment below property (with authentication enabled, standard http should be disabled)
collector.service.port=8080
- b) Enable a client's certificate verification
- collector.service.secure.clientauth=1
+ b) Enable a client's certificate verification
+ auth.method=certOnly (only certificate verification)
+ or
+ auth.method=certBasicAuth ( certificate verification with basic auth verification )
3) Restart the collector
cd /opt/app/VESCollector
./bin/appController.sh stop
collector.service.secure.port: -1
tomcat.maxthreads: '200'
collector.keystore.file.location: "/opt/app/dcae-certificate/keystore.jks"
- header.authflag: 0
+ auth.method: "noAuth"
collector.service.port: 8080
streams_publishes:
sec_fault_unsecure:
"parameters": [
{
"name": "collector.service.port",
- "value": -1,
- "description": "standard http port collector will open for listening; this will be disabled when header.authflag is set to 1",
+ "value": 8080,
+ "description": "standard http port collector will open for listening;",
"sourced_at_deployment": false,
"policy_editable": false,
"designer_editable": false
"policy_editable": false,
"designer_editable": true
},
- {
- "name": "collector.service.secure.clientauth",
- "value": 0,
- "description": "Mutual TLS authentication flag; enables an authentication of the client to the server",
- "sourced_at_deployment": false,
- "policy_editable": false,
- "designer_editable": false
- },
{
"name": "collector.keystore.file.location",
"value": "/opt/app/dcae-certificate/keystore.jks",
"designer_editable": false
},
{
- "name": "header.authflag",
- "value": 1,
+ "name": "auth.method",
+ "value": "noAuth",
"description": "Basic Authentication flag; when enabled only secure port will be supported.",
"sourced_at_deployment": false,
"policy_editable": false,
type: string
docker_collector.service.secure.port:
type: string
- docker_header.authflag:
+ docker_auth.method:
type: string
docker_header.authlist:
type: string
docker_collector.schema.file: ./etc/CommonEventFormat_27.2.json
docker_collector.service.port: '8080'
docker_collector.service.secure.port: '-1'
- docker_header.authflag: '0'
+ docker_auth.method: noAuth
docker_header.authlist: userid1,base64encodepwd1|userid2,base64encodepwd2
docker_tomcat.maxthreads: '200'
location_id:
type: string
docker_collector.service.secure.port:
type: string
- docker_header.authflag:
+ docker_auth.method:
type: string
docker_header.authlist:
type: string
get_input: docker_collector.service.port
collector.service.secure.port:
get_input: docker_collector.service.secure.port
- header.authflag:
- get_input: docker_header.authflag
+ auth.method:
+ get_input: docker_auth.method
header.authlist:
get_input: docker_header.authlist
tomcat.maxthreads:
## Normally:\r
##\r
## - 8080 is http service\r
-## - https is disabled by default (-1)\r
+## - https is disabled by default\r
##\r
## - At this time, the server always binds to 0.0.0.0\r
##\r
-## The default port when header.authflag is disabled (0)\r
+##\r
collector.service.port=8080\r
\r
-## The secure port is required if header.authflag is set to 1 (true)\r
## Authentication is only supported via secure port\r
## When enabled - require valid keystore defined\r
collector.service.secure.port=8443\r
\r
-collector.service.secure.clientauth=0\r
+# auth.method flags:\r
+#\r
+# noAuth - default option - no security (http)\r
+# certOnly - auth by certificate (https)\r
+# basicAuth - auth by basic auth username and password (https)\r
+# certBasicAuth - auth by certificate and basic auth username / password (https)\r
+auth.method=noAuth\r
+\r
+## Combination of userid,hashPassword encoded pwd list to be supported\r
+## userid and pwd comma separated; pipe delimitation between each pair\r
+## Password is generated by crypt-password library using BCrypt algorithm stored in dcaegen2/sdk package\r
+## or https://nexus.onap.org/#nexus-search;quick~crypt-password\r
+header.authlist=sample1,$2a$10$0buh.2WeYwN868YMwnNNEuNEAMNYVU9.FSMJGyIKV3dGET/7oGOi6\r
\r
## The keystore must be setup per installation when secure port is configured\r
collector.keystore.file.location=etc/keystore\r
collector.truststore.file.location=etc/truststore\r
collector.truststore.passwordfile=etc/trustpasswordfile\r
\r
-###############################################################################\r
## Processing\r
##\r
## If there's a problem that prevents the collector from processing alarms,\r
collector.dmaap.streamid=fault=ves-fault|syslog=ves-syslog|heartbeat=ves-heartbeat|measurementsForVfScaling=ves-measurement|mobileFlow=ves-mobileflow|other=ves-other|stateChange=ves-statechange|thresholdCrossingAlert=ves-thresholdCrossingAlert|voiceQuality=ves-voicequality|sipSignaling=ves-sipsignaling|notification=ves-notification|pnfRegistration=ves-pnfRegistration\r
collector.dmaapfile=./etc/DmaapConfig.json\r
\r
-## authflag control authentication by the collector\r
-## If enabled (1) - then authlist has to be defined\r
-## When authflag is enabled, only secure port will be supported\r
-## To disable enter 0\r
-header.authflag=0\r
-\r
-## Combination of userid,hashPassword encoded pwd list to be supported\r
-## userid and pwd comma separated; pipe delimitation between each pair\r
-header.authlist=sample1,$2a$10$0buh.2WeYwN868YMwnNNEuNEAMNYVU9.FSMJGyIKV3dGET/7oGOi6\r
-\r
## Event transformation Flag - when set expects configurable transformation\r
## defined under ./etc/eventTransform.json\r
## Enabled by default; to disable set to 0\r
event.transform.flag=1\r
\r
# Describes at what frequency (measured in minutes) should application try to fetch config from CBS\r
-collector.dynamic.config.update.frequency=5\r
-\r
-###############################################################################\r
-##\r
-## Tomcat control\r
-##\r
-#tomcat.maxthreads=(tomcat default, which is usually 200)\r
-\r
+collector.dynamic.config.update.frequency=5
\ No newline at end of file
</parent>\r
<groupId>org.onap.dcaegen2.collectors.ves</groupId>\r
<artifactId>VESCollector</artifactId>\r
- <version>1.4.2-SNAPSHOT</version>\r
+ <version>1.4.3-SNAPSHOT</version>\r
<name>dcaegen2-collectors-ves</name>\r
<description>VESCollector</description>\r
<properties>\r
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.json.JSONObject;
+import org.onap.dcae.common.configuration.AuthMethodType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
return properties.getInt("collector.schema.checkflag", -1) > 0;
}
- public boolean authorizationEnabled() {
- return properties.getInt("header.authflag", 0) > 0;
- }
-
public JsonSchema jsonSchema(String version) {
return loadedJsonSchemas.get(version)
.orElse(loadedJsonSchemas.get(FALLBACK_VES_VERSION))
return prependWithUserDirOnRelative(properties.getString("collector.keystore.file.location", "etc/keystore"));
}
- public boolean clientTlsAuthenticationEnabled() {
- return httpsEnabled() && properties.getInt("collector.service.secure.clientauth", 0) > 0;
- }
-
public String truststorePasswordFileLocation() {
return prependWithUserDirOnRelative(properties.getString("collector.truststore.passwordfile", "etc/trustpasswordfile"));
}
return prependWithUserDirOnRelative(properties.getString("collector.dmaapfile", "etc/DmaapConfig.json"));
}
+ public String authMethod(){
+ return properties.getString("auth.method", AuthMethodType.NO_AUTH.value());
+ }
+
public Map<String, String[]> dMaaPStreamsMapping() {
String streamIdsProperty = properties.getString("collector.dmaap.streamid", null);
if (streamIdsProperty == null) {
import java.nio.file.Path;
import org.springframework.boot.web.server.Ssl;
+import org.springframework.boot.web.server.Ssl.ClientAuth;
public class SSLContextCreator {
private final String keyStorePassword;
private Path trustStoreFile;
private String trustStorePassword;
private boolean hasTlsClientAuthentication = false;
+ private ClientAuth clientAuth;
public static SSLContextCreator create(final Path keyStoreFile, final String certAlias, final String password) {
return new SSLContextCreator(keyStoreFile, certAlias, password);
this.keyStorePassword = password;
}
- public SSLContextCreator withTlsClientAuthentication(final Path trustStoreFile, final String password) {
- hasTlsClientAuthentication = true;
+ public SSLContextCreator withTlsClientAuthentication(final Path trustStoreFile, final String password, final ClientAuth clientAuth) {
+ this.clientAuth = clientAuth;
+ this.hasTlsClientAuthentication = true;
this.trustStoreFile = trustStoreFile;
this.trustStorePassword = password;
ssl.setTrustStore(trustStore);
ssl.setTrustStorePassword(trustStorePassword);
- ssl.setClientAuth(Ssl.ClientAuth.NEED);
+ ssl.setClientAuth(clientAuth);
}
public Ssl build() {
if (hasTlsClientAuthentication) {
configureTrustStore(ssl);
}
-
return ssl;
}
}
\ No newline at end of file
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018 Nokia. All rights reserved.s
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.common.configuration;
+
+public interface AuthMethod {
+ void configure();
+}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018 Nokia. All rights reserved.s
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.common.configuration;
+
+public enum AuthMethodType {
+
+ NO_AUTH("noAuth"),CERT_ONLY("certOnly"),CERT_BASIC_AUTH("certBasicAuth"),BASIC_AUTH("basicAuth");
+
+ private final String value;
+
+ AuthMethodType(String value) {
+ this.value = value;
+ }
+
+ public String value() {
+ return value;
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018 Nokia. All rights reserved.s
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.common.configuration;
+
+import org.onap.dcae.ApplicationSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
+
+public class BasicAuth implements AuthMethod {
+
+ private static final Logger log = LoggerFactory.getLogger(BasicAuth.class);
+ private final ConfigurableServletWebServerFactory container;
+ private final ApplicationSettings properties;
+
+ public BasicAuth(ConfigurableServletWebServerFactory container, ApplicationSettings properties) {
+ this.container = container;
+ this.properties = properties;
+ }
+
+ @Override
+ public void configure() {
+ SslContextCreator sslContextCreator = new SslContextCreator(properties);
+ container.setPort(properties.httpsPort());
+ container.setSsl(sslContextCreator.simpleHttpsContext());
+ log.info(String.format("Application work in %s mode on %s port.",
+ properties.authMethod(), properties.httpsPort()));
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018 Nokia. All rights reserved.s
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.common.configuration;
+
+import org.onap.dcae.ApplicationSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.server.Ssl.ClientAuth;
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
+
+public class CertAuth implements AuthMethod {
+
+ private static final Logger log = LoggerFactory.getLogger(CertAuth.class);
+ private final ConfigurableServletWebServerFactory container;
+ private final ApplicationSettings properties;
+
+ public CertAuth(ConfigurableServletWebServerFactory container, ApplicationSettings properties) {
+ this.container = container;
+ this.properties = properties;
+ }
+
+ @Override
+ public void configure() {
+ SslContextCreator sslContextCreator = new SslContextCreator(properties);
+ container.setSsl(sslContextCreator.httpsContextWithTlsAuthentication(ClientAuth.NEED));
+ container.setPort(properties.httpsPort());
+ log.info(String.format("Application work in %s mode on %s port.",
+ properties.authMethod(), properties.httpsPort()));
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018 Nokia. All rights reserved.s
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.common.configuration;
+
+import org.onap.dcae.ApplicationSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.server.Ssl.ClientAuth;
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
+
+public class CertBasicAuth implements AuthMethod{
+
+ private static final Logger log = LoggerFactory.getLogger(CertAuth.class);
+ private final ConfigurableServletWebServerFactory container;
+ private final ApplicationSettings properties;
+
+ public CertBasicAuth(ConfigurableServletWebServerFactory container, ApplicationSettings properties) {
+ this.container = container;
+ this.properties = properties;
+ }
+
+ @Override
+ public void configure() {
+ SslContextCreator sslContextCreator = new SslContextCreator(properties);
+ container.setPort(properties.httpsPort());
+ container.setSsl(sslContextCreator.httpsContextWithTlsAuthentication(ClientAuth.WANT));
+ log.info(String.format("Application work in %s mode on %s port.",
+ properties.authMethod(), properties.httpsPort()));
+ }
+}
+
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018 Nokia. All rights reserved.s
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.common.configuration;
+
+import org.onap.dcae.ApplicationSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
+
+public class NoAuth implements AuthMethod {
+
+ private static final Logger log = LoggerFactory.getLogger(NoAuth.class);
+
+ private final ConfigurableServletWebServerFactory container;
+ private final ApplicationSettings properties;
+
+ public NoAuth(ConfigurableServletWebServerFactory container, ApplicationSettings properties) {
+ this.container = container;
+ this.properties = properties;
+ }
+
+ @Override
+ public void configure() {
+ if (validateAuthMethod()){
+ container.setPort(properties.httpsPort());
+ logContainerConfiguration(properties.httpsPort());
+ }
+ else {
+ container.setPort(properties.httpPort());
+ logContainerConfiguration(properties.httpPort());
+ }
+ }
+
+ private boolean validateAuthMethod() {
+ return properties.authMethod().equalsIgnoreCase(AuthMethodType.BASIC_AUTH.value())
+ || properties.authMethod().equalsIgnoreCase(AuthMethodType.CERT_ONLY.value())
+ || properties.authMethod().equalsIgnoreCase(AuthMethodType.CERT_BASIC_AUTH.value());
+ }
+
+ private void logContainerConfiguration(int port) {
+ log.info(String.format("Application work in %s mode on %s port.", properties.authMethod(), port));
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018 Nokia. All rights reserved.s
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.common.configuration;
+
+import static java.nio.file.Files.readAllBytes;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import org.onap.dcae.ApplicationException;
+import org.onap.dcae.ApplicationSettings;
+import org.onap.dcae.common.SSLContextCreator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.server.Ssl;
+import org.springframework.boot.web.server.Ssl.ClientAuth;
+
+public class SslContextCreator {
+
+ private static final Logger log = LoggerFactory.getLogger(CertAuth.class);
+ private final ApplicationSettings properties;
+
+ public SslContextCreator(ApplicationSettings properties) {
+ this.properties = properties;
+ }
+
+ public Ssl httpsContextWithTlsAuthentication(ClientAuth clientAuth) {
+ final SSLContextCreator sslContextCreator = simpleHttpsContextBuilder();
+
+ log.info("Enabling TLS client authorization");
+
+ final Path trustStore = toAbsolutePath(properties.truststoreFileLocation());
+ log.info("Using trustStore path: " + trustStore);
+
+ final Path trustPasswordFileLocation = toAbsolutePath(properties.truststorePasswordFileLocation());
+ final String trustStorePassword = getKeyStorePassword(trustPasswordFileLocation);
+ log.info("Using trustStore password from: " + trustPasswordFileLocation);
+
+ return sslContextCreator.withTlsClientAuthentication(trustStore, trustStorePassword, clientAuth).build();
+ }
+
+ public Ssl simpleHttpsContext(){
+ return simpleHttpsContextBuilder().build();
+ }
+
+ private SSLContextCreator simpleHttpsContextBuilder() {
+ log.info("Enabling SSL");
+
+ final Path keyStorePath = toAbsolutePath(properties.keystoreFileLocation());
+ log.info("Using keyStore path: " + keyStorePath);
+
+ final Path keyStorePasswordLocation = toAbsolutePath(properties.keystorePasswordFileLocation());
+ final String keyStorePassword = getKeyStorePassword(keyStorePasswordLocation);
+ log.info("Using keyStore password from: " + keyStorePasswordLocation);
+ return SSLContextCreator.create(keyStorePath, getKeyStoreAlias(keyStorePath, keyStorePassword), keyStorePassword);
+ }
+
+ private String getKeyStoreAlias(Path keyStorePath, String keyStorePassword) {
+ KeyStore keyStore = getKeyStore();
+ try(InputStream keyStoreData = new FileInputStream(keyStorePath.toString())){
+ keyStore.load(keyStoreData, keyStorePassword.toCharArray());
+ String alias = keyStore.aliases().nextElement();
+ log.info("Actual key store alias is: " + alias);
+ return alias;
+ } catch (IOException | GeneralSecurityException ex) {
+ log.error("Cannot load Key Store alias cause: " + ex);
+ throw new ApplicationException(ex);
+ }
+ }
+
+ private KeyStore getKeyStore() {
+ try {
+ return KeyStore.getInstance(KeyStore.getDefaultType());
+ } catch (KeyStoreException ex) {
+ log.error("Cannot create Key Store instance cause: " + ex);
+ throw new ApplicationException(ex);
+ }
+ }
+
+ private Path toAbsolutePath(final String path) {
+ return Paths.get(path).toAbsolutePath();
+ }
+
+ private String getKeyStorePassword(final Path location) {
+ try {
+ return new String(readAllBytes(location));
+ } catch (IOException e) {
+ log.error("Could not read keystore password from: '" + location + "'.", e);
+ throw new ApplicationException(e);
+ }
+ }
+}
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.onap.dcae.ApplicationSettings;
+import org.onap.dcae.common.configuration.AuthMethodType;
import org.onap.dcaegen2.services.sdk.security.CryptPassword;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(ApiAuthInterceptor.class);
private final CryptPassword cryptPassword = new CryptPassword();
- private final ApplicationSettings applicationSettings;
+ private final ApplicationSettings settings;
+ private Logger errorLogger;
- private Logger errorLog;
- ApiAuthInterceptor(ApplicationSettings applicationSettings, Logger errorLog) {
- this.applicationSettings = applicationSettings;
- this.errorLog = errorLog;
+ public ApiAuthInterceptor(ApplicationSettings applicationSettings, Logger errorLogger) {
+ this.settings = applicationSettings;
+ this.errorLogger = errorLogger;
}
@Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
- Object handler) throws IOException {
- if (applicationSettings.authorizationEnabled()) {
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws IOException {
+
+ if(settings.authMethod().equalsIgnoreCase(AuthMethodType.CERT_BASIC_AUTH.value())){
+ if (request.getAttribute("javax.servlet.request.X509Certificate") != null){
+ LOG.info("Request is authorized by certificate ");
+ return true;
+ }
+ }
+
+ if (isBasicAuth()) {
String authorizationHeader = request.getHeader("Authorization");
if (authorizationHeader == null || !isAuthorized(authorizationHeader)) {
- response.setStatus(400);
- errorLog.error("EVENT_RECEIPT_FAILURE: Unauthorized user");
+ response.setStatus(401);
+ errorLogger.error("EVENT_RECEIPT_FAILURE: Unauthorized user");
response.getWriter().write(ApiException.UNAUTHORIZED_USER.toJSON().toString());
return false;
}
+ LOG.info("Request is authorized by basic auth");
}
return true;
}
+ private boolean isBasicAuth() {
+ return settings.authMethod().equalsIgnoreCase(AuthMethodType.BASIC_AUTH.value())
+ || settings.authMethod().equalsIgnoreCase(AuthMethodType.CERT_BASIC_AUTH.value());
+ }
+
private boolean isAuthorized(String authorizationHeader) {
try {
String encodedData = authorizationHeader.split(" ")[1];
String decodedData = new String(Base64.getDecoder().decode(encodedData));
String providedUser = decodedData.split(":")[0].trim();
String providedPassword = decodedData.split(":")[1].trim();
- Option<String> maybeSavedPassword = applicationSettings.validAuthorizationCredentials().get(providedUser);
+ Option<String> maybeSavedPassword = settings.validAuthorizationCredentials().get(providedUser);
boolean userRegistered = maybeSavedPassword.isDefined();
return userRegistered && cryptPassword.matches(providedPassword,maybeSavedPassword.get());
} catch (Exception e) {
package org.onap.dcae.restapi;
-import static java.nio.file.Files.readAllBytes;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
+import java.util.HashMap;
+import java.util.Map;
import org.onap.dcae.ApplicationException;
import org.onap.dcae.ApplicationSettings;
-import org.onap.dcae.common.SSLContextCreator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.onap.dcae.common.configuration.AuthMethod;
+import org.onap.dcae.common.configuration.AuthMethodType;
+import org.onap.dcae.common.configuration.BasicAuth;
+import org.onap.dcae.common.configuration.CertAuth;
+import org.onap.dcae.common.configuration.CertBasicAuth;
+import org.onap.dcae.common.configuration.NoAuth;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.web.server.Ssl;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;
@Component
public class ServletConfig implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
- private static final Logger log = LoggerFactory.getLogger(ServletConfig.class);
-
@Autowired
private ApplicationSettings properties;
@Override
public void customize(ConfigurableServletWebServerFactory container) {
- final boolean hasClientTlsAuthentication = properties.clientTlsAuthenticationEnabled();
- if (hasClientTlsAuthentication || properties.authorizationEnabled()) {
- container.setSsl(hasClientTlsAuthentication ? httpsContextWithTlsAuthentication() : simpleHttpsContext());
- int port = properties.httpsPort();
- container.setPort(port);
- log.info("Application https port: " + port);
- } else {
- int port = properties.httpPort();
- container.setPort(port);
- log.info("Application http port: " + port);
- }
-
- }
-
- private SSLContextCreator simpleHttpsContextBuilder() {
- log.info("Enabling SSL");
-
- final Path keyStorePath = toAbsolutePath(properties.keystoreFileLocation());
- log.info("Using keyStore path: " + keyStorePath);
-
- final Path keyStorePasswordLocation = toAbsolutePath(properties.keystorePasswordFileLocation());
- final String keyStorePassword = getKeyStorePassword(keyStorePasswordLocation);
- log.info("Using keyStore password from: " + keyStorePasswordLocation);
- return SSLContextCreator.create(keyStorePath, getKeyStoreAlias(keyStorePath, keyStorePassword), keyStorePassword);
- }
-
- private String getKeyStoreAlias(Path keyStorePath, String keyStorePassword) {
- KeyStore keyStore = getKeyStore();
- try(InputStream keyStoreData = new FileInputStream(keyStorePath.toString())){
- keyStore.load(keyStoreData, keyStorePassword.toCharArray());
- String alias = keyStore.aliases().nextElement();
- log.info("Actual key store alias is: " + alias);
- return alias;
- } catch (IOException | GeneralSecurityException ex) {
- log.error("Cannot load Key Store alias cause: " + ex);
- throw new ApplicationException(ex);
- }
- }
-
- private KeyStore getKeyStore() {
- try {
- return KeyStore.getInstance(KeyStore.getDefaultType());
- } catch (KeyStoreException ex) {
- log.error("Cannot create Key Store instance cause: " + ex);
- throw new ApplicationException(ex);
- }
- }
-
- private Ssl simpleHttpsContext() {
- return simpleHttpsContextBuilder().build();
- }
-
- private Ssl httpsContextWithTlsAuthentication() {
- final SSLContextCreator sslContextCreator = simpleHttpsContextBuilder();
-
- log.info("Enabling TLS client authorization");
-
- final Path trustStore = toAbsolutePath(properties.truststoreFileLocation());
- log.info("Using trustStore path: " + trustStore);
-
- final Path trustPasswordFileLocation = toAbsolutePath(properties.truststorePasswordFileLocation());
- final String trustStorePassword = getKeyStorePassword(trustPasswordFileLocation);
- log.info("Using trustStore password from: " + trustPasswordFileLocation);
-
- return sslContextCreator.withTlsClientAuthentication(trustStore, trustStorePassword).build();
+ provideAuthConfigurations(container).getOrDefault(properties.authMethod(),
+ notSupportedOperation()).configure();
}
- private Path toAbsolutePath(final String path) {
- return Paths.get(path).toAbsolutePath();
+ private Map<String, AuthMethod> provideAuthConfigurations(ConfigurableServletWebServerFactory container) {
+ Map<String, AuthMethod> authMethods = new HashMap<>();
+ authMethods.put(AuthMethodType.CERT_ONLY.value(), new CertAuth(container, properties));
+ authMethods.put(AuthMethodType.BASIC_AUTH.value(), new BasicAuth(container, properties));
+ authMethods.put(AuthMethodType.CERT_BASIC_AUTH.value(), new CertBasicAuth(container, properties));
+ authMethods.put(AuthMethodType.NO_AUTH.value(), new NoAuth(container, properties));
+ return authMethods;
}
- private String getKeyStorePassword(final Path location) {
- try {
- return new String(readAllBytes(location));
- } catch (IOException e) {
- log.error("Could not read keystore password from: '" + location + "'.", e);
- throw new ApplicationException(e);
- }
+ private AuthMethod notSupportedOperation() {
+ return () -> {
+ throw new ApplicationException(
+ "Provided auth method not allowed: " + properties.authMethod());
+ };
}
}
\ No newline at end of file
assertEquals(dmaapStreamID, HashMap.empty());
}
- @Test
- public void shouldReturnIfAuthorizationIsEnabled() throws IOException {
- // when
- boolean authorizationEnabled = fromTemporaryConfiguration("header.authflag=1")
- .authorizationEnabled();
-
- // then
- assertTrue(authorizationEnabled);
- }
-
@Test
public void shouldAuthorizationBeDisabledByDefault() throws IOException {
// when
- boolean authorizationEnabled = fromTemporaryConfiguration().authorizationEnabled();
+ boolean authorizationEnabled = fromTemporaryConfiguration().authMethod().contains("noAuth");
// then
- assertFalse(authorizationEnabled);
+ assertTrue(authorizationEnabled);
}
@Test
import io.vavr.collection.HashMap;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
+import org.onap.dcae.common.configuration.AuthMethodType;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpStatus;
class HttpsWithTLSAuthenticationAndBasicAuthTest extends TestClassBase {
@Test
- public void shouldHttpsRequestWithoutBasicAuthFail() {
- assertThrows(Exception.class, this::makeHttpsRequestWithClientCert);
+ public void shouldHttpsRequestWithoutBasicAuthSucceed() {
+ assertEquals(HttpStatus.OK, makeHttpsRequestWithClientCert().getStatusCode());
}
@Test
static class HttpConfiguration extends TLSTestBase.ConfigurationBase {
@Override
protected void configureSettings(ApplicationSettings settings) {
+ when(settings.authMethod()).thenReturn(AuthMethodType.NO_AUTH.value());
}
}
protected void configureSettings(ApplicationSettings settings) {
when(settings.keystoreFileLocation()).thenReturn(KEYSTORE.toString());
when(settings.keystorePasswordFileLocation()).thenReturn(KEYSTORE_PASSWORD_FILE.toString());
- when(settings.authorizationEnabled()).thenReturn(true);
+ when(settings.authMethod()).thenReturn(AuthMethodType.BASIC_AUTH.value());
when(settings.validAuthorizationCredentials()).thenReturn(HashMap.of(USERNAME, "$2a$10$51tDgG2VNLde5E173Ay/YO.Fq.aD.LR2Rp8pY3QAKriOSPswvGviy"));
}
}
@Override
protected void configureSettings(ApplicationSettings settings) {
super.configureSettings(settings);
- when(settings.authorizationEnabled()).thenReturn(false);
- when(settings.clientTlsAuthenticationEnabled()).thenReturn(true);
+ when(settings.authMethod()).thenReturn(AuthMethodType.CERT_ONLY.value());
when(settings.truststoreFileLocation()).thenReturn(TRUSTSTORE.toString());
when(settings.truststorePasswordFileLocation()).thenReturn(TRUSTSTORE_PASSWORD_FILE.toString());
}
@Override
protected void configureSettings(ApplicationSettings settings) {
super.configureSettings(settings);
- when(settings.authorizationEnabled()).thenReturn(true);
+ when(settings.authMethod()).thenReturn(AuthMethodType.CERT_BASIC_AUTH.value());
}
}
-}
+}
\ No newline at end of file
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.onap.dcae.ApplicationSettings;
+import org.onap.dcae.common.configuration.AuthMethodType;
import org.slf4j.Logger;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
// given
final HttpServletRequest request = createEmptyRequest();
- when(settings.authorizationEnabled()).thenReturn(false);
+ when(settings.authMethod()).thenReturn(AuthMethodType.NO_AUTH.value());
// when
final boolean isAuthorized = sut.preHandle(request, response, obj);
// given
final HttpServletRequest request = createEmptyRequest();
- when(settings.authorizationEnabled()).thenReturn(true);
+ when(settings.authMethod()).thenReturn(AuthMethodType.BASIC_AUTH.value());
when(response.getWriter()).thenReturn(writer);
// when
// then
assertFalse(isAuthorized);
- verify(response).setStatus(HttpStatus.BAD_REQUEST.value());
+ verify(response).setStatus(HttpStatus.UNAUTHORIZED.value());
verify(writer).write(ApiException.UNAUTHORIZED_USER.toJSON().toString());
}
// given
final HttpServletRequest request = createRequestWithAuthorizationHeader();
- when(settings.authorizationEnabled()).thenReturn(true);
+ when(settings.authMethod()).thenReturn(AuthMethodType.BASIC_AUTH.value());
when(response.getWriter()).thenReturn(writer);
// when
// then
assertFalse(isAuthorized);
- verify(response).setStatus(HttpStatus.BAD_REQUEST.value());
+ verify(response).setStatus(HttpStatus.UNAUTHORIZED.value());
verify(writer).write(ApiException.UNAUTHORIZED_USER.toJSON().toString());
}
public void shouldSucceed() throws IOException {
// given
final HttpServletRequest request = createRequestWithAuthorizationHeader();
- when(settings.authorizationEnabled()).thenReturn(true);
+ when(settings.authMethod()).thenReturn(AuthMethodType.CERT_ONLY.value());
when(settings.validAuthorizationCredentials()).thenReturn(
HashMap.of(USERNAME, "$2a$10$BsZkEynNm/93wbAeeZuxJeu6IHRyQl4XReqDg2BtYOFDhUsz20.3G"));
when(response.getWriter()).thenReturn(writer);
.header(HttpHeaders.AUTHORIZATION, "FooBar")
.buildRequest(null);
- when(settings.authorizationEnabled()).thenReturn(true);
+ when(settings.authMethod()).thenReturn(AuthMethodType.BASIC_AUTH.value());
when(settings.validAuthorizationCredentials()).thenReturn(CREDENTIALS);
when(response.getWriter()).thenReturn(writer);
// then
assertFalse(isAuthorized);
- verify(response).setStatus(HttpStatus.BAD_REQUEST.value());
+ verify(response).setStatus(HttpStatus.UNAUTHORIZED.value());
verify(writer).write(ApiException.UNAUTHORIZED_USER.toJSON().toString());
}
}
{
- "header.authflag": 1,
+ "auth.method": "noAuth",
"collector.inputQueue.maxPending": 8096,
"collector.schema.checkflag": 1,
"collector.keystore.file.location": "/opt/app/dcae-certificate/keystore.jks",
{
- "header.authflag": "1",
+ "auth.method": "noAuth",
"collector.schema.file": "{\"v1\": \"./etc/CommonEventFormat_27.2.json\", \"v2\": \"./etc/CommonEventFormat_27.2.json\", \"v3\": \"./etc/CommonEventFormat_27.2.json\", \"v4\": \"./etc/CommonEventFormat_27.2.json\", \"v5\": \"./etc/CommonEventFormat_28.4.json\"}",
"collector.keystore.passwordfile": "/opt/app/dcae-certificate/.password",
"tomcat.maxthreads": "200",
collector.schema.file={\"v1\":\"./etc/CommonEventFormat_27.2.json\",\"v2\":\"./etc/CommonEventFormat_27.2.json\",\"v3\":\"./etc/CommonEventFormat_27.2.json\",\"v4\":\"./etc/CommonEventFormat_27.2.json\",\"v5\":\"./etc/CommonEventFormat_28.4.json\"}
collector.dmaap.streamid=fault=ves-fault,ves-fault-secondary|syslog=ves-syslog,ves-syslog-secondary|heartbeat=ves-heartbeat,ves-heartbeat-secondary|measurementsForVfScaling=ves-measurement,ves-measurement-secondary|mobileFlow=ves-mobileflow,ves-mobileflow-secondary|other=ves-other,ves-other-secondary|stateChange=ves-statechange,ves-statechange-secondary|thresholdCrossingAlert=ves-thresholdCrossingAlert,ves-thresholdCrossingAlert-secondary|voiceQuality=ves-voicequality,ves-voicequality-secondary|sipSignaling=ves-sipsignaling,ves-sipsignaling-secondary
collector.dmaapfile=./etc/DmaapConfig.json
-header.authflag=1
+auth.method=noAuth
header.authlist=sample1,$2a$10$pgjaxDzSuc6XVFEeqvxQ5u90DKJnM/u7TJTcinAlFJVaavXMWf/Zi|userid1,$2a$10$61gNubgJJl9lh3nvQvY9X.x4e5ETWJJ7ao7ZhJEvmfJigov26Z6uq|userid2,$2a$10$G52y/3uhuhWAMy.bx9Se8uzWinmbJa.dlm1LW6bYPdPkkywLDPLiy
event.transform.flag=1
collector.inputQueue.maxPending = 8096
collector.schema.file={\"v1\":\"./etc/CommonEventFormat_27.2.json\",\"v2\":\"./etc/CommonEventFormat_27.2.json\",\"v3\":\"./etc/CommonEventFormat_27.2.json\",\"v4\":\"./etc/CommonEventFormat_27.2.json\",\"v5\":\"./etc/CommonEventFormat_28.4.json\"}\r
collector.dmaap.streamid=fault=sec_fault|syslog=sec_syslog|heartbeat=sec_heartbeat|measurementsForVfScaling=sec_measurement|mobileFlow=sec_mobileflow|other=sec_other|stateChange=sec_statechange|thresholdCrossingAlert=sec_thresholdCrossingAlert|voiceQuality=ves_voicequality|sipSignaling=ves_sipsignaling\r
collector.dmaapfile=./etc/DmaapConfig.json\r
-header.authflag=1\r
+auth.method=noAuth\r
header.authlist=sample1,$2a$10$pgjaxDzSuc6XVFEeqvxQ5u90DKJnM/u7TJTcinAlFJVaavXMWf/Zi|userid1,$2a$10$61gNubgJJl9lh3nvQvY9X.x4e5ETWJJ7ao7ZhJEvmfJigov26Z6uq|userid2,$2a$10$G52y/3uhuhWAMy.bx9Se8uzWinmbJa.dlm1LW6bYPdPkkywLDPLiy\r
event.transform.flag=1\r
\r
major=1
minor=4
-patch=2
+patch=3
base_version=${major}.${minor}.${patch}
release_version=${base_version}
snapshot_version=${base_version}-SNAPSHOT