KEYCLOAK-18503 Regex Policy for authorization service
This commit is contained in:
parent
b7a4fd8745
commit
52ced98f92
11 changed files with 616 additions and 1 deletions
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.keycloak.authorization.policy.provider.regex;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.attribute.Attributes;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.representations.idm.authorization.RegexPolicyRepresentation;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:yoshiyuki.tabata.jy@hitachi.com">Yoshiyuki Tabata</a>
|
||||
*/
|
||||
public class RegexPolicyProvider implements PolicyProvider {
|
||||
|
||||
private final BiFunction<Policy, AuthorizationProvider, RegexPolicyRepresentation> representationFunction;
|
||||
|
||||
public RegexPolicyProvider(BiFunction<Policy, AuthorizationProvider, RegexPolicyRepresentation> representationFunction) {
|
||||
this.representationFunction = representationFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(Evaluation evaluation) {
|
||||
AuthorizationProvider authorizationProvider = evaluation.getAuthorizationProvider();
|
||||
RegexPolicyRepresentation policy = representationFunction.apply(evaluation.getPolicy(), authorizationProvider);
|
||||
Attributes.Entry targetClaim = evaluation.getContext().getIdentity().getAttributes().getValue(policy.getTargetClaim());
|
||||
|
||||
if (targetClaim == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Pattern pattern = Pattern.compile(policy.getPattern());
|
||||
Matcher matcher = pattern.matcher(targetClaim.asString(0));
|
||||
if (matcher.matches()) {
|
||||
evaluation.grant();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.keycloak.authorization.policy.provider.regex;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.RegexPolicyRepresentation;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:yoshiyuki.tabata.jy@hitachi.com">Yoshiyuki Tabata</a>
|
||||
*/
|
||||
public class RegexPolicyProviderFactory implements PolicyProviderFactory<RegexPolicyRepresentation> {
|
||||
|
||||
private RegexPolicyProvider provider = new RegexPolicyProvider(this::toRepresentation);
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(KeycloakSession session) {
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "regex";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Regex";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return "Identity Based";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolicyProvider create(AuthorizationProvider authorization) {
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegexPolicyRepresentation toRepresentation(Policy policy, AuthorizationProvider authorization) {
|
||||
RegexPolicyRepresentation representation = new RegexPolicyRepresentation();
|
||||
Map<String, String> config = policy.getConfig();
|
||||
|
||||
representation.setTargetClaim(config.get("targetClaim"));
|
||||
representation.setPattern(config.get("pattern"));
|
||||
|
||||
return representation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<RegexPolicyRepresentation> getRepresentationType() {
|
||||
return RegexPolicyRepresentation.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Policy policy, RegexPolicyRepresentation representation, AuthorizationProvider authorization) {
|
||||
updatePolicy(policy, representation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Policy policy, RegexPolicyRepresentation representation, AuthorizationProvider authorization) {
|
||||
updatePolicy(policy, representation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onImport(Policy policy, PolicyRepresentation representation, AuthorizationProvider authorization) {
|
||||
policy.setConfig(representation.getConfig());
|
||||
}
|
||||
|
||||
private void updatePolicy(Policy policy, RegexPolicyRepresentation representation) {
|
||||
Map<String, String> config = new HashMap<>(policy.getConfig());
|
||||
|
||||
config.put("targetClaim", representation.getTargetClaim());
|
||||
config.put("pattern", representation.getPattern());
|
||||
|
||||
policy.setConfig(config);
|
||||
}
|
||||
}
|
|
@ -45,3 +45,4 @@ org.keycloak.authorization.policy.provider.client.ClientPolicyProviderFactory
|
|||
org.keycloak.authorization.policy.provider.group.GroupPolicyProviderFactory
|
||||
org.keycloak.authorization.policy.provider.permission.UMAPolicyProviderFactory
|
||||
org.keycloak.authorization.policy.provider.clientscope.ClientScopePolicyProviderFactory
|
||||
org.keycloak.authorization.policy.provider.regex.RegexPolicyProviderFactory
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.representations.idm.authorization;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:yoshiyuki.tabata.jy@hitachi.com">Yoshiyuki Tabata</a>
|
||||
*/
|
||||
public class RegexPolicyRepresentation extends AbstractPolicyRepresentation {
|
||||
|
||||
private String targetClaim;
|
||||
private String pattern;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "regex";
|
||||
}
|
||||
|
||||
public String getTargetClaim() {
|
||||
return targetClaim;
|
||||
}
|
||||
|
||||
public void setTargetClaim(String targetClaim) {
|
||||
this.targetClaim = targetClaim;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
}
|
|
@ -106,4 +106,7 @@ public interface PoliciesResource {
|
|||
|
||||
@Path("client-scope")
|
||||
ClientScopePoliciesResource clientScope();
|
||||
|
||||
@Path("regex")
|
||||
RegexPoliciesResource regex();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.admin.client.resource;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.keycloak.representations.idm.authorization.RegexPolicyRepresentation;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:yoshiyuki.tabata.jy@hitachi.com">Yoshiyuki Tabata</a>
|
||||
*/
|
||||
public interface RegexPoliciesResource {
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Response create(RegexPolicyRepresentation representation);
|
||||
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.authz;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.AuthorizationResource;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.ClientsResource;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.authorization.client.AuthorizationDeniedException;
|
||||
import org.keycloak.authorization.client.AuthzClient;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
|
||||
import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
|
||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.AuthorizationRequest;
|
||||
import org.keycloak.representations.idm.authorization.AuthorizationResponse;
|
||||
import org.keycloak.representations.idm.authorization.PermissionRequest;
|
||||
import org.keycloak.representations.idm.authorization.RegexPolicyRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
||||
import org.keycloak.testsuite.util.ClientBuilder;
|
||||
import org.keycloak.testsuite.util.RealmBuilder;
|
||||
import org.keycloak.testsuite.util.UserBuilder;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:yoshiyuki.tabata.jy@hitachi.com">Yoshiyuki Tabata</a>
|
||||
*/
|
||||
@AuthServerContainerExclude(AuthServer.REMOTE)
|
||||
public class RegexPolicyTest extends AbstractAuthzTest {
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
ProtocolMapperRepresentation userAttrFooProtocolMapper = new ProtocolMapperRepresentation();
|
||||
userAttrFooProtocolMapper.setName("userAttrFoo");
|
||||
userAttrFooProtocolMapper.setProtocolMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
userAttrFooProtocolMapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
Map<String, String> configFoo = new HashMap<>();
|
||||
configFoo.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
configFoo.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
configFoo.put(OIDCAttributeMapperHelper.JSON_TYPE, "String");
|
||||
configFoo.put("user.attribute", "foo");
|
||||
configFoo.put("claim.name", "foo");
|
||||
userAttrFooProtocolMapper.setConfig(configFoo);
|
||||
|
||||
ProtocolMapperRepresentation userAttrBarProtocolMapper = new ProtocolMapperRepresentation();
|
||||
userAttrBarProtocolMapper.setName("userAttrBar");
|
||||
userAttrBarProtocolMapper.setProtocolMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
userAttrBarProtocolMapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
Map<String, String> configBar = new HashMap<>();
|
||||
configBar.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
configBar.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
configBar.put(OIDCAttributeMapperHelper.JSON_TYPE, "String");
|
||||
configBar.put("user.attribute", "bar");
|
||||
configBar.put("claim.name", "bar");
|
||||
userAttrBarProtocolMapper.setConfig(configBar);
|
||||
|
||||
testRealms.add(RealmBuilder.create().name("authz-test")
|
||||
.user(UserBuilder.create().username("marta").password("password").addAttribute("foo", "foo").addAttribute("bar",
|
||||
"barbar"))
|
||||
.user(UserBuilder.create().username("taro").password("password").addAttribute("foo", "faa").addAttribute("bar",
|
||||
"bbarbar"))
|
||||
.client(ClientBuilder.create().clientId("resource-server-test").secret("secret").authorizationServicesEnabled(true)
|
||||
.redirectUris("http://localhost/resource-server-test").directAccessGrants()
|
||||
.protocolMapper(userAttrFooProtocolMapper, userAttrBarProtocolMapper))
|
||||
.build());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void configureAuthorization() throws Exception {
|
||||
createResource("Resource A");
|
||||
createResource("Resource B");
|
||||
|
||||
createRegexPolicy("Regex foo Policy", "foo", "foo");
|
||||
createRegexPolicy("Regex bar Policy", "bar", "^bar.+$");
|
||||
|
||||
createResourcePermission("Resource A Permission", "Resource A", "Regex foo Policy");
|
||||
createResourcePermission("Resource B Permission", "Resource B", "Regex bar Policy");
|
||||
}
|
||||
|
||||
private void createResource(String name) {
|
||||
AuthorizationResource authorization = getClient().authorization();
|
||||
ResourceRepresentation resource = new ResourceRepresentation(name);
|
||||
|
||||
authorization.resources().create(resource).close();
|
||||
}
|
||||
|
||||
private void createRegexPolicy(String name, String targetClaim, String pattern) {
|
||||
RegexPolicyRepresentation policy = new RegexPolicyRepresentation();
|
||||
|
||||
policy.setName(name);
|
||||
policy.setTargetClaim(targetClaim);
|
||||
policy.setPattern(pattern);
|
||||
|
||||
getClient().authorization().policies().regex().create(policy).close();
|
||||
}
|
||||
|
||||
private void createResourcePermission(String name, String resource, String... policies) {
|
||||
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
|
||||
|
||||
permission.setName(name);
|
||||
permission.addResource(resource);
|
||||
permission.addPolicy(policies);
|
||||
|
||||
getClient().authorization().permissions().resource().create(permission).close();
|
||||
}
|
||||
|
||||
private ClientResource getClient() {
|
||||
return getClient(getRealm());
|
||||
}
|
||||
|
||||
private ClientResource getClient(RealmResource realm) {
|
||||
ClientsResource clients = realm.clients();
|
||||
return clients.findByClientId("resource-server-test").stream()
|
||||
.map(representation -> clients.get(representation.getId())).findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Expected client [resource-server-test]"));
|
||||
}
|
||||
|
||||
private RealmResource getRealm() {
|
||||
try {
|
||||
return getAdminClient().realm("authz-test");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to create admin client");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithExpectedUserAttribute() {
|
||||
// Access Resource A with marta.
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
PermissionRequest request = new PermissionRequest("Resource A");
|
||||
String ticket = authzClient.protection().permission().create(request).getTicket();
|
||||
AuthorizationResponse response = authzClient.authorization("marta", "password")
|
||||
.authorize(new AuthorizationRequest(ticket));
|
||||
assertNotNull(response.getToken());
|
||||
|
||||
// Access Resource B with marta.
|
||||
request = new PermissionRequest("Resource B");
|
||||
ticket = authzClient.protection().permission().create(request).getTicket();
|
||||
response = authzClient.authorization("marta", "password").authorize(new AuthorizationRequest(ticket));
|
||||
assertNotNull(response.getToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithoutExpectedUserAttribute() {
|
||||
// Access Resource A with taro.
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
PermissionRequest request = new PermissionRequest("Resource A");
|
||||
String ticket = authzClient.protection().permission().create(request).getTicket();
|
||||
try {
|
||||
authzClient.authorization("taro", "password").authorize(new AuthorizationRequest(ticket));
|
||||
fail("Should fail.");
|
||||
} catch (AuthorizationDeniedException ignore) {
|
||||
|
||||
}
|
||||
|
||||
// Access Resource B with taro.
|
||||
request = new PermissionRequest("Resource B");
|
||||
ticket = authzClient.protection().permission().create(request).getTicket();
|
||||
try {
|
||||
authzClient.authorization("taro", "password").authorize(new AuthorizationRequest(ticket));
|
||||
fail("Should fail.");
|
||||
} catch (AuthorizationDeniedException ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private AuthzClient getAuthzClient() {
|
||||
return AuthzClient.create(getClass().getResourceAsStream("/authorization-test/default-keycloak.json"));
|
||||
}
|
||||
}
|
|
@ -1692,6 +1692,13 @@ authz-add-client-scope-policy=Add Client Scope Policy
|
|||
authz-no-client-scopes-assigned=No client scopes assigned.
|
||||
authz-policy-client-scope-client-scopes.tooltip=Specifies which client scope(s) are allowed by this policy.
|
||||
select-a-client-scope=Select a client scope
|
||||
# Authz Regex Policy Detail
|
||||
authz-add-regex-policy=Add Regex Policy
|
||||
regex=Regex
|
||||
authz-policy-target-claim=Target Claim
|
||||
authz-policy-target-claim.tooltip=Specifies the target claim which the policy will fetch.
|
||||
authz-policy-regex-pattern=Regex Pattern
|
||||
authz-policy-regex-pattern.tooltip=Specifies the regex pattern.
|
||||
|
||||
# Authz Permission List
|
||||
authz-no-permissions-available=No permissions available.
|
||||
|
|
|
@ -418,6 +418,28 @@ module.config(['$routeProvider', function ($routeProvider) {
|
|||
}
|
||||
},
|
||||
controller: 'ResourceServerPolicyClientScopeDetailCtrl'
|
||||
}).when('/realms/:realm/clients/:client/authz/resource-server/policy/regex/create', {
|
||||
templateUrl: resourceUrl + '/partials/authz/policy/provider/resource-server-policy-regex-detail.html',
|
||||
resolve: {
|
||||
realm: function (RealmLoader) {
|
||||
return RealmLoader();
|
||||
},
|
||||
client : function(ClientLoader) {
|
||||
return ClientLoader();
|
||||
}
|
||||
},
|
||||
controller: 'ResourceServerPolicyRegexDetailCtrl'
|
||||
}).when('/realms/:realm/clients/:client/authz/resource-server/policy/regex/:id', {
|
||||
templateUrl: resourceUrl + '/partials/authz/policy/provider/resource-server-policy-regex-detail.html',
|
||||
resolve: {
|
||||
realm: function (RealmLoader) {
|
||||
return RealmLoader();
|
||||
},
|
||||
client : function(ClientLoader) {
|
||||
return ClientLoader();
|
||||
}
|
||||
},
|
||||
controller: 'ResourceServerPolicyRegexDetailCtrl'
|
||||
}).when('/realms/:realm/roles/:role/permissions', {
|
||||
templateUrl : resourceUrl + '/partials/authz/mgmt/realm-role-permissions.html',
|
||||
resolve : {
|
||||
|
|
|
@ -2192,6 +2192,28 @@ module.controller('ResourceServerPolicyClientScopeDetailCtrl', function($scope,
|
|||
}, realm, client, $scope);
|
||||
});
|
||||
|
||||
module.controller('ResourceServerPolicyRegexDetailCtrl', function($scope, realm, client, PolicyController) {
|
||||
PolicyController.onInit({
|
||||
getPolicyType : function() {
|
||||
return "regex";
|
||||
},
|
||||
|
||||
onInit : function() {
|
||||
},
|
||||
|
||||
onInitUpdate : function(policy) {
|
||||
},
|
||||
|
||||
onUpdate : function() {
|
||||
delete $scope.policy.config;
|
||||
},
|
||||
|
||||
onCreate : function() {
|
||||
delete $scope.policy.config;
|
||||
}
|
||||
}, realm, client, $scope);
|
||||
});
|
||||
|
||||
module.service("PolicyController", function($http, $route, $location, ResourceServer, ResourceServerPolicy, ResourceServerPermission, AuthzDialog, Notifications, policyViewState, PolicyProvider, viewState) {
|
||||
|
||||
var PolicyController = {};
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
<!--
|
||||
~ JBoss, Home of Professional Open Source.
|
||||
~ Copyright 2021 Red Hat, Inc., and individual contributors
|
||||
~ as indicated by the @author tags.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
|
||||
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server">{{:: 'authz-authorization' |
|
||||
translate}}</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy">{{:: 'authz-policies'
|
||||
| translate}}</a></li>
|
||||
<li data-ng-show="policyState.state.policy.name != null && historyBackOnSaveOrCancel">{{policyState.state.policy.name}}</li>
|
||||
<li data-ng-show="policyState.state.policy.name == null && historyBackOnSaveOrCancel">{{::
|
||||
policyState.state.previousPage.name | translate}}</li>
|
||||
<li data-ng-show="create">{{:: 'authz-add-regex-policy' | translate}}</li>
|
||||
<li data-ng-hide="create">{{:: 'regex' | translate}}</li>
|
||||
<li data-ng-hide="create">{{originalPolicy.name}}</li>
|
||||
</ol>
|
||||
|
||||
<h1 data-ng-show="create">{{:: 'authz-add-regex-policy' | translate}}</h1>
|
||||
<h1 data-ng-hide="create">
|
||||
{{originalPolicy.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create"
|
||||
data-ng-click="remove()"></i>
|
||||
</h1>
|
||||
|
||||
<form class="form-horizontal" name="clientForm" novalidate>
|
||||
<fieldset class="border-top">
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} <span class="required">*</span></label>
|
||||
<div class="col-sm-6">
|
||||
<input class="form-control" type="text" id="name" name="name" data-ng-model="policy.name" autofocus required
|
||||
data-ng-blur="checkNewNameAvailability()">
|
||||
</div>
|
||||
<kc-tooltip>{{:: 'authz-policy-name.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="description">{{:: 'description' | translate}} </label>
|
||||
<div class="col-sm-6">
|
||||
<input class="form-control" type="text" id="description" name="description"
|
||||
data-ng-model="policy.description">
|
||||
</div>
|
||||
<kc-tooltip>{{:: 'authz-policy-description.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="targetClaim">{{:: 'authz-policy-target-claim' | translate}} <span
|
||||
class="required">*</span></label>
|
||||
<div class="col-sm-6">
|
||||
<input class="form-control" type="text" id="targetClaim" name="targetClaim"
|
||||
data-ng-model="policy.targetClaim" required>
|
||||
</div>
|
||||
<kc-tooltip>{{:: 'authz-policy-target-claim.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="pattern">{{:: 'authz-policy-regex-pattern' | translate}} <span
|
||||
class="required">*</span></label>
|
||||
<div class="col-sm-6">
|
||||
<input class="form-control" type="text" id="pattern" name="pattern" data-ng-model="policy.pattern" required>
|
||||
</div>
|
||||
<kc-tooltip>{{:: 'authz-policy-regex-pattern.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group clearfix">
|
||||
<label class="col-md-2 control-label" for="logic">{{:: 'authz-policy-logic' | translate}}</label>
|
||||
|
||||
<div class="col-sm-1">
|
||||
<select class="form-control" id="logic" data-ng-model="policy.logic">
|
||||
<option value="POSITIVE">{{:: 'authz-policy-logic-positive' | translate}}</option>
|
||||
<option value="NEGATIVE">{{:: 'authz-policy-logic-negative' | translate}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<kc-tooltip>{{:: 'authz-policy-logic.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<input type="hidden" data-ng-model="policy.type" />
|
||||
</fieldset>
|
||||
<div class="form-group" data-ng-show="access.manageAuthorization">
|
||||
<div class="col-md-10 col-md-offset-2">
|
||||
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
|
||||
<button kc-reset data-ng-disabled="!changed && !historyBackOnSaveOrCancel">{{:: 'cancel' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<kc-menu></kc-menu>
|
Loading…
Reference in a new issue