You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@eagle.apache.org by mw...@apache.org on 2016/10/14 04:13:51 UTC
incubator-eagle git commit: [EAGLE-582] add simple Basic Authentication registration to server appl…
Repository: incubator-eagle
Updated Branches:
refs/heads/master 7bd5d1d2a -> 649adb1ae
[EAGLE-582] add simple Basic Authentication registration to server appl\u2026
This is one of the sub-tasks of ticket EAGLE-433, to successfully register a simple Basic Authentication authenticator to the server application.
With this check-in, when the server is up, any access to rest api method that has a Auth annotation on it's User field will require correct credentials.
Author: anyway1021 <mw...@apache.org>
Closes #468 from anyway1021/EAGLE-582.
Project: http://git-wip-us.apache.org/repos/asf/incubator-eagle/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-eagle/commit/649adb1a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-eagle/tree/649adb1a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-eagle/diff/649adb1a
Branch: refs/heads/master
Commit: 649adb1ae400e026a8e932d53bd813f03fecb2d1
Parents: 7bd5d1d
Author: anyway1021 <mw...@apache.org>
Authored: Fri Oct 14 12:13:23 2016 +0800
Committer: anyway1021 <mw...@apache.org>
Committed: Fri Oct 14 12:13:23 2016 +0800
----------------------------------------------------------------------
.../eagle/common/authentication/User.java | 45 ++++++
eagle-server/pom.xml | 23 +++
.../apache/eagle/server/ServerApplication.java | 22 +--
.../org/apache/eagle/server/ServerConfig.java | 14 ++
.../authentication/AuthenticationMode.java | 51 +++++++
.../AuthenticationModeIdentifier.java | 105 ++++++++++++++
.../authentication/AuthenticationRegister.java | 41 ++++++
.../SwitchableBasicAuthProvider.java | 50 +++++++
.../AbstractSwitchableAuthenticator.java | 48 +++++++
.../authenticator/LdapBasicAuthenticator.java | 40 ++++++
.../authenticator/SimpleBasicAuthenticator.java | 43 ++++++
.../config/AuthenticationSettings.java | 119 ++++++++++++++++
.../authentication/config/LdapSettings.java | 142 +++++++++++++++++++
.../authentication/config/SimpleSettings.java | 46 ++++++
.../src/main/resources/application.conf | 2 +-
.../src/main/resources/configuration.yml | 48 ++++++-
.../TestBasicAuthenticationResource.java | 39 +++++
.../src/test/resources/configuration.yml | 45 ++++++
pom.xml | 13 +-
19 files changed, 924 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/authentication/User.java
----------------------------------------------------------------------
diff --git a/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/authentication/User.java b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/authentication/User.java
new file mode 100644
index 0000000..85388cd
--- /dev/null
+++ b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/authentication/User.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.common.authentication;
+
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.Set;
+
+public class User implements Principal, Serializable {
+ private String username = "Unauthenticated";
+ private Set<String> roles = null;
+
+ public User() {}
+
+ public User(String username) {
+ this.username = username;
+ }
+
+ public User(String username, Set<String> roles) {
+ this.username = username;
+ this.roles = roles;
+ }
+
+ public Set<String> getRoles() {
+ return roles;
+ }
+
+ public String getName() {
+ return username;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/pom.xml
----------------------------------------------------------------------
diff --git a/eagle-server/pom.xml b/eagle-server/pom.xml
index 21bda30..7fe4397 100644
--- a/eagle-server/pom.xml
+++ b/eagle-server/pom.xml
@@ -133,6 +133,14 @@
<groupId>org.wso2.orbit.com.lmax</groupId>
<artifactId>disruptor</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ </exclusion>
</exclusions>
</dependency>
<dependency>
@@ -144,6 +152,12 @@
<groupId>org.apache.eagle</groupId>
<artifactId>eagle-security-hbase-auditlog</artifactId>
<version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.apache.eagle</groupId>
@@ -157,6 +171,15 @@
<artifactId>eagle-alert-app</artifactId>
<version>${project.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>io.dropwizard</groupId>
+ <artifactId>dropwizard-auth</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ </dependency>
</dependencies>
<profiles>
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/ServerApplication.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/ServerApplication.java b/eagle-server/src/main/java/org/apache/eagle/server/ServerApplication.java
index 2dc39b1..2ae95a6 100644
--- a/eagle-server/src/main/java/org/apache/eagle/server/ServerApplication.java
+++ b/eagle-server/src/main/java/org/apache/eagle/server/ServerApplication.java
@@ -17,25 +17,26 @@
package org.apache.eagle.server;
import com.google.inject.Injector;
import com.hubspot.dropwizard.guice.GuiceBundle;
+import com.sun.jersey.api.core.PackagesResourceConfig;
+import io.dropwizard.Application;
+import io.dropwizard.assets.AssetsBundle;
import io.dropwizard.lifecycle.Managed;
+import io.dropwizard.setup.Bootstrap;
+import io.dropwizard.setup.Environment;
+import io.swagger.jaxrs.config.BeanConfig;
+import io.swagger.jaxrs.listing.ApiListingResource;
import org.apache.eagle.alert.coordinator.CoordinatorListener;
import org.apache.eagle.alert.resource.SimpleCORSFiler;
+import org.apache.eagle.common.authentication.User;
import org.apache.eagle.log.base.taggedlog.EntityJsonModule;
import org.apache.eagle.log.base.taggedlog.TaggedLogAPIEntity;
import org.apache.eagle.metadata.service.ApplicationStatusUpdateService;
+import org.apache.eagle.server.authentication.AuthenticationRegister;
import org.apache.eagle.server.managedtask.ApplicationTask;
import org.apache.eagle.server.module.GuiceBundleLoader;
-import com.sun.jersey.api.core.PackagesResourceConfig;
-import io.dropwizard.Application;
-import io.dropwizard.assets.AssetsBundle;
-import io.dropwizard.setup.Bootstrap;
-import io.dropwizard.setup.Environment;
-import io.swagger.jaxrs.config.BeanConfig;
-import io.swagger.jaxrs.listing.ApiListingResource;
-
-import java.util.EnumSet;
import javax.servlet.DispatcherType;
+import java.util.EnumSet;
class ServerApplication extends Application<ServerConfig> {
private GuiceBundle guiceBundle;
@@ -79,6 +80,9 @@ class ServerApplication extends Application<ServerConfig> {
environment.servlets().addFilter(SimpleCORSFiler.class.getName(), new SimpleCORSFiler())
.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
+ // add authentication filters
+ new AuthenticationRegister<>(configuration, environment, User.class).register();
+
// context listener
environment.servlets().addServletListeners(new CoordinatorListener());
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/ServerConfig.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/ServerConfig.java b/eagle-server/src/main/java/org/apache/eagle/server/ServerConfig.java
index 58442d9..0afe63b 100644
--- a/eagle-server/src/main/java/org/apache/eagle/server/ServerConfig.java
+++ b/eagle-server/src/main/java/org/apache/eagle/server/ServerConfig.java
@@ -19,6 +19,8 @@ package org.apache.eagle.server;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import io.dropwizard.Configuration;
+import org.apache.eagle.server.authentication.config.AuthenticationSettings;
+import org.codehaus.jackson.annotate.JsonProperty;
public class ServerConfig extends Configuration {
private static final String SERVER_NAME = "Apache Eagle";
@@ -29,10 +31,22 @@ public class ServerConfig extends Configuration {
private static final String LICENSE = "Apache License (Version 2.0)";
private static final String LICENSE_URL = "http://www.apache.org/licenses/LICENSE-2.0";
+ private AuthenticationSettings auth = new AuthenticationSettings();
+
public Config getConfig() {
return ConfigFactory.load();
}
+ @JsonProperty("auth")
+ public AuthenticationSettings getAuth() {
+ return auth;
+ }
+
+ @JsonProperty("auth")
+ public void setAuth(AuthenticationSettings auth) {
+ this.auth = auth;
+ }
+
static String getServerName() {
return SERVER_NAME;
}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationMode.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationMode.java b/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationMode.java
new file mode 100644
index 0000000..8a7208f
--- /dev/null
+++ b/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationMode.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication;
+
+import io.dropwizard.auth.Authenticator;
+import io.dropwizard.auth.CachingAuthenticator;
+import io.dropwizard.auth.basic.BasicCredentials;
+
+public abstract class AuthenticationMode<P> {
+ private static final String PREFIX_VALUE = "Basic";
+
+ protected AuthenticationModeIdentifier identifier = null;
+
+ private Authenticator<BasicCredentials, P> authenticator = null;
+
+ public AuthenticationMode(AuthenticationModeIdentifier identifier) {
+ this.identifier = identifier;
+ this.authenticator = createAuthenticator();
+ }
+
+ abstract Authenticator<BasicCredentials, P> createAuthenticator();
+
+ abstract String getRealm();
+
+ Authenticator<BasicCredentials, P> getAuthenticator() {
+ return identifier.cacheRequired() ? cache(authenticator) : authenticator;
+ }
+
+ private Authenticator<BasicCredentials, P> cache(Authenticator<BasicCredentials, P> authenticator) {
+ return new CachingAuthenticator<BasicCredentials, P>(identifier.getMetricRegistry(), authenticator, identifier.getCacheBuilderSpec());
+ }
+
+ AuthenticationModeIdentifier getIdentifier() {
+ return identifier;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationModeIdentifier.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationModeIdentifier.java b/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationModeIdentifier.java
new file mode 100644
index 0000000..979bcbf
--- /dev/null
+++ b/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationModeIdentifier.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication;
+
+import com.codahale.metrics.MetricRegistry;
+import com.google.common.cache.CacheBuilderSpec;
+import io.dropwizard.auth.Authenticator;
+import io.dropwizard.auth.basic.BasicCredentials;
+import io.dropwizard.setup.Environment;
+import org.apache.eagle.common.authentication.User;
+import org.apache.eagle.server.authentication.authenticator.LdapBasicAuthenticator;
+import org.apache.eagle.server.authentication.authenticator.SimpleBasicAuthenticator;
+import org.apache.eagle.server.authentication.config.AuthenticationSettings;
+
+public class AuthenticationModeIdentifier {
+ private static final String SIMPLE_MODE_KEYWORD = "simple";
+ private static final String SIMPLE_MODE_REALM = "SIMPLE_AUTHENTICATION";
+ private static final String LDAP_MODE_KEYWORD = "ldap";
+ private static final String LDAP_MODE_REALM = "LDAP_AUTHENTICATION";
+
+ private AuthenticationSettings settings = null;
+ private Environment environment = null;
+
+ private AuthenticationModeIdentifier(AuthenticationSettings settings, Environment environment) {
+ this.settings = settings;
+ this.environment = environment;
+ }
+
+ static AuthenticationModeIdentifier initiate(AuthenticationSettings config, Environment environment) {
+ return new AuthenticationModeIdentifier(config, environment);
+ }
+
+ AuthenticationMode<User> identify() {
+ String modeKeyword = getModeKeyword();
+ if (SIMPLE_MODE_KEYWORD.equalsIgnoreCase(modeKeyword)) {
+ return new AuthenticationMode<User>(this) {
+ public Authenticator<BasicCredentials, User> createAuthenticator() {
+ return new SimpleBasicAuthenticator(getIdentifier().getSettings());
+ }
+
+ public String getRealm() {
+ return AuthenticationModeIdentifier.SIMPLE_MODE_REALM;
+ }
+ };
+ }
+ if (LDAP_MODE_KEYWORD.equalsIgnoreCase(modeKeyword)) {
+ return new AuthenticationMode<User>(this) {
+ public Authenticator<BasicCredentials, User> createAuthenticator() {
+ return new LdapBasicAuthenticator(getIdentifier().getSettings());
+ }
+
+ public String getRealm() {
+ return AuthenticationModeIdentifier.LDAP_MODE_REALM;
+ }
+ };
+ }
+ throw new RuntimeException(String.format("No matching mode can be found: %s", modeKeyword));
+ }
+
+ MetricRegistry getMetricRegistry() {
+ return environment.metrics();
+ }
+
+ boolean cacheRequired() {
+ return settings.needsCaching();
+ }
+
+ boolean authorizationRequired() {
+ return settings.needsAuthorization();
+ }
+
+ boolean parameterAnnotationEnabled() {
+ return settings.byAnnotated();
+ }
+
+ CacheBuilderSpec getCacheBuilderSpec() {
+ return CacheBuilderSpec.parse(settings.getCachePolicy());
+ }
+
+ AuthenticationSettings getSettings() {
+ return settings;
+ }
+
+ private Environment getEnvironment() {
+ return environment;
+ }
+
+ private String getModeKeyword() {
+ return settings.getMode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationRegister.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationRegister.java b/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationRegister.java
new file mode 100644
index 0000000..65d2171
--- /dev/null
+++ b/eagle-server/src/main/java/org/apache/eagle/server/authentication/AuthenticationRegister.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication;
+
+import io.dropwizard.setup.Environment;
+import org.apache.eagle.common.authentication.User;
+import org.apache.eagle.server.ServerConfig;
+
+import java.security.Principal;
+
+public class AuthenticationRegister<P extends Principal> {
+ private ServerConfig serverConfig = null;
+ private Environment environment = null;
+ private Class<P> principalClass = null;
+
+ public AuthenticationRegister(ServerConfig serverConfig, Environment environment, Class<P> principalClass) {
+ this.serverConfig = serverConfig;
+ this.environment = environment;
+ this.principalClass = principalClass;
+ }
+
+ public void register() {
+ AuthenticationMode<User> mode = AuthenticationModeIdentifier.initiate(serverConfig.getAuth(), environment).identify();
+
+ environment.jersey().register(new SwitchableBasicAuthProvider(mode.getAuthenticator(), mode.getRealm()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/authentication/SwitchableBasicAuthProvider.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/authentication/SwitchableBasicAuthProvider.java b/eagle-server/src/main/java/org/apache/eagle/server/authentication/SwitchableBasicAuthProvider.java
new file mode 100644
index 0000000..74f286d
--- /dev/null
+++ b/eagle-server/src/main/java/org/apache/eagle/server/authentication/SwitchableBasicAuthProvider.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication;
+
+import com.sun.jersey.api.core.HttpContext;
+import com.sun.jersey.api.model.Parameter;
+import com.sun.jersey.core.spi.component.ComponentContext;
+import com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable;
+import com.sun.jersey.spi.inject.Injectable;
+import io.dropwizard.auth.Auth;
+import io.dropwizard.auth.Authenticator;
+import io.dropwizard.auth.basic.BasicAuthProvider;
+import io.dropwizard.auth.basic.BasicCredentials;
+import org.apache.eagle.server.authentication.authenticator.AbstractSwitchableAuthenticator;
+
+public class SwitchableBasicAuthProvider<P> extends BasicAuthProvider<P> {
+ private AbstractSwitchableAuthenticator<BasicCredentials, P> switchableAuthenticator = null;
+
+ public SwitchableBasicAuthProvider(Authenticator<BasicCredentials, P> authenticator, String realm) {
+ super(authenticator, realm);
+ if (authenticator instanceof AbstractSwitchableAuthenticator) {
+ switchableAuthenticator = (AbstractSwitchableAuthenticator<BasicCredentials, P>) authenticator;
+ }
+ }
+
+ public Injectable<?> getInjectable(ComponentContext ic, Auth a, Parameter c) {
+ if (switchableAuthenticator != null && !switchableAuthenticator.getSettings().isEnabled()) {
+ return new AbstractHttpContextInjectable<P>() {
+ public P getValue(HttpContext c) {
+ return switchableAuthenticator.getUnauthenticatedPrincipal();
+ }
+ };
+ }
+ return super.getInjectable(ic, a, c);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/AbstractSwitchableAuthenticator.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/AbstractSwitchableAuthenticator.java b/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/AbstractSwitchableAuthenticator.java
new file mode 100644
index 0000000..5ca12fb
--- /dev/null
+++ b/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/AbstractSwitchableAuthenticator.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication.authenticator;
+
+import io.dropwizard.auth.Authenticator;
+import org.apache.eagle.server.authentication.config.AuthenticationSettings;
+
+public abstract class AbstractSwitchableAuthenticator<C, P> implements Authenticator<C, P> {
+ private AuthenticationSettings settings;
+ private Class<P> principalClass;
+ private P unauthenticatedPrincipal;
+
+ public AbstractSwitchableAuthenticator(AuthenticationSettings settings, Class<P> principalClass) {
+ this.settings = settings;
+ this.principalClass = principalClass;
+ }
+
+ public AuthenticationSettings getSettings() {
+ return settings;
+ }
+
+ public P getUnauthenticatedPrincipal() {
+ try {
+ if (unauthenticatedPrincipal == null) {
+ unauthenticatedPrincipal = principalClass.newInstance();
+ }
+ return unauthenticatedPrincipal;
+ } catch (InstantiationException e) {
+ throw new RuntimeException(String.format("Filed to instantiate %s", principalClass.getName()), e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(String.format("Illegal access to %s", principalClass.getName()), e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticator.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticator.java b/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticator.java
new file mode 100644
index 0000000..59abc52
--- /dev/null
+++ b/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticator.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication.authenticator;
+
+import com.google.common.base.Optional;
+import io.dropwizard.auth.AuthenticationException;
+import io.dropwizard.auth.basic.BasicCredentials;
+import org.apache.eagle.common.authentication.User;
+import org.apache.eagle.server.authentication.config.AuthenticationSettings;
+
+public class LdapBasicAuthenticator extends AbstractSwitchableAuthenticator<BasicCredentials, User> {
+ private AuthenticationSettings config = null;
+
+ public LdapBasicAuthenticator(AuthenticationSettings settings) {
+ super(settings, User.class);
+ }
+
+ public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException {
+ // TODO need to implement ldap authentication logic
+ boolean pass = true;
+ if (pass) {
+ return Optional.of(new User("ldap.username"));
+ }
+ return Optional.absent();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticator.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticator.java b/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticator.java
new file mode 100644
index 0000000..910bc92
--- /dev/null
+++ b/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticator.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication.authenticator;
+
+import com.google.common.base.Optional;
+import io.dropwizard.auth.AuthenticationException;
+import io.dropwizard.auth.basic.BasicCredentials;
+import org.apache.eagle.common.authentication.User;
+import org.apache.eagle.server.authentication.config.AuthenticationSettings;
+
+public class SimpleBasicAuthenticator extends AbstractSwitchableAuthenticator<BasicCredentials, User> {
+ private String acceptedUsername = null;
+ private String acceptedPassword = null;
+
+ public SimpleBasicAuthenticator(AuthenticationSettings settings) {
+ super(settings, User.class);
+ acceptedUsername = settings.getSimple().getUsername();
+ acceptedPassword = settings.getSimple().getPassword();
+ }
+
+ public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException {
+ String username = credentials.getUsername();
+ if (acceptedUsername.equals(username) && acceptedPassword.equals(credentials.getPassword())) {
+ return Optional.of(new User(username));
+ }
+ return Optional.absent();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/AuthenticationSettings.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/AuthenticationSettings.java b/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/AuthenticationSettings.java
new file mode 100644
index 0000000..642a9c2
--- /dev/null
+++ b/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/AuthenticationSettings.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication.config;
+
+import io.dropwizard.Configuration;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+public class AuthenticationSettings extends Configuration {
+ private boolean enabled = false;
+ private String mode = null;
+ private boolean caching = false;
+ private String cachePolicy = null;
+ private boolean authorization = false;
+ private boolean annotated = true;
+ private SimpleSettings simple = new SimpleSettings();
+ private LdapSettings ldap = new LdapSettings();
+
+ @JsonProperty
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ @JsonProperty
+ public AuthenticationSettings setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ return this;
+ }
+
+ @JsonProperty
+ public String getMode() {
+ return mode;
+ }
+
+ @JsonProperty
+ public AuthenticationSettings setMode(String mode) {
+ this.mode = mode;
+ return this;
+ }
+
+ @JsonProperty
+ public boolean needsCaching() {
+ return caching;
+ }
+
+ @JsonProperty
+ public AuthenticationSettings setCaching(boolean caching) {
+ this.caching = caching;
+ return this;
+ }
+
+ @JsonProperty
+ public String getCachePolicy() {
+ return cachePolicy;
+ }
+
+ @JsonProperty
+ public AuthenticationSettings setCachePolicy(String cachePolicy) {
+ this.cachePolicy = cachePolicy;
+ return this;
+ }
+
+ @JsonProperty
+ public boolean needsAuthorization() {
+ return authorization;
+ }
+
+ @JsonProperty
+ public AuthenticationSettings setAuthorization(boolean authorization) {
+ this.authorization = authorization;
+ return this;
+ }
+
+ @JsonProperty
+ public boolean byAnnotated() {
+ return annotated;
+ }
+
+ @JsonProperty
+ public AuthenticationSettings setAnnotated(boolean annotated) {
+ this.annotated = annotated;
+ return this;
+ }
+
+ @JsonProperty("ldap")
+ public LdapSettings getLdap() {
+ return ldap;
+ }
+
+ @JsonProperty("ldap")
+ public AuthenticationSettings setLdap(LdapSettings ldap) {
+ this.ldap = ldap;
+ return this;
+ }
+
+ @JsonProperty("simple")
+ public SimpleSettings getSimple() {
+ return simple;
+ }
+
+ @JsonProperty("simple")
+ public AuthenticationSettings setSimple(SimpleSettings simple) {
+ this.simple = simple;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/LdapSettings.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/LdapSettings.java b/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/LdapSettings.java
new file mode 100644
index 0000000..0d04645
--- /dev/null
+++ b/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/LdapSettings.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication.config;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+public class LdapSettings {
+ private String uri = null;
+ private String userFilter = null;
+ private String groupFilter = null;
+ private String userNameAttribute = null;
+ private String groupNameAttribute = null;
+ private String groupMembershipAttribute = null;
+ private String groupClassName = null;
+ private String[] restrictToGroups = null;
+ private String connectTimeout = null;
+ private String readTimeout = null;
+
+ @JsonProperty
+ public String getUri() {
+ return uri;
+ }
+
+ @JsonProperty
+ public LdapSettings setUri(String uri) {
+ this.uri = uri;
+ return this;
+ }
+
+ @JsonProperty
+ public String getUserFilter() {
+ return userFilter;
+ }
+
+ @JsonProperty
+ public LdapSettings setUserFilter(String userFilter) {
+ this.userFilter = userFilter;
+ return this;
+ }
+
+ @JsonProperty
+ public String getGroupFilter() {
+ return groupFilter;
+ }
+
+ @JsonProperty
+ public LdapSettings setGroupFilter(String groupFilter) {
+ this.groupFilter = groupFilter;
+ return this;
+ }
+
+ @JsonProperty
+ public String getUserNameAttribute() {
+ return userNameAttribute;
+ }
+
+ @JsonProperty
+ public LdapSettings setUserNameAttribute(String userNameAttribute) {
+ this.userNameAttribute = userNameAttribute;
+ return this;
+ }
+
+ @JsonProperty
+ public String getGroupNameAttribute() {
+ return groupNameAttribute;
+ }
+
+ @JsonProperty
+ public LdapSettings setGroupNameAttribute(String groupNameAttribute) {
+ this.groupNameAttribute = groupNameAttribute;
+ return this;
+ }
+
+ @JsonProperty
+ public String getGroupMembershipAttribute() {
+ return groupMembershipAttribute;
+ }
+
+ @JsonProperty
+ public LdapSettings setGroupMembershipAttribute(String groupMembershipAttribute) {
+ this.groupMembershipAttribute = groupMembershipAttribute;
+ return this;
+ }
+
+ @JsonProperty
+ public String getGroupClassName() {
+ return groupClassName;
+ }
+
+ @JsonProperty
+ public LdapSettings setGroupClassName(String groupClassName) {
+ this.groupClassName = groupClassName;
+ return this;
+ }
+
+ @JsonProperty
+ public String[] getRestrictToGroups() {
+ return restrictToGroups;
+ }
+
+ @JsonProperty
+ public LdapSettings setRestrictToGroups(String[] restrictToGroups) {
+ this.restrictToGroups = restrictToGroups;
+ return this;
+ }
+
+ @JsonProperty
+ public String getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ @JsonProperty
+ public LdapSettings setConnectTimeout(String connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ return this;
+ }
+
+ @JsonProperty
+ public String getReadTimeout() {
+ return readTimeout;
+ }
+
+ @JsonProperty
+ public LdapSettings setReadTimeout(String readTimeout) {
+ this.readTimeout = readTimeout;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/SimpleSettings.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/SimpleSettings.java b/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/SimpleSettings.java
new file mode 100644
index 0000000..ecdb094
--- /dev/null
+++ b/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/SimpleSettings.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication.config;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+public class SimpleSettings {
+ private String username = null;
+ private String password = null;
+
+ @JsonProperty
+ public String getUsername() {
+ return username;
+ }
+
+ @JsonProperty
+ public SimpleSettings setUsername(String username) {
+ this.username = username;
+ return this;
+ }
+
+ @JsonProperty
+ public String getPassword() {
+ return password;
+ }
+
+ @JsonProperty
+ public SimpleSettings setPassword(String password) {
+ this.password = password;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/resources/application.conf
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/resources/application.conf b/eagle-server/src/main/resources/application.conf
index f23f9f1..f2ec772 100644
--- a/eagle-server/src/main/resources/application.conf
+++ b/eagle-server/src/main/resources/application.conf
@@ -115,4 +115,4 @@ coordinator {
initDelayMillis = 1000
delayMillis = 30000
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/main/resources/configuration.yml
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/resources/configuration.yml b/eagle-server/src/main/resources/configuration.yml
index 6dc864d..6090c4f 100644
--- a/eagle-server/src/main/resources/configuration.yml
+++ b/eagle-server/src/main/resources/configuration.yml
@@ -19,4 +19,50 @@ server:
port: 9090
adminConnectors:
- type: http
- port: 9091
\ No newline at end of file
+ port: 9091
+
+
+# ---------------------------------------------
+# Eagle Authentication Configuration
+# ---------------------------------------------
+auth:
+ # indicating if authentication is enabled, true for enabled, false for disabled
+ enabled: false
+
+ # indicating authentication mode, "simple" or "ldap"
+ mode: simple
+
+ # indicating whether to use cache: cache is usually used for authentications that may
+ # not handle high throughput (an RDBMS or LDAP server, for example)
+ caching: false
+
+ # indicating the cache policy, containing maximumSize and expireAfterWrite, e.g. maximumSize=10000, expireAfterWrite=10m
+ cachePolicy: maximumSize=10000, expireAfterWrite=1m
+
+ # indicating whether authorization is needed
+ authorization: false
+
+ # indicating whether @Auth annotation on parameters is needed
+ annotated: true
+
+ # for basic authentication, effective only when auth.mode=simple
+ simple:
+ # username for basic authentication, effective only when auth.mode=simple
+ username: admin
+ # password for basic authentication, effective only when auth.mode=simple
+ password: secret
+
+ # for ldap authentication, effective only when auth.mode=ldap
+ ldap:
+ uri: ldaps://ldap.server.address:636
+ userFilter: ou=x,dc=y,dc=z
+ groupFilter: ou=x,dc=y,dc=z
+ userNameAttribute: cn
+ groupNameAttribute: cn
+ groupMembershipAttribute: memberUid
+ groupClassName: posixGroup
+ restrictToGroups:
+ - user
+ - admin
+ connectTimeout: 500ms
+ readTimeout: 500ms
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/test/java/org/apache/eagle/server/authentication/resource/TestBasicAuthenticationResource.java
----------------------------------------------------------------------
diff --git a/eagle-server/src/test/java/org/apache/eagle/server/authentication/resource/TestBasicAuthenticationResource.java b/eagle-server/src/test/java/org/apache/eagle/server/authentication/resource/TestBasicAuthenticationResource.java
new file mode 100644
index 0000000..0ea6666
--- /dev/null
+++ b/eagle-server/src/test/java/org/apache/eagle/server/authentication/resource/TestBasicAuthenticationResource.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.eagle.server.authentication.resource;
+
+import io.dropwizard.auth.Auth;
+import org.apache.eagle.common.authentication.User;
+import org.apache.eagle.metadata.resource.RESTResponse;
+import org.junit.Ignore;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Ignore
+@Path("/test")
+public class TestBasicAuthenticationResource {
+ @GET
+ @Path("/ba/simple")
+ @Produces(MediaType.APPLICATION_JSON)
+ public RESTResponse<User> getIt(@Auth User user) {
+ return RESTResponse.<User>builder().data(user).success(true).status(Response.Status.OK).get();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/eagle-server/src/test/resources/configuration.yml
----------------------------------------------------------------------
diff --git a/eagle-server/src/test/resources/configuration.yml b/eagle-server/src/test/resources/configuration.yml
index c671ade..6795aac 100644
--- a/eagle-server/src/test/resources/configuration.yml
+++ b/eagle-server/src/test/resources/configuration.yml
@@ -19,3 +19,48 @@ server:
adminConnectors:
- type: http
port: 9091
+
+# ---------------------------------------------
+# Eagle Authentication Configuration
+# ---------------------------------------------
+auth:
+ # indicating if authentication is enabled, true for enabled, false for disabled
+ enabled: false
+
+ # indicating authentication mode, "simple" or "ldap"
+ mode: simple
+
+ # indicating whether to use cache: cache is usually used for authentications that may
+ # not handle high throughput (an RDBMS or LDAP server, for example)
+ caching: false
+
+ # indicating the cache policy, containing maximumSize and expireAfterWrite, e.g. maximumSize=10000, expireAfterWrite=10m
+ cachePolicy: maximumSize=10000, expireAfterWrite=1m
+
+ # indicating whether authorization is needed
+ authorization: false
+
+ # indicating whether @Auth annotation on parameters is needed
+ annotated: true
+
+ # for basic authentication, effective only when auth.mode=simple
+ simple:
+ # username for basic authentication, effective only when auth.mode=simple
+ username: admin
+ # password for basic authentication, effective only when auth.mode=simple
+ password: secret
+
+ # for ldap authentication, effective only when auth.mode=ldap
+ ldap:
+ uri: ldaps://ldap.server.address:636
+ userFilter: ou=x,dc=y,dc=z
+ groupFilter: ou=x,dc=y,dc=z
+ userNameAttribute: cn
+ groupNameAttribute: cn
+ groupMembershipAttribute: memberUid
+ groupClassName: posixGroup
+ restrictToGroups:
+ - user
+ - admin
+ connectTimeout: 500ms
+ readTimeout: 500ms
http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/649adb1a/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 7b61650..6dc1d6c 100755
--- a/pom.xml
+++ b/pom.xml
@@ -307,7 +307,8 @@
<metrics-elasticsearch-reporter.version>2.2.0</metrics-elasticsearch-reporter.version>
<common.cli.version>1.3.1</common.cli.version>
- <ullink.slack.version>0.6.0</ullink.slack.version>
+ <ullink.slack.version>0.6.0</ullink.slack.version>
+ <javax-ws-rs.rs-api.version>2.0.1</javax-ws-rs.rs-api.version>
<!-- dropwizard -->
<dropwizard.version>0.7.1</dropwizard.version>
@@ -861,6 +862,16 @@
</exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>io.dropwizard</groupId>
+ <artifactId>dropwizard-auth</artifactId>
+ <version>${dropwizard.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <version>${javax-ws-rs.rs-api.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
<profiles>