f4ce592f76ef8db2068a0679bc9db7f2ab6b5948
[dcaegen2/collectors/hv-ves.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * dcaegen2-collectors-veshv
4  * ================================================================================
5  * Copyright (C) 2019 NOKIA
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.onap.dcae.collectors.veshv.config.impl
21
22 import arrow.core.None
23 import arrow.core.Option
24 import arrow.core.Some
25 import arrow.core.getOrElse
26 import arrow.core.toOption
27 import org.onap.dcae.collectors.veshv.config.api.model.CbsConfiguration
28 import org.onap.dcae.collectors.veshv.config.api.model.CollectorConfiguration
29 import org.onap.dcae.collectors.veshv.config.api.model.HvVesConfiguration
30 import org.onap.dcae.collectors.veshv.config.api.model.Route
31 import org.onap.dcae.collectors.veshv.config.api.model.ServerConfiguration
32 import org.onap.dcae.collectors.veshv.config.api.model.ValidationException
33 import org.onap.dcae.collectors.veshv.ssl.boundary.SecurityConfiguration
34 import org.onap.dcae.collectors.veshv.utils.arrow.OptionUtils.binding
35 import org.onap.dcae.collectors.veshv.utils.arrow.doOnEmpty
36 import org.onap.dcae.collectors.veshv.utils.arrow.mapBinding
37 import org.onap.dcae.collectors.veshv.utils.logging.LogLevel
38 import org.onap.dcae.collectors.veshv.utils.logging.Logger
39 import org.onap.dcaegen2.services.sdk.security.ssl.ImmutableSecurityKeys
40 import org.onap.dcaegen2.services.sdk.security.ssl.ImmutableSecurityKeysStore
41 import org.onap.dcaegen2.services.sdk.security.ssl.Passwords
42 import java.io.File
43 import java.nio.file.Path
44 import java.time.Duration
45
46 /**
47  * @author Jakub Dudycz <jakub.dudycz@nokia.com>
48  * @since March 2019
49  */
50 internal class ConfigurationValidator {
51
52     fun validate(partialConfig: PartialConfiguration) =
53             logger.info { "About to validate configuration: $partialConfig" }.let {
54                 binding {
55                     val logLevel = determineLogLevel(partialConfig.logLevel)
56
57                     val serverConfiguration = validatedServerConfiguration(partialConfig)
58                             .doOnEmpty { logger.debug { "Cannot bind server configuration" } }
59                             .bind()
60
61                     val cbsConfiguration = validatedCbsConfiguration(partialConfig)
62                             .doOnEmpty { logger.debug { "Cannot bind cbs configuration" } }
63                             .bind()
64
65                     val securityConfiguration = determineSecurityConfiguration(partialConfig)
66                             .doOnEmpty { logger.debug { "Cannot bind security configuration" } }
67                             .bind()
68
69                     val collectorConfiguration = validatedCollectorConfig(partialConfig)
70                             .doOnEmpty { logger.debug { "Cannot bind collector configuration" } }
71                             .bind()
72
73                     HvVesConfiguration(
74                             serverConfiguration,
75                             cbsConfiguration,
76                             securityConfiguration,
77                             collectorConfiguration,
78                             logLevel
79                     )
80                 }.toEither { ValidationException("Some required configuration options are missing") }
81             }
82
83
84     private fun determineLogLevel(logLevel: Option<LogLevel>) =
85             logLevel.getOrElse {
86                 logger.warn {
87                     "Missing or invalid \"logLevel\" field. " +
88                             "Using default log level ($DEFAULT_LOG_LEVEL)"
89                 }
90                 DEFAULT_LOG_LEVEL
91             }
92
93     private fun validatedServerConfiguration(partial: PartialConfiguration) =
94             partial.mapBinding {
95                 ServerConfiguration(
96                         it.listenPort.bind(),
97                         Duration.ofSeconds(it.idleTimeoutSec.bind())
98                 )
99             }
100
101     internal fun validatedCbsConfiguration(partial: PartialConfiguration) =
102             partial.mapBinding {
103                 CbsConfiguration(
104                         Duration.ofSeconds(it.firstRequestDelaySec.bind()),
105                         Duration.ofSeconds(it.requestIntervalSec.bind())
106                 )
107             }
108
109     private fun determineSecurityConfiguration(partial: PartialConfiguration) =
110             partial.sslDisable.fold({ createSecurityConfiguration(partial) }, { sslDisabled ->
111                 if (sslDisabled) {
112                     Some(SecurityConfiguration(None))
113                 } else {
114                     createSecurityConfiguration(partial)
115                 }
116             })
117
118     private fun createSecurityConfiguration(partial: PartialConfiguration): Option<SecurityConfiguration> =
119             partial.mapBinding {
120                 SecurityConfiguration(
121                         createSecurityKeys(
122                                 File(it.keyStoreFile.bind()).toPath(),
123                                 File(it.keyStorePasswordFile.bind()).toPath(),
124                                 File(it.trustStoreFile.bind()).toPath(),
125                                 File(it.trustStorePasswordFile.bind()).toPath()
126                         ).toOption()
127                 )
128             }
129
130     private fun createSecurityKeys(keyStorePath: Path,
131                                    keyStorePasswordPath: Path,
132                                    trustStorePath: Path,
133                                    trustStorePasswordPath: Path) =
134             ImmutableSecurityKeys.builder()
135                     .keyStore(ImmutableSecurityKeysStore.of(keyStorePath))
136                     .keyStorePassword(Passwords.fromPath(keyStorePasswordPath))
137                     .trustStore(ImmutableSecurityKeysStore.of(trustStorePath))
138                     .trustStorePassword(Passwords.fromPath(trustStorePasswordPath))
139                     .build()
140
141     private fun validatedCollectorConfig(partial: PartialConfiguration) =
142             partial.mapBinding { config ->
143                 CollectorConfiguration(
144                         config.streamPublishers.bind().map { Route(it.name(), it) }
145                 )
146             }
147
148     companion object {
149         val DEFAULT_LOG_LEVEL = LogLevel.INFO
150         private val logger = Logger(ConfigurationValidator::class)
151     }
152 }