Fixes #10656: Sub realm localization GET endpoints can be called using tokens issued by the master realm. (#10660)

* Fixes #10656: Sub realm localization GET endpoints can be called using tokens issued by the master realm.

* Fixes #10656: Added some tests
This commit is contained in:
Christoph Leistert 2022-08-25 09:02:07 +02:00 committed by GitHub
parent 7f999a4629
commit 5408d25e09
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 178 additions and 12 deletions

View file

@ -24,7 +24,6 @@ import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import java.io.IOException; import java.io.IOException;
@ -47,7 +46,6 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
import org.keycloak.utils.StringUtil; import org.keycloak.utils.StringUtil;
@ -134,9 +132,7 @@ public class RealmLocalizationResource {
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Stream<String> getRealmLocalizationLocales() { public Stream<String> getRealmLocalizationLocales() {
if (!AdminPermissions.realms(session, auth.adminAuth()).isAdmin()) { auth.requireAnyAdminRole();
throw new ForbiddenException();
}
return realm.getRealmLocalizationTexts().keySet().stream().sorted(); return realm.getRealmLocalizationTexts().keySet().stream().sorted();
} }
@ -144,10 +140,8 @@ public class RealmLocalizationResource {
@Path("{locale}") @Path("{locale}")
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Map<String, String> getRealmLocalizationTexts(@PathParam("locale") String locale, @QueryParam("useRealmDefaultLocaleFallback") Boolean useFallback) { public Map<String, String> getRealmLocalizationTexts(@PathParam("locale") String locale, @QueryParam("useRealmDefaultLocaleFallback") Boolean useFallback) {
if (!AdminPermissions.realms(session, auth.adminAuth()).isAdmin()) { auth.requireAnyAdminRole();
throw new ForbiddenException();
}
Map<String, String> realmLocalizationTexts = new HashMap<>(); Map<String, String> realmLocalizationTexts = new HashMap<>();
if(useFallback != null && useFallback && StringUtil.isNotBlank(realm.getDefaultLocale())) { if(useFallback != null && useFallback && StringUtil.isNotBlank(realm.getDefaultLocale())) {
@ -164,9 +158,7 @@ public class RealmLocalizationResource {
@GET @GET
@Produces(MediaType.TEXT_PLAIN) @Produces(MediaType.TEXT_PLAIN)
public String getRealmLocalizationText(@PathParam("locale") String locale, @PathParam("key") String key) { public String getRealmLocalizationText(@PathParam("locale") String locale, @PathParam("key") String key) {
if (!AdminPermissions.realms(session, auth.adminAuth()).isAdmin()) { auth.requireAnyAdminRole();
throw new ForbiddenException();
}
String text = session.realms().getLocalizationTextsById(realm, locale, key); String text = session.realms().getLocalizationTextsById(realm, locale, key);
if (text != null) { if (text != null) {

View file

@ -1795,6 +1795,180 @@ public class PermissionsTest extends AbstractKeycloakTest {
}, clients.get("none"), false); }, clients.get("none"), false);
} }
@Test
public void localizations() {
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmSpecificLocales();
}
}, clients.get("view-realm"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmSpecificLocales();
}
}, clients.get("manage-realm"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmSpecificLocales();
}
}, clients.get("multi"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmSpecificLocales();
}
}, clients.get("master-admin"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmSpecificLocales();
}
}, clients.get("none"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmSpecificLocales();
}
}, clients.get("REALM2"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationText("en", "test");
}
}, clients.get("view-realm"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationText("en", "test");
}
}, clients.get("manage-realm"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationText("en", "test");
}
}, clients.get("multi"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationText("en", "test");
}
}, clients.get("master-admin"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationText("en", "test");
}
}, clients.get("none"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationText("en", "test");
}
}, clients.get("REALM2"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationTexts("en", false);
}
}, clients.get("view-realm"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationTexts("en", false);
}
}, clients.get("manage-realm"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationTexts("en", false);
}
}, clients.get("multi"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationTexts("en", false);
}
}, clients.get("master-admin"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationTexts("en", false);
}
}, clients.get("none"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().getRealmLocalizationTexts("en", false);
}
}, clients.get("REALM2"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().createOrUpdateRealmLocalizationTexts("en", Collections.<String, String>emptyMap());
}
}, clients.get("view-realm"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().createOrUpdateRealmLocalizationTexts("en", Collections.<String, String>emptyMap());
}
}, clients.get("manage-realm"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().createOrUpdateRealmLocalizationTexts("en", Collections.<String, String>emptyMap());
}
}, clients.get("master-admin"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().createOrUpdateRealmLocalizationTexts("en", Collections.<String, String>emptyMap());
}
}, clients.get("none"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationText("en", "test");
}
}, clients.get("REALM2"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationText("en", "test");
}
}, clients.get("view-realm"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationText("en", "test");
}
}, clients.get("manage-realm"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationText("en", "test");
}
}, clients.get("master-admin"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationText("en", "test");
}
}, clients.get("none"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationText("en", "test");
}
}, clients.get("REALM2"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationTexts("en");
}
}, clients.get("view-realm"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationTexts("en");
}
}, clients.get("manage-realm"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationTexts("en");
}
}, clients.get("master-admin"), true);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationTexts("en");
}
}, clients.get("none"), false);
invoke(new Invocation() {
public void invoke(RealmResource realm) {
realm.localization().deleteRealmLocalizationTexts("en");
}
}, clients.get("REALM2"), false);
}
private void invoke(final Invocation invocation, Resource resource, boolean manage) { private void invoke(final Invocation invocation, Resource resource, boolean manage) {
invoke(new InvocationWithResponse() { invoke(new InvocationWithResponse() {
public void invoke(RealmResource realm, AtomicReference<Response> response) { public void invoke(RealmResource realm, AtomicReference<Response> response) {