Juan Hernandez has uploaded a new change for review. Change subject: core: Add Keystone authenticator ......................................................................
core: Add Keystone authenticator This patch adds an initial version of the OpenStack Keystone authenticator. It performs authentication connnecting to the Keystone service and requesting a token using the configured URL and tenant and the given user name. To enable this authenticator create a configuration file with the following content to the /etc/ovirt-engine/auth.d directory: # # The name of the authentication profile, this should match # the name of the tenant, but this isn't enforced: # name=mytenant # # The type of the authenticator: # authenticator.type=keystone # # Keystone specific parameters: # keystone.url=http://server:5000/v3 keystone.tenant=mytenant # # The type of the directory: # directory.type=nop Note that this patch doesn't add a Keystone directory, that will be added in later patches. Also note that this authenticator doesn't yet support TLS for the communications with the Keystone server. This is a must for real environments and will be added in later patches or in a later incarnation of this same patch. Change-Id: I9588f015ac8766e38163665e4eec68b9d5638a6d Signed-off-by: Juan Hernandez <juan.hernan...@redhat.com> --- M backend/manager/modules/authentication/pom.xml A backend/manager/modules/authentication/src/main/java/org/ovirt/engine/core/authentication/openstack/KeystoneAuthenticator.java A backend/manager/modules/authentication/src/main/java/org/ovirt/engine/core/authentication/openstack/KeystoneAuthenticatorFactory.java M backend/manager/modules/authentication/src/main/resources/META-INF/services/org.ovirt.engine.core.authentication.AuthenticatorFactory 4 files changed, 177 insertions(+), 0 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/49/21149/1 diff --git a/backend/manager/modules/authentication/pom.xml b/backend/manager/modules/authentication/pom.xml index 179834f..47a967e 100644 --- a/backend/manager/modules/authentication/pom.xml +++ b/backend/manager/modules/authentication/pom.xml @@ -34,6 +34,18 @@ <artifactId>commons-lang</artifactId> </dependency> + <dependency> + <groupId>com.woorea</groupId> + <artifactId>keystone-client</artifactId> + <version>${openstack-client.version}</version> + </dependency> + + <dependency> + <groupId>com.woorea</groupId> + <artifactId>keystone-model</artifactId> + <version>${openstack-client.version}</version> + </dependency> + </dependencies> <build> diff --git a/backend/manager/modules/authentication/src/main/java/org/ovirt/engine/core/authentication/openstack/KeystoneAuthenticator.java b/backend/manager/modules/authentication/src/main/java/org/ovirt/engine/core/authentication/openstack/KeystoneAuthenticator.java new file mode 100644 index 0000000..dab544f --- /dev/null +++ b/backend/manager/modules/authentication/src/main/java/org/ovirt/engine/core/authentication/openstack/KeystoneAuthenticator.java @@ -0,0 +1,92 @@ +package org.ovirt.engine.core.authentication.openstack; + +import com.woorea.openstack.base.client.OpenStackResponseException; +import com.woorea.openstack.keystone.Keystone; +import com.woorea.openstack.keystone.api.TokensResource; +import org.ovirt.engine.core.authentication.PasswordAuthenticator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This authenticator authenticates the internal connecting to a OpenStack Keystone identity management server. To + * configure it create a an authenticator profile like this: + * + * <pre> + * name=keystone + * module=org.ovirt.engine.core.authentication + * authenticator.type=keystone + * keystone.url=http://server:5000/v3 + * keystone.tenant=mytenant + * directory.type=nop + * </pre> + */ +public class KeystoneAuthenticator implements PasswordAuthenticator { + // The log: + private static final Logger log = LoggerFactory.getLogger(KeystoneAuthenticator.class); + + // The name of the authenticator: + private String name; + + // The name of the tenant: + private String tenant; + + // The Keystone client: + private Keystone client; + + /** + * Create a new Keystone authenticator. + * + * @param name the name of the authenticator + * @param url the URL of the Keystone service + * @param tenant the name of the Keystone tenant + */ + public KeystoneAuthenticator(String name, String url, String tenant) { + // Save the name of the authenticator and the tenant: + this.name = name; + this.tenant = tenant; + + // Create the Keystone client: + client = new Keystone(url); + } + + /** + * {@inheritDoc} + */ + @Override + public String getName() { + return name; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean authenticate(String user, char[] password) { + // Create the authentiction request: + TokensResource.Authenticate request = client.tokens().authenticate() + .withUsernamePassword(user, new String(password)) + .withTenantName(tenant); + + // Execute the request, if it succeeds without an exception then the user is correctly authenticaticated (note + // that we don't really need the returned token, just need to check if the request succeeds or not): + try { + request.execute(); + return true; + } + catch (OpenStackResponseException exception) { + // The 401 response code corresponds to authentication failure, whilest other codes may indicate + // configuration problems, so in those cases it is worth sending the complete stack trace to the log: + if (exception.getStatus() != 401) { + log.warn( + "Keystone authentication for user \"{}\" failed with error code \"{}\", this may indicate a " + + "configuration problem.", + user, + exception.getStatus(), + exception + ); + } + return false; + } + } +} diff --git a/backend/manager/modules/authentication/src/main/java/org/ovirt/engine/core/authentication/openstack/KeystoneAuthenticatorFactory.java b/backend/manager/modules/authentication/src/main/java/org/ovirt/engine/core/authentication/openstack/KeystoneAuthenticatorFactory.java new file mode 100644 index 0000000..57749ec --- /dev/null +++ b/backend/manager/modules/authentication/src/main/java/org/ovirt/engine/core/authentication/openstack/KeystoneAuthenticatorFactory.java @@ -0,0 +1,72 @@ +package org.ovirt.engine.core.authentication.openstack; + +import java.io.File; + +import org.ovirt.engine.core.authentication.Authenticator; +import org.ovirt.engine.core.authentication.AuthenticatorFactory; +import org.ovirt.engine.core.authentication.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class KeystoneAuthenticatorFactory implements AuthenticatorFactory { + // The log: + private static final Logger log = LoggerFactory.getLogger(KeystoneAuthenticatorFactory.class); + + // The type supported by this factory: + private static final String TYPE = "keystone"; + + // Names of configuration views: + private static final String KEYSTONE_VIEW = "keystone"; + + // Names of the configuration parameters: + private static final String NAME_PARAMETER = "name"; + private static final String URL_PARAMETER = "url"; + private static final String TENANT_PARAMETER = "tenant"; + + @Override + public String getType() { + return TYPE; + } + + @Override + public Authenticator create(File file, Configuration config) { + // Get the name of the authenticator: + String name = config.getInheritedString(NAME_PARAMETER); + if (name == null) { + log.error( + "The configuration file \"{}\" doesn't contain the name of the authenticator.", + file.getAbsolutePath() + ); + return null; + } + + // Get the Keystone vuew: + Configuration keystoneView = config.getInheritedView(KEYSTONE_VIEW); + + // Get the Keystone URL: + String url = keystoneView.getString(URL_PARAMETER); + if (url == null) { + log.error( + "The configuration file \"{}\" doesn't contain the parameter \"{}\", this is mandatory and should " + + "contain the URL of the Keystone service.", + file.getAbsolutePath(), + keystoneView.getAbsoluteKey(URL_PARAMETER) + ); + return null; + } + + // Get the name of the tenant: + String tenant = keystoneView.getString(TENANT_PARAMETER); + if (tenant == null) { + log.error( + "The configuration file \"{}\" doesn't contain the parameter \"{}\", this is mandatory and should " + + "contain the name of the OpenStack tenant.", + keystoneView.getAbsoluteKey(TENANT_PARAMETER) + ); + return null; + } + + // We are good, create the authenticator: + return new KeystoneAuthenticator(name, url, tenant); + } +} diff --git a/backend/manager/modules/authentication/src/main/resources/META-INF/services/org.ovirt.engine.core.authentication.AuthenticatorFactory b/backend/manager/modules/authentication/src/main/resources/META-INF/services/org.ovirt.engine.core.authentication.AuthenticatorFactory index 2bea66f..e5e211f 100644 --- a/backend/manager/modules/authentication/src/main/resources/META-INF/services/org.ovirt.engine.core.authentication.AuthenticatorFactory +++ b/backend/manager/modules/authentication/src/main/resources/META-INF/services/org.ovirt.engine.core.authentication.AuthenticatorFactory @@ -5,4 +5,5 @@ org.ovirt.engine.core.authentication.header.HeaderAuthenticatorFactory org.ovirt.engine.core.authentication.internal.InternalAuthenticatorFactory org.ovirt.engine.core.authentication.kerberos.KerberosPasswordAuthenticatorFactory +org.ovirt.engine.core.authentication.openstack.KeystoneAuthenticatorFactory org.ovirt.engine.core.authentication.nop.NopAuthenticatorFactory -- To view, visit http://gerrit.ovirt.org/21149 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I9588f015ac8766e38163665e4eec68b9d5638a6d Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Juan Hernandez <juan.hernan...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches