Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feature/secrets-pro…
Browse files Browse the repository at this point in the history
…vider
  • Loading branch information
1azyman committed Feb 5, 2024
2 parents 5420420 + a5f3ea0 commit a33f637
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 71 deletions.
2 changes: 0 additions & 2 deletions docs/concepts/query/midpoint-query-language/errors/index.adoc
Expand Up @@ -3,8 +3,6 @@
:page-display-order: 500
:page-toc: top
:toclevels: 3
:sectnums:
:sectnumlevels: 3


While searching with midPoint Query Language you can encounter various error messages.
Expand Down
8 changes: 6 additions & 2 deletions docs/concepts/query/midpoint-query-language/index.adoc
Expand Up @@ -2,8 +2,6 @@
:page-display-order: 100
:page-toc: top
:toclevels: 3
:sectnums:
:sectnumlevels: 3
:page-moved-from: /midpoint/reference/concepts/query/axiom-query-language/

_MidPoint Query Language_ is designed to query objects in midPoint repository.
Expand Down Expand Up @@ -71,6 +69,12 @@ filter:

To start with midPoint Query Language, please read xref:introduction.adoc[*Introduction to midPoint Query Language*].


=== Using in midPoint Studio

xref:/midpoint/tools/studio[Midpoint Studio] is great tool helping midPoint engineers and administrators with configuration and daily work.
You can use midPoint Query Language for xref:/midpoint/tools/studio/usage#_browsing_objects[querying of midPoint objects in midPoint Studio] as well.

=== Query Playground

To experiment with the query language, there is hardly a better place than the actual running midPoint.
Expand Down
2 changes: 0 additions & 2 deletions docs/concepts/query/midpoint-query-language/introduction.adoc
Expand Up @@ -3,8 +3,6 @@
:page-display-order: 100
:page-toc: top
:toclevels: 2
:sectnums:
:sectnumlevels: 3


This document provides introduction to the *midPoint Query Language*.
Expand Down
24 changes: 18 additions & 6 deletions docs/concepts/query/query-concepts/index.adoc
Expand Up @@ -6,8 +6,6 @@ scripts: [ 'multi-source.js' ]
:page-display-order: 300
:page-toc: top
:toclevels: 3
:sectnums:
:sectnumlevels: 3

This document contain advanced documentation describing concepts of querying in midPoint and midPoint Query language building blocks. New midPoint users and engineers may find this information hard to follow and confusing.

Expand Down Expand Up @@ -1531,8 +1529,8 @@ For authoritative information about provisioning filter interpretation, see link

Filters can be created using Fluent Java API or via XML (or equivalentYAML/JSON).

The following samples are taken from link:https://github.com/Evolveum/midpoint/blob/master/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java[TestQueryConvertor] class.
XML versions are in the files named `test*.xml` in link:https://github.com/Evolveum/midpoint/tree/master/infra/schema/src/test/resources/queryconvertor[this directory].
The following samples are taken from link:https://github.com/Evolveum/midpoint/blob/master/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConverter.java[TestQueryConvertor] class.
XML versions are in the files named `test*.xml` in link:https://github.com/Evolveum/midpoint/tree/master/infra/schema/src/test/resources/queryconverter[this directory].

==== Primitive filters

Expand Down Expand Up @@ -2140,6 +2138,20 @@ The operation may return specified number of entries or less.
Following is the example for using paging in the query.

.Paging example
[source,midPoint-query]
----
<q:query xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3">
<q:filter>
<q:text>activation/administrativeStatus="enabled"</q:text>
</q:filter>
<q:paging>
<q:orderBy>name</q:orderBy>
<q:offset>0</q:offset>
<q:maxSize>10</q:maxSize>
</q:paging>
</q:query>
----

[source,xml]
----
<q:query xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3">
Expand All @@ -2151,8 +2163,8 @@ Following is the example for using paging in the query.
</q:filter>
<q:paging>
<q:orderBy>name</q:orderBy>
<offset>0</offset>
<maxSize>10</maxSize>
<q:offset>0</q:offset>
<q:maxSize>10</q:maxSize>
</q:paging>
</q:query>
----
Expand Down
Expand Up @@ -31,8 +31,7 @@
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Optional;
import java.util.Properties;
import java.util.*;

import static org.testng.AssertJUnit.assertNotNull;

Expand Down Expand Up @@ -70,7 +69,6 @@ public abstract class TestAbstractOidcRestModule extends TestAbstractAuthenticat
private static final String TRUSTING_ASYMMETRIC_CERT_KEY = "trustingAsymmetricCertificate";
private static final String KEY_STORE_PATH_KEY = "keyStorePath";
private static final String USER_INFO_URI_KEY = "userInfoUri";
private static final String KID_KEY = "kid";

private Properties properties;

Expand Down Expand Up @@ -156,73 +154,123 @@ public void test003OidcAuthByJWSUriWithWrongAlg() throws Exception {

@Test
public void test004OidcAuthByPublicKey() throws Exception {
String securityContent = getSecurityPolicy(SECURITY_POLICY_PUBLIC_KEY);
securityContent = securityContent.replace(createTag(TRUSTING_ASYMMETRIC_CERT_KEY), getPublicKey());
replaceSecurityPolicy(securityContent);

Map<String, String> publicKeys = getPublicKeys();
boolean allKeysFails = true;
WebClient client = prepareClient();

when();
Response response = client.get();

then();
assertSuccess(response);
for (String publicKeyKid : publicKeys.keySet()) {
String securityContent = getSecurityPolicy(SECURITY_POLICY_PUBLIC_KEY);
securityContent = securityContent.replace(createTag(TRUSTING_ASYMMETRIC_CERT_KEY), publicKeys.get(publicKeyKid));
replaceSecurityPolicy(securityContent);

when();
Response response = client.get();

boolean success = true;
then();
try {
assertSuccess(response);
} catch (AssertionError e) {
success = false;
LOGGER.error("Couldn't use key with kid " + publicKeyKid + " for test.", e);
getDummyAuditService().clear();
}
if (success) {
allKeysFails = false;
break;
}
}
if (allKeysFails) {
throw new AssertionError("Test for each public keys fails.");
}
}

@Test
public void test005oidcAuthByPublicKeyWithWrongAlg() throws Exception {
String securityContent = getSecurityPolicy(SECURITY_POLICY_PUBLIC_KEY_WRONG_ALG);
securityContent = securityContent.replace(createTag(TRUSTING_ASYMMETRIC_CERT_KEY), getPublicKey());
replaceSecurityPolicy(securityContent);

Map<String, String> publicKeys = getPublicKeys();
boolean oneIsSuccess = false;
WebClient client = prepareClient();

when();
Response response = client.get();

then();
assertUnsuccess(response);
for (String publicKeyKid : publicKeys.keySet()) {
String securityContent = getSecurityPolicy(SECURITY_POLICY_PUBLIC_KEY_WRONG_ALG);
securityContent = securityContent.replace(createTag(TRUSTING_ASYMMETRIC_CERT_KEY), publicKeys.get(publicKeyKid));
replaceSecurityPolicy(securityContent);

when();
Response response = client.get();

then();
try {
assertUnsuccess(response);
} catch (AssertionError e) {
LOGGER.error("Unexpected success assert for using key with kid " + publicKeyKid + " for test.", e);
oneIsSuccess = true;
break;
}
}
if (oneIsSuccess) {
throw new AssertionError("Test for each public keys fails.");
}
}

@Test
public void test006OidcAuthByPublicKeyAsKeystore() throws Exception {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null);
String publicKey = getPublicKey();

byte[] certBytes;
if (Base64.isBase64(publicKey)) {
boolean isBase64Url = publicKey.contains("-") || publicKey.contains("_");
certBytes = Base64Utility.decode(publicKey, isBase64Url);
} else {
certBytes = publicKey.getBytes();
}
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate certificate = cf.generateCertificate(new ByteArrayInputStream(certBytes));
keystore.setCertificateEntry("cert", certificate);
Map<String, String> publicKeys = getPublicKeys();
boolean allKeysFails = true;

String pathToKeystore = MIDPOINT_HOME + "/test-keystore";
File file = new File(pathToKeystore);
file.deleteOnExit();
if (file.exists()) {
file.delete();
}

FileOutputStream out = new FileOutputStream(file);
keystore.store(out, "secret".toCharArray());
out.close();

String securityContent = getSecurityPolicy(SECURITY_POLICY_PUBLIC_KEY_KEYSTORE);
securityContent = securityContent.replace(createTag(KEY_STORE_PATH_KEY), pathToKeystore);
replaceSecurityPolicy(securityContent);

WebClient client = prepareClient();

when();
Response response = client.get();

then();
assertSuccess(response);
for (String publicKeyKid : publicKeys.keySet()) {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null);
String publicKey = publicKeys.get(publicKeyKid);

byte[] certBytes;
if (Base64.isBase64(publicKey)) {
boolean isBase64Url = publicKey.contains("-") || publicKey.contains("_");
certBytes = Base64Utility.decode(publicKey, isBase64Url);
} else {
certBytes = publicKey.getBytes();
}
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate certificate = cf.generateCertificate(new ByteArrayInputStream(certBytes));
keystore.setCertificateEntry("cert", certificate);

File file = new File(pathToKeystore);
file.deleteOnExit();
if (file.exists()) {
file.delete();
}

FileOutputStream out = new FileOutputStream(file);
keystore.store(out, "secret".toCharArray());
out.close();

when();
Response response = client.get();

boolean success = true;
then();
try {
assertSuccess(response);
} catch (AssertionError e) {
success = false;
LOGGER.error("Couldn't use key with kid " + publicKeyKid + " for test.", e);
getDummyAuditService().clear();
}
if (success) {
allKeysFails = false;
break;
}
}
if (allKeysFails) {
throw new AssertionError("Test for each public keys fails.");
}
}

@Test
Expand Down Expand Up @@ -259,18 +307,22 @@ protected WebClient prepareClientForOpaqueToken() {
return prepareClient();
}

private String getPublicKey() {
private Map<String, String> getPublicKeys() {
Map<String, String> publicKeys = new HashMap<>();
try {
Optional<Object> jsonWithKey = ((JSONArray) JSONObjectUtils.parse(
WebClient.create(getJwksUri()).get().readEntity(String.class)).get("keys"))
.stream().filter(json ->
JSONArray keys = ((JSONArray) JSONObjectUtils.parse(
WebClient.create(getJwksUri()).get().readEntity(String.class)).get("keys"));
keys.stream()
.filter(json ->
((JSONObject) json).containsKey("use")
&& "sig".equals(((JSONObject) json).get("use"))
&& (getProperty(KID_KEY) == null || getProperty(KID_KEY).equals(((JSONObject) json).get("kid"))))
.findFirst();
return (String) ((JSONArray)((JSONObject)jsonWithKey.get()).get("x5c")).get(0);
&& "sig".equals(((JSONObject) json).get("use")))
.forEach(key ->
publicKeys.put(
(String) ((JSONObject) key).get("kid"),
(String) ((JSONArray) ((JSONObject) key).get("x5c")).get(0)));
return publicKeys;
} catch (Exception e) {
LOGGER.error("Couldn't get public key for keycloak", e);
LOGGER.error("Couldn't get public key from IDP", e);
return null;
}
}
Expand Down

0 comments on commit a33f637

Please sign in to comment.