mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 13:07:02 +00:00
ABAC Policy instead of tag
This commit is contained in:
parent
d95189e36f
commit
f95e8b8645
@ -298,6 +298,70 @@ object AbacRuleEngine {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Execute all active ABAC rules with a specific policy (OR logic - at least one must pass)
|
||||
* @param logic The logic to apply: "AND" (all must pass), "OR" (any must pass), "XOR" (exactly one must pass)
|
||||
*
|
||||
* @param policy The policy to filter rules by
|
||||
* @param authenticatedUserId The ID of the authenticated user
|
||||
* @param onBehalfOfUserId Optional ID of user being acted on behalf of
|
||||
* @param userId The ID of the target user to evaluate
|
||||
* @param callContext Call context for fetching objects
|
||||
* @param bankId Optional bank ID
|
||||
* @param accountId Optional account ID
|
||||
* @param viewId Optional view ID
|
||||
* @param transactionId Optional transaction ID
|
||||
* @param transactionRequestId Optional transaction request ID
|
||||
* @param customerId Optional customer ID
|
||||
* @return Box[Boolean] - Full(true) if at least one rule passes (OR logic), Full(false) if all fail
|
||||
*/
|
||||
def executeRulesByPolicy(
|
||||
policy: String,
|
||||
authenticatedUserId: String,
|
||||
onBehalfOfUserId: Option[String] = None,
|
||||
userId: Option[String] = None,
|
||||
callContext: CallContext,
|
||||
bankId: Option[String] = None,
|
||||
accountId: Option[String] = None,
|
||||
viewId: Option[String] = None,
|
||||
transactionId: Option[String] = None,
|
||||
transactionRequestId: Option[String] = None,
|
||||
customerId: Option[String] = None
|
||||
): Box[Boolean] = {
|
||||
val rules = MappedAbacRuleProvider.getActiveAbacRulesByPolicy(policy)
|
||||
|
||||
if (rules.isEmpty) {
|
||||
// No rules for this policy - default to allow
|
||||
Full(true)
|
||||
} else {
|
||||
// Execute all rules and check if at least one passes
|
||||
val results = rules.map { rule =>
|
||||
executeRule(
|
||||
ruleId = rule.abacRuleId,
|
||||
authenticatedUserId = authenticatedUserId,
|
||||
onBehalfOfUserId = onBehalfOfUserId,
|
||||
userId = userId,
|
||||
callContext = callContext,
|
||||
bankId = bankId,
|
||||
accountId = accountId,
|
||||
viewId = viewId,
|
||||
transactionId = transactionId,
|
||||
transactionRequestId = transactionRequestId,
|
||||
customerId = customerId
|
||||
)
|
||||
}
|
||||
|
||||
// Count successes and failures
|
||||
val successes = results.filter {
|
||||
case Full(true) => true
|
||||
case _ => false
|
||||
}
|
||||
|
||||
// At least one rule must pass (OR logic)
|
||||
Full(successes.nonEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate ABAC rule code by attempting to compile it
|
||||
*
|
||||
|
||||
@ -14,6 +14,7 @@ trait AbacRuleTrait {
|
||||
def ruleCode: String
|
||||
def isActive: Boolean
|
||||
def description: String
|
||||
def policy: String
|
||||
def createdByUserId: String
|
||||
def updatedByUserId: String
|
||||
}
|
||||
@ -30,6 +31,7 @@ class AbacRule extends AbacRuleTrait with LongKeyedMapper[AbacRule] with IdPK wi
|
||||
override def defaultValue = true
|
||||
}
|
||||
object Description extends MappedText(this)
|
||||
object Policy extends MappedText(this)
|
||||
object CreatedByUserId extends MappedString(this, 255)
|
||||
object UpdatedByUserId extends MappedString(this, 255)
|
||||
|
||||
@ -38,6 +40,7 @@ class AbacRule extends AbacRuleTrait with LongKeyedMapper[AbacRule] with IdPK wi
|
||||
override def ruleCode: String = RuleCode.get
|
||||
override def isActive: Boolean = IsActive.get
|
||||
override def description: String = Description.get
|
||||
override def policy: String = Policy.get
|
||||
override def createdByUserId: String = CreatedByUserId.get
|
||||
override def updatedByUserId: String = UpdatedByUserId.get
|
||||
}
|
||||
@ -51,10 +54,13 @@ trait AbacRuleProvider {
|
||||
def getAbacRuleByName(ruleName: String): Box[AbacRuleTrait]
|
||||
def getAllAbacRules(): List[AbacRuleTrait]
|
||||
def getActiveAbacRules(): List[AbacRuleTrait]
|
||||
def getAbacRulesByPolicy(policy: String): List[AbacRuleTrait]
|
||||
def getActiveAbacRulesByPolicy(policy: String): List[AbacRuleTrait]
|
||||
def createAbacRule(
|
||||
ruleName: String,
|
||||
ruleCode: String,
|
||||
description: String,
|
||||
policy: String,
|
||||
isActive: Boolean,
|
||||
createdBy: String
|
||||
): Box[AbacRuleTrait]
|
||||
@ -63,6 +69,7 @@ trait AbacRuleProvider {
|
||||
ruleName: String,
|
||||
ruleCode: String,
|
||||
description: String,
|
||||
policy: String,
|
||||
isActive: Boolean,
|
||||
updatedBy: String
|
||||
): Box[AbacRuleTrait]
|
||||
@ -87,10 +94,23 @@ object MappedAbacRuleProvider extends AbacRuleProvider {
|
||||
AbacRule.findAll(By(AbacRule.IsActive, true))
|
||||
}
|
||||
|
||||
override def getAbacRulesByPolicy(policy: String): List[AbacRuleTrait] = {
|
||||
AbacRule.findAll().filter { rule =>
|
||||
rule.policy.split(",").map(_.trim).contains(policy)
|
||||
}
|
||||
}
|
||||
|
||||
override def getActiveAbacRulesByPolicy(policy: String): List[AbacRuleTrait] = {
|
||||
AbacRule.findAll(By(AbacRule.IsActive, true)).filter { rule =>
|
||||
rule.policy.split(",").map(_.trim).contains(policy)
|
||||
}
|
||||
}
|
||||
|
||||
override def createAbacRule(
|
||||
ruleName: String,
|
||||
ruleCode: String,
|
||||
description: String,
|
||||
policy: String,
|
||||
isActive: Boolean,
|
||||
createdBy: String
|
||||
): Box[AbacRuleTrait] = {
|
||||
@ -99,6 +119,7 @@ object MappedAbacRuleProvider extends AbacRuleProvider {
|
||||
.RuleName(ruleName)
|
||||
.RuleCode(ruleCode)
|
||||
.Description(description)
|
||||
.Policy(policy)
|
||||
.IsActive(isActive)
|
||||
.CreatedByUserId(createdBy)
|
||||
.UpdatedByUserId(createdBy)
|
||||
@ -111,6 +132,7 @@ object MappedAbacRuleProvider extends AbacRuleProvider {
|
||||
ruleName: String,
|
||||
ruleCode: String,
|
||||
description: String,
|
||||
policy: String,
|
||||
isActive: Boolean,
|
||||
updatedBy: String
|
||||
): Box[AbacRuleTrait] = {
|
||||
@ -121,6 +143,7 @@ object MappedAbacRuleProvider extends AbacRuleProvider {
|
||||
.RuleName(ruleName)
|
||||
.RuleCode(ruleCode)
|
||||
.Description(description)
|
||||
.Policy(policy)
|
||||
.IsActive(isActive)
|
||||
.UpdatedByUserId(updatedBy)
|
||||
.saveMe()
|
||||
|
||||
@ -266,6 +266,19 @@ object Constant extends MdcLoggable {
|
||||
// ABAC Cache Prefixes (with global namespace and versioning)
|
||||
def ABAC_RULE_PREFIX: String = getVersionedCachePrefix(ABAC_RULE_NAMESPACE)
|
||||
|
||||
// ABAC Policy Constants
|
||||
final val ABAC_POLICY_ACCOUNT_ACCESS = "account-access"
|
||||
|
||||
// List of all ABAC Policies
|
||||
final val ABAC_POLICIES: List[String] = List(
|
||||
ABAC_POLICY_ACCOUNT_ACCESS
|
||||
)
|
||||
|
||||
// Map of ABAC Policies to their descriptions
|
||||
final val ABAC_POLICY_DESCRIPTIONS: Map[String, String] = Map(
|
||||
ABAC_POLICY_ACCOUNT_ACCESS -> "Rules for controlling access to account information and account-related operations"
|
||||
)
|
||||
|
||||
final val CAN_SEE_TRANSACTION_OTHER_BANK_ACCOUNT = "can_see_transaction_other_bank_account"
|
||||
final val CAN_SEE_TRANSACTION_METADATA = "can_see_transaction_metadata"
|
||||
final val CAN_SEE_TRANSACTION_DESCRIPTION = "can_see_transaction_description"
|
||||
|
||||
@ -27,7 +27,7 @@ import code.api.v5_0_0.{ViewJsonV500, ViewsJsonV500}
|
||||
import code.api.v5_1_0.{JSONFactory510, PostCustomerLegalNameJsonV510}
|
||||
import code.api.dynamic.entity.helper.{DynamicEntityHelper, DynamicEntityInfo}
|
||||
import code.api.v6_0_0.JSONFactory600.{AddUserToGroupResponseJsonV600, DynamicEntityDiagnosticsJsonV600, DynamicEntityIssueJsonV600, GroupEntitlementJsonV600, GroupEntitlementsJsonV600, GroupJsonV600, GroupsJsonV600, PostGroupJsonV600, PostGroupMembershipJsonV600, PostResetPasswordUrlJsonV600, PutGroupJsonV600, ReferenceTypeJsonV600, ReferenceTypesJsonV600, ResetPasswordUrlJsonV600, RoleWithEntitlementCountJsonV600, RolesWithEntitlementCountsJsonV600, ScannedApiVersionJsonV600, UpdateViewJsonV600, UserGroupMembershipJsonV600, UserGroupMembershipsJsonV600, ValidateUserEmailJsonV600, ValidateUserEmailResponseJsonV600, ViewJsonV600, ViewPermissionJsonV600, ViewPermissionsJsonV600, ViewsJsonV600, createAbacRuleJsonV600, createAbacRulesJsonV600, createActiveRateLimitsJsonV600, createCallLimitJsonV600, createRedisCallCountersJson}
|
||||
import code.api.v6_0_0.{AbacRuleJsonV600, AbacRuleResultJsonV600, AbacRulesJsonV600, CacheConfigJsonV600, CacheInfoJsonV600, CacheNamespaceInfoJsonV600, CreateAbacRuleJsonV600, CurrentConsumerJsonV600, ExecuteAbacRuleJsonV600, InMemoryCacheStatusJsonV600, RedisCacheStatusJsonV600, UpdateAbacRuleJsonV600}
|
||||
import code.api.v6_0_0.{AbacRuleJsonV600, AbacRuleResultJsonV600, AbacRulesJsonV600, CacheConfigJsonV600, CacheInfoJsonV600, CacheNamespaceInfoJsonV600, CreateAbacRuleJsonV600, CurrentConsumerJsonV600, ExecuteAbacRuleJsonV600, InMemoryCacheStatusJsonV600, RedisCacheStatusJsonV600, UpdateAbacRuleJsonV600, AbacPoliciesJsonV600, AbacPolicyJsonV600}
|
||||
import code.api.v6_0_0.OBPAPI6_0_0
|
||||
import code.abacrule.{AbacRuleEngine, MappedAbacRuleProvider}
|
||||
import code.metrics.APIMetrics
|
||||
@ -4732,6 +4732,7 @@ trait APIMethods600 {
|
||||
rule_name = "admin_only",
|
||||
rule_code = """user.emailAddress.contains("admin")""",
|
||||
description = "Only allow access to users with admin email",
|
||||
policy = "user-access,admin",
|
||||
is_active = true
|
||||
),
|
||||
AbacRuleJsonV600(
|
||||
@ -4740,6 +4741,7 @@ trait APIMethods600 {
|
||||
rule_code = """user.emailAddress.contains("admin")""",
|
||||
is_active = true,
|
||||
description = "Only allow access to users with admin email",
|
||||
policy = "user-access,admin",
|
||||
created_by_user_id = "user123",
|
||||
updated_by_user_id = "user123"
|
||||
),
|
||||
@ -4779,6 +4781,7 @@ trait APIMethods600 {
|
||||
ruleName = createJson.rule_name,
|
||||
ruleCode = createJson.rule_code,
|
||||
description = createJson.description,
|
||||
policy = createJson.policy,
|
||||
isActive = createJson.is_active,
|
||||
createdBy = user.userId
|
||||
)
|
||||
@ -4815,6 +4818,7 @@ trait APIMethods600 {
|
||||
rule_code = """user.emailAddress.contains("admin")""",
|
||||
is_active = true,
|
||||
description = "Only allow access to users with admin email",
|
||||
policy = "user-access,admin",
|
||||
created_by_user_id = "user123",
|
||||
updated_by_user_id = "user123"
|
||||
),
|
||||
@ -4870,6 +4874,7 @@ trait APIMethods600 {
|
||||
rule_code = """user.emailAddress.contains("admin")""",
|
||||
is_active = true,
|
||||
description = "Only allow access to users with admin email",
|
||||
policy = "user-access,admin",
|
||||
created_by_user_id = "user123",
|
||||
updated_by_user_id = "user123"
|
||||
)
|
||||
@ -4899,6 +4904,75 @@ trait APIMethods600 {
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
getAbacRulesByPolicy,
|
||||
implementedInApiVersion,
|
||||
nameOf(getAbacRulesByPolicy),
|
||||
"GET",
|
||||
"/management/abac-rules/policy/POLICY",
|
||||
"Get ABAC Rules by Policy",
|
||||
s"""Get all ABAC rules that belong to a specific policy.
|
||||
|
|
||||
|Multiple rules can share the same policy. Rules with multiple policies (comma-separated)
|
||||
|will be returned if any of their policies match the requested policy.
|
||||
|
|
||||
|**Documentation:**
|
||||
|- ${Glossary.getGlossaryItemLink("ABAC_Simple_Guide")} - Getting started with ABAC rules
|
||||
|- ${Glossary.getGlossaryItemLink("ABAC_Parameters_Summary")} - Complete list of all 18 parameters
|
||||
|- ${Glossary.getGlossaryItemLink("ABAC_Object_Properties_Reference")} - Detailed property reference
|
||||
|
|
||||
|${userAuthenticationMessage(true)}
|
||||
|
|
||||
|""".stripMargin,
|
||||
EmptyBody,
|
||||
AbacRulesJsonV600(
|
||||
abac_rules = List(
|
||||
AbacRuleJsonV600(
|
||||
abac_rule_id = "abc123",
|
||||
rule_name = "admin_only",
|
||||
rule_code = """user.emailAddress.contains("admin")""",
|
||||
is_active = true,
|
||||
description = "Only allow access to users with admin email",
|
||||
policy = "user-access,admin",
|
||||
created_by_user_id = "user123",
|
||||
updated_by_user_id = "user123"
|
||||
),
|
||||
AbacRuleJsonV600(
|
||||
abac_rule_id = "def456",
|
||||
rule_name = "admin_department_check",
|
||||
rule_code = """user.department == "admin"""",
|
||||
is_active = true,
|
||||
description = "Check if user is in admin department",
|
||||
policy = "admin",
|
||||
created_by_user_id = "user123",
|
||||
updated_by_user_id = "user123"
|
||||
)
|
||||
)
|
||||
),
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagABAC),
|
||||
Some(List(canGetAbacRule))
|
||||
)
|
||||
|
||||
lazy val getAbacRulesByPolicy: OBPEndpoint = {
|
||||
case "management" :: "abac-rules" :: "policy" :: policy :: Nil JsonGet _ => {
|
||||
cc => implicit val ec = EndpointContext(Some(cc))
|
||||
for {
|
||||
(Full(user), callContext) <- authenticatedAccess(cc)
|
||||
_ <- NewStyle.function.hasEntitlement("", user.userId, canGetAbacRule, callContext)
|
||||
rules <- Future {
|
||||
MappedAbacRuleProvider.getAbacRulesByPolicy(policy)
|
||||
}
|
||||
} yield {
|
||||
(createAbacRulesJsonV600(rules), HttpCode.`200`(callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
updateAbacRule,
|
||||
implementedInApiVersion,
|
||||
@ -4920,6 +4994,7 @@ trait APIMethods600 {
|
||||
rule_name = "admin_only_updated",
|
||||
rule_code = """user.emailAddress.contains("admin") && user.provider == "obp"""",
|
||||
description = "Only allow access to OBP admin users",
|
||||
policy = "user-access,admin,obp",
|
||||
is_active = true
|
||||
),
|
||||
AbacRuleJsonV600(
|
||||
@ -4928,6 +5003,7 @@ trait APIMethods600 {
|
||||
rule_code = """user.emailAddress.contains("admin") && user.provider == "obp"""",
|
||||
is_active = true,
|
||||
description = "Only allow access to OBP admin users",
|
||||
policy = "user-access,admin,obp",
|
||||
created_by_user_id = "user123",
|
||||
updated_by_user_id = "user456"
|
||||
),
|
||||
@ -4962,6 +5038,7 @@ trait APIMethods600 {
|
||||
ruleName = updateJson.rule_name,
|
||||
ruleCode = updateJson.rule_code,
|
||||
description = updateJson.description,
|
||||
policy = updateJson.policy,
|
||||
isActive = updateJson.is_active,
|
||||
updatedBy = user.userId
|
||||
)
|
||||
@ -5079,11 +5156,13 @@ trait APIMethods600 {
|
||||
rule_name = "Check User Identity",
|
||||
rule_code = "authenticatedUser.userId == user.userId",
|
||||
description = "Verify that the authenticated user matches the target user",
|
||||
policy = "user-access",
|
||||
is_active = true
|
||||
),
|
||||
AbacRuleExampleJsonV600(
|
||||
rule_name = "Check Specific Bank",
|
||||
rule_code = "bankOpt.isDefined && bankOpt.get.bankId.value == \"gh.29.uk\"",
|
||||
policy = "bank-access",
|
||||
description = "Verify that the bank context is defined and matches a specific bank ID",
|
||||
is_active = true
|
||||
)
|
||||
@ -5247,48 +5326,56 @@ trait APIMethods600 {
|
||||
rule_name = "Branch Manager Internal Account Access",
|
||||
rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"branch\" && accountAttributes.exists(aa => aa.name == \"branch\" && a.value == aa.value)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(_.accountType == \"CURRENT\")",
|
||||
description = "Allow GET access to current accounts when user has CanReadAccountsAtOneBank role and branch matches account's branch",
|
||||
policy = "account-access",
|
||||
is_active = true
|
||||
),
|
||||
AbacRuleExampleJsonV600(
|
||||
rule_name = "Internal Network High-Value Transaction Review",
|
||||
rule_code = "callContext.exists(_.ipAddress.exists(_.startsWith(\"10.\"))) && authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && transactionOpt.exists(_.amount > 10000)",
|
||||
description = "Allow users with CanReadTransactionsAtOneBank role on internal network to review high-value transactions over 10,000",
|
||||
policy = "transaction-access",
|
||||
is_active = true
|
||||
),
|
||||
AbacRuleExampleJsonV600(
|
||||
rule_name = "Department Head Same-Department Account Read where overdrawn",
|
||||
rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(ua => ua.name == \"department\" && accountAttributes.exists(aa => aa.name == \"department\" && ua.value == aa.value)) && callContext.exists(_.url.exists(_.contains(\"/accounts/\"))) && accountOpt.exists(_.balance < 0)",
|
||||
description = "Allow users with CanReadAccountsAtOneBank role to read overdrawn accounts in their department",
|
||||
policy = "account-access",
|
||||
is_active = true
|
||||
),
|
||||
AbacRuleExampleJsonV600(
|
||||
rule_name = "Manager Internal Network Transaction Approval",
|
||||
rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanCreateTransactionRequest\") && callContext.exists(_.ipAddress.exists(ip => ip.startsWith(\"10.\") || ip.startsWith(\"192.168.\"))) && transactionRequestOpt.exists(tr => tr.status == \"PENDING\" && tr.charge.value.toDouble < 50000)",
|
||||
description = "Allow users with CanCreateTransactionRequest role on internal network to approve pending transaction requests under 50,000",
|
||||
policy = "transaction-request",
|
||||
is_active = true
|
||||
),
|
||||
AbacRuleExampleJsonV600(
|
||||
rule_name = "KYC Officer Customer Creation from Branch",
|
||||
rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanCreateCustomer\") && authenticatedUserAttributes.exists(a => a.name == \"certification\" && a.value == \"kyc_certified\") && callContext.exists(_.verb.exists(_ == \"POST\")) && callContext.exists(_.ipAddress.exists(_.startsWith(\"10.20.\"))) && customerAttributes.exists(ca => ca.name == \"onboarding_status\" && ca.value == \"pending\")",
|
||||
description = "Allow users with CanCreateCustomer role and KYC certification to create customers via POST from branch network (10.20.x.x) when status is pending",
|
||||
policy = "customer-access",
|
||||
is_active = true
|
||||
),
|
||||
AbacRuleExampleJsonV600(
|
||||
rule_name = "International Team Foreign Currency Transaction",
|
||||
rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"team\" && a.value == \"international\") && callContext.exists(_.url.exists(_.contains(\"/transactions/\"))) && transactionOpt.exists(t => t.currency != \"USD\" && t.amount < 100000) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"international_enabled\" && aa.value == \"true\"))",
|
||||
description = "Allow international team users with CanReadTransactionsAtOneBank role to access foreign currency transactions under 100k on international-enabled accounts",
|
||||
policy = "transaction-access",
|
||||
is_active = true
|
||||
),
|
||||
AbacRuleExampleJsonV600(
|
||||
rule_name = "Assistant with Limited Delegation Account View",
|
||||
rule_code = "onBehalfOfUserOpt.isDefined && onBehalfOfUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"assistant_of\" && onBehalfOfUserOpt.exists(u => a.value == u.userId)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"tier\" && List(\"gold\", \"platinum\").contains(aa.value)))",
|
||||
description = "Allow assistants to view gold/platinum accounts via GET when acting on behalf of a user with CanReadAccountsAtOneBank role",
|
||||
policy = "account-access",
|
||||
is_active = true
|
||||
),
|
||||
AbacRuleExampleJsonV600(
|
||||
rule_name = "Fraud Analyst High-Risk Transaction Access",
|
||||
rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && callContext.exists(c => c.verb.exists(_ == \"GET\") && c.implementedByPartialFunction.exists(_.contains(\"Transaction\"))) && transactionAttributes.exists(ta => ta.name == \"risk_score\" && ta.value.toInt >= 75) && transactionOpt.exists(_.status.exists(_ != \"COMPLETED\"))",
|
||||
description = "Allow users with CanReadTransactionsAtOneBank role to GET high-risk (score ≥75) non-completed transactions",
|
||||
policy = "transaction-access",
|
||||
is_active = true
|
||||
)
|
||||
),
|
||||
@ -5315,6 +5402,59 @@ trait APIMethods600 {
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
getAbacPolicies,
|
||||
implementedInApiVersion,
|
||||
nameOf(getAbacPolicies),
|
||||
"GET",
|
||||
"/management/abac-policies",
|
||||
"Get ABAC Policies",
|
||||
s"""Get the list of allowed ABAC policy names.
|
||||
|
|
||||
|ABAC rules are organized by policies. Each rule must have at least one policy assigned.
|
||||
|Rules can have multiple policies (comma-separated). This endpoint returns the list of
|
||||
|standardized policy names that should be used when creating or updating rules.
|
||||
|
|
||||
|${userAuthenticationMessage(true)}
|
||||
|
|
||||
|""".stripMargin,
|
||||
EmptyBody,
|
||||
AbacPoliciesJsonV600(
|
||||
policies = List(
|
||||
AbacPolicyJsonV600(
|
||||
policy = "account-access",
|
||||
description = "Rules for controlling access to account information"
|
||||
)
|
||||
)
|
||||
),
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagABAC),
|
||||
Some(List(canGetAbacRule))
|
||||
)
|
||||
|
||||
lazy val getAbacPolicies: OBPEndpoint = {
|
||||
case "management" :: "abac-policies" :: Nil JsonGet _ => {
|
||||
cc => implicit val ec = EndpointContext(Some(cc))
|
||||
for {
|
||||
(Full(user), callContext) <- authenticatedAccess(cc)
|
||||
_ <- NewStyle.function.hasEntitlement("", user.userId, canGetAbacRule, callContext)
|
||||
} yield {
|
||||
val policies = Constant.ABAC_POLICIES.map { policy =>
|
||||
AbacPolicyJsonV600(
|
||||
policy = policy,
|
||||
description = Constant.ABAC_POLICY_DESCRIPTIONS.getOrElse(policy, "No description available")
|
||||
)
|
||||
}
|
||||
|
||||
(AbacPoliciesJsonV600(policies), HttpCode.`200`(callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
validateAbacRule,
|
||||
implementedInApiVersion,
|
||||
|
||||
@ -380,6 +380,7 @@ case class CreateAbacRuleJsonV600(
|
||||
rule_name: String,
|
||||
rule_code: String,
|
||||
description: String,
|
||||
policy: String,
|
||||
is_active: Boolean
|
||||
)
|
||||
|
||||
@ -387,6 +388,7 @@ case class UpdateAbacRuleJsonV600(
|
||||
rule_name: String,
|
||||
rule_code: String,
|
||||
description: String,
|
||||
policy: String,
|
||||
is_active: Boolean
|
||||
)
|
||||
|
||||
@ -396,6 +398,7 @@ case class AbacRuleJsonV600(
|
||||
rule_code: String,
|
||||
is_active: Boolean,
|
||||
description: String,
|
||||
policy: String,
|
||||
created_by_user_id: String,
|
||||
updated_by_user_id: String
|
||||
)
|
||||
@ -462,6 +465,7 @@ case class AbacRuleExampleJsonV600(
|
||||
rule_name: String,
|
||||
rule_code: String,
|
||||
description: String,
|
||||
policy: String,
|
||||
is_active: Boolean
|
||||
)
|
||||
|
||||
@ -473,6 +477,15 @@ case class AbacRuleSchemaJsonV600(
|
||||
notes: List[String]
|
||||
)
|
||||
|
||||
case class AbacPolicyJsonV600(
|
||||
policy: String,
|
||||
description: String
|
||||
)
|
||||
|
||||
case class AbacPoliciesJsonV600(
|
||||
policies: List[AbacPolicyJsonV600]
|
||||
)
|
||||
|
||||
object JSONFactory600 extends CustomJsonFormats with MdcLoggable {
|
||||
|
||||
def createRedisCallCountersJson(
|
||||
@ -1086,6 +1099,7 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable {
|
||||
rule_code = rule.ruleCode,
|
||||
is_active = rule.isActive,
|
||||
description = rule.description,
|
||||
policy = rule.policy,
|
||||
created_by_user_id = rule.createdByUserId,
|
||||
updated_by_user_id = rule.updatedByUserId
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user