Skip to content

Commit

Permalink
[PM-9363] Disable cipher key encryption for older server versions (#4006
Browse files Browse the repository at this point in the history
)
  • Loading branch information
mpbw2 authored Oct 3, 2024
1 parent c8dcafe commit 1d84479
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package com.x8bit.bitwarden.data.platform.manager
import com.x8bit.bitwarden.data.platform.datasource.disk.model.ServerConfig
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
import com.x8bit.bitwarden.data.platform.repository.ServerConfigRepository
import com.x8bit.bitwarden.data.platform.util.isServerVersionAtLeast
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

private const val CIPHER_KEY_ENCRYPTION_KEY = "enableCipherKeyEncryption"
private const val CIPHER_KEY_ENC_MIN_SERVER_VERSION = "2024.2.0"

/**
* Primary implementation of [FeatureFlagManager].
Expand All @@ -16,7 +18,13 @@ class FeatureFlagManagerImpl(
) : FeatureFlagManager {

override val sdkFeatureFlags: Map<String, Boolean>
get() = mapOf(CIPHER_KEY_ENCRYPTION_KEY to true)
get() = mapOf(
CIPHER_KEY_ENCRYPTION_KEY to
isServerVersionAtLeast(
serverConfigRepository.serverConfigStateFlow.value,
CIPHER_KEY_ENC_MIN_SERVER_VERSION,
),
)

override fun <T : Any> getFeatureFlagFlow(key: FlagKey<T>): Flow<T> =
serverConfigRepository
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.x8bit.bitwarden.data.platform.util

import com.x8bit.bitwarden.data.platform.datasource.disk.model.ServerConfig
import kotlin.text.split
import kotlin.text.toIntOrNull

private const val VERSION_SEPARATOR = "."
private const val SUFFIX_SEPARATOR = "-"

/**
* Checks if the server version is greater than another provided version, returns true if it is.
*/
fun isServerVersionAtLeast(serverConfig: ServerConfig?, version: String): Boolean {
val serverVersion = serverConfig
?.serverData
?.version

if (serverVersion.isNullOrEmpty() || version.isEmpty()) {
return false
}

val serverVersionParts = getVersionComponents(serverVersion)
val otherVersionParts = getVersionComponents(version)

if (serverVersionParts.isNullOrEmpty() || otherVersionParts.isNullOrEmpty()) {
return false
}

// Must iterate through all indices to establish if versions are equal
for (i in serverVersionParts.indices) {
val serverPart = serverVersionParts.getOrNull(i)?.toIntOrNull() ?: 0
val otherPart = otherVersionParts.getOrNull(i)?.toIntOrNull() ?: 0

if (serverPart > otherPart) {
return true
} else if (serverPart < otherPart) {
return false
}
}

// Versions are equal
return true
}

/**
* Extracts the version components from a version string, disregarding any suffixes.
*/
private fun getVersionComponents(version: String?): List<String>? {
val versionComponents = version?.split(SUFFIX_SEPARATOR)?.first()
return versionComponents?.split(VERSION_SEPARATOR)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponse
import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson.ServerJson
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
import com.x8bit.bitwarden.data.platform.repository.util.FakeServerConfigRepository
import com.x8bit.bitwarden.data.platform.util.isServerVersionAtLeast
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.JsonPrimitive
import org.junit.Test
Expand All @@ -33,6 +34,53 @@ class FeatureFlagManagerTest {
assertEquals(expected, actual)
}

@Test
fun `server version is at least supplied version`() {
val result =
isServerVersionAtLeast(
fakeServerConfigRepository.serverConfigStateFlow.value,
"2024.2.0",
)

// This relies on the fake server version being "2024.7.0"
assertTrue(result)
}

@Test
fun `server version is not at least supplied version`() {
val result =
isServerVersionAtLeast(
fakeServerConfigRepository.serverConfigStateFlow.value,
"2024.12.0-suffix",
)

// This relies on the fake server version being "2024.7.0"
assertFalse(result)
}

@Test
fun `server version is the same as supplied version`() {
val result =
isServerVersionAtLeast(
fakeServerConfigRepository.serverConfigStateFlow.value,
"2024.7.0",
)

// This relies on the fake server version being "2024.7.0"
assertTrue(result)
}

@Test
fun `server version is not the same as blank supplied version`() {
val result =
isServerVersionAtLeast(
fakeServerConfigRepository.serverConfigStateFlow.value,
"",
)

assertFalse(result)
}

@Test
fun `ServerConfigRepository flow with value should trigger new flags`() = runTest {
fakeServerConfigRepository.serverConfigValue = null
Expand Down

0 comments on commit 1d84479

Please sign in to comment.