CraftCamp /
php-abac
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace PhpAbac; |
||
| 4 | |||
| 5 | use PhpAbac\Manager\{ |
||
| 6 | AttributeManager, |
||
| 7 | CacheManager, |
||
| 8 | ComparisonManager, |
||
| 9 | PolicyRuleManager |
||
| 10 | }; |
||
| 11 | use PhpAbac\Model\PolicyRuleAttribute; |
||
| 12 | |||
| 13 | final class Abac |
||
| 14 | { |
||
| 15 | /** @var PolicyRuleManager **/ |
||
| 16 | private $policyRuleManager; |
||
| 17 | /** @var AttributeManager **/ |
||
| 18 | private $attributeManager; |
||
| 19 | /** @var CacheManager **/ |
||
| 20 | private $cacheManager; |
||
| 21 | /** @var ComparisonManager **/ |
||
| 22 | private $comparisonManager; |
||
| 23 | /** @var array **/ |
||
| 24 | private $errors; |
||
| 25 | |||
| 26 | 4 | public function __construct(PolicyRuleManager $policyRuleManager, AttributeManager $attributeManager, ComparisonManager $comparisonManager, CacheManager $cacheManager) |
|
| 27 | { |
||
| 28 | 4 | $this->attributeManager = $attributeManager; |
|
| 29 | 4 | $this->policyRuleManager = $policyRuleManager; |
|
| 30 | 4 | $this->cacheManager = $cacheManager; |
|
| 31 | 4 | $this->comparisonManager = $comparisonManager; |
|
| 32 | 4 | } |
|
| 33 | |||
| 34 | /** |
||
| 35 | * Return true if both user and object respects all the rules conditions |
||
| 36 | * If the objectId is null, policy rules about its attributes will be ignored |
||
| 37 | * In case of mismatch between attributes and expected values, |
||
| 38 | * an array with the concerned attributes slugs will be returned. |
||
| 39 | * |
||
| 40 | * Available options are : |
||
| 41 | * * dynamic_attributes: array |
||
| 42 | * * cache_result: boolean |
||
| 43 | * * cache_ttl: integer |
||
| 44 | * * cache_driver: string |
||
| 45 | * |
||
| 46 | * Available cache drivers are : |
||
| 47 | * * memory |
||
| 48 | */ |
||
| 49 | 4 | public function enforce(string $ruleName, $user, $resource = null, array $options = []): bool |
|
| 50 | { |
||
| 51 | 4 | $this->errors = []; |
|
| 52 | // If there is dynamic attributes, we pass them to the comparison manager |
||
| 53 | // When a comparison will be performed, the passed values will be retrieved and used |
||
| 54 | 4 | if (isset($options[ 'dynamic_attributes' ])) { |
|
| 55 | 1 | $this->comparisonManager->setDynamicAttributes($options[ 'dynamic_attributes' ]); |
|
| 56 | } |
||
| 57 | // Retrieve cache value for the current rule and values if cache item is valid |
||
| 58 | 4 | if (($cacheResult = isset($options[ 'cache_result' ]) && $options[ 'cache_result' ] === true) === true) { |
|
| 59 | $cacheItem = $this->cacheManager->getItem("$ruleName-{$user->getId()}-" . (($resource !== null) ? $resource->getId() : ''), (isset($options[ 'cache_driver' ])) ? $options[ 'cache_driver' ] : null, (isset($options[ 'cache_ttl' ])) ? $options[ 'cache_ttl' ] : null); |
||
| 60 | // We check if the cache value s valid before returning it |
||
| 61 | if (($cacheValue = $cacheItem->get()) !== null) { |
||
| 62 | return $cacheValue; |
||
| 63 | } |
||
| 64 | } |
||
| 65 | 4 | $policyRules = $this->policyRuleManager->getRule($ruleName, $user, $resource); |
|
| 66 | |||
| 67 | 4 | foreach ($policyRules as $policyRule) { |
|
| 68 | // For each policy rule attribute, we retrieve the attribute value and proceed configured extra data |
||
| 69 | 4 | foreach ($policyRule->getPolicyRuleAttributes() as $pra) { |
|
| 70 | /** @var PolicyRuleAttribute $pra */ |
||
| 71 | 4 | $attribute = $pra->getAttribute(); |
|
| 72 | |||
| 73 | 4 | $getter_params = $this->prepareGetterParams($pra->getGetterParams(), $user, $resource); |
|
| 74 | 4 | $attribute->setValue($this->attributeManager->retrieveAttribute($attribute, $user, $resource, $getter_params)); |
|
| 75 | 4 | if (count($pra->getExtraData()) > 0) { |
|
| 76 | 3 | $this->processExtraData($pra, $user, $resource); |
|
| 77 | } |
||
| 78 | 4 | $this->comparisonManager->compare($pra); |
|
| 79 | } |
||
| 80 | // The given result could be an array of rejected attributes or true |
||
| 81 | // True means that the rule is correctly enforced for the given user and resource |
||
| 82 | 4 | $this->errors = $this->comparisonManager->getResult(); |
|
| 83 | 4 | if (count($this->errors) === 0) { |
|
| 84 | 4 | break; |
|
| 85 | } |
||
| 86 | } |
||
| 87 | 4 | if ($cacheResult) { |
|
| 88 | $cacheItem->set((count($this->errors) > 0) ? $this->errors : true); |
||
| 89 | $this->cacheManager->save($cacheItem); |
||
| 90 | } |
||
| 91 | 4 | return count($this->errors) === 0; |
|
| 92 | } |
||
| 93 | |||
| 94 | 4 | public function getErrors(): array |
|
| 95 | { |
||
| 96 | 4 | return $this->errors; |
|
| 97 | } |
||
| 98 | |||
| 99 | /** |
||
| 100 | * Function to prepare Getter Params when getter require parameters ( this parameters must be specified in configuration file) |
||
| 101 | * |
||
| 102 | * @param $getter_params |
||
| 103 | * @param $user |
||
| 104 | * @param $resource |
||
| 105 | * |
||
| 106 | * @return array |
||
| 107 | */ |
||
| 108 | 4 | private function prepareGetterParams($getter_params, $user, $resource) |
|
| 109 | { |
||
| 110 | 4 | if (empty($getter_params)) { |
|
| 111 | 4 | return []; |
|
| 112 | } |
||
| 113 | 2 | $values = []; |
|
| 114 | 2 | foreach ($getter_params as $getter_name=>$params) { |
|
|
0 ignored issues
–
show
Coding Style
introduced
by
Loading history...
|
|||
| 115 | 2 | foreach ($params as $param) { |
|
| 116 | 2 | if ('@' !== $param[ 'param_name' ][ 0 ]) { |
|
| 117 | $values[$getter_name][] = $param[ 'param_value' ]; |
||
| 118 | } else { |
||
| 119 | 2 | $values[$getter_name][] = $this->attributeManager->retrieveAttribute($this->attributeManager->getAttribute($param[ 'param_value' ]), $user, $resource); |
|
| 120 | } |
||
| 121 | } |
||
| 122 | } |
||
| 123 | 2 | return $values; |
|
| 124 | } |
||
| 125 | |||
| 126 | 3 | private function processExtraData(PolicyRuleAttribute $pra, $user, $resource) |
|
| 127 | { |
||
| 128 | 3 | foreach ($pra->getExtraData() as $key => $data) { |
|
| 129 | switch ($key) { |
||
| 130 | 3 | case 'with': |
|
| 131 | // This data has to be removed for it will be stored elsewhere |
||
| 132 | // in the policy rule attribute |
||
| 133 | 3 | $pra->removeExtraData('with'); |
|
| 134 | // The "with" extra data is an array of attributes, which are objects |
||
| 135 | // Once we process it as policy rule attributes, we set it as the main policy rule attribute value |
||
| 136 | 3 | $subPolicyRuleAttributes = []; |
|
| 137 | |||
| 138 | 3 | foreach ($this->policyRuleManager->processRuleAttributes($data, $user, $resource) as $subPolicyRuleAttribute) { |
|
| 139 | 3 | $subPolicyRuleAttributes[] = $subPolicyRuleAttribute; |
|
| 140 | } |
||
| 141 | 3 | $pra->setValue($subPolicyRuleAttributes); |
|
| 142 | // This data can be used in complex comparisons |
||
| 143 | 3 | $pra->addExtraData('attribute', $pra->getAttribute()); |
|
| 144 | 3 | $pra->addExtraData('user', $user); |
|
| 145 | 3 | $pra->addExtraData('resource', $resource); |
|
| 146 | 3 | break; |
|
| 147 | } |
||
| 148 | } |
||
| 149 | 3 | } |
|
| 150 | } |
||
| 151 |