From 6e25761e2f0200fd408d4cfeee5326bd1164b597 Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Mon, 14 Oct 2024 17:08:17 -0300 Subject: [PATCH 1/2] WIP config --- .../certificate_pinning_configuration.dart | 20 +++++++ .../lib/split_configuration.dart | 11 ++++ ...ertificate_pinning_configuration_test.dart | 59 +++++++++++++++++++ .../test/splitio_configuration_test.dart | 14 ++++- 4 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 splitio_platform_interface/lib/certificate_pinning_configuration.dart create mode 100644 splitio_platform_interface/test/certificate_pinning_configuration_test.dart diff --git a/splitio_platform_interface/lib/certificate_pinning_configuration.dart b/splitio_platform_interface/lib/certificate_pinning_configuration.dart new file mode 100644 index 0000000..9166ec1 --- /dev/null +++ b/splitio_platform_interface/lib/certificate_pinning_configuration.dart @@ -0,0 +1,20 @@ +class CertificatePinningConfiguration { + + final Map> _pins = {}; + + Map> get pins => _pins; + + CertificatePinningConfiguration addPin(String host, String pin) { + pin = pin.trim(); + if (pin.isEmpty) { + return this; + } + + if (!_pins.containsKey(host)) { + _pins[host] = {}; + } + + _pins[host]?.add(pin); + return this; + } +} \ No newline at end of file diff --git a/splitio_platform_interface/lib/split_configuration.dart b/splitio_platform_interface/lib/split_configuration.dart index 4a56668..3856c41 100644 --- a/splitio_platform_interface/lib/split_configuration.dart +++ b/splitio_platform_interface/lib/split_configuration.dart @@ -1,3 +1,4 @@ +import 'package:splitio_platform_interface/certificate_pinning_configuration.dart'; import 'package:splitio_platform_interface/split_sync_config.dart'; class SplitConfiguration { @@ -44,6 +45,8 @@ class SplitConfiguration { /// [logLevel] Enables logging according to the level specified. Options are [SplitLogLevel.verbose], [SplitLogLevel.none], [SplitLogLevel.debug], [SplitLogLevel.info], [SplitLogLevel.warning], and [SplitLogLevel.error]. /// /// [readyTimeout] Maximum amount of time in seconds to wait before firing the SDK_READY_TIMED_OUT event. Defaults to 10 seconds. + /// + /// [certificatePinningConfig] Certificate pinning configuration. It is a map where the key is the host and the value is a set of base64 SHA-256 or base64 SHA-1 hashes of the SPKI. SplitConfiguration({ int? featuresRefreshRate, int? segmentsRefreshRate, @@ -70,6 +73,7 @@ class SplitConfiguration { bool? encryptionEnabled, SplitLogLevel? logLevel, int? readyTimeout = 10, + CertificatePinningConfiguration? certificatePinningConfig, }) { if (featuresRefreshRate != null) { configurationMap['featuresRefreshRate'] = featuresRefreshRate; @@ -175,6 +179,13 @@ class SplitConfiguration { if (readyTimeout != null) { configurationMap['readyTimeout'] = readyTimeout; } + + if (certificatePinningConfig != null && + certificatePinningConfig.pins.isNotEmpty) { + configurationMap['certificatePinningConfiguration'] = { + 'pins': certificatePinningConfig.pins + }; + } } } diff --git a/splitio_platform_interface/test/certificate_pinning_configuration_test.dart b/splitio_platform_interface/test/certificate_pinning_configuration_test.dart new file mode 100644 index 0000000..2d3ab77 --- /dev/null +++ b/splitio_platform_interface/test/certificate_pinning_configuration_test.dart @@ -0,0 +1,59 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:splitio_platform_interface/certificate_pinning_configuration.dart'; + +void main() { + test('single pin can be added', () { + var config = CertificatePinningConfiguration(); + config.addPin('host', 'pin'); + + expect(config.pins, { + 'host': {'pin'} + }); + }); + + test('multiple pins can be added for the same host', () { + var config = CertificatePinningConfiguration(); + config.addPin('host', 'pin1'); + config.addPin('host', 'pin2'); + + expect(config.pins, { + 'host': {'pin1', 'pin2'} + }); + }); + + test('multiple pins can be added for multiple hosts', () { + var config = CertificatePinningConfiguration(); + config.addPin('host1', 'pin1'); + config.addPin('host2', 'pin2'); + config.addPin('host1', 'pin2'); + + expect(config.pins, { + 'host1': {'pin1', 'pin2'}, + 'host2': {'pin2'} + }); + }); + + test('same pin for same host is not duplicated', () { + var config = CertificatePinningConfiguration(); + config.addPin('host', 'pin'); + config.addPin('host', 'pin'); + + expect(config.pins, { + 'host': {'pin'} + }); + }); + + test('only whitespace pin is not added', () { + var config = CertificatePinningConfiguration(); + config.addPin('host', ' '); + + expect(config.pins, {}); + }); + + test('empty pin is not added', () { + var config = CertificatePinningConfiguration(); + config.addPin('host', ''); + + expect(config.pins, {}); + }); +} diff --git a/splitio_platform_interface/test/splitio_configuration_test.dart b/splitio_platform_interface/test/splitio_configuration_test.dart index 9921f57..595330d 100644 --- a/splitio_platform_interface/test/splitio_configuration_test.dart +++ b/splitio_platform_interface/test/splitio_configuration_test.dart @@ -1,4 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; +import 'package:splitio_platform_interface/certificate_pinning_configuration.dart'; import 'package:splitio_platform_interface/split_configuration.dart'; import 'package:splitio_platform_interface/split_sync_config.dart'; @@ -29,8 +30,11 @@ void main() { userConsent: UserConsent.declined, encryptionEnabled: true, logLevel: SplitLogLevel.debug, - readyTimeout: 1 - ); + readyTimeout: 1, + certificatePinningConfig: CertificatePinningConfiguration() + .addPin('host1', 'pin1') + .addPin('host2', 'pin3') + .addPin('host1', 'pin2')); expect(config.configurationMap['eventFlushInterval'], 2000); expect(config.configurationMap['eventsPerPush'], 300); @@ -63,6 +67,10 @@ void main() { expect(config.configurationMap['encryptionEnabled'], true); expect(config.configurationMap['logLevel'], 'debug'); expect(config.configurationMap['readyTimeout'], 1); + expect(config.configurationMap['certificatePinningConfiguration'], { + 'host1': ['pin1', 'pin2'], + 'host2': ['pin3'] + }); }); test('no special values leaves map empty', () async { @@ -74,7 +82,7 @@ void main() { test('sets values are mapped correctly', () async { final SplitConfiguration config = SplitConfiguration( - syncConfig: SyncConfig.flagSets(['one', 'two']), + syncConfig: SyncConfig.flagSets(['one', 'two']), ); expect(config.configurationMap['syncConfig']['syncConfigNames'], []); From 7459365f5e27c608870f5dbb700371180c21799a Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Mon, 14 Oct 2024 19:26:47 -0300 Subject: [PATCH 2/2] Fix test --- splitio_platform_interface/test/splitio_configuration_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/splitio_platform_interface/test/splitio_configuration_test.dart b/splitio_platform_interface/test/splitio_configuration_test.dart index 595330d..0b402b8 100644 --- a/splitio_platform_interface/test/splitio_configuration_test.dart +++ b/splitio_platform_interface/test/splitio_configuration_test.dart @@ -67,7 +67,7 @@ void main() { expect(config.configurationMap['encryptionEnabled'], true); expect(config.configurationMap['logLevel'], 'debug'); expect(config.configurationMap['readyTimeout'], 1); - expect(config.configurationMap['certificatePinningConfiguration'], { + expect(config.configurationMap['certificatePinningConfiguration']['pins'], { 'host1': ['pin1', 'pin2'], 'host2': ['pin3'] });