diff --git a/splitio/CHANGELOG.md b/splitio/CHANGELOG.md index cda5564..7eee903 100644 --- a/splitio/CHANGELOG.md +++ b/splitio/CHANGELOG.md @@ -1,3 +1,9 @@ +# 0.1.10 (Oct 18, 2024) +* Added certificate pinning functionality. This feature allows you to pin a certificate to the SDK, ensuring that the SDK only communicates with servers that present this certificate. Read more in our documentation. +* Updated iOS SDK to `2.26.1` & Android SDK to `4.2.2` + +# 0.1.10-rc.1 (Oct 17, 2024) + # 0.1.9+1 (Jun 7, 2024) * Updated Android SDK to `4.1.1` 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/example/pubspec.lock b/splitio/example/pubspec.lock index a22e0ac..d6ac02a 100644 --- a/splitio/example/pubspec.lock +++ b/splitio/example/pubspec.lock @@ -166,31 +166,31 @@ packages: path: ".." relative: true source: path - version: "0.1.9+1" + version: "0.1.10" splitio_android: dependency: transitive description: name: splitio_android - sha256: b7ddd9f8a694ed610dd3ecd770f16d4ce016c3211d2f56fc5a094ef58bc543fb + sha256: b2ebb1ef9c9f1399b5dca7b008dd90f1cdf3c05da4da74154ff0a5489bafd114 url: "https://pub.dev" source: hosted - version: "0.1.9+1" + version: "0.1.10" splitio_ios: dependency: transitive description: name: splitio_ios - sha256: e9b5427a7c8efa67846a5ccbe70d13d3286f50f382b369416bff7c509478b50f + sha256: bf59562ef13c55b528886f3f9383ec4a5608d9de42e910256ba7fb025b310fa0 url: "https://pub.dev" source: hosted - version: "0.1.9" + version: "0.1.10" splitio_platform_interface: dependency: transitive description: name: splitio_platform_interface - sha256: eb0ec278e782bb403856f0921d2023ed8ed1a9e97eafb0f3de5cc4a107d1e04f + sha256: "2f0457991d18d654486264a66dacf54c7cf23cd88bbb73ed299d69dbbc2fd49b" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.5.0" stack_trace: dependency: transitive description: 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/pubspec.yaml b/splitio/pubspec.yaml index 4acfba3..5d655e9 100644 --- a/splitio/pubspec.yaml +++ b/splitio/pubspec.yaml @@ -1,6 +1,6 @@ name: splitio description: Official plugin for split.io, the platform for controlled rollouts, which serves features to your users via feature flags to manage your complete customer experience. -version: 0.1.9+1 +version: 0.1.10 homepage: https://split.io/ repository: https://github.com/splitio/flutter-sdk-plugin/tree/main/splitio/ @@ -19,9 +19,9 @@ 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.10 + splitio_ios: ^0.1.10 + splitio_platform_interface: ^1.5.0 dev_dependencies: flutter_test: diff --git a/splitio_android/CHANGELOG.md b/splitio_android/CHANGELOG.md index c54fc7d..3195dac 100644 --- a/splitio_android/CHANGELOG.md +++ b/splitio_android/CHANGELOG.md @@ -1,3 +1,10 @@ +# 0.1.10 (Oct 18, 2024) +* Updated Android SDK to `4.2.2` + +# 0.1.10-rc.2 (Oct 17, 2024) + +# 0.1.10-rc.1 (Oct 17, 2024) + # 0.1.9+1 (Jun 7, 2024) * Updated Android SDK to `4.1.1` 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..29282f0 100644 --- a/splitio_android/pubspec.yaml +++ b/splitio_android/pubspec.yaml @@ -1,7 +1,7 @@ name: splitio_android description: The official Android implementation of splitio Flutter plugin. repository: https://github.com/splitio/flutter-sdk-plugin/tree/main/splitio_android -version: 0.1.9+1 +version: 0.1.10 environment: sdk: ">=2.16.2 <4.0.0" @@ -19,7 +19,7 @@ flutter: dependencies: flutter: sdk: flutter - splitio_platform_interface: ^1.4.0 + splitio_platform_interface: ^1.5.0 dev_dependencies: flutter_test: diff --git a/splitio_ios/CHANGELOG.md b/splitio_ios/CHANGELOG.md index 515ca93..e0c647f 100644 --- a/splitio_ios/CHANGELOG.md +++ b/splitio_ios/CHANGELOG.md @@ -1,3 +1,10 @@ +# 0.1.10 (Oct 18, 2024) +* Updated iOS SDK to `2.26.1` + +# 0.1.10-rc.2 (Oct 17, 2024) + +# 0.1.10-rc.1 (Oct 17, 2024) + # 0.1.9 (May 22, 2024) * Updated iOS SDK to `2.25.0` 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. diff --git a/splitio_ios/pubspec.yaml b/splitio_ios/pubspec.yaml index 151c673..9a08683 100644 --- a/splitio_ios/pubspec.yaml +++ b/splitio_ios/pubspec.yaml @@ -1,7 +1,7 @@ name: splitio_ios description: The official iOS implementation of splitio Flutter plugin. repository: https://github.com/splitio/flutter-sdk-plugin/tree/main/splitio_ios -version: 0.1.9 +version: 0.1.10 environment: sdk: ">=2.16.2 <4.0.0" @@ -18,7 +18,7 @@ flutter: dependencies: flutter: sdk: flutter - splitio_platform_interface: ^1.4.0 + splitio_platform_interface: ^1.5.0 dev_dependencies: flutter_test: diff --git a/splitio_platform_interface/CHANGELOG.md b/splitio_platform_interface/CHANGELOG.md index 83981ae..3e5e7e1 100644 --- a/splitio_platform_interface/CHANGELOG.md +++ b/splitio_platform_interface/CHANGELOG.md @@ -1,3 +1,10 @@ +# 1.5.0 (Oct 18, 2024) +* Added certificate pinning functionality. This feature allows you to pin a certificate to the SDK, ensuring that the SDK only communicates with servers that present this certificate. Read more in our documentation. + +# 1.5.0-rc.2 (Oct 17, 2024) + +# 1.5.0-rc.1 (Oct 17, 2024) + # 1.4.0 (Nov 9, 2023) * Added support for Flag Sets, which enables grouping feature flags and interacting with the group rather than individually (more details in our documentation): * Added new variations of the get treatment methods to support evaluating flags in given flag set/s. diff --git a/splitio_platform_interface/lib/split_certificate_pinning_configuration.dart b/splitio_platform_interface/lib/split_certificate_pinning_configuration.dart new file mode 100644 index 0000000..78b9a0b --- /dev/null +++ b/splitio_platform_interface/lib/split_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..e6a12fc 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/split_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. + /// + /// [certificatePinningConfiguration] Certificate pinning configuration. Pins need to have the format of a base64 SHA-256 or base64 SHA-1 hashes of the SPKI (ex.: "sha256/7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y="). SplitConfiguration({ int? featuresRefreshRate, int? segmentsRefreshRate, @@ -70,6 +73,7 @@ class SplitConfiguration { bool? encryptionEnabled, SplitLogLevel? logLevel, int? readyTimeout = 10, + CertificatePinningConfiguration? certificatePinningConfiguration, }) { if (featuresRefreshRate != null) { configurationMap['featuresRefreshRate'] = featuresRefreshRate; @@ -175,6 +179,13 @@ class SplitConfiguration { if (readyTimeout != null) { configurationMap['readyTimeout'] = readyTimeout; } + + if (certificatePinningConfiguration != null && + certificatePinningConfiguration.pins.isNotEmpty) { + configurationMap['certificatePinningConfiguration'] = { + 'pins': certificatePinningConfiguration.pins + }; + } } } diff --git a/splitio_platform_interface/pubspec.yaml b/splitio_platform_interface/pubspec.yaml index 7869a30..72db712 100644 --- a/splitio_platform_interface/pubspec.yaml +++ b/splitio_platform_interface/pubspec.yaml @@ -2,7 +2,7 @@ name: splitio_platform_interface description: A common platform interface for the splitio plugin. # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 1.4.0 +version: 1.5.0 repository: https://github.com/splitio/flutter-sdk-plugin/tree/main/splitio_platform_interface environment: 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..e8c43d2 --- /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/split_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..a98d9ce 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/split_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, + certificatePinningConfiguration: 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']['pins'], { + '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'], []);