Yair Zaslavsky has uploaded a new change for review. Change subject: aaa: Extensions tester tool ......................................................................
aaa: Extensions tester tool Change-Id: I7ea2f9c62ced5bdd3801c9f6d8087a35e3c21886 Topic: AAA Signed-off-by: Yair Zaslavsky <yzasl...@redhat.com> --- A backend/manager/extension-tool/pom.xml A backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsTool.java A backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolArguments.java A backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolExecutor.java A backend/manager/extension-tool/src/main/modules/module.xml A backend/manager/extension-tool/src/main/modules/org/ovirt/engine/core/extension-tool/main/module.xml A backend/manager/extension-tool/src/main/resources/extensions-tool/help.properties A backend/manager/extension-tool/src/main/resources/extensions-tool/jaas.conf A backend/manager/extension-tool/src/main/resources/extensions-tool/log4j.xml M backend/manager/modules/extensions-manager/src/main/java/org/ovirt/engine/core/extensions/mgr/ExtensionsManager.java M backend/manager/modules/pom.xml M backend/manager/pom.xml M backend/manager/tools/pom.xml M backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml M ovirt-engine.spec.in A packaging/bin/extensions-tool.sh 16 files changed, 952 insertions(+), 5 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/14/27814/1 diff --git a/backend/manager/extension-tool/pom.xml b/backend/manager/extension-tool/pom.xml new file mode 100644 index 0000000..4d0ffa2 --- /dev/null +++ b/backend/manager/extension-tool/pom.xml @@ -0,0 +1,158 @@ +<?xml version="1.0"?> + +<project + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.ovirt.engine.core</groupId> + <artifactId>manager</artifactId> + <version>3.5.0-SNAPSHOT</version> + </parent> + + <artifactId>extension-tool</artifactId> + <packaging>jar</packaging> + <name>oVirt Engine extensions tool</name> + <description>oVirt Engine extensions tools</description> + + <dependencies> + <dependency> + <groupId>${engine.groupId}</groupId> + <artifactId>common</artifactId> + <version>${engine.version}</version> + </dependency> + + <dependency> + <groupId>${engine.groupId}</groupId> + <artifactId>aaa</artifactId> + <version>${engine.version}</version> + </dependency> + + + <dependency> + <groupId>${engine.groupId}</groupId> + <artifactId>utils</artifactId> + <version>${engine.version}</version> + </dependency> + + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + </dependency> + + <dependency> + <groupId>commons-configuration</groupId> + <artifactId>commons-configuration</artifactId> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${engine.groupId}</groupId> + <artifactId>extensions-manager</artifactId> + <version>${engine.version}</version> + </dependency> + + + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <additionalClasspathElements> + <additionalClasspathElement>${basedir}/**/src/test/java</additionalClasspathElement> + </additionalClasspathElements> + <excludes> + <exclude>**/EngineConfigLogicTest.java</exclude> + <exclude>**/EngineConfigTest.java</exclude> + <exclude>**/MailSenderTest.java</exclude> + <exclude>**/StandaloneDataSourceTest.java</exclude> + <exclude>**/NotificationServiceTest.java</exclude> + <exclude>**/EngineMonitorServiceTest.java</exclude> + </excludes> + </configuration> + </plugin> + + <!-- Create the JBoss module: --> + <plugin> + <groupId>org.ovirt.engine</groupId> + <artifactId>jboss-modules-maven-plugin</artifactId> + </plugin> + <plugin> + <artifactId>maven-checkstyle-plugin</artifactId> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>enable-tools-itests</id> + <dependencies> + <dependency> + <groupId>postgresql</groupId> + <artifactId>postgresql</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration combine.self="override"> + <excludes/> + </configuration> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>findbugs</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>findbugs-maven-plugin</artifactId> + <version>${findbugs.version}</version> + <configuration> + <xmlOutput>true</xmlOutput> + <!-- Optional directory to put findbugs xdoc xml report --> + <excludeFilterFile> ${basedir}/exclude-filters.xml</excludeFilterFile> + <xmlOutputDirectory>target/site</xmlOutputDirectory> + </configuration> + </plugin> + </plugins> + </build> + </profile> + + <profile> + <id>findbugs-general</id> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>findbugs-maven-plugin</artifactId> + <version>${findbugs.version}</version> + <configuration> + <xmlOutput>true</xmlOutput> + <!-- Optional directory to put findbugs xdoc xml report --> + <excludeFilterFile> ${basedir}/exclude-filters.xml, ${basedir}/../../../exclude-filters-general.xml</excludeFilterFile> + <xmlOutputDirectory>target/site</xmlOutputDirectory> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsTool.java b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsTool.java new file mode 100644 index 0000000..3395a50 --- /dev/null +++ b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsTool.java @@ -0,0 +1,292 @@ +package org.ovirt.engine.exttool; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.log4j.Logger; +import org.ovirt.engine.api.extensions.Base; +import org.ovirt.engine.api.extensions.ExtMap; +import org.ovirt.engine.api.extensions.ExtUUID; +import org.ovirt.engine.api.extensions.aaa.Authn; +import org.ovirt.engine.api.extensions.aaa.Authz; +import org.ovirt.engine.core.aaa.SearchQueryParsingUtils; +import org.ovirt.engine.core.extensions.mgr.ExtensionProxy; +import org.ovirt.engine.core.extensions.mgr.ExtensionsManager; + +public class ExtensionsTool { + + private static Logger log = Logger.getLogger(ExtensionsTool.class); + private ExtensionProxy authnExtension; + private ExtensionsManager extensionsManager; + + public ExtensionsTool(ExtensionsToolArguments args, ExtensionsManager extensionsManager) { + this.extensionsManager = extensionsManager; + try { + switch (args.getAction()) { + case ExtensionsToolArguments.ACTION_AUTH_SEQUENCE: + doAuthSequence(args); + break; + + case ExtensionsToolArguments.ACTION_QUERY_BY_IDS: + doQueryByIds(args); + break; + + case ExtensionsToolArguments.ACTION_QUERY_BY_NAME: + doQueryByName(args); + break; + + } + } catch (Exception ex) { + log.error(ex.getMessage()); + if (log.isDebugEnabled()) { + log.debug("", ex); + } + } + } + + + private void doAuthSequence(ExtensionsToolArguments args) throws Exception { + String user = null; + String password = null; + if (args.contains(ExtensionsToolArguments.ARG_USER)) { + user = args.get(ExtensionsToolArguments.ARG_USER); + } else { + System.out.print("Please enter user: "); + user = System.console().readLine(); + } + + if (args.contains(ExtensionsToolArguments.ARG_PASSWORD_ENV_KEY)) { + password = System.getenv(args.get(ExtensionsToolArguments.ARG_PASSWORD_ENV_KEY)); + } else if (args.contains(ExtensionsToolArguments.ARG_PASSWORD_FILE)) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader( new FileInputStream(args.get(ExtensionsToolArguments.ARG_PASSWORD_FILE))))) { + password = reader.readLine(); + } + } else { + System.out.print("Please enter password: "); + password = new String(System.console().readPassword()); + } + + File authnConfig = new File(args.<String> get(ExtensionsToolArguments.ARG_AUTHN_NAME)); + if (!authnConfig.exists()) { + throw new Exception("Could not find authn extension configuration at the path specified"); + } + authnExtension = extensionsManager.activate(extensionsManager.load(authnConfig)); + ExtMap outMap = authnExtension.invoke(new ExtMap().mput( + Base.InvokeKeys.COMMAND, + Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS + ).mput( + Authn.InvokeKeys.USER, + user + ).mput( + Authn.InvokeKeys.CREDENTIALS, + password + ) + ); + ExtMap authRecord = processAuthnResult(outMap, "AUTHENTICATE_CREDENTIALS"); + + if (args.get(ExtensionsToolArguments.ARG_AUTHZ_NAME) != null) { + ExtensionProxy authzExtension = getAuthzExtension(args); + if (authzExtension != null) { + ExtMap outputMap = authzExtension.invoke(new ExtMap().mput( + Base.InvokeKeys.COMMAND, + Authz.InvokeCommands.FETCH_PRINCIPAL_RECORD).mput( + Authn.InvokeKeys.AUTH_RECORD, + authRecord + ) + .mput( + Authz.InvokeKeys.RESOLVE_GROUPS_RECURSIVE, + Boolean.parseBoolean(args.get(ExtensionsToolArguments.ARG_RESOLVE_GROUPS_RECURSIVE, "false")) + ) + ); + printPrincipalRecord(outputMap.<ExtMap> get(Authz.InvokeKeys.PRINCIPAL_RECORD)); + processAuthzResult(outputMap, "FETCH_PRINCIPAL"); + } + + } + if (authRecord != null) { + if ((authnExtension.getContext().<Long> get(Authn.ContextKeys.CAPABILITIES) & Authn.Capabilities.LOGOUT) != 0) { + ExtMap outputMap = authnExtension.invoke(new ExtMap().mput( + Base.InvokeKeys.COMMAND, + Authn.InvokeCommands.LOGOUT + ).mput( + Authn.InvokeKeys.PRINCIPAL, + authRecord.<String> get(Authn.AuthRecord.PRINCIPAL) + ) + ); + authRecord = processAuthnResult(outputMap, "LOGOUT"); + } + else { + log.info("The extension does not support logout"); + } + } + } + + private ExtensionProxy getAuthzExtension(ExtensionsToolArguments args) throws Exception { + File authzConfig = new File(args.<String> get(ExtensionsToolArguments.ARG_AUTHZ_NAME)); + if (!authzConfig.exists()) { + throw new Exception("Could not find authz extension configuration at the path specified"); + } + return extensionsManager.activate(extensionsManager.load(authzConfig)); + } + + private ExtMap processAuthnResult(ExtMap outMap, String operation) throws Exception { + if (outMap.<Integer> get(Base.InvokeKeys.RESULT) != Base.InvokeResult.SUCCESS) { + throw new Exception(String.format("Base.InvokeResult code is: %1$s. Invocation of %2$s failed.", + outMap.<Integer> get(Base.InvokeKeys.RESULT), operation)); + } + + log.info(String.format("Successful invocation of %1$s", operation)); + if (outMap.<Integer> get(Authn.InvokeKeys.RESULT) != Authn.AuthResult.SUCCESS) { + throw new Exception(String.format("Authn.Result code is: %1$s", + outMap.<Integer> get(Authn.InvokeKeys.RESULT))); + } + printAuthRecord(outMap.<ExtMap> get(Authn.InvokeKeys.AUTH_RECORD)); + return outMap.get(Authn.InvokeKeys.AUTH_RECORD); + } + + private void processAuthzResult(ExtMap outMap, String operation) throws Exception { + if (outMap.<Integer> get(Base.InvokeKeys.RESULT) != Base.InvokeResult.SUCCESS) { + throw new Exception(String.format("Base.InvokeResult code is: %1$s. Invocation of %2$s failed", outMap.<Integer> get(Base.InvokeKeys.RESULT), operation)); + } + log.info(String.format("Successful invocation of %1$s", operation)); + if (outMap.<Integer> get(Authz.InvokeKeys.STATUS) != Authz.Status.SUCCESS) { + throw new Exception(String.format("Authz.Status code is: %1$s", outMap.<Integer> get(Authz.InvokeKeys.STATUS))); + } + } + + private void doQueryByName(ExtensionsToolArguments args) throws Exception { + runQuery( + args, + SearchQueryParsingUtils.generateQueryForName( + args.get(ExtensionsToolArguments.ARG_NAME), + getEntityByArgs(args) + ) + ); + } + + private void doQueryByIds(ExtensionsToolArguments args) throws Exception { + ExtensionProxy authzExtension = getAuthzExtension(args); + List<List<String>> idsBatches = + SearchQueryParsingUtils.getIdsBatches(authzExtension, + Arrays.asList(args.get(ExtensionsToolArguments.ARG_IDS, "").split(","))); + log.info(String.format("Going to split the ids to %1$s batches for execution", idsBatches.size())); + ExtUUID entity = getEntityByArgs(args); + for (List<String> ids : idsBatches) { + runQuery(args, + SearchQueryParsingUtils.generateQueryMap(ids, entity)); + } + log.info("Finished running all queries"); + } + + private ExtUUID getEntityByArgs(ExtensionsToolArguments args) { + return args.get(ExtensionsToolArguments.ARG_QUERY_ENTITY) + .equals(ExtensionsToolArguments.QUERY_ENTITY_GROUP) ? + Authz.QueryEntity.GROUP : Authz.QueryEntity.PRINCIPAL; + } + + private void runQuery(ExtensionsToolArguments args, ExtMap filter) throws Exception { + ExtUUID entity = getEntityByArgs(args); + ExtensionProxy authzExtension = getAuthzExtension(args); + ExtMap outMap = authzExtension.invoke(new ExtMap().mput( + Base.InvokeKeys.COMMAND, + Authz.InvokeCommands.QUERY_OPEN + ).mput( + Authz.InvokeKeys.QUERY_ENTITY, + entity + ).mput( + Authz.InvokeKeys.RESOLVE_GROUPS_RECURSIVE, + Boolean.parseBoolean(args.get(ExtensionsToolArguments.ARG_RESOLVE_GROUPS_RECURSIVE, "false")) + ).mput( + Authz.InvokeKeys.QUERY_FILTER, + filter + )); + processAuthzResult(outMap, "QueryOpen"); + if (outMap.get(Base.InvokeKeys.RESULT).equals(Base.InvokeResult.SUCCESS)) { + do { + ExtMap inputMap = new ExtMap().mput( + Base.InvokeKeys.COMMAND, + Authz.InvokeCommands.QUERY_EXECUTE + ).mput( + Authz.InvokeKeys.QUERY_OPAQUE, + outMap.get(Authz.InvokeKeys.QUERY_OPAQUE) + ); + if (args.contains(ExtensionsToolArguments.ARG_PAGE_SIZE)) { + inputMap.put(Authz.InvokeKeys.PAGE_SIZE, + Integer.parseInt(args.get(ExtensionsToolArguments.ARG_PAGE_SIZE))); + } + outMap = authzExtension.invoke(inputMap); + processAuthzResult(outMap, "QueryExecute"); + if (outMap.get(Base.InvokeKeys.RESULT).equals(Base.InvokeResult.SUCCESS)) { + List<ExtMap> results = outMap.<List<ExtMap>> get(Authz.InvokeKeys.QUERY_RESULT); + if (results != null) { + for (ExtMap result: results) { + if (entity.equals(Authz.QueryEntity.GROUP)) { + printGroupRecord(result); + } else { + printPrincipalRecord(result); + } + } + } + } + + } while (outMap.get(Authz.InvokeKeys.QUERY_RESULT) != null); + log.info("Finished all executions, closing query"); + outMap = authzExtension.invoke(new ExtMap().mput( + Base.InvokeKeys.COMMAND, + Authz.InvokeCommands.QUERY_CLOSE + ).mput( + Authz.InvokeKeys.QUERY_OPAQUE, + outMap.get(Authz.InvokeKeys.QUERY_OPAQUE) + )); + processAuthzResult(outMap, "QueryClose"); + } + } + + private void printPrincipalRecord(ExtMap extMap) { + if (extMap != null) { + log.info(String.format("PrincipalRecord: ID %s, name: %s, display name: %s, email: %s, first name: %s, last name: %s, department: %s, title: %s", + extMap.get(Authz.PrincipalRecord.ID, ""), + extMap.get(Authz.PrincipalRecord.NAME, ""), + extMap.get(Authz.PrincipalRecord.DISPLAY_NAME, ""), + extMap.get(Authz.PrincipalRecord.EMAIL, ""), + extMap.get(Authz.PrincipalRecord.FIRST_NAME, ""), + extMap.get(Authz.PrincipalRecord.LAST_NAME, ""), + extMap.get(Authz.PrincipalRecord.DEPARTMENT, ""), + extMap.get(Authz.PrincipalRecord.TITLE, "") + )); + log.info("Groups of PrincipalRecord: "); + for (ExtMap group : extMap.<List<ExtMap>> get(Authz.PrincipalRecord.GROUPS, + Collections.<ExtMap> emptyList())) { + printGroupRecord(group); + } + log.info("End of groups of PrincipalRecord: "); + + } + + } + + private void printGroupRecord(ExtMap extMap) { + if (extMap != null) { + log.info(String.format("GroupRecord: ID %s, name: %s, Display name: %s", + extMap.get(Authz.GroupRecord.ID, ""), + extMap.get(Authz.GroupRecord.NAME, ""), + extMap.get(Authz.GroupRecord.DISPLAY_NAME, "") + )); + } + + } + + private void printAuthRecord(ExtMap extMap) { + if (extMap != null) { + log.info(String.format("AuthRecord: Principal %s, ValidTo: %s", + extMap.get(Authn.AuthRecord.PRINCIPAL, ""), + extMap.get(Authn.AuthRecord.VALID_TO, ""))); + } + } + +} diff --git a/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolArguments.java b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolArguments.java new file mode 100644 index 0000000..581ec75 --- /dev/null +++ b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolArguments.java @@ -0,0 +1,253 @@ +package org.ovirt.engine.exttool; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.ovirt.engine.core.uutils.cli.ArgumentBuilder; +import org.ovirt.engine.core.uutils.cli.ExtendedCliParser; + +public class ExtensionsToolArguments { + + private static final String HELP_PROPERTIES = "/extensions-tool/help.properties"; + private String action; + + //LOG + public static final String ARG_LOG_LEVEL = "--log-level"; + public static final String ARG_LOG_FILE = "--log-file"; + public static final String ARG_LOG4J_CONFIG = "--log4j-config"; + public static final String ARG_CONFIG_FILE = "--config-file"; + + // Actions + public static final String ACTION_AUTH_SEQUENCE = "auth-sequence"; + public static final String ACTION_QUERY_BY_NAME = "query-by-name"; + public static final String ACTION_QUERY_BY_IDS = "query-by-ids"; + public static final String ACTION_HELP = "help"; + + // Auth arguments + public static final String ARG_USER = "--user"; + public static final String ARG_AUTHN_NAME = "--authn"; + public static final String ARG_PASSWORD_FILE = "--password-file"; + public static final String ARG_PASSWORD_ENV_KEY = "--password-env-key"; + + // Query arguments + public static final String ARG_AUTHZ_NAME = "--authz"; + public static final String ARG_QUERY_ENTITY = "--query-entity"; + public static final String ARG_PAGE_SIZE = "--page-size"; + public static final String ARG_IDS = "--ids"; + public static final String ARG_NAME = "--name"; + public static final String ARG_RESOLVE_GROUPS_RECURSIVE = "--resolve-groups-recursive"; + public static final String ARG_MAX_QUERY_RESULTS = "--max-query-results"; + + // Query entity values + public static final String QUERY_ENTITY_PRINCIPAL = "principal"; + public static final String QUERY_ENTITY_GROUP = "group"; + + private Map<String, String> argMap; + + /** + * Returns set of required args for specified action + */ + private Set<String> getRequiredArgs(String action) { + Set<String> result = new LinkedHashSet<>(); + + if (ACTION_AUTH_SEQUENCE.equals(action)) { + result.add(ARG_AUTHN_NAME); + } else if (ACTION_QUERY_BY_IDS.equals(action)) { + result.add(ARG_IDS); + result.add(ARG_PAGE_SIZE); + result.add(ARG_AUTHZ_NAME); + result.add(ARG_QUERY_ENTITY); + result.add(ARG_MAX_QUERY_RESULTS); + } else if (ACTION_QUERY_BY_NAME.equals(action)) { + result.add(ARG_NAME); + result.add(ARG_PAGE_SIZE); + result.add(ARG_AUTHZ_NAME); + result.add(ARG_QUERY_ENTITY); + result.add(ARG_MAX_QUERY_RESULTS); + } + return result; + } + + public void parse(String[] args) throws Exception { + if (args.length < 1 || ACTION_HELP.equals(args[0])) { + // print help + argMap = new HashMap<>(); + argMap.put(ACTION_HELP, null); + return; + } + + action = args[0]; + + if (!(ACTION_AUTH_SEQUENCE.equals(args[0]) || ACTION_QUERY_BY_IDS.equals(args[0]) || ACTION_QUERY_BY_NAME.equals(args[0]))) { + throw new Exception("invalid action"); + } + + + if (args.length > 1) { + // entered more args than just action, parse them + ExtendedCliParser parser = initParser(action); + argMap = parser.parse(args, 1, args.length); + } else { + argMap = new HashMap<>(); + } + + // check that all required args are present + for (String arg : getRequiredArgs(args[0])) { + if (!argMap.containsKey(arg)) { + throw new Exception("Not all required args are present"); + } + } + } + + public String get(String key) { + return argMap.get(key); + } + + public String get(String key, String defaultValue) { + return argMap.containsKey(key) ? argMap.get(key) : defaultValue; + } + + public void printHelp() { + Properties helpProp = new Properties(); + try (InputStream is = getClass().getResourceAsStream(HELP_PROPERTIES)) { + helpProp.load(is); + } catch (Exception ex) { + System.out.println("Error reading help content"); + } + if (!helpProp.isEmpty()) { + System.out.println(helpProp.getProperty("help.usage")); + System.out.println(helpProp.getProperty("help.actions")); + System.out.println(helpProp.getProperty("help.options")); + } + } + + public boolean contains(String key) { + return argMap.containsKey(key); + } + + private ExtendedCliParser initParser(String action) { + ExtendedCliParser parser = new ExtendedCliParser(); + + parser.addArg(new ArgumentBuilder() + .longName(ARG_CONFIG_FILE) + .valueRequired(true) + .build()); + + parser.addArg(new ArgumentBuilder() + .longName(ARG_LOG_FILE) + .valueRequired(true) + .build()); + + parser.addArg(new ArgumentBuilder() + .longName(ARG_LOG_LEVEL) + .valueRequired(true) + .build()); + + parser.addArg(new ArgumentBuilder() + .longName(ARG_LOG4J_CONFIG) + .valueRequired(true) + .build()); + + if ((ACTION_AUTH_SEQUENCE.equals(action))) { + parser.addArg(new ArgumentBuilder(). + longName(ARG_USER). + valueRequired(false). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_AUTHN_NAME). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_PASSWORD_FILE). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_PASSWORD_ENV_KEY). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_AUTHZ_NAME). + valueRequired(false). + build()); + + } else if (ACTION_QUERY_BY_IDS.equals(action)) { + parser.addArg(new ArgumentBuilder(). + longName(ARG_IDS). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_PAGE_SIZE). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_AUTHZ_NAME). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_QUERY_ENTITY). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_RESOLVE_GROUPS_RECURSIVE). + valueRequired(false). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_MAX_QUERY_RESULTS). + valueRequired(true). + build()); + + } else if (ACTION_QUERY_BY_NAME.equals(action)) { + parser.addArg(new ArgumentBuilder(). + longName(ARG_NAME). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_PAGE_SIZE). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_AUTHZ_NAME). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_QUERY_ENTITY). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_MAX_QUERY_RESULTS). + valueRequired(true). + build()); + + parser.addArg(new ArgumentBuilder(). + longName(ARG_RESOLVE_GROUPS_RECURSIVE). + valueRequired(false). + build()); + + } + return parser; + } + + public String getAction() { + return action; + } + + + +} diff --git a/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolExecutor.java b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolExecutor.java new file mode 100644 index 0000000..285d978 --- /dev/null +++ b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolExecutor.java @@ -0,0 +1,65 @@ +package org.ovirt.engine.exttool; + + +import static org.ovirt.engine.exttool.ExtensionsToolArguments.ACTION_HELP; +import static org.ovirt.engine.exttool.ExtensionsToolArguments.ARG_LOG4J_CONFIG; +import static org.ovirt.engine.exttool.ExtensionsToolArguments.ARG_LOG_FILE; +import static org.ovirt.engine.exttool.ExtensionsToolArguments.ARG_LOG_LEVEL; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.log4j.helpers.LogLog; +import org.ovirt.engine.core.extensions.mgr.ExtensionsManager; +import org.ovirt.engine.core.utils.log.Log4jUtils; + +public class ExtensionsToolExecutor { + public static void setupLogging(String log4jConfig, String logFile, String logLevel) { + URL cfgFileUrl = null; + try { + if (log4jConfig == null) { + cfgFileUrl = ExtensionsToolExecutor.class.getResource("/extensions-tool/log4j.xml"); + } else { + cfgFileUrl = new File(log4jConfig).toURI().toURL(); + } + Log4jUtils.setupLogging(cfgFileUrl); + } catch (MalformedURLException ex) { + throw new IllegalArgumentException( + String.format("Error loading log4j configuration from '%s': %s", cfgFileUrl, ex.getMessage()), + ex); + } + + if (logFile != null) { + Log4jUtils.addFileAppender(logFile, logLevel); + } + } + + public static void main(String... args) { + ExtensionsToolArguments testerArgs = null; + try { + // suppress displaying log4j warnings due to accessing logs when parsing params + LogLog.setQuietMode(true); + testerArgs = new ExtensionsToolArguments(); + testerArgs.parse(args); + LogLog.setQuietMode(false); + + setupLogging(testerArgs.get(ARG_LOG4J_CONFIG), testerArgs.get(ARG_LOG_FILE), testerArgs.get(ARG_LOG_LEVEL)); + ExtensionsTool tester = new ExtensionsTool(testerArgs, new ExtensionsManager()); + + } catch (Throwable t) { + System.out.println(t.getMessage()); + System.exit(1); + } + + try { + if (testerArgs.contains(ACTION_HELP)) { + testerArgs.printHelp(); + System.exit(0); + } else { + } + } catch (Exception e) { + } + } + +} diff --git a/backend/manager/extension-tool/src/main/modules/module.xml b/backend/manager/extension-tool/src/main/modules/module.xml new file mode 100644 index 0000000..80a52f8 --- /dev/null +++ b/backend/manager/extension-tool/src/main/modules/module.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<module xmlns="urn:jboss:module:1.1" name="org.ovirt.engine.core.tools"> + + <resources> + <resource-root path="tools.jar"/> + </resources> + + <dependencies> + <module name="javax.api"/> + <module name="javax.mail.api"/> + <module name="org.apache.commons.collections"/> + <module name="org.apache.commons.configuration"/> + <module name="org.apache.commons.lang"/> + <module name="org.apache.commons.logging"/> + <module name="org.apache.log4j"/> + <module name="org.ovirt.engine.api.ovirt-engine-extensions-api"/> + <module name="org.ovirt.engine.core.aaa"/> + <module name="org.ovirt.engine.core.common"/> + <module name="org.ovirt.engine.core.compat"/> + <module name="org.ovirt.engine.core.extensions-manager"/> + <module name="org.ovirt.engine.core.utils"/> + <module name="org.ovirt.engine.core.uutils"/> + <module name="org.postgresql"/> + <module name="org.snmp4j"/> + <module name="sun.jdk"/> + </dependencies> +</module> diff --git a/backend/manager/extension-tool/src/main/modules/org/ovirt/engine/core/extension-tool/main/module.xml b/backend/manager/extension-tool/src/main/modules/org/ovirt/engine/core/extension-tool/main/module.xml new file mode 100644 index 0000000..0a60de8 --- /dev/null +++ b/backend/manager/extension-tool/src/main/modules/org/ovirt/engine/core/extension-tool/main/module.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<module xmlns="urn:jboss:module:1.1" name="org.ovirt.engine.core.extension-tool"> + + <resources> + <resource-root path="extension-tool.jar"/> + </resources> + + <dependencies> + <module name="javax.api"/> + <module name="org.apache.commons.collections"/> + <module name="org.apache.commons.configuration"/> + <module name="org.apache.commons.lang"/> + <module name="org.apache.commons.logging"/> + <module name="org.apache.log4j"/> + <module name="org.ovirt.engine.api.ovirt-engine-extensions-api"/> + <module name="org.ovirt.engine.core.aaa"/> + <module name="org.ovirt.engine.core.common"/> + <module name="org.ovirt.engine.core.compat"/> + <module name="org.ovirt.engine.core.extensions-manager"/> + <module name="org.ovirt.engine.core.utils"/> + <module name="org.ovirt.engine.core.uutils"/> + <module name="sun.jdk"/> + </dependencies> +</module> diff --git a/backend/manager/extension-tool/src/main/resources/extensions-tool/help.properties b/backend/manager/extension-tool/src/main/resources/extensions-tool/help.properties new file mode 100644 index 0000000..c27d218 --- /dev/null +++ b/backend/manager/extension-tool/src/main/resources/extensions-tool/help.properties @@ -0,0 +1,59 @@ +help.usage=usage: extensions-tool <action> [<args>] + +help.actions=\ +Available actions:\ +\n\tauth-sequence runs an authentication sequence (authenticate, fetch principal, logout)\ +\n\tquery-by-name queries principal by name \ +\n\tduery-by-ids queries principals by idss \ +\n\ +\nauth-sequence:\ +\n\textensions-tester auth-sequence [--user=USER] --authn=AUTHN_CONF_FILE [--authz=AUTHZ_CONF_FILE] [--log-file=LOG_FILE] [--log4j-config=LOG4J_XML_FILE] [--password-file=PASSWORD_FILE] [--password-env-key=PASSWORD_ENV_KEY]\ +\n\ +\nquery-by-name:\ +\n\textensions-tester query-by-name --authz=AUTHZ_CONF_FILE --name=NAME --page-size=PAGE_SIZE --max-query-results=MAX_QUERY_RESULTS [--log-file=LOG_FILE] [--log4j-config=LOG4J_XML_FILE] [--resolve-groups-recursive=FLAG]\ +\n\ +\nquery-by-ids:\ +\n\textensions-tester query-by-ids -authz=AUTHZ_CONF_FILEE --ids=LIST_OF_IDS --page-size=PAGE_SIZE --max-query-results=MAX_QUERY_RESULTS [--log-file=LOG_FILE] [--log4j-config=LOG4J_XML_FILE] [--resolve-groups-recursive=FLAG]\ +\n\ + +help.options=\ +\nOptions:\ +\n--user=USER\ +\n\tUser to perform authentication with.\ +\n\ +\n--authn=AUTHN_PROVIDER_NAME\ +\n\tPath to configuration fo authn.\ +\n\ +\n--authz=AUTHZ_CONF_FILE\ +\n\tPath to configuration of authz.\ +\n\ +\n--password-file=PASSWORD_FILE\ +\n\tPath to file the password will be read from, if the argument is provided.\ +\n--log-file=LOG_FILE\ +\n +\n--password-env-key=PASSWORD_ENV_KEY\ +\n +\n\tName of environment variable containing the password value, if the argument is provided.\ +\n +\n\tPath to file used for logging.\ +\n\ +\n--log-level=LOG_LEVEL\ +\n\tSets log level, one of DEBUG (default), INFO, WARN, ERROR (case insensitive).\ +\n +\n--log4j-config=LOG4J_XML_FILE\ +\n\tPath to log4j configuration file which logging configuration is loaded from.\ +\n\ +\n--help\ +\n\tShow this help message and exit.\ +\n\ +\n--name=NAME\ +\n\tName of principal or group to query.\ +\n\ +\n--ids=IDS\ +\n\tComma delimited string of IDS to query.\ +\n +\n--log4j-config=LOG4J_XML_FILE\ +\n +\n\tSets log4j.xml file which logging configuration is loaded from.\ +\n\ + diff --git a/backend/manager/extension-tool/src/main/resources/extensions-tool/jaas.conf b/backend/manager/extension-tool/src/main/resources/extensions-tool/jaas.conf new file mode 100644 index 0000000..69c4b0b --- /dev/null +++ b/backend/manager/extension-tool/src/main/resources/extensions-tool/jaas.conf @@ -0,0 +1,4 @@ +EngineKerberosAuth { + com.sun.security.auth.module.Krb5LoginModule required client=TRUE; +}; + diff --git a/backend/manager/extension-tool/src/main/resources/extensions-tool/log4j.xml b/backend/manager/extension-tool/src/main/resources/extensions-tool/log4j.xml new file mode 100644 index 0000000..7b0580b --- /dev/null +++ b/backend/manager/extension-tool/src/main/resources/extensions-tool/log4j.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> + +<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> + <appender name="null-appender" class="org.apache.log4j.varia.NullAppender" /> + <root> + <level value="DEBUG"/> + <!-- + We need this, because log4j writes warning messages to stderr + if no appender is configured and we add appender only if proper + command line argument is specified. + --> + <appender-ref ref="null-appender" /> + </root> +</log4j:configuration> diff --git a/backend/manager/modules/extensions-manager/src/main/java/org/ovirt/engine/core/extensions/mgr/ExtensionsManager.java b/backend/manager/modules/extensions-manager/src/main/java/org/ovirt/engine/core/extensions/mgr/ExtensionsManager.java index 4f7f996..0d5a68d 100644 --- a/backend/manager/modules/extensions-manager/src/main/java/org/ovirt/engine/core/extensions/mgr/ExtensionsManager.java +++ b/backend/manager/modules/extensions-manager/src/main/java/org/ovirt/engine/core/extensions/mgr/ExtensionsManager.java @@ -243,7 +243,7 @@ return results; } - public void activate(String extensionName) { + public ExtensionProxy activate(String extensionName) { ExtensionEntry entry = loadedEntries.get(extensionName); if (entry != null && entry.enabled) { entry.extension.getContext().put( @@ -297,6 +297,7 @@ dumpConfig(entry.extension); setChanged(); notifyObservers(); + return entry.extension; } } diff --git a/backend/manager/modules/pom.xml b/backend/manager/modules/pom.xml index dd56a22..f410d43 100644 --- a/backend/manager/modules/pom.xml +++ b/backend/manager/modules/pom.xml @@ -34,6 +34,7 @@ <module>services</module> <module>docs</module> <module>welcome</module> + <module>xmlaaa</module> </modules> <dependencies> diff --git a/backend/manager/pom.xml b/backend/manager/pom.xml index b743555..b616e0b 100644 --- a/backend/manager/pom.xml +++ b/backend/manager/pom.xml @@ -1,4 +1,4 @@ -<?xml version="1.0"?> +<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -14,5 +14,6 @@ <module>dependencies</module> <module>modules</module> <module>tools</module> + <module>extension-tool</module> </modules> -</project> +</project> \ No newline at end of file diff --git a/backend/manager/tools/pom.xml b/backend/manager/tools/pom.xml index ee3b340..d49e4ad 100644 --- a/backend/manager/tools/pom.xml +++ b/backend/manager/tools/pom.xml @@ -31,6 +31,13 @@ <artifactId>common</artifactId> <version>${engine.version}</version> </dependency> + + <dependency> + <groupId>${engine.groupId}</groupId> + <artifactId>aaa</artifactId> + <version>${engine.version}</version> + </dependency> + <dependency> <groupId>${engine.groupId}</groupId> @@ -59,6 +66,12 @@ <version>${junit.version}</version> <scope>test</scope> </dependency> + <dependency> + <groupId>${engine.groupId}</groupId> + <artifactId>extensions-manager</artifactId> + <version>${engine.version}</version> + </dependency> + </dependencies> diff --git a/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml b/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml index 47de050..80a52f8 100644 --- a/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml +++ b/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml @@ -14,13 +14,15 @@ <module name="org.apache.commons.lang"/> <module name="org.apache.commons.logging"/> <module name="org.apache.log4j"/> + <module name="org.ovirt.engine.api.ovirt-engine-extensions-api"/> + <module name="org.ovirt.engine.core.aaa"/> <module name="org.ovirt.engine.core.common"/> <module name="org.ovirt.engine.core.compat"/> + <module name="org.ovirt.engine.core.extensions-manager"/> <module name="org.ovirt.engine.core.utils"/> <module name="org.ovirt.engine.core.uutils"/> <module name="org.postgresql"/> <module name="org.snmp4j"/> <module name="sun.jdk"/> </dependencies> - </module> diff --git a/ovirt-engine.spec.in b/ovirt-engine.spec.in index 0f4a915..97ab974 100644 --- a/ovirt-engine.spec.in +++ b/ovirt-engine.spec.in @@ -557,7 +557,7 @@ # /var creation # install -dm 755 "%{buildroot}/%{engine_state}"/{content,setup/answers} -install -dm 755 "%{buildroot}/%{engine_log}"/{host-deploy,setup,notifier,engine-manage-domains,dump} +install -dm 755 "%{buildroot}/%{engine_log}"/{host-deploy,setup,notifier,engine-manage-domains,dump,extensions-tool} install -dm 755 "%{buildroot}/%{engine_cache}" install -dm 755 "%{buildroot}/%{engine_run}/notifier" @@ -595,6 +595,7 @@ %{engine_jboss_modules}/org/ovirt/engine/core/aaa/main/aaa.jar %{engine_jboss_modules}/org/ovirt/engine/core/common/main/common.jar %{engine_jboss_modules}/org/ovirt/engine/core/compat/main/compat.jar +%{engine_jboss_modules}/org/ovirt/engine/core/extension-tool/main/extension-tool.jar %{engine_jboss_modules}/org/ovirt/engine/core/dal/main/dal.jar %{engine_jboss_modules}/org/ovirt/engine/core/extensions-manager/main/extensions-manager.jar %{engine_jboss_modules}/org/ovirt/engine/core/searchbackend/main/searchbackend.jar @@ -1006,6 +1007,7 @@ %{_bindir}/engine-backup %{_bindir}/engine-config %{_bindir}/engine-manage-domains +%{_bindir}/extensions-tool %{_mandir}/man8/engine-backup.* %{_mandir}/man8/engine-config.* %{_mandir}/man8/engine-manage-domains.* @@ -1013,6 +1015,7 @@ %{engine_data}/bin/engine-config.sh %{engine_data}/bin/engine-manage-domains.sh %{engine_data}/bin/engine-prolog.sh +%{engine_data}/bin/extensions-tool.sh %{engine_data}/bin/ovirt-engine-role.sh %{engine_data}/conf/jaas.conf %{engine_data}/services/ovirt-engine-notifier diff --git a/packaging/bin/extensions-tool.sh b/packaging/bin/extensions-tool.sh new file mode 100755 index 0000000..f91c74c --- /dev/null +++ b/packaging/bin/extensions-tool.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# +# This script is designed to run the manage domains utility. +# The tool's configuration should be under the /etc directory. +# + +# Load the prolog: +. "$(dirname "$(readlink -f "$0")")"/engine-prolog.sh + +# +# Add this option to the java command line to enable remote debugging in +# all IP addresses and port 8787: +# +# -Xrunjdwp:transport=dt_socket,address=0.0.0.0:8787,server=y,suspend=y +# +# Note that the "suspend=y" options is needed to suspend the execution +# of the JVM till you connect with the debugger, otherwise it is +# not possible to debug the execution of the main method. +# + +exec "${JAVA_HOME}/bin/java" \ + -Djboss.modules.write-indexes=false \ + -jar "${JBOSS_HOME}/jboss-modules.jar" \ + -dependencies org.ovirt.engine.core.extension-tool \ + -class org.ovirt.engine.exttool.ExtensionsToolExecutor \ + "$@" -- To view, visit http://gerrit.ovirt.org/27814 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I7ea2f9c62ced5bdd3801c9f6d8087a35e3c21886 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Yair Zaslavsky <yzasl...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches