From 6e25761e2f0200fd408d4cfeee5326bd1164b597 Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Mon, 14 Oct 2024 17:08:17 -0300 Subject: [PATCH 1/6] 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/6] 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'] }); From e12b8ad94f2f6564320e725525e636d00263e8f1 Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Tue, 15 Oct 2024 12:27:40 -0300 Subject: [PATCH 3/6] Android changes --- splitio/example/pubspec.lock | 21 ++++------ splitio/pubspec.yaml | 9 ++-- splitio_android/android/build.gradle | 2 +- .../splitio/SplitClientConfigHelper.java | 35 ++++++++++++++++ .../splitio/SplitClientConfigHelperTest.java | 41 +++++++++++++++++++ splitio_android/pubspec.yaml | 3 +- splitio_ios/pubspec.yaml | 3 +- 7 files changed, 96 insertions(+), 18 deletions(-) diff --git a/splitio/example/pubspec.lock b/splitio/example/pubspec.lock index a22e0ac..df08e5d 100644 --- a/splitio/example/pubspec.lock +++ b/splitio/example/pubspec.lock @@ -170,26 +170,23 @@ packages: splitio_android: dependency: transitive description: - name: splitio_android - sha256: b7ddd9f8a694ed610dd3ecd770f16d4ce016c3211d2f56fc5a094ef58bc543fb - url: "https://pub.dev" - source: hosted + path: "../../splitio_android" + relative: true + source: path version: "0.1.9+1" splitio_ios: dependency: transitive description: - name: splitio_ios - sha256: e9b5427a7c8efa67846a5ccbe70d13d3286f50f382b369416bff7c509478b50f - url: "https://pub.dev" - source: hosted + path: "../../splitio_ios" + relative: true + source: path version: "0.1.9" splitio_platform_interface: dependency: transitive description: - name: splitio_platform_interface - sha256: eb0ec278e782bb403856f0921d2023ed8ed1a9e97eafb0f3de5cc4a107d1e04f - url: "https://pub.dev" - source: hosted + path: "../../splitio_platform_interface" + relative: true + source: path version: "1.4.0" stack_trace: dependency: transitive diff --git a/splitio/pubspec.yaml b/splitio/pubspec.yaml index 4acfba3..f02f0e4 100644 --- a/splitio/pubspec.yaml +++ b/splitio/pubspec.yaml @@ -19,9 +19,12 @@ flutter: dependencies: flutter: sdk: flutter - splitio_android: ^0.1.9+1 - splitio_ios: ^0.1.9 - splitio_platform_interface: ^1.4.0 + splitio_android: # ^0.1.9+1 + path: ../splitio_android + splitio_ios: # ^0.1.9 + path: ../splitio_ios + splitio_platform_interface: # ^1.4.0 + path: ../splitio_platform_interface dev_dependencies: flutter_test: diff --git a/splitio_android/android/build.gradle b/splitio_android/android/build.gradle index 98c41c1..cf5924c 100644 --- a/splitio_android/android/build.gradle +++ b/splitio_android/android/build.gradle @@ -36,7 +36,7 @@ android { } dependencies { - implementation 'io.split.client:android-client:4.1.1' + implementation 'io.split.client:android-client:4.2.2' testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-core:3.12.4' diff --git a/splitio_android/android/src/main/java/io/split/splitio/SplitClientConfigHelper.java b/splitio_android/android/src/main/java/io/split/splitio/SplitClientConfigHelper.java index 8aa0e78..ce83e03 100644 --- a/splitio_android/android/src/main/java/io/split/splitio/SplitClientConfigHelper.java +++ b/splitio_android/android/src/main/java/io/split/splitio/SplitClientConfigHelper.java @@ -4,8 +4,10 @@ import androidx.annotation.Nullable; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import io.split.android.client.ServiceEndpoints; @@ -13,6 +15,7 @@ import io.split.android.client.SplitFilter; import io.split.android.client.SyncConfig; import io.split.android.client.impressions.ImpressionListener; +import io.split.android.client.network.CertificatePinningConfiguration; import io.split.android.client.shared.UserConsent; import io.split.android.client.utils.logger.SplitLogLevel; @@ -46,6 +49,8 @@ class SplitClientConfigHelper { private static final String ENCRYPTION_ENABLED = "encryptionEnabled"; private static final String LOG_LEVEL = "logLevel"; private static final String READY_TIMEOUT = "readyTimeout"; + private static final String CERTIFICATE_PINNING_CONFIGURATION = "certificatePinningConfiguration"; + private static final String CERTIFICATE_PINNING_CONFIGURATION_PINS = "pins"; /** * Creates a {@link SplitClientConfig} object from a map. @@ -219,6 +224,24 @@ static SplitClientConfig fromMap(@NonNull Map configurationMap, builder.ready((int) TimeUnit.SECONDS.toMillis(readyTimeout)); // Android SDK uses this parameter in millis } + Map certificatePinningConfig = getObjectMap(configurationMap, CERTIFICATE_PINNING_CONFIGURATION); + if (certificatePinningConfig != null) { + Map> pins = getListMap(certificatePinningConfig, CERTIFICATE_PINNING_CONFIGURATION_PINS); + if (pins != null && !pins.isEmpty()) { + Set hosts = pins.keySet(); + CertificatePinningConfiguration.Builder certPinningConfigBuilder = CertificatePinningConfiguration.builder(); + for (String host : hosts) { + Set hostPins = new HashSet<>(pins.get(host)); + if (!hostPins.isEmpty()) { + for (String pin : hostPins) { + certPinningConfigBuilder.addPin(host, pin); + } + } + } + builder.certificatePinningConfiguration(certPinningConfigBuilder.build()); + } + } + return builder.serviceEndpoints(serviceEndpointsBuilder.build()).build(); } @@ -274,4 +297,16 @@ private static Map> getListMap(Map map, Str return null; } + + @Nullable + private static Map getObjectMap(Map map, String key) { + if (map.containsKey(key)) { + Object value = map.get(key); + if (value != null && value.getClass().isAssignableFrom(HashMap.class)) { + return (HashMap) value; + } + } + + return null; + } } diff --git a/splitio_android/android/src/test/java/io/split/splitio/SplitClientConfigHelperTest.java b/splitio_android/android/src/test/java/io/split/splitio/SplitClientConfigHelperTest.java index 6c16b8f..18691f0 100644 --- a/splitio_android/android/src/test/java/io/split/splitio/SplitClientConfigHelperTest.java +++ b/splitio_android/android/src/test/java/io/split/splitio/SplitClientConfigHelperTest.java @@ -11,14 +11,21 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import io.split.android.client.SplitClientConfig; import io.split.android.client.SplitFilter; import io.split.android.client.impressions.ImpressionListener; +import io.split.android.client.network.CertificatePin; +import io.split.android.client.network.CertificatePinningConfiguration; import io.split.android.client.service.impressions.ImpressionsMode; import io.split.android.client.shared.UserConsent; +import io.split.android.client.utils.logger.LogPrinter; +import io.split.android.client.utils.logger.Logger; import io.split.android.client.utils.logger.SplitLogLevel; public class SplitClientConfigHelperTest { @@ -178,4 +185,38 @@ public void syncConfigWithFlagSetsIsMappedCorrectly() { assertEquals(Arrays.asList("set_1", "set_2"), splitClientConfig.syncConfig().getFilters().get(0).getValues()); assertEquals(SplitFilter.Type.BY_SET, splitClientConfig.syncConfig().getFilters().get(0).getType()); } + + @Test + public void certificatePinningConfigurationValuesAreMappedCorrectly() { + Logger.instance().setPrinter(mock(LogPrinter.class)); + + Map configValues = new HashMap<>(); + Map pinningConfigValues = new HashMap<>(); + Map> pins = new HashMap<>(); + + Set hostOnePins = new HashSet<>(); + hostOnePins.add("sha256/pin1"); + hostOnePins.add("sha1/pin2"); + pins.put("host1", hostOnePins); + pins.put("host2", Collections.singleton("sha256/pin2")); + pinningConfigValues.put("pins", pins); + configValues.put("certificatePinningConfiguration", pinningConfigValues); + + SplitClientConfig splitClientConfig = SplitClientConfigHelper + .fromMap(configValues, mock(ImpressionListener.class)); + + CertificatePinningConfiguration actualConfig = splitClientConfig.certificatePinningConfiguration(); + assertNotNull(actualConfig); + assertEquals(2, actualConfig.getPins().size()); + assertEquals(2, actualConfig.getPins().get("host1").size()); + assertEquals(1, actualConfig.getPins().get("host2").size()); + + Set host1Pins = actualConfig.getPins().get("host1"); + Iterator iterator = host1Pins.iterator(); + assertEquals("sha256", iterator.next().getAlgorithm()); + assertEquals("sha1", iterator.next().getAlgorithm()); + + Set host2Pins = actualConfig.getPins().get("host2"); + assertEquals("sha256", host2Pins.iterator().next().getAlgorithm()); + } } diff --git a/splitio_android/pubspec.yaml b/splitio_android/pubspec.yaml index e6e36c8..488f82e 100644 --- a/splitio_android/pubspec.yaml +++ b/splitio_android/pubspec.yaml @@ -19,7 +19,8 @@ flutter: dependencies: flutter: sdk: flutter - splitio_platform_interface: ^1.4.0 + splitio_platform_interface: #^1.4.0 + path: ../splitio_platform_interface dev_dependencies: flutter_test: diff --git a/splitio_ios/pubspec.yaml b/splitio_ios/pubspec.yaml index 151c673..ccd78f9 100644 --- a/splitio_ios/pubspec.yaml +++ b/splitio_ios/pubspec.yaml @@ -18,7 +18,8 @@ flutter: dependencies: flutter: sdk: flutter - splitio_platform_interface: ^1.4.0 + splitio_platform_interface: #^1.4.0 + path: ../splitio_platform_interface dev_dependencies: flutter_test: From 72fac8dda1379909fc71e6809b6f4474985532a6 Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Tue, 15 Oct 2024 17:03:10 -0300 Subject: [PATCH 4/6] iOS changes --- splitio/example/ios/Podfile.lock | 10 +++---- splitio_ios/example/ios/Podfile.lock | 10 +++---- .../SplitClientConfigHelperTests.swift | 21 +++++++++++++++ splitio_ios/example/pubspec.lock | 7 +++-- .../ios/Classes/SplitClientConfigHelper.swift | 27 ++++++++++++++++--- splitio_ios/ios/splitio_ios.podspec | 4 +-- 6 files changed, 59 insertions(+), 20 deletions(-) diff --git a/splitio/example/ios/Podfile.lock b/splitio/example/ios/Podfile.lock index 6d9b1ac..cea8fa6 100644 --- a/splitio/example/ios/Podfile.lock +++ b/splitio/example/ios/Podfile.lock @@ -1,9 +1,9 @@ PODS: - Flutter (1.0.0) - - Split (2.25.0) - - splitio_ios (0.5.0): + - Split (2.26.1) + - splitio_ios (0.6.0): - Flutter - - Split (~> 2.25.0) + - Split (~> 2.26.1) DEPENDENCIES: - Flutter (from `Flutter`) @@ -21,8 +21,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - Split: 268875814285de6ab6cd25744e170b407651a080 - splitio_ios: f6af0613ceedf0c037673afe256479bb0f6fc6ec + Split: 15cab642eb8b8bb4f289a2190f7b26e655f99756 + splitio_ios: 931b5df7148d0dca9acb31a65505bd619f198fcf PODFILE CHECKSUM: 4e8f8b2be68aeea4c0d5beb6ff1e79fface1d048 diff --git a/splitio_ios/example/ios/Podfile.lock b/splitio_ios/example/ios/Podfile.lock index 522e427..2a8c261 100644 --- a/splitio_ios/example/ios/Podfile.lock +++ b/splitio_ios/example/ios/Podfile.lock @@ -1,9 +1,9 @@ PODS: - Flutter (1.0.0) - - Split (2.25.0) - - splitio_ios (0.5.0): + - Split (2.26.1) + - splitio_ios (0.6.0): - Flutter - - Split (~> 2.25.0) + - Split (~> 2.26.1) DEPENDENCIES: - Flutter (from `Flutter`) @@ -21,8 +21,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - Split: 268875814285de6ab6cd25744e170b407651a080 - splitio_ios: f6af0613ceedf0c037673afe256479bb0f6fc6ec + Split: 15cab642eb8b8bb4f289a2190f7b26e655f99756 + splitio_ios: 931b5df7148d0dca9acb31a65505bd619f198fcf PODFILE CHECKSUM: aed42fc5c94ade572556b7ed357c5c57f1bd83a2 diff --git a/splitio_ios/example/ios/SplitTests/SplitClientConfigHelperTests.swift b/splitio_ios/example/ios/SplitTests/SplitClientConfigHelperTests.swift index 339e629..d07edd7 100644 --- a/splitio_ios/example/ios/SplitTests/SplitClientConfigHelperTests.swift +++ b/splitio_ios/example/ios/SplitTests/SplitClientConfigHelperTests.swift @@ -48,6 +48,7 @@ class SplitClientConfigHelperTests: XCTestCase { XCTAssertTrue(splitClientConfig.encryptionEnabled) XCTAssertEqual(.verbose, splitClientConfig.logLevel) XCTAssertEqual(10000, splitClientConfig.sdkReadyTimeOut) + XCTAssertNil(splitClientConfig.certificatePinningConfig) } func testEnableDebugLogLevelIsMappedCorrectly() { @@ -114,4 +115,24 @@ class SplitClientConfigHelperTests: XCTestCase { XCTAssertEqual(.bySet, splitClientConfig.sync.filters[0].type) XCTAssertEqual(["set_1", "set_2"], splitClientConfig.sync.filters[0].values) } + + func testCertificatePinningConfigurationValuesAreMappedCorrectly() { + let configValues = [ + "certificatePinningConfiguration": [ + "pins": [ + "host1": [ "sha256/pin1", "sha1/pin2" ], + "host2": [ "sha256/pin2" ] + ] + ] + ] + + let splitClientConfig: SplitClientConfig = SplitClientConfigHelper.fromMap(configurationMap: configValues, impressionListener: nil) + let actualConfig = splitClientConfig.certificatePinningConfig?.pins + + let containsPins = actualConfig?.contains { pin in + (pin.host == "host1" && pin.algo == KeyHashAlgo.sha256) && + (pin.host == "host1" && pin.algo == KeyHashAlgo.sha1) && + (pin.host == "host2" && pin.algo == KeyHashAlgo.sha256 ) + } + } } diff --git a/splitio_ios/example/pubspec.lock b/splitio_ios/example/pubspec.lock index 6f5b775..23342f6 100644 --- a/splitio_ios/example/pubspec.lock +++ b/splitio_ios/example/pubspec.lock @@ -170,10 +170,9 @@ packages: splitio_platform_interface: dependency: transitive description: - name: splitio_platform_interface - sha256: eb0ec278e782bb403856f0921d2023ed8ed1a9e97eafb0f3de5cc4a107d1e04f - url: "https://pub.dev" - source: hosted + path: "../../splitio_platform_interface" + relative: true + source: path version: "1.4.0" stack_trace: dependency: transitive diff --git a/splitio_ios/ios/Classes/SplitClientConfigHelper.swift b/splitio_ios/ios/Classes/SplitClientConfigHelper.swift index feaaa5d..025237b 100644 --- a/splitio_ios/ios/Classes/SplitClientConfigHelper.swift +++ b/splitio_ios/ios/Classes/SplitClientConfigHelper.swift @@ -31,6 +31,8 @@ class SplitClientConfigHelper { static private let ENCRYPTION_ENABLED = "encryptionEnabled" static private let LOG_LEVEL = "logLevel" static private let READY_TIMEOUT = "readyTimeout" + static private let CERTIFICATE_PINNING_CONFIGURATION = "certificatePinningConfiguration" + static private let CERTIFICATE_PINNING_CONFIGURATION_PINS = "pins"; static func fromMap(configurationMap: [String: Any?], impressionListener: SplitImpressionListener?) -> SplitClientConfig { let config = SplitClientConfig() @@ -143,6 +145,8 @@ class SplitClientConfigHelper { } } + config.serviceEndpoints = serviceEndpointsBuilder.build() + if let impressionListener = impressionListener { config.impressionListener = impressionListener } @@ -168,11 +172,11 @@ class SplitClientConfigHelper { config.sync = syncConfigBuilder.build() } } - + if let impressionsMode = configurationMap[IMPRESSIONS_MODE] as? String { config.impressionsMode = impressionsMode.uppercased() } - + if let syncEnabled = configurationMap[SYNC_ENABLED] as? Bool { config.syncEnabled = syncEnabled } @@ -213,14 +217,29 @@ class SplitClientConfigHelper { config.sdkReadyTimeOut = readyTimeout * 1000 // iOS SDK uses this parameter in millis } - config.serviceEndpoints = serviceEndpointsBuilder.build() + if let certPinningConfig = configurationMap[CERTIFICATE_PINNING_CONFIGURATION] as? [String: Any?] { + if let pins = certPinningConfig[CERTIFICATE_PINNING_CONFIGURATION_PINS] as? [String: [String]] { + let pinningConfigBuilder = CertificatePinningConfig.builder() + for (hostName, hostPins) in pins { + for hostPin in hostPins { + pinningConfigBuilder.addPin(host: hostName, keyHash: hostPin) + } + } + + do { + try config.certificatePinningConfig = pinningConfigBuilder.build() + } catch { + + } + } + } return config } static func impressionListenerEnabled(configurationMap: [String: Any?]) -> Bool { if configurationMap[IMPRESSION_LISTENER] != nil { - if let impressionListenerEnabled = configurationMap[IMPRESSION_LISTENER] as? Bool { + if configurationMap[IMPRESSION_LISTENER] is Bool { return true } } diff --git a/splitio_ios/ios/splitio_ios.podspec b/splitio_ios/ios/splitio_ios.podspec index 9fcdaeb..401300a 100644 --- a/splitio_ios/ios/splitio_ios.podspec +++ b/splitio_ios/ios/splitio_ios.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'splitio_ios' - s.version = '0.5.0' + s.version = '0.6.0' s.summary = 'split.io official Flutter plugin.' s.description = <<-DESC split.io official Flutter plugin. @@ -15,7 +15,7 @@ split.io official Flutter plugin. s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.dependency 'Flutter' - s.dependency 'Split', '~> 2.25.0' + s.dependency 'Split', '~> 2.26.1' s.platform = :ios, '9.0' # Flutter.framework does not contain a i386 slice. From 2317237e95fb881afe2174c46d96b004dc444555 Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Tue, 15 Oct 2024 17:56:09 -0300 Subject: [PATCH 5/6] Add missing export; rename file --- splitio/lib/splitio.dart | 1 + ...ration.dart => split_certificate_pinning_configuration.dart} | 0 splitio_platform_interface/lib/split_configuration.dart | 2 +- .../test/certificate_pinning_configuration_test.dart | 2 +- splitio_platform_interface/test/splitio_configuration_test.dart | 2 +- 5 files changed, 4 insertions(+), 3 deletions(-) rename splitio_platform_interface/lib/{certificate_pinning_configuration.dart => split_certificate_pinning_configuration.dart} (100%) diff --git a/splitio/lib/splitio.dart b/splitio/lib/splitio.dart index 0c2c2d6..029d523 100644 --- a/splitio/lib/splitio.dart +++ b/splitio/lib/splitio.dart @@ -9,6 +9,7 @@ export 'package:splitio_platform_interface/split_impression.dart'; export 'package:splitio_platform_interface/split_result.dart'; export 'package:splitio_platform_interface/split_sync_config.dart'; export 'package:splitio_platform_interface/split_view.dart'; +export 'package:splitio_platform_interface/split_certificate_pinning_configuration.dart'; typedef ClientReadinessCallback = void Function(SplitClient splitClient); diff --git a/splitio_platform_interface/lib/certificate_pinning_configuration.dart b/splitio_platform_interface/lib/split_certificate_pinning_configuration.dart similarity index 100% rename from splitio_platform_interface/lib/certificate_pinning_configuration.dart rename to splitio_platform_interface/lib/split_certificate_pinning_configuration.dart diff --git a/splitio_platform_interface/lib/split_configuration.dart b/splitio_platform_interface/lib/split_configuration.dart index 3856c41..7367e79 100644 --- a/splitio_platform_interface/lib/split_configuration.dart +++ b/splitio_platform_interface/lib/split_configuration.dart @@ -1,4 +1,4 @@ -import 'package:splitio_platform_interface/certificate_pinning_configuration.dart'; +import 'package:splitio_platform_interface/split_certificate_pinning_configuration.dart'; import 'package:splitio_platform_interface/split_sync_config.dart'; class SplitConfiguration { diff --git a/splitio_platform_interface/test/certificate_pinning_configuration_test.dart b/splitio_platform_interface/test/certificate_pinning_configuration_test.dart index 2d3ab77..e8c43d2 100644 --- a/splitio_platform_interface/test/certificate_pinning_configuration_test.dart +++ b/splitio_platform_interface/test/certificate_pinning_configuration_test.dart @@ -1,5 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:splitio_platform_interface/certificate_pinning_configuration.dart'; +import 'package:splitio_platform_interface/split_certificate_pinning_configuration.dart'; void main() { test('single pin can be added', () { diff --git a/splitio_platform_interface/test/splitio_configuration_test.dart b/splitio_platform_interface/test/splitio_configuration_test.dart index 0b402b8..dfbb705 100644 --- a/splitio_platform_interface/test/splitio_configuration_test.dart +++ b/splitio_platform_interface/test/splitio_configuration_test.dart @@ -1,5 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:splitio_platform_interface/certificate_pinning_configuration.dart'; +import 'package:splitio_platform_interface/split_certificate_pinning_configuration.dart'; import 'package:splitio_platform_interface/split_configuration.dart'; import 'package:splitio_platform_interface/split_sync_config.dart'; From fe9f6c08a76493f082b0ed08b3f71f5f04635d0d Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Thu, 17 Oct 2024 09:47:39 -0300 Subject: [PATCH 6/6] Replace Set with List --- .../lib/split_certificate_pinning_configuration.dart | 6 +++--- .../lib/split_configuration.dart | 10 +++++----- .../test/splitio_configuration_test.dart | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/splitio_platform_interface/lib/split_certificate_pinning_configuration.dart b/splitio_platform_interface/lib/split_certificate_pinning_configuration.dart index 9166ec1..78b9a0b 100644 --- a/splitio_platform_interface/lib/split_certificate_pinning_configuration.dart +++ b/splitio_platform_interface/lib/split_certificate_pinning_configuration.dart @@ -1,8 +1,8 @@ class CertificatePinningConfiguration { - final Map> _pins = {}; + final Map> _pins = {}; - Map> get pins => _pins; + Map> get pins => _pins; CertificatePinningConfiguration addPin(String host, String pin) { pin = pin.trim(); @@ -11,7 +11,7 @@ class CertificatePinningConfiguration { } if (!_pins.containsKey(host)) { - _pins[host] = {}; + _pins[host] = []; } _pins[host]?.add(pin); diff --git a/splitio_platform_interface/lib/split_configuration.dart b/splitio_platform_interface/lib/split_configuration.dart index 7367e79..e1bf0f9 100644 --- a/splitio_platform_interface/lib/split_configuration.dart +++ b/splitio_platform_interface/lib/split_configuration.dart @@ -46,7 +46,7 @@ class SplitConfiguration { /// /// [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. + /// [certificatePinningConfiguration] 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, @@ -73,7 +73,7 @@ class SplitConfiguration { bool? encryptionEnabled, SplitLogLevel? logLevel, int? readyTimeout = 10, - CertificatePinningConfiguration? certificatePinningConfig, + CertificatePinningConfiguration? certificatePinningConfiguration, }) { if (featuresRefreshRate != null) { configurationMap['featuresRefreshRate'] = featuresRefreshRate; @@ -180,10 +180,10 @@ class SplitConfiguration { configurationMap['readyTimeout'] = readyTimeout; } - if (certificatePinningConfig != null && - certificatePinningConfig.pins.isNotEmpty) { + if (certificatePinningConfiguration != null && + certificatePinningConfiguration.pins.isNotEmpty) { configurationMap['certificatePinningConfiguration'] = { - 'pins': certificatePinningConfig.pins + 'pins': certificatePinningConfiguration.pins }; } } diff --git a/splitio_platform_interface/test/splitio_configuration_test.dart b/splitio_platform_interface/test/splitio_configuration_test.dart index dfbb705..a98d9ce 100644 --- a/splitio_platform_interface/test/splitio_configuration_test.dart +++ b/splitio_platform_interface/test/splitio_configuration_test.dart @@ -31,7 +31,7 @@ void main() { encryptionEnabled: true, logLevel: SplitLogLevel.debug, readyTimeout: 1, - certificatePinningConfig: CertificatePinningConfiguration() + certificatePinningConfiguration: CertificatePinningConfiguration() .addPin('host1', 'pin1') .addPin('host2', 'pin3') .addPin('host1', 'pin2'));