mirror of
https://github.com/corda/corda.git
synced 2024-12-19 21:17:58 +00:00
CORDA-2554 - Bootstrapper - option to include contracts to whitelist from signed JARs (#4712)
* NetworkBoostrapper can optionally whitelist contracts from signed jars based on include_whitelist.txt file. * refactoring, docs * logs * add ne parameters to the generateWhitelist method at the end * Addressing review comments. * CORDA-2577 disable non-downgrade rule - test fix and docs
This commit is contained in:
parent
5a4db990e7
commit
9da30b431f
@ -91,7 +91,8 @@ By default the Bootstrapper will whitelist all the contracts found in the unsign
|
||||
Whitelisted contracts are checked by `Zone constraints`, while contract classes from signed JARs will be checked by `Signature constraints`.
|
||||
To prevent certain contracts from unsigned JARs from being whitelisted, add their fully qualified class name in the ``exclude_whitelist.txt``.
|
||||
These will instead use the more restrictive ``HashAttachmentConstraint``.
|
||||
Refer to :doc:`api-contract-constraints` to understand the implication of different constraint types before adding ``exclude_whitelist.txt`` files.
|
||||
To add certain contracts from signed JARs to whitelist, add their fully qualified class name in the ``include_whitelist.txt``.
|
||||
Refer to :doc:`api-contract-constraints` to understand the implication of different constraint types before adding ``exclude_whitelist.txt`` or ``include_whitelist.txt`` files.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -247,8 +247,10 @@ internal constructor(private val initSerEnv: Boolean,
|
||||
println("Gathering notary identities")
|
||||
val notaryInfos = gatherNotaryInfos(nodeInfoFiles, configs)
|
||||
println("Generating contract implementations whitelist")
|
||||
// Only add contracts to the whitelist from unsigned jars
|
||||
val newWhitelist = generateWhitelist(existingNetParams, readExcludeWhitelist(directory), cordappJars.filter { !isSigned(it) }.map(contractsJarConverter))
|
||||
val signedJars = cordappJars.filter { isSigned(it) } // signed JARs are excluded by default, optionally include them in order to transition states from CZ whitelist to signature constraint
|
||||
val unsignedJars = cordappJars - signedJars
|
||||
val newWhitelist = generateWhitelist(existingNetParams, readExcludeWhitelist(directory), unsignedJars.map(contractsJarConverter),
|
||||
readIncludeWhitelist(directory), signedJars.map(contractsJarConverter))
|
||||
val newNetParams = installNetworkParameters(notaryInfos, newWhitelist, existingNetParams, nodeDirs, networkParametersOverrides)
|
||||
if (newNetParams != existingNetParams) {
|
||||
println("${if (existingNetParams == null) "New" else "Updated"} $newNetParams")
|
||||
|
@ -1,10 +1,7 @@
|
||||
package net.corda.nodeapi.internal.network
|
||||
|
||||
import net.corda.core.contracts.ContractClassName
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.exists
|
||||
import net.corda.core.internal.readAllLines
|
||||
import net.corda.core.internal.toMultiMap
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.node.services.AttachmentId
|
||||
import net.corda.nodeapi.internal.ContractsJar
|
||||
@ -12,15 +9,18 @@ import org.slf4j.LoggerFactory
|
||||
import java.nio.file.Path
|
||||
|
||||
private const val EXCLUDE_WHITELIST_FILE_NAME = "exclude_whitelist.txt"
|
||||
private const val INCLUDE_WHITELIST_FILE_NAME = "include_whitelist.txt"
|
||||
private val logger = LoggerFactory.getLogger("net.corda.nodeapi.internal.network.WhitelistGenerator")
|
||||
|
||||
fun generateWhitelist(networkParameters: NetworkParameters?,
|
||||
excludeContracts: List<ContractClassName>,
|
||||
cordappJars: List<ContractsJar>): Map<ContractClassName, List<AttachmentId>> {
|
||||
cordappJars: List<ContractsJar>,
|
||||
includeContracts: List<ContractClassName>,
|
||||
optionalCordappJars: List<ContractsJar>): Map<ContractClassName, List<AttachmentId>> {
|
||||
val existingWhitelist = networkParameters?.whitelistedContractImplementations ?: emptyMap()
|
||||
|
||||
if (excludeContracts.isNotEmpty()) {
|
||||
logger.info("Exclude contracts from whitelist: ${excludeContracts.joinToString()}")
|
||||
logger.info("Exclude contracts from $EXCLUDE_WHITELIST_FILE_NAME: ${excludeContracts.joinToString()}")
|
||||
existingWhitelist.keys.forEach {
|
||||
require(it !in excludeContracts) { "$it is already part of the existing whitelist and cannot be excluded." }
|
||||
}
|
||||
@ -30,14 +30,23 @@ fun generateWhitelist(networkParameters: NetworkParameters?,
|
||||
.flatMap { jar -> (jar.scan() - excludeContracts).map { it to jar.hash } }
|
||||
.toMultiMap()
|
||||
|
||||
return (newWhiteList.keys + existingWhitelist.keys).associateBy({ it }) {
|
||||
if (includeContracts.isNotEmpty())
|
||||
logger.info("Include contracts from $INCLUDE_WHITELIST_FILE_NAME: ${includeContracts.joinToString()} present in JARs: $optionalCordappJars.")
|
||||
|
||||
val newSignedJarsWhiteList = optionalCordappJars
|
||||
.flatMap { jar -> (jar.scan()).filter { includeContracts.contains(it) }.map { it to jar.hash } }
|
||||
.toMultiMap()
|
||||
|
||||
return (newWhiteList.keys + existingWhitelist.keys + newSignedJarsWhiteList.keys).associateBy({ it }) {
|
||||
val existingHashes = existingWhitelist[it] ?: emptyList()
|
||||
val newHashes = newWhiteList[it] ?: emptyList()
|
||||
(existingHashes + newHashes).distinct()
|
||||
val newHashesFormSignedJar = newSignedJarsWhiteList[it] ?: emptyList()
|
||||
(existingHashes + newHashes + newHashesFormSignedJar).distinct()
|
||||
}
|
||||
}
|
||||
|
||||
fun readExcludeWhitelist(directory: Path): List<String> {
|
||||
val file = directory / EXCLUDE_WHITELIST_FILE_NAME
|
||||
return if (file.exists()) file.readAllLines().map(String::trim) else emptyList()
|
||||
}
|
||||
fun readExcludeWhitelist(directory: Path): List<String> = readAllLines(directory / EXCLUDE_WHITELIST_FILE_NAME)
|
||||
|
||||
fun readIncludeWhitelist(directory: Path): List<String> = readAllLines(directory / INCLUDE_WHITELIST_FILE_NAME)
|
||||
|
||||
private fun readAllLines(path: Path) : List<String> = if (path.exists()) path.readAllLines().map(String::trim) else emptyList()
|
||||
|
@ -129,7 +129,9 @@ class WhitelistGeneratorTest {
|
||||
return generateWhitelist(
|
||||
testNetworkParameters(whitelistedContractImplementations = existingWhitelist),
|
||||
excludeContracts,
|
||||
contractJars
|
||||
contractJars,
|
||||
emptyList(),
|
||||
emptyList()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user