From 7a45a7cc88a7de29e1acdc0174b7b6aa7a37af57 Mon Sep 17 00:00:00 2001 From: Piotr Limanowski Date: Wed, 3 Jan 2024 11:39:46 +0100 Subject: [PATCH] Add mandatory SLULA license acceptance flag (close #405) Since introducing a new license we need to explicitly check if the user has accepted the terms. Therefore a new flag is added. By default it is set to false but can be overrided by either: - setting `license.accept = true` in the config file - setting `env ACCEPT_LIMITED_USE_LICENSE=true` - appending `-Dlicense.accept=true` --- .../telemetry/sender_config/config.hocon | 1 + .../telemetry/sender_config/config_disabled.hocon | 1 + .github/workflows/ssc-collector-config/config.hocon | 1 + core/src/main/resources/reference.conf | 5 +++++ .../Config.scala | 13 ++++++++++++- .../Run.scala | 13 +++++++++++++ .../ConfigParserSpec.scala | 3 ++- .../TestUtils.scala | 3 ++- examples/config.kafka.extended.hocon | 5 +++++ examples/config.kafka.minimal.hocon | 4 ++++ examples/config.kinesis.extended.hocon | 5 +++++ examples/config.kinesis.minimal.hocon | 4 ++++ examples/config.nsq.extended.hocon | 5 +++++ examples/config.nsq.minimal.hocon | 7 +++++-- examples/config.pubsub.extended.hocon | 5 +++++ examples/config.pubsub.minimal.hocon | 4 ++++ examples/config.sqs.extended.hocon | 5 +++++ examples/config.sqs.minimal.hocon | 3 +++ examples/config.stdout.extended.hocon | 5 +++++ examples/config.stdout.minimal.hocon | 3 +++ kafka/src/it/resources/collector.hocon | 1 + .../KafkaConfigSpec.scala | 3 ++- .../it/resources/collector-cookie-anonymous.hocon | 1 + .../resources/collector-cookie-attributes-1.hocon | 1 + .../resources/collector-cookie-attributes-2.hocon | 1 + .../src/it/resources/collector-cookie-domain.hocon | 1 + .../it/resources/collector-cookie-fallback.hocon | 1 + .../it/resources/collector-cookie-no-domain.hocon | 1 + .../src/it/resources/collector-custom-paths.hocon | 1 + .../collector-doNotTrackCookie-disabled.hocon | 1 + .../collector-doNotTrackCookie-enabled.hocon | 1 + kinesis/src/it/resources/collector.hocon | 1 + .../sinks/KinesisConfigSpec.scala | 3 ++- .../NsqConfigSpec.scala | 3 ++- pubsub/src/it/resources/collector.hocon | 1 + .../ConfigSpec.scala | 3 ++- .../SqsConfigSpec.scala | 3 ++- 37 files changed, 112 insertions(+), 10 deletions(-) diff --git a/.github/workflows/integration_tests/telemetry/sender_config/config.hocon b/.github/workflows/integration_tests/telemetry/sender_config/config.hocon index 9979af681..96dcc7f10 100644 --- a/.github/workflows/integration_tests/telemetry/sender_config/config.hocon +++ b/.github/workflows/integration_tests/telemetry/sender_config/config.hocon @@ -1,5 +1,6 @@ # 'collector' contains configuration options for the main Scala collector. collector { + license { accept = true } # The collector runs as a web service specified on the following interface and port. interface = "0.0.0.0" port = "9292" diff --git a/.github/workflows/integration_tests/telemetry/sender_config/config_disabled.hocon b/.github/workflows/integration_tests/telemetry/sender_config/config_disabled.hocon index 30885a8fc..e3dd731eb 100644 --- a/.github/workflows/integration_tests/telemetry/sender_config/config_disabled.hocon +++ b/.github/workflows/integration_tests/telemetry/sender_config/config_disabled.hocon @@ -1,5 +1,6 @@ # 'collector' contains configuration options for the main Scala collector. collector { + license { accept = true } # The collector runs as a web service specified on the following interface and port. interface = "0.0.0.0" port = "10292" diff --git a/.github/workflows/ssc-collector-config/config.hocon b/.github/workflows/ssc-collector-config/config.hocon index 2137caead..10e6b6df9 100644 --- a/.github/workflows/ssc-collector-config/config.hocon +++ b/.github/workflows/ssc-collector-config/config.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = 0.0.0.0 port = 12345 diff --git a/core/src/main/resources/reference.conf b/core/src/main/resources/reference.conf index 1a91ba19b..be3b75e40 100644 --- a/core/src/main/resources/reference.conf +++ b/core/src/main/resources/reference.conf @@ -1,4 +1,9 @@ { + license { + accept = false + accept = ${?ACCEPT_LIMITED_USE_LICENSE} + } + paths {} p3p { diff --git a/core/src/main/scala/com.snowplowanalytics.snowplow.collector.core/Config.scala b/core/src/main/scala/com.snowplowanalytics.snowplow.collector.core/Config.scala index a9d16e78e..f4f99567a 100644 --- a/core/src/main/scala/com.snowplowanalytics.snowplow.collector.core/Config.scala +++ b/core/src/main/scala/com.snowplowanalytics.snowplow.collector.core/Config.scala @@ -39,7 +39,8 @@ case class Config[+SinkConfig]( networking: Config.Networking, enableDefaultRedirect: Boolean, redirectDomains: Set[String], - preTerminationPeriod: FiniteDuration + preTerminationPeriod: FiniteDuration, + license: Config.License ) object Config { @@ -154,7 +155,17 @@ object Config { idleTimeout: FiniteDuration ) + case class License( + accept: Boolean + ) + implicit def decoder[SinkConfig: Decoder]: Decoder[Config[SinkConfig]] = { + implicit val license: Decoder[License] = { + val truthy = Set("true", "yes", "on", "1") + Decoder + .forProduct1("accept")((s: String) => License(truthy(s.toLowerCase()))) + .or(Decoder.forProduct1("accept")((b: Boolean) => License(b))) + } implicit val p3p = deriveDecoder[P3P] implicit val crossDomain = deriveDecoder[CrossDomain] implicit val sameSite: Decoder[SameSite] = Decoder.instance { cur => diff --git a/core/src/main/scala/com.snowplowanalytics.snowplow.collector.core/Run.scala b/core/src/main/scala/com.snowplowanalytics.snowplow.collector.core/Run.scala index da842f9a8..78da39188 100644 --- a/core/src/main/scala/com.snowplowanalytics.snowplow.collector.core/Run.scala +++ b/core/src/main/scala/com.snowplowanalytics.snowplow.collector.core/Run.scala @@ -58,6 +58,7 @@ object Run { ): F[ExitCode] = { val eitherT = for { config <- ConfigParser.fromPath[F, SinkConfig](path) + _ <- checkLicense(config.license.accept) _ <- EitherT.right[ExitCode](fromConfig(appInfo, mkSinks, telemetryInfo, config)) } yield ExitCode.Success @@ -67,6 +68,18 @@ object Run { } } + private def checkLicense[F[_]: Sync](acceptLicense: Boolean): EitherT[F, ExitCode, _] = + EitherT.liftF { + if (acceptLicense) + Sync[F].unit + else + Sync[F].raiseError( + new IllegalStateException( + "Please accept the terms of the Snowplow Limited Use License Agreement to proceed. See https://docs.snowplow.io/docs/pipeline-components-and-applications/stream-collector/configure/#license for more information on the license and how to configure this." + ) + ) + } + private def fromConfig[F[_]: Async: Tracking, SinkConfig]( appInfo: AppInfo, mkSinks: MkSinks[F, SinkConfig], diff --git a/core/src/test/scala/com.snowplowanalytics.snowplow.collector.core/ConfigParserSpec.scala b/core/src/test/scala/com.snowplowanalytics.snowplow.collector.core/ConfigParserSpec.scala index 310df4365..3f25aeea5 100644 --- a/core/src/test/scala/com.snowplowanalytics.snowplow.collector.core/ConfigParserSpec.scala +++ b/core/src/test/scala/com.snowplowanalytics.snowplow.collector.core/ConfigParserSpec.scala @@ -52,7 +52,8 @@ class ConfigParserSpec extends Specification with CatsEffect { .copy[SinkConfig]( paths = Map.empty[String, String], streams = expectedStreams, - ssl = TestUtils.testConfig.ssl.copy(enable = true) + ssl = TestUtils.testConfig.ssl.copy(enable = true), + license = Config.License(false) ) ConfigParser.fromPath[IO, SinkConfig](Some(path)).value.map(_ should beRight(expected)) diff --git a/core/src/test/scala/com.snowplowanalytics.snowplow.collector.core/TestUtils.scala b/core/src/test/scala/com.snowplowanalytics.snowplow.collector.core/TestUtils.scala index 184f32bde..5db8643cf 100644 --- a/core/src/test/scala/com.snowplowanalytics.snowplow.collector.core/TestUtils.scala +++ b/core/src/test/scala/com.snowplowanalytics.snowplow.collector.core/TestUtils.scala @@ -132,6 +132,7 @@ object TestUtils { moduleVersion = None, instanceId = None, autoGeneratedId = None - ) + ), + license = License(accept = true) ) } diff --git a/examples/config.kafka.extended.hocon b/examples/config.kafka.extended.hocon index a25110c23..217d0a5af 100644 --- a/examples/config.kafka.extended.hocon +++ b/examples/config.kafka.extended.hocon @@ -15,6 +15,11 @@ # 'collector' contains configuration options for the main Scala collector. collector { + # Full license text available in LICENSE.md + license { + accept = true + } + # The collector runs as a web service specified on the following interface and port. interface = "0.0.0.0" port = 8080 diff --git a/examples/config.kafka.minimal.hocon b/examples/config.kafka.minimal.hocon index 1547b5c1e..cc7c5a869 100644 --- a/examples/config.kafka.minimal.hocon +++ b/examples/config.kafka.minimal.hocon @@ -1,4 +1,8 @@ collector { + license { + accept = true + } + interface = "0.0.0.0" port = 8080 diff --git a/examples/config.kinesis.extended.hocon b/examples/config.kinesis.extended.hocon index 167e38459..c2820c129 100644 --- a/examples/config.kinesis.extended.hocon +++ b/examples/config.kinesis.extended.hocon @@ -15,6 +15,11 @@ # 'collector' contains configuration options for the main Scala collector. collector { + # Full license text available in LICENSE.md + license { + accept = true + } + # The collector runs as a web service specified on the following interface and port. interface = "0.0.0.0" port = 8080 diff --git a/examples/config.kinesis.minimal.hocon b/examples/config.kinesis.minimal.hocon index 9501390a5..30ee8f174 100644 --- a/examples/config.kinesis.minimal.hocon +++ b/examples/config.kinesis.minimal.hocon @@ -1,4 +1,8 @@ collector { + license { + accept = true + } + interface = "0.0.0.0" port = 8080 diff --git a/examples/config.nsq.extended.hocon b/examples/config.nsq.extended.hocon index 3bb4f0b49..804a6d2f5 100644 --- a/examples/config.nsq.extended.hocon +++ b/examples/config.nsq.extended.hocon @@ -15,6 +15,11 @@ # 'collector' contains configuration options for the main Scala collector. collector { + # Full license text available in LICENSE.md + license { + accept = true + } + # The collector runs as a web service specified on the following interface and port. interface = "0.0.0.0" port = 8080 diff --git a/examples/config.nsq.minimal.hocon b/examples/config.nsq.minimal.hocon index 2b7afa7ca..f3cafd6dc 100644 --- a/examples/config.nsq.minimal.hocon +++ b/examples/config.nsq.minimal.hocon @@ -1,4 +1,7 @@ collector { + license { + accept = true + } interface = "0.0.0.0" port = 8080 @@ -6,8 +9,8 @@ collector { good { name = "good" host = "nsqHost" - } - + } + bad { name = "bad" host = "nsqHost" diff --git a/examples/config.pubsub.extended.hocon b/examples/config.pubsub.extended.hocon index 75ed92377..3b24f30d5 100644 --- a/examples/config.pubsub.extended.hocon +++ b/examples/config.pubsub.extended.hocon @@ -15,6 +15,11 @@ # 'collector' contains configuration options for the main Scala collector. collector { + # Full license text available in LICENSE.md + license { + accept = true + } + # The collector runs as a web service specified on the following interface and port. interface = "0.0.0.0" port = 8080 diff --git a/examples/config.pubsub.minimal.hocon b/examples/config.pubsub.minimal.hocon index b6fdb8d05..fec7ef8a3 100644 --- a/examples/config.pubsub.minimal.hocon +++ b/examples/config.pubsub.minimal.hocon @@ -1,4 +1,8 @@ collector { + license { + accept = true + } + interface = "0.0.0.0" port = 8080 diff --git a/examples/config.sqs.extended.hocon b/examples/config.sqs.extended.hocon index 0b6f50184..0ebfbce0a 100644 --- a/examples/config.sqs.extended.hocon +++ b/examples/config.sqs.extended.hocon @@ -10,6 +10,11 @@ # 'collector' contains configuration options for the main Scala collector. collector { + # Full license text available in LICENSE.md + license { + accept = true + } + # The collector runs as a web service specified on the following interface and port. interface = "0.0.0.0" port = 8080 diff --git a/examples/config.sqs.minimal.hocon b/examples/config.sqs.minimal.hocon index 9501390a5..137baa0af 100644 --- a/examples/config.sqs.minimal.hocon +++ b/examples/config.sqs.minimal.hocon @@ -1,4 +1,7 @@ collector { + license { + accept = true + } interface = "0.0.0.0" port = 8080 diff --git a/examples/config.stdout.extended.hocon b/examples/config.stdout.extended.hocon index 86b132a6e..a29437811 100644 --- a/examples/config.stdout.extended.hocon +++ b/examples/config.stdout.extended.hocon @@ -15,6 +15,11 @@ # 'collector' contains configuration options for the main Scala collector. collector { + # Full license text available in LICENSE.md + license { + accept = true + } + # The collector runs as a web service specified on the following interface and port. interface = "0.0.0.0" port = 8080 diff --git a/examples/config.stdout.minimal.hocon b/examples/config.stdout.minimal.hocon index 3b2e212d6..4b318e039 100644 --- a/examples/config.stdout.minimal.hocon +++ b/examples/config.stdout.minimal.hocon @@ -1,4 +1,7 @@ collector { + license { + accept = true + } interface = "0.0.0.0" port = 8080 diff --git a/kafka/src/it/resources/collector.hocon b/kafka/src/it/resources/collector.hocon index 2468a977b..afdf83333 100644 --- a/kafka/src/it/resources/collector.hocon +++ b/kafka/src/it/resources/collector.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kafka/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/KafkaConfigSpec.scala b/kafka/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/KafkaConfigSpec.scala index 75d056060..6dc8ea4db 100644 --- a/kafka/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/KafkaConfigSpec.scala +++ b/kafka/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/KafkaConfigSpec.scala @@ -158,6 +158,7 @@ object KafkaConfigSpec { networking = Config.Networking( maxConnections = 1024, idleTimeout = 610.seconds - ) + ), + license = Config.License(accept = true) ) } diff --git a/kinesis/src/it/resources/collector-cookie-anonymous.hocon b/kinesis/src/it/resources/collector-cookie-anonymous.hocon index 14f4ed802..41edde52f 100644 --- a/kinesis/src/it/resources/collector-cookie-anonymous.hocon +++ b/kinesis/src/it/resources/collector-cookie-anonymous.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kinesis/src/it/resources/collector-cookie-attributes-1.hocon b/kinesis/src/it/resources/collector-cookie-attributes-1.hocon index e661116da..d67d6695c 100644 --- a/kinesis/src/it/resources/collector-cookie-attributes-1.hocon +++ b/kinesis/src/it/resources/collector-cookie-attributes-1.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kinesis/src/it/resources/collector-cookie-attributes-2.hocon b/kinesis/src/it/resources/collector-cookie-attributes-2.hocon index 14f4ed802..41edde52f 100644 --- a/kinesis/src/it/resources/collector-cookie-attributes-2.hocon +++ b/kinesis/src/it/resources/collector-cookie-attributes-2.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kinesis/src/it/resources/collector-cookie-domain.hocon b/kinesis/src/it/resources/collector-cookie-domain.hocon index 4a7eaee7c..cc4a991ae 100644 --- a/kinesis/src/it/resources/collector-cookie-domain.hocon +++ b/kinesis/src/it/resources/collector-cookie-domain.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kinesis/src/it/resources/collector-cookie-fallback.hocon b/kinesis/src/it/resources/collector-cookie-fallback.hocon index 8c9c874f6..be55026e2 100644 --- a/kinesis/src/it/resources/collector-cookie-fallback.hocon +++ b/kinesis/src/it/resources/collector-cookie-fallback.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kinesis/src/it/resources/collector-cookie-no-domain.hocon b/kinesis/src/it/resources/collector-cookie-no-domain.hocon index 14f4ed802..41edde52f 100644 --- a/kinesis/src/it/resources/collector-cookie-no-domain.hocon +++ b/kinesis/src/it/resources/collector-cookie-no-domain.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kinesis/src/it/resources/collector-custom-paths.hocon b/kinesis/src/it/resources/collector-custom-paths.hocon index a39c6d87d..0d291144a 100644 --- a/kinesis/src/it/resources/collector-custom-paths.hocon +++ b/kinesis/src/it/resources/collector-custom-paths.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kinesis/src/it/resources/collector-doNotTrackCookie-disabled.hocon b/kinesis/src/it/resources/collector-doNotTrackCookie-disabled.hocon index 6f6f54155..36c210b16 100644 --- a/kinesis/src/it/resources/collector-doNotTrackCookie-disabled.hocon +++ b/kinesis/src/it/resources/collector-doNotTrackCookie-disabled.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kinesis/src/it/resources/collector-doNotTrackCookie-enabled.hocon b/kinesis/src/it/resources/collector-doNotTrackCookie-enabled.hocon index 0604641ae..9873cb528 100644 --- a/kinesis/src/it/resources/collector-doNotTrackCookie-enabled.hocon +++ b/kinesis/src/it/resources/collector-doNotTrackCookie-enabled.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kinesis/src/it/resources/collector.hocon b/kinesis/src/it/resources/collector.hocon index 0183b1258..7feb06585 100644 --- a/kinesis/src/it/resources/collector.hocon +++ b/kinesis/src/it/resources/collector.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/kinesis/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/sinks/KinesisConfigSpec.scala b/kinesis/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/sinks/KinesisConfigSpec.scala index aa365da64..ce5eec188 100644 --- a/kinesis/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/sinks/KinesisConfigSpec.scala +++ b/kinesis/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/sinks/KinesisConfigSpec.scala @@ -186,7 +186,8 @@ object KinesisConfigSpec { moduleVersion = None, instanceId = None, autoGeneratedId = None - ) + ), + license = Config.License(accept = true) ) } diff --git a/nsq/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/NsqConfigSpec.scala b/nsq/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/NsqConfigSpec.scala index be9fefa37..8db7091ae 100644 --- a/nsq/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/NsqConfigSpec.scala +++ b/nsq/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/NsqConfigSpec.scala @@ -157,6 +157,7 @@ object NsqConfigSpec { networking = Config.Networking( maxConnections = 1024, idleTimeout = 610.seconds - ) + ), + license = Config.License(accept = true) ) } diff --git a/pubsub/src/it/resources/collector.hocon b/pubsub/src/it/resources/collector.hocon index d964fbe56..08533efbd 100644 --- a/pubsub/src/it/resources/collector.hocon +++ b/pubsub/src/it/resources/collector.hocon @@ -1,4 +1,5 @@ collector { + license { accept = true } interface = "0.0.0.0" port = ${PORT} diff --git a/pubsub/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/ConfigSpec.scala b/pubsub/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/ConfigSpec.scala index 1dcebe092..ab54e0175 100644 --- a/pubsub/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/ConfigSpec.scala +++ b/pubsub/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/ConfigSpec.scala @@ -177,7 +177,8 @@ object ConfigSpec { moduleVersion = None, instanceId = None, autoGeneratedId = None - ) + ), + license = Config.License(accept = true) ) } diff --git a/sqs/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/SqsConfigSpec.scala b/sqs/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/SqsConfigSpec.scala index 77e301bdd..e71089b2e 100644 --- a/sqs/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/SqsConfigSpec.scala +++ b/sqs/src/test/scala/com.snowplowanalytics.snowplow.collectors.scalastream/SqsConfigSpec.scala @@ -166,7 +166,8 @@ object SqsConfigSpec { moduleVersion = None, instanceId = None, autoGeneratedId = None - ) + ), + license = Config.License(accept = true) ) }