Corda-1286 Fix embedded shell when rpc users from remoted database (#2910)

This commit is contained in:
szymonsztuka 2018-04-03 19:13:41 +01:00 committed by Michele Sollecito
parent 7deb802547
commit 7ec65901b6
4 changed files with 40 additions and 6 deletions

View File

@ -23,6 +23,7 @@ import net.corda.node.VersionInfo
import net.corda.node.internal.artemis.ArtemisBroker
import net.corda.node.internal.artemis.BrokerAddresses
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.internal.security.RPCSecurityManagerWithAdditionalUser
import net.corda.node.internal.security.RPCSecurityManagerImpl
import net.corda.node.serialization.KryoServerSerializationScheme
import net.corda.node.services.api.NodePropertiesStore
@ -30,7 +31,7 @@ import net.corda.node.services.api.SchemaService
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.config.SecurityConfiguration
import net.corda.node.services.config.VerifierType
import net.corda.node.services.config.shell.shellUser
import net.corda.node.services.config.shell.localShellUser
import net.corda.node.services.config.shouldInitCrashShell
import net.corda.node.services.messaging.*
import net.corda.node.services.rpc.ArtemisRpcBroker
@ -162,7 +163,9 @@ open class Node(configuration: NodeConfiguration,
val securityManagerConfig = configuration.security?.authService ?:
SecurityConfiguration.AuthService.fromUsers(configuration.rpcUsers)
securityManager = RPCSecurityManagerImpl(if (configuration.shouldInitCrashShell()) securityManagerConfig.copyWithAdditionalUser(configuration.shellUser()) else securityManagerConfig)
securityManager = with(RPCSecurityManagerImpl(securityManagerConfig)) {
if (configuration.shouldInitCrashShell()) RPCSecurityManagerWithAdditionalUser(this, localShellUser()) else this
}
val serverAddress = configuration.messagingServerAddress ?: makeLocalMessageBroker(networkParameters)
val rpcServerAddresses = if (configuration.rpcOptions.standAloneBroker) {

View File

@ -186,7 +186,7 @@ private object RPCPermissionResolver : PermissionResolver {
}
}
private class ShiroAuthorizingSubject(
class ShiroAuthorizingSubject(
private val subjectId: PrincipalCollection,
private val manager: DefaultSecurityManager) : AuthorizingSubject {
@ -201,7 +201,7 @@ private fun buildCredentialMatcher(type: PasswordEncryption) = when (type) {
PasswordEncryption.SHIRO_1_CRYPT -> PasswordMatcher()
}
private class InMemoryRealm(users: List<User>,
class InMemoryRealm(users: List<User>,
realmId: String,
passwordEncryption: PasswordEncryption = PasswordEncryption.NONE) : AuthorizingRealm() {

View File

@ -0,0 +1,32 @@
package net.corda.node.internal.security
import net.corda.nodeapi.internal.config.User
import org.apache.shiro.mgt.DefaultSecurityManager
import org.apache.shiro.subject.SimplePrincipalCollection
import javax.security.auth.login.FailedLoginException
/**
* Wrapper for [RPCSecurityManager] which creates in-memory [AuthorizingSubject] for [User].
* Can be used to add on a specific [User] on top of the principals provided by the [RPCSecurityManager] realm.
*/
class RPCSecurityManagerWithAdditionalUser(private val delegate: RPCSecurityManager, private val user: User) : RPCSecurityManager by delegate {
private val realmId = user.username + "Realm"
private val shellAuthorizingSubject = ShiroAuthorizingSubject(subjectId = SimplePrincipalCollection(user.username, id.value),
manager = DefaultSecurityManager(InMemoryRealm(listOf(user), realmId)))
@Throws(FailedLoginException::class)
override fun authenticate(principal: String, password: Password): AuthorizingSubject =
if (user.username == principal && user.password == password.valueAsString) {
shellAuthorizingSubject
} else {
delegate.authenticate(principal, password)
}
override fun buildSubject(principal: String): AuthorizingSubject =
if (user.username == principal) {
shellAuthorizingSubject
} else {
delegate.buildSubject(principal)
}
}

View File

@ -40,5 +40,4 @@ fun NodeConfiguration.toShellConfig(): ShellConfiguration {
noLocalShell = this.noLocalShell)
}
private fun localShellUser() = User("shell", "shell", setOf(Permissions.all()))
fun NodeConfiguration.shellUser() = shouldInitCrashShell()?.let { localShellUser() }
fun localShellUser() = User("shell", "shell", setOf(Permissions.all()))