package org.ovirt.engine.exttool.aaa;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.ovirt.engine.api.extensions.Base;
import org.ovirt.engine.api.extensions.ExtKey;
import org.ovirt.engine.api.extensions.ExtMap;
import org.ovirt.engine.api.extensions.ExtUUID;
import org.ovirt.engine.api.extensions.aaa.Acct;
import org.ovirt.engine.api.extensions.aaa.Authn;
import org.ovirt.engine.api.extensions.aaa.Authz;
import org.ovirt.engine.api.extensions.aaa.Mapping;
import org.ovirt.engine.core.extensions.mgr.ExtensionProxy;
import org.ovirt.engine.core.extensions.mgr.ExtensionsManager;
import org.ovirt.engine.core.uutils.cli.parser.ArgumentsParser;
import org.ovirt.engine.exttool.core.ExitException;
import org.ovirt.engine.exttool.core.ModuleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AAAServiceImpl implements ModuleService {
private static final Logger log = LoggerFactory.getLogger(AAAServiceImpl.class);
@FunctionalInterface
private interface Logic {
void execute(AAAServiceImpl module);
}
private enum Action {
AUTHZ_FETCH_PRINCIPAL_RECORD(
module -> {
ExtensionProxy authzExtension = module.getExtensionsManager().getExtensionByName((String) module.argMap.get("extension-name"));
log.info("API: -->Authz.InvokeCommands.FETCH_PRINCIPAL_RECORD principal='{}'", module.argMap.get("principal-name"));
ExtMap outMap = authzExtension.invoke(
new ExtMap().mput(
Authz.InvokeKeys.PRINCIPAL,
module.argMap.get("principal-name")
).mput(
Base.InvokeKeys.COMMAND,
Authz.InvokeCommands.FETCH_PRINCIPAL_RECORD
).mput(
Authz.InvokeKeys.QUERY_FLAGS,
getAuthzFlags((List<String>) module.argMap.get("authz-flag"))
)
);
log.info(
"API: <--Authz.InvokeCommands.FETCH_PRINCIPAL_RECORD status={}",
getFieldNameByValue(Authz.Status.class, outMap.<Integer> get(Authz.InvokeKeys.STATUS))
);
if (outMap.<Integer> get(Authz.InvokeKeys.STATUS) != Authz.Status.SUCCESS) {
throw new RuntimeException(
String.format(
"Authz.Status code is: %1$s",
getFieldNameByValue(Authz.Status.class, outMap.<Integer> get(Authz.InvokeKeys.STATUS))
)
);
}
Dump.PRINCIPAL_RECORD.dump(module, outMap.get(Authz.InvokeKeys.PRINCIPAL_RECORD));
}
),
AUTHN_AUTHENTICATE_CREDENTIALS(
module -> {
ExtensionProxy authnExtension = module.getExtensionsManager().getExtensionByName((String) module.argMap.get("extension-name"));
log.info("API: -->Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS user='{}'", module.argMap.get("user-name"));
ExtMap outMap = authnExtension.invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS
).mput(
Authn.InvokeKeys.USER,
module.argMap.get("user-name")
).mput(
Authn.InvokeKeys.CREDENTIALS,
getPassword((String)module.argMap.get("password"))
)
);
log.info(
"API: <--Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS result={}",
getFieldNameByValue(Authn.AuthResult.class, outMap.<Integer> get(Authn.InvokeKeys.RESULT))
);
Dump.AUTH_RECORD.dump(module, outMap.get(Authn.InvokeKeys.AUTH_RECORD));
if (outMap.<Integer> get(Authn.InvokeKeys.RESULT) != Authn.AuthResult.SUCCESS) {
throw new RuntimeException(
String.format(
"Authn.Result code is: %1$s",
getFieldNameByValue(Authn.AuthResult.class, outMap.<Integer> get(Authn.InvokeKeys.RESULT))
)
);
}
}
),
CHANGE_CREDENTIALS(
module -> {
AAAProfile aaaprofile = module.new AAAProfile((String)module.argMap.get("profile"));
if ((aaaprofile.getAuthnExtension().getContext().<Long>get(Authn.ContextKeys.CAPABILITIES, 0L) & Authn.Capabilities.CREDENTIALS_CHANGE) == 0 &&
!(Boolean)module.argMap.get("ignore-capabilities")) {
throw new IllegalArgumentException("Unsupported operation: CREDENTIALS_CHANGE");
}
String user = aaaprofile.mapUser((String)module.argMap.get("user-name"));
log.info("API: -->Authn.InvokeCommands.CREDENTIALS_CHANGES profile='{}' user='{}'", aaaprofile.getProfile(), user);
ExtMap outMap = aaaprofile.getAuthnExtension().invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Authn.InvokeCommands.CREDENTIALS_CHANGE
).mput(
Authn.InvokeKeys.USER,
user
).mput(
Authn.InvokeKeys.CREDENTIALS,
getPassword((String)module.argMap.get("password"))
).mput(
Authn.InvokeKeys.CREDENTIALS_NEW,
getPassword((String)module.argMap.get("password-new"), "New password: ")
)
);
log.info(
"API: <--Authn.InvokeCommands.CREDENTIALS_CHANGES profile='{}' result={}",
aaaprofile.getProfile(),
getFieldNameByValue(Authn.AuthResult.class, outMap.<Integer> get(Authn.InvokeKeys.RESULT))
);
if (outMap.<Integer>get(Base.InvokeKeys.RESULT) != Base.InvokeResult.SUCCESS ||
outMap.<Integer>get(Authn.InvokeKeys.RESULT) != Authn.AuthResult.SUCCESS) {
throw new RuntimeException("Password change failed");
}
log.info("Password successfully changed");
}
),
LOGIN_USER(
module -> {
AAAProfile aaaprofile = module.new AAAProfile((String)module.argMap.get("profile"));
String user = aaaprofile.mapUser((String)module.argMap.get("user-name"));
log.info("API: -->Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS profile='{}' user='{}'", aaaprofile.getProfile(), user);
ExtMap outMap = aaaprofile.getAuthnExtension().invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS
).mput(
Authn.InvokeKeys.USER,
user
).mput(
Authn.InvokeKeys.CREDENTIALS,
getPassword((String)module.argMap.get("password"))
)
);
log.info(
"API: <--Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS profile='{}' result={}",
aaaprofile.getProfile(),
getFieldNameByValue(Authn.AuthResult.class, outMap.<Integer> get(Authn.InvokeKeys.RESULT))
);
ExtMap authRecord = outMap.get(Authn.InvokeKeys.AUTH_RECORD);
Dump.AUTH_RECORD.dump(module, authRecord);
if (outMap.<Integer> get(Authn.InvokeKeys.RESULT) != Authn.AuthResult.SUCCESS) {
module.acctReport(
Acct.ReportReason.PRINCIPAL_LOGIN_FAILED,
aaaprofile.getAuthzName(),
authRecord,
null,
user,
"User '%1$s' could not login"
);
throw new RuntimeException(
String.format(
"Authn.Result code is: %1$s",
getFieldNameByValue(Authn.AuthResult.class, outMap.<Integer> get(Authn.InvokeKeys.RESULT))
)
);
}
if(aaaprofile.getMappingExtension() != null) {
log.info("API: -->Mapping.InvokeCommands.MAP_AUTH_RECORD");
Dump.AUTH_RECORD.dump(module, authRecord);
authRecord = aaaprofile.getMappingExtension().invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Mapping.InvokeCommands.MAP_AUTH_RECORD
).mput(
Authn.InvokeKeys.AUTH_RECORD,
authRecord
),
true
).get(
Authn.InvokeKeys.AUTH_RECORD,
authRecord
);
log.info("API: <--Mapping.InvokeCommands.MAP_AUTH_RECORD");
Dump.AUTH_RECORD.dump(module, authRecord);
}
log.info(
"API: -->Authz.InvokeCommands.FETCH_PRINCIPAL_RECORD principal='{}'",
(Object) authRecord.get(Authn.AuthRecord.PRINCIPAL)
);
outMap = module.getExtensionsManager().getExtensionByName(aaaprofile.getAuthzName()).invoke(
new ExtMap().
mput(
Base.InvokeKeys.COMMAND,
Authz.InvokeCommands.FETCH_PRINCIPAL_RECORD
).mput(
Authn.InvokeKeys.AUTH_RECORD,
authRecord
).mput(
Authz.InvokeKeys.QUERY_FLAGS,
Authz.QueryFlags.RESOLVE_GROUPS | Authz.QueryFlags.RESOLVE_GROUPS_RECURSIVE
)
);
log.info(
"API: <--Authz.InvokeCommands.FETCH_PRINCIPAL_RECORD status={}",
getFieldNameByValue(Authz.Status.class, outMap.<Integer> get(Authz.InvokeKeys.STATUS))
);
ExtMap principalRecord = outMap.get(Authz.InvokeKeys.PRINCIPAL_RECORD);
Dump.PRINCIPAL_RECORD.dump(module, principalRecord);
if (outMap.<Integer> get(Authz.InvokeKeys.STATUS) != Authz.Status.SUCCESS) {
if (principalRecord == null) {
module.acctReport(
Acct.ReportReason.PRINCIPAL_NOT_FOUND,
aaaprofile.getAuthzName(),
authRecord,
null,
user,
"User '%1$s' could not be found"
);
} else {
module.acctReport(
Acct.ReportReason.PRINCIPAL_LOGIN_FAILED,
aaaprofile.getAuthzName(),
authRecord,
principalRecord,
user,
"User '%1$s' could not be found"
);
}
throw new RuntimeException(
String.format(
"Authz.Status code is: %1$s",
getFieldNameByValue(Authz.Status.class, outMap.<Integer> get(Authz.InvokeKeys.STATUS))
)
);
}
module.acctReport(
Acct.ReportReason.PRINCIPAL_LOGIN_CREDENTIALS,
aaaprofile.getAuthzName(),
authRecord,
principalRecord,
user,
"Principal '%1$s' logged in"
);
if ((aaaprofile.getAuthnExtension().getContext().<Long> get(Authn.ContextKeys.CAPABILITIES) & Authn.Capabilities.LOGOUT) != 0) {
log.info("API: -->Authn.InvokeCommands.LOGOUT principal='{}'", authRecord.<String> get(Authn.AuthRecord.PRINCIPAL));
aaaprofile.getAuthnExtension().invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Authn.InvokeCommands.LOGOUT
).mput(
Authn.InvokeKeys.AUTH_RECORD,
authRecord
)
);
log.info("API: <--Authn.InvokeCommands.LOGOUT");
}
module.acctReport(
Acct.ReportReason.PRINCIPAL_LOGOUT,
aaaprofile.getAuthzName(),
authRecord,
principalRecord,
user,
"Principal '%1$s' logged out"
);
}
),
SEARCH(
module -> {
ExtensionProxy authzExtension = module.getExtensionsManager().getExtensionByName((String) module.argMap.get("extension-name"));
ExtUUID entity = getQueryEntity((String)module.argMap.get("entity"));
ExtMap filter = createQueryFilter(entity, module.argMap);
Dump.QUERY_FILTER_RECORD.dump(module, filter, "");
Collection<String> namespaces = authzExtension.getContext().get(
Authz.ContextKeys.AVAILABLE_NAMESPACES,
Collections.<String>emptyList()
);
if (module.argMap.get("namespace") != null) {
namespaces = (Collection<String>)module.argMap.get("namespace");
}
for (String namespace : namespaces) {
log.info("API: -->Authz.InvokeCommands.QUERY_OPEN namespace='{}'", namespace);
ExtMap outMap = authzExtension.invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Authz.InvokeCommands.QUERY_OPEN
).mput(
Authz.InvokeKeys.QUERY_ENTITY,
entity
).mput(
Authz.InvokeKeys.QUERY_FLAGS,
getAuthzFlags((List<String>)module.argMap.get("authz-flag"))
).mput(
Authz.InvokeKeys.QUERY_FILTER,
filter
).mput(
Authz.InvokeKeys.NAMESPACE,
namespace
)
);
log.info("API: <--Authz.InvokeCommands.QUERY_OPEN");
Object opaque = outMap.get(Authz.InvokeKeys.QUERY_OPAQUE);
boolean done = false;
while (!done) {
log.info("API: -->Authz.InvokeCommands.QUERY_EXECUTE");
outMap = authzExtension.invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Authz.InvokeCommands.QUERY_EXECUTE
).mput(
Authz.InvokeKeys.QUERY_OPAQUE,
opaque
).mput(
Authz.InvokeKeys.PAGE_SIZE,
module.argMap.get("page-size")
)
);
Collection<ExtMap> results = outMap.get(Authz.InvokeKeys.QUERY_RESULT);
log.info("API: <--Authz.InvokeCommands.QUERY_EXECUTE count={}", results == null ? "END" : results.size());
if (results == null) {
done = true;
} else {
for (ExtMap result : results) {
if (Authz.QueryEntity.PRINCIPAL.equals(entity)) {
Dump.PRINCIPAL_RECORD.dump(module, result);
} else if (Authz.QueryEntity.GROUP.equals(entity)) {
Dump.GROUP_RECORD.dump(module, result);
}
}
}
}
log.info("API: -->Authz.InvokeCommands.QUERY_CLOSE");
authzExtension.invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Authz.InvokeCommands.QUERY_CLOSE
).mput(
Authz.InvokeKeys.QUERY_OPAQUE,
opaque
)
);
log.info("API: <--Authz.InvokeCommands.QUERY_CLOSE");
}
}
);
private Logic logic;
private Action(Logic logic) {
this.logic = logic;
}
Map<String, Object> parse(Map<String, String> substitutions, Properties props, List<String> actionArgs) {
ArgumentsParser parser = new ArgumentsParser(props, actionArgs.remove(0));
parser.getSubstitutions().putAll(substitutions);
parser.parse(actionArgs);
Map<String, Object> argMap = parser.getParsedArgs();
if((Boolean)argMap.get("help")) {
System.out.format("Usage: %s", parser.getUsage());
throw new ExitException("Help", 0);
}
if(!parser.getErrors().isEmpty()) {
for(Throwable t : parser.getErrors()) {
log.error(t.getMessage());
}
throw new ExitException("Parsing error", 1);
}
if (actionArgs.size() != 0) {
log.error("Extra parameters in command-line");
throw new ExitException("Parsing error", 1);
}
return argMap;
}
void execute(AAAServiceImpl module) {
logic.execute(module);
}
}
@FunctionalInterface
private interface DumpFormat {
void dump(AAAServiceImpl module, ExtMap map, String indent);
}
private enum Dump {
AUTH_RECORD(
(module, map, indent) -> {
if (map != null) {
log.info("--- Begin AuthRecord ---");
dumpRecord(module, map, Collections.emptySet(), "AuthRecord", "");
log.info("--- End AuthRecord ---");
}
}
),
PRINCIPAL_RECORD(
new DumpFormat() {
@Override
public void dump(AAAServiceImpl module, ExtMap map, String indent) {
if (map != null) {
log.info("{}--- Begin PrincipalRecord ---", indent);
dumpRecord(module, map, Collections.singleton(Authz.PrincipalRecord.GROUPS), "PrincipalRecord", indent);
for (ExtMap group : map.<Collection<ExtMap>>get(Authz.PrincipalRecord.GROUPS, Collections.<ExtMap> emptyList())) {
GROUP_RECORD.dump(module, group, indent + " ");
}
log.info("{}--- End PrincipalRecord ---", indent);
}
}
}
),
GROUP_RECORD(
(module, map, indent) -> dumpGroups(module, map, indent, new HashSet<>())
),
QUERY_FILTER_RECORD(
new DumpFormat() {
@Override
public void dump(AAAServiceImpl module, ExtMap map, String indent) {
if (map != null) {
log.info("{}--- Begin QueryFilterRecord ---", indent);
dumpRecord(module, map, Collections.singleton(Authz.QueryFilterRecord.FILTER), "QueryFilterRecord", indent);
for (ExtMap filter : map.<Collection<ExtMap>>get(Authz.QueryFilterRecord.FILTER, Collections.<ExtMap> emptyList())) {
dump(module, filter, indent + " ");
}
log.info("{}--- End QueryFilterRecord ---", indent);
}
}
}
);
private DumpFormat dumpFormat;
private Dump(DumpFormat dumpFormat) {
this.dumpFormat = dumpFormat;
}
private static void dumpGroups(AAAServiceImpl module, ExtMap map, String indent, Set<String> loopPrevention) {
if (map != null ) {
loopPrevention.add(map.get(Authz.GroupRecord.ID));
log.info("{}--- Begin GroupRecord ---", indent);
dumpRecord(module, map, Collections.singleton(Authz.GroupRecord.GROUPS), "GroupRecord", indent);
map.<Collection<ExtMap>>get(Authz.GroupRecord.GROUPS, Collections.<ExtMap> emptyList())
.stream()
.filter(group -> !loopPrevention.contains(group.<String>get(Authz.GroupRecord.ID)))
.forEach(group -> dumpGroups(module, group, indent + " ", loopPrevention));
log.info("{}--- End GroupRecord ---", indent);
}
}
private static void dumpRecord(AAAServiceImpl module, ExtMap extMap, Set<ExtKey> ignore, String title, String indent) {
if (extMap != null) {
log.debug("{}{}: {}", indent, title, extMap);
Collection<ExtKey> keys = new HashSet<>(extMap.keySet());
if (module.argModuleMap.get("key") != null) {
Collection<ExtKey> k = new HashSet<>();
for (String uuid : (List<String>)module.argModuleMap.get("key")) {
k.add(new ExtKey("Unknown", Object.class, uuid));
}
keys.retainAll(k);
}
for (ExtKey key : keys) {
if (ignore.contains(key)) {
continue;
}
if ((key.getFlags() & ExtKey.Flags.SKIP_DUMP) != 0) {
continue;
}
module.output(
((String)module.argModuleMap.get("format")).replace(
"{key}",
key.getUuid().getUuid().toString()
).replace(
"{name}",
key.getUuid().getName()
).replace(
"{value}",
(key.getFlags() & ExtKey.Flags.SENSITIVE) != 0 ? "***" : extMap.get(key).toString()
),
indent
);
}
}
}
public void dump(AAAServiceImpl module, ExtMap map, String indent) {
dumpFormat.dump(module, map, indent);
}
public void dump(AAAServiceImpl module, ExtMap map) {
dump(module, map, "");
}
}
private ExtMap context;
private Action action;
private Map<String, Object> argModuleMap;
private Map<String, Object> argMap;
private static <T> List<T> safeList(List<T> list) {
return list == null ? Collections.emptyList() : list;
}
private ExtensionsManager getExtensionsManager() {
return (ExtensionsManager)context.get(ContextKeys.EXTENSION_MANAGER);
}
private ExtensionProxy getExtensionByProfile(String name) {
ExtensionProxy ret = getExtensionByConfigKey(Authn.ConfigKeys.PROFILE_NAME, name);
if (ret == null) {
throw new IllegalArgumentException(String.format("Profile '%1$s' not found", name));
}
return ret;
}
private ExtensionProxy getExtensionByConfigKey(String key, String value) {
ExtensionProxy ret = null;
for(ExtensionProxy proxy : getExtensionsManager().getExtensionsByService(Authn.class.getName())) {
if (
value.equals(
proxy.getContext().<Properties>get(
Base.ContextKeys.CONFIGURATION
).getProperty(key)
)
) {
ret = proxy;
break;
}
}
return ret;
}
private void output(String s, String logIndent) {
if ("log".equals(argModuleMap.get("output"))) {
log.info("{}{}", logIndent, s);
} else if ("stdout".equals(argModuleMap.get("output"))) {
System.out.println(s);
}
}
private static String getPassword(String what) {
return getPassword(what, "Password: ");
}
private static String getPassword(String what, String prompt) {
String[] keyValue = what.split(":", 2);
String type = keyValue[0];
String value = keyValue[1];
String password = null;
if ("pass".equals(type)) {
password = value;
} else if ("file".equals(type)) {
try(
InputStream is = new FileInputStream(value);
Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader breader = new BufferedReader(reader)
) {
password = breader.readLine();
} catch (IOException ex) {
throw new IllegalArgumentException(String.format("Unable to read file '%s'.", value));
}
} else if ("env".equals(type)) {
password = System.getenv(value);
} else if ("interactive".equals(type)) {
if (System.console() == null) {
throw new RuntimeException("Console is not available, interactive password prompt is impossible");
}
System.out.print(prompt);
char[] passwordChars = System.console().readPassword();
if (passwordChars == null) {
throw new RuntimeException("Cannot read password");
}
password = new String(passwordChars);
} else {
throw new IllegalArgumentException(String.format("Invalid type: '%s'", type));
}
return password;
}
public String getName() {
return "aaa";
}
public String getDescription() {
return "AAA interfaces.";
}
public void setContext(ExtMap context) {
this.context = context;
}
public ExtMap getContext() {
return context;
}
@Override
public void parseArguments(List<String> args) throws Exception {
args.remove(0);
Properties props = new Properties();
try (
InputStream in = AAAServiceImpl.class.getResourceAsStream("arguments.properties");
Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8)
) {
props.load(reader);
}
Map<String, String> substitutions = context.get(ContextKeys.CLI_PARSER_SUBSTITUTIONS);
ArgumentsParser parser = new ArgumentsParser(props, "module");
parser.getSubstitutions().putAll(substitutions);
parser.parse(args);
argModuleMap = parser.getParsedArgs();
if((Boolean)argModuleMap.get("help")) {
System.out.format("Usage: %s", parser.getUsage());
throw new ExitException("Help", 0);
}
if(!parser.getErrors().isEmpty()) {
for(Throwable t : parser.getErrors()) {
log.error(t.getMessage());
}
throw new ExitException("Parsing error", 1);
}
if (args.size() < 1) {
log.error("Action not provided");
throw new ExitException("Action not provided", 1);
}
try {
action = Action.valueOf(args.get(0).toUpperCase().replace("-", "_"));
} catch(IllegalArgumentException e) {
log.error("Invalid action '{}'", args.get(0));
throw new ExitException("Invalid action", 1);
}
argMap = action.parse(substitutions, props, args);
}
@Override
public void run() throws Exception {
int iterations = (Integer)argModuleMap.get("iterations");
for (int i = 0; i < iterations; i++) {
log.info("Iteration: {}", i);
action.execute(this);
}
}
private static ExtMap createQueryFilter(ExtUUID entity, Map<String, Object> argMap) {
List<ExtMap> filter = new ArrayList<>();
for (String name : safeList((List<String>) argMap.get("entity-name"))) {
filter.add(
createQueryFilterElement(
Authz.QueryEntity.GROUP.equals(entity) ? Authz.GroupRecord.NAME : Authz.PrincipalRecord.NAME,
name
)
);
}
for (String id : safeList((List<String>)argMap.get("entity-id"))) {
filter.add(
createQueryFilterElement(
Authz.QueryEntity.GROUP.equals(entity) ? Authz.GroupRecord.ID : Authz.PrincipalRecord.ID,
id
)
);
}
return new ExtMap().mput(
Authz.InvokeKeys.QUERY_ENTITY,
entity
).mput(
Authz.QueryFilterRecord.OPERATOR,
Authz.QueryFilterOperator.OR
).mput(
Authz.QueryFilterRecord.FILTER,
filter
);
}
private static ExtMap createQueryFilterElement(ExtKey key, String value) {
return new ExtMap().mput(
Authz.QueryFilterRecord.OPERATOR,
Authz.QueryFilterOperator.EQ
).mput(
Authz.QueryFilterRecord.KEY,
key
).mput(
key,
value
);
}
private static ExtUUID getQueryEntity(String entity) {
try {
return (ExtUUID) Authz.QueryEntity.class.getDeclaredField(
entity.toUpperCase()
).get(Authz.QueryEntity.class);
} catch (IllegalAccessException | NoSuchFieldException ex) {
throw new RuntimeException(ex);
}
}
private static int getAuthzFlags(List<String> flags) {
int ret = 0;
for (String f : safeList(flags)) {
try {
ret |= Authz.QueryFlags.class.getDeclaredField(f.toUpperCase().replace("-", "_")).getInt(new Authz.QueryFlags());
} catch(NoSuchFieldException | IllegalAccessException ex) {
log.error("Unknown Authz flag '{}' (ignored)", f);
}
}
return ret;
}
public static <T> String getFieldNameByValue(Class clz, T v) {
for (Field f : clz.getFields()) {
try {
if (v.equals(f.get(null))) {
return f.getName();
}
} catch (IllegalAccessException e) {
// ignore
}
}
return null;
}
private void acctReport(int reason, String authzName, ExtMap authRecord, ExtMap principalRecord, String user, String msg) {
String displayUser = null;
if (displayUser == null && principalRecord != null) {
displayUser = principalRecord.get(Authz.PrincipalRecord.NAME);
}
if (displayUser == null && authRecord != null) {
displayUser = authRecord.get(Authn.AuthRecord.PRINCIPAL);
}
if (displayUser == null) {
displayUser = user;
}
String displayMessage = String.format(msg, displayUser);
List<ExtensionProxy> acctExtensions = getExtensionsManager().getExtensionsByService(Acct.class.getName());
if (acctExtensions != null) {
ExtMap input = new ExtMap().mput(
Acct.InvokeKeys.REASON,
reason
).mput(
Base.InvokeKeys.COMMAND,
Acct.InvokeCommands.REPORT
).mput(
Acct.InvokeKeys.PRINCIPAL_RECORD,
new ExtMap().mput(
Acct.PrincipalRecord.AUTHZ_NAME,
authzName
).mput(
Acct.PrincipalRecord.AUTH_RECORD,
authRecord
).mput(
Acct.PrincipalRecord.PRINCIPAL_RECORD,
principalRecord
).mput(
Acct.PrincipalRecord.USER,
displayUser
).mput(
Acct.InvokeKeys.MESSAGE,
String.format(displayMessage, displayUser)
)
);
for (ExtensionProxy proxy : acctExtensions) {
log.info(
"API: -->Acct.InvokeCommands.REPORT extension={}, reason={}, user='{}', message='{}'",
proxy.getContext().get(Base.ContextKeys.INSTANCE_NAME),
getFieldNameByValue(Acct.ReportReason.class, reason),
displayUser,
displayMessage
);
proxy.invoke(input);
log.info("API: <--Acct.InvokeCommands.REPORT");
}
}
}
class AAAProfile {
private ExtensionProxy authnExtension = null;
private ExtensionProxy authzExtension = null;
private ExtensionProxy mappingExtension = null;
private String mappingName = null;
private String authzName = null;
private String authnName = null;
private String profile = null;
public AAAProfile(String profile) {
this.profile = profile;
this.authnExtension = getExtensionByProfile(profile);
this.mappingName = this.authnExtension.getContext().<Properties>get(Base.ContextKeys.CONFIGURATION).getProperty(Authn.ConfigKeys.MAPPING_PLUGIN);
this.authzName = this.authnExtension.getContext().<Properties>get(Base.ContextKeys.CONFIGURATION).getProperty(Authn.ConfigKeys.AUTHZ_PLUGIN);
this.authnName = this.authnExtension.getContext().get(Base.ContextKeys.INSTANCE_NAME);
this.authzExtension = getExtensionsManager().getExtensionByName(authzName);
if(this.mappingName != null) {
this.mappingExtension = getExtensionsManager().getExtensionByName(mappingName);
}
log.info(
"Profile='{}' authn='{}' authz='{}' mapping='{}'",
getProfile(),
getAuthnName(),
getAuthzName(),
getMappingName()
);
}
public String mapUser(String user) {
if(getMappingExtension()!= null) {
log.info("API: -->Mapping.InvokeCommands.MAP_USER profile='{}' user='{}'", getProfile(), user);
user = getMappingExtension().invoke(
new ExtMap().mput(
Base.InvokeKeys.COMMAND,
Mapping.InvokeCommands.MAP_USER
).mput(
Mapping.InvokeKeys.USER,
user
),
true
).get(Mapping.InvokeKeys.USER, user);
log.info("API: <--Mapping.InvokeCommands.MAP_USER profile='{}' user='{}'", getProfile(), user);
}
return user;
}
public ExtensionProxy getAuthnExtension() {
return authnExtension;
}
public ExtensionProxy getAuthzExtension() {
return authzExtension;
}
public ExtensionProxy getMappingExtension() {
return mappingExtension;
}
public String getMappingName() {
return mappingName;
}
public String getAuthzName() {
return authzName;
}
public String getAuthnName() {
return authnName;
}
public String getProfile() {
return profile;
}
}
}