Add a toggle to use context attributes on the regex policy provider
Signed-off-by: remi <remi.tuveri@gmail.com>
This commit is contained in:
parent
326ba672cd
commit
b22efeec78
7 changed files with 91 additions and 5 deletions
|
@ -73,7 +73,9 @@ public class RegexPolicyProvider implements PolicyProvider {
|
|||
}
|
||||
|
||||
private String getClaimValue(Evaluation evaluation, RegexPolicyRepresentation policy) {
|
||||
Attributes attributes = evaluation.getContext().getIdentity().getAttributes();
|
||||
Attributes attributes = policy.isTargetContextAttributes()
|
||||
? evaluation.getContext().getAttributes()
|
||||
: evaluation.getContext().getIdentity().getAttributes();
|
||||
String targetClaim = policy.getTargetClaim();
|
||||
|
||||
try {
|
||||
|
|
|
@ -81,6 +81,7 @@ public class RegexPolicyProviderFactory implements PolicyProviderFactory<RegexPo
|
|||
|
||||
representation.setTargetClaim(config.get("targetClaim"));
|
||||
representation.setPattern(config.get("pattern"));
|
||||
representation.setTargetContextAttributes(Boolean.parseBoolean(config.get("targetContextAttributes")));
|
||||
|
||||
return representation;
|
||||
}
|
||||
|
@ -110,6 +111,7 @@ public class RegexPolicyProviderFactory implements PolicyProviderFactory<RegexPo
|
|||
|
||||
config.put("targetClaim", representation.getTargetClaim());
|
||||
config.put("pattern", representation.getPattern());
|
||||
config.put("targetContextAttributes", String.valueOf(representation.isTargetContextAttributes()));
|
||||
|
||||
policy.setConfig(config);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ public class RegexPolicyRepresentation extends AbstractPolicyRepresentation {
|
|||
|
||||
private String targetClaim;
|
||||
private String pattern;
|
||||
private boolean targetContextAttributes;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
|
@ -45,4 +46,12 @@ public class RegexPolicyRepresentation extends AbstractPolicyRepresentation {
|
|||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public boolean isTargetContextAttributes() {
|
||||
return targetContextAttributes;
|
||||
}
|
||||
|
||||
public void setTargetContextAttributes(boolean targetContextAttributes) {
|
||||
this.targetContextAttributes = targetContextAttributes;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2337,6 +2337,8 @@ roleID=Role ID
|
|||
roleNameLdapAttributeHelp=Name of LDAP attribute, which is used in role objects for name and RDN of role. Usually it will be 'cn'. In this case typical group/role object may have DN like 'cn\=role1,ou\=finance,dc\=example,dc\=org'.
|
||||
origin=Origin
|
||||
regexPattern=Regex pattern
|
||||
targetContextAttributes=Target Context Attributes
|
||||
targetContextAttributesHelp=Defines the evaluation of context attributes (claims) instead of identity attributes
|
||||
filteredByClaim=Verify essential claim
|
||||
rowCancelBtnAriaLabel=Cancel edits for {{messageBundle}}
|
||||
validateSignatureHelp=Enable/disable signature validation of external IDP signatures.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { useFormContext } from "react-hook-form";
|
||||
import { FormGroup } from "@patternfly/react-core";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { Checkbox, FormGroup } from "@patternfly/react-core";
|
||||
|
||||
import { HelpItem } from "ui-shared";
|
||||
import { KeycloakTextInput } from "../../../components/keycloak-text-input/KeycloakTextInput";
|
||||
|
@ -8,6 +8,7 @@ import { KeycloakTextInput } from "../../../components/keycloak-text-input/Keycl
|
|||
export const Regex = () => {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
control,
|
||||
register,
|
||||
formState: { errors },
|
||||
} = useFormContext();
|
||||
|
@ -54,6 +55,29 @@ export const Regex = () => {
|
|||
{...register("pattern", { required: true })}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("targetContextAttributes")}
|
||||
fieldId="targetContextAttributes"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("targetContextAttributesHelp")}
|
||||
fieldLabelId="targetContextAttributes"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="targetContextAttributes"
|
||||
defaultValue={false}
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<Checkbox
|
||||
id="targetContextAttributes"
|
||||
isChecked={field.value}
|
||||
onChange={field.onChange}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1241,7 +1241,7 @@ public class RepresentationToModel {
|
|||
PolicyProviderFactory provider = authorization.getProviderFactory(model.getType());
|
||||
|
||||
if (provider == null) {
|
||||
throw new RuntimeException("Could find policy provider with type [" + model.getType() + "]");
|
||||
throw new RuntimeException("Couldn't find policy provider with type [" + model.getType() + "]");
|
||||
}
|
||||
|
||||
if (representation instanceof PolicyRepresentation) {
|
||||
|
|
|
@ -107,6 +107,7 @@ public class RegexPolicyTest extends AbstractAuthzTest {
|
|||
.user(UserBuilder.create().username("my-user").password("password").addAttribute("canCreateItems","true"))
|
||||
.user(UserBuilder.create().username("my-user2").password("password").addAttribute("canCreateItems","false"))
|
||||
.user(UserBuilder.create().username("my-user3").password("password").addAttribute("otherClaim","something"))
|
||||
.user(UserBuilder.create().username("context-user").password("password").addAttribute("custom", "foo"))
|
||||
.group(GroupBuilder.create().name("ADMIN").singleAttribute("attribute","example").build())
|
||||
.user(UserBuilder.create().username("admin").password("password").addGroups("ADMIN"))
|
||||
|
||||
|
@ -125,6 +126,7 @@ public class RegexPolicyTest extends AbstractAuthzTest {
|
|||
createResource("Resource D");
|
||||
createResource("Resource E");
|
||||
createResource("Resource ITEM");
|
||||
createResource("Resource CONTEXT");
|
||||
ScopeRepresentation scopeRead = new ScopeRepresentation();
|
||||
scopeRead.setName("read");
|
||||
ScopeRepresentation scopeDelete = new ScopeRepresentation();
|
||||
|
@ -141,6 +143,7 @@ public class RegexPolicyTest extends AbstractAuthzTest {
|
|||
createRegexPolicy("Regex json-array Policy", "json-complex.some-array[1]", "bar");
|
||||
createRegexPolicy("Regex user attribute to json-Complex Policy", "customPermissions.canCreateItems", "true");
|
||||
createRegexPolicyExtended("attribute-policy","attributes.values","^example$",Logic.POSITIVE);
|
||||
createRegexPolicy("Regex context policy", "custom", "^foo$", true);
|
||||
|
||||
createResourcePermission("Resource A Permission", "Resource A", "Regex foo Policy");
|
||||
createResourcePermission("Resource B Permission", "Resource B", "Regex bar Policy");
|
||||
|
@ -151,7 +154,7 @@ public class RegexPolicyTest extends AbstractAuthzTest {
|
|||
createResourcePermission("Resource ITEM Permission", "Resource ITEM", "Regex user attribute to json-Complex Policy");
|
||||
createResourceScopesPermissionExtended("read-permission","service",DecisionStrategy.UNANIMOUS,"read","attribute-policy");
|
||||
|
||||
|
||||
createResourcePermission("Resource CONTEXT Permission", "Resource CONTEXT", "Regex context policy");
|
||||
}
|
||||
|
||||
private void createResource(String name) {
|
||||
|
@ -170,11 +173,16 @@ public class RegexPolicyTest extends AbstractAuthzTest {
|
|||
|
||||
|
||||
private void createRegexPolicy(String name, String targetClaim, String pattern) {
|
||||
createRegexPolicy(name, targetClaim, pattern, false);
|
||||
}
|
||||
|
||||
private void createRegexPolicy(String name, String targetClaim, String pattern, Boolean targetContextAttributes) {
|
||||
RegexPolicyRepresentation policy = new RegexPolicyRepresentation();
|
||||
|
||||
policy.setName(name);
|
||||
policy.setTargetClaim(targetClaim);
|
||||
policy.setPattern(pattern);
|
||||
policy.setTargetContextAttributes(targetContextAttributes);
|
||||
|
||||
getClient().authorization().policies().regex().create(policy).close();
|
||||
}
|
||||
|
@ -359,6 +367,8 @@ private void createRegexPolicyExtended(String name, String targetClaim, String p
|
|||
|
||||
// Access Resource D with taro.
|
||||
request = new PermissionRequest("Resource D");
|
||||
PermissionResponse foo = authzClient.protection().permission().create(request);
|
||||
|
||||
ticket = authzClient.protection().permission().create(request).getTicket();
|
||||
try {
|
||||
authzClient.authorization("taro", "password").authorize(new AuthorizationRequest(ticket));
|
||||
|
@ -368,6 +378,43 @@ private void createRegexPolicyExtended(String name, String targetClaim, String p
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithExpectedContextAttribute() {
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
PermissionRequest request = new PermissionRequest("Resource CONTEXT");
|
||||
request.setClaim("custom", "foo");
|
||||
String ticket = authzClient.protection().permission().create(request).getTicket();
|
||||
AuthorizationRequest theRequest = new AuthorizationRequest(ticket);
|
||||
AuthorizationResponse response = authzClient.authorization("my-user", "password").authorize(theRequest);
|
||||
assertNotNull(response.getToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithExpectedContextAttributeAsUserAttribute() {
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
PermissionRequest request = new PermissionRequest("Resource CONTEXT");
|
||||
String ticket = authzClient.protection().permission().create(request).getTicket();
|
||||
try {
|
||||
authzClient.authorization("context-user", "password").authorize(new AuthorizationRequest(ticket));
|
||||
fail("failed because it should thrown an exception with 403 Forbidden Status");
|
||||
} catch (AuthorizationDeniedException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithoutExpectedContextAttribute() {
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
PermissionRequest request = new PermissionRequest("Resource CONTEXT");
|
||||
String ticket = authzClient.protection().permission().create(request).getTicket();
|
||||
try {
|
||||
authzClient.authorization("my-user", "password").authorize(new AuthorizationRequest(ticket));
|
||||
fail("failed because it should thrown an exception with 403 Forbidden Status");
|
||||
} catch (AuthorizationDeniedException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private AuthzClient getAuthzClient() {
|
||||
return AuthzClient.create(getClass().getResourceAsStream("/authorization-test/default-keycloak.json"));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue