package org.ovirt.engine.core.sso.search;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.ovirt.engine.api.extensions.Base;
import org.ovirt.engine.api.extensions.ExtMap;
import org.ovirt.engine.api.extensions.aaa.Authn;
import org.ovirt.engine.api.extensions.aaa.Authz;
import org.ovirt.engine.core.extensions.mgr.ExtensionProxy;
public class AuthzUtils {
@FunctionalInterface
private interface QueryResultHandler {
boolean handle(Collection<ExtMap> queryResults);
}
private static final int QUERIES_RESULTS_LIMIT = 1000;
private static final int PAGE_SIZE = 500;
public static String getName(ExtensionProxy proxy) {
return proxy.getContext().get(Base.ContextKeys.INSTANCE_NAME);
}
public static boolean supportsPasswordAuthentication(ExtensionProxy proxy) {
return (proxy.getContext().<Long>get(Authn.ContextKeys.CAPABILITIES, 0L) & Authn.Capabilities.AUTHENTICATE_PASSWORD) != 0;
}
public static ExtMap fetchPrincipalRecord(
final ExtensionProxy extension,
String principal,
boolean resolveGroups,
boolean resolveGroupsRecursive) {
return fetchPrincipalRecordImpl(
extension,
new ExtMap().mput(
Authz.InvokeKeys.PRINCIPAL,
principal
),
resolveGroups,
resolveGroupsRecursive
);
}
private static ExtMap fetchPrincipalRecordImpl(
final ExtensionProxy extension,
ExtMap m, boolean resolveGroups,
boolean resolveGroupsRecursive) {
ExtMap ret = null;
ExtMap output = extension.invoke(
m.mput(
Base.InvokeKeys.COMMAND,
Authz.InvokeCommands.FETCH_PRINCIPAL_RECORD
).mput(
Authz.InvokeKeys.QUERY_FLAGS,
(resolveGroups ? Authz.QueryFlags.RESOLVE_GROUPS : 0) |
(resolveGroupsRecursive ? Authz.QueryFlags.RESOLVE_GROUPS_RECURSIVE : 0)
));
if (output.<Integer>get(Authz.InvokeKeys.STATUS) == Authz.Status.SUCCESS) {
ret = output.get(Authz.InvokeKeys.PRINCIPAL_RECORD);
}
return ret;
}
public static Collection<ExtMap> queryPrincipalRecords(
final ExtensionProxy extension,
final String namespace,
final ExtMap filter,
boolean groupsResolving,
boolean groupsResolvingRecursive) {
ExtMap inputMap = new ExtMap().mput(
Authz.InvokeKeys.QUERY_ENTITY,
Authz.QueryEntity.PRINCIPAL
).mput(
Authz.InvokeKeys.QUERY_FLAGS,
queryFlagValue(groupsResolving, groupsResolvingRecursive)
).mput(
Authz.InvokeKeys.QUERY_FILTER,
filter
).mput(
Authz.InvokeKeys.NAMESPACE,
namespace
);
return populateRecords(
extension,
namespace,
inputMap);
}
public static Collection<ExtMap> queryGroupRecords(
final ExtensionProxy extension,
final String namespace,
final ExtMap filter,
boolean groupsResolving,
boolean groupsResolvingRecursive) {
ExtMap inputMap = new ExtMap().mput(
Authz.InvokeKeys.QUERY_ENTITY,
Authz.QueryEntity.GROUP
).mput(
Authz.InvokeKeys.QUERY_FLAGS,
queryFlagValue(groupsResolving, groupsResolvingRecursive)
).mput(
Authz.InvokeKeys.QUERY_FILTER,
filter
).mput(
Authz.InvokeKeys.NAMESPACE,
namespace
);
return populateRecords(
extension,
namespace,
inputMap);
}
public static Collection<ExtMap> populateRecords(
final ExtensionProxy extension,
final String namespace,
final ExtMap input) {
final Collection<ExtMap> records = new ArrayList<>();
queryImpl(extension, namespace, input, queryResults -> {
boolean result = true;
for (ExtMap queryResult : queryResults) {
if (records.size() < QUERIES_RESULTS_LIMIT) {
records.add(queryResult);
} else {
result = false;
break;
}
}
return result;
});
return records;
}
private static void queryImpl(
final ExtensionProxy extension,
final String namespace,
final ExtMap input,
final QueryResultHandler handler) {
Object opaque = extension.invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Authz.InvokeCommands.QUERY_OPEN
).mput(
Authz.InvokeKeys.NAMESPACE,
namespace
).mput(
input
)
).get(Authz.InvokeKeys.QUERY_OPAQUE);
Collection<ExtMap> result = null;
try {
do {
result = extension.invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Authz.InvokeCommands.QUERY_EXECUTE
).mput(
Authz.InvokeKeys.QUERY_OPAQUE,
opaque
).mput(
Authz.InvokeKeys.PAGE_SIZE,
PAGE_SIZE
)
).get(Authz.InvokeKeys.QUERY_RESULT);
} while (result != null && handler.handle(result));
} finally {
extension.invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Authz.InvokeCommands.QUERY_CLOSE
).mput(
Authz.InvokeKeys.QUERY_OPAQUE,
opaque
)
);
}
}
public static List<ExtMap> findPrincipalsByIds(
final ExtensionProxy extension,
final String namespace,
final Collection<String> ids,
final boolean groupsResolving,
final boolean groupsResolvingRecursive) {
List<ExtMap> results = new ArrayList<>();
SearchParsingUtils.getIdsBatches(extension.getContext(), ids).forEach(
batch ->
results.addAll(
queryPrincipalRecords(
extension,
namespace,
SearchParsingUtils.generateQueryMap(
batch,
Authz.QueryEntity.PRINCIPAL
),
groupsResolving,
groupsResolvingRecursive
)
));
return results;
}
public static Collection<ExtMap> findGroupRecordsByIds(
final ExtensionProxy extension,
final String namespace,
final Collection<String> ids,
final boolean groupsResolving,
final boolean groupsResolvingRecursive) {
Collection<ExtMap> results = new ArrayList<>();
SearchParsingUtils.getIdsBatches(extension.getContext(), ids).forEach(
batch -> results.addAll(
queryGroupRecords(
extension,
namespace,
SearchParsingUtils.generateQueryMap(
batch,
Authz.QueryEntity.GROUP
),
groupsResolving,
groupsResolvingRecursive)));
return results;
}
private static int queryFlagValue(boolean resolveGroups, boolean resolveGroupsRecursive) {
int result = 0;
if (resolveGroups) {
result |= Authz.QueryFlags.RESOLVE_GROUPS;
}
if (resolveGroupsRecursive) {
result |= Authz.QueryFlags.RESOLVE_GROUPS_RECURSIVE | Authz.QueryFlags.RESOLVE_GROUPS;
}
return result;
}
}