Create header files for discussion of possible flow audit api.

Fix compile error

Address PR comments

Change from a general interface to a restricted set of audit event types.

Fixup after rebase
This commit is contained in:
Matthew Nesbit
2017-05-02 15:09:31 +01:00
parent 9d19473578
commit 540fd746bb
10 changed files with 236 additions and 8 deletions

View File

@ -168,10 +168,32 @@ abstract class FlowLogic<out T> {
return result
}
/**
* Flows can call this method to ensure that the active FlowInitiator is authorised for a particular action.
* This provides fine grained control over application level permissions, when RPC control over starting the flow is insufficient,
* or the permission is runtime dependent upon the choices made inside long lived flow code.
* For example some users may have restricted limits on how much cash they can transfer, or whether they can change certain fields.
* An audit event is always recorded whenever this method is used.
* If the permission is not granted for the FlowInitiator a FlowException is thrown.
* @param permissionName is a string representing the desired permission. Each flow is given a distinct namespace for these permissions.
* @param extraAuditData in the audit log for this permission check these extra key value pairs will be recorded.
*/
@Throws(FlowException::class)
fun checkFlowPermission(permissionName: String, extraAuditData: Map<String,String>) = stateMachine.checkFlowPermission(permissionName, extraAuditData)
/**
* Flows can call this method to record application level flow audit events
* @param eventType is a string representing the type of event. Each flow is given a distinct namespace for these names.
* @param comment a general human readable summary of the event.
* @param extraAuditData in the audit log for this permission check these extra key value pairs will be recorded.
*/
fun recordAuditEvent(eventType: String, comment: String, extraAuditData: Map<String,String>) = stateMachine.recordAuditEvent(eventType, comment, extraAuditData)
/**
* Override this to provide a [ProgressTracker]. If one is provided and stepped, the framework will do something
* helpful with the progress reports. If this flow is invoked as a subflow of another, then the
* tracker will be made a child of the current step in the parent. If it's null, this flow doesn't track
* helpful with the progress reports e.g record to the audit service. If this flow is invoked as a subflow of another,
* then the tracker will be made a child of the current step in the parent. If it's null, this flow doesn't track
* progress.
*
* Note that this has to return a tracker before the flow is invoked. You can't change your mind half way

View File

@ -10,6 +10,7 @@ import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.UntrustworthyData
import org.slf4j.Logger
import java.security.Principal
import java.util.*
/**
@ -18,14 +19,23 @@ import java.util.*
* or via the Corda Shell [FlowInitiator.Shell].
*/
@CordaSerializable
sealed class FlowInitiator {
sealed class FlowInitiator : Principal {
/** Started using [net.corda.core.messaging.CordaRPCOps.startFlowDynamic]. */
data class RPC(val username: String) : FlowInitiator()
data class RPC(val username: String) : FlowInitiator() {
override fun getName(): String = username
}
/** Started when we get new session initiation request. */
data class Peer(val party: Party) : FlowInitiator()
data class Peer(val party: Party) : FlowInitiator() {
override fun getName(): String = party.name.toString()
}
/** Started as scheduled activity. */
data class Scheduled(val scheduledState: ScheduledStateRef) : FlowInitiator()
object Shell : FlowInitiator() // TODO When proper ssh access enabled, add username/use RPC?
data class Scheduled(val scheduledState: ScheduledStateRef) : FlowInitiator() {
override fun getName(): String = "Scheduler"
}
// TODO When proper ssh access enabled, add username/use RPC?
object Shell : FlowInitiator() {
override fun getName(): String = "Shell User"
}
}
/**
@ -59,6 +69,10 @@ interface FlowStateMachine<R> {
@Suspendable
fun waitForLedgerCommit(hash: SecureHash, sessionFlow: FlowLogic<*>): SignedTransaction
fun checkFlowPermission(permissionName: String, extraAuditData: Map<String,String>)
fun recordAuditEvent(eventType: String, comment: String, extraAuditData: Map<String,String>)
val serviceHub: ServiceHub
val logger: Logger
val id: StateMachineRunId

View File

@ -55,6 +55,12 @@ class ProgressTracker(vararg steps: Step) {
open class Step(open val label: String) {
open val changes: Observable<Change> get() = Observable.empty()
open fun childProgressTracker(): ProgressTracker? = null
/**
* A flow may populate this property with flow specific context data.
* The extra data will be recorded to the audit logs when the flow progresses.
* Even if empty the basic details (i.e. label) of the step will be recorded for audit purposes.
*/
open val extraAuditData: Map<String, String> get() = emptyMap()
}
// Sentinel objects. Overrides equals() to survive process restarts and serialization.