Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 30841200C23 for ; Wed, 22 Feb 2017 09:12:40 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 2F11C160B75; Wed, 22 Feb 2017 08:12:40 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 362CA160B72 for ; Wed, 22 Feb 2017 09:12:38 +0100 (CET) Received: (qmail 20517 invoked by uid 500); 22 Feb 2017 08:12:37 -0000 Mailing-List: contact commits-help@eagle.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@eagle.apache.org Delivered-To: mailing list commits@eagle.apache.org Received: (qmail 20501 invoked by uid 99); 22 Feb 2017 08:12:37 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 22 Feb 2017 08:12:37 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 36981DFF13; Wed, 22 Feb 2017 08:12:37 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: hao@apache.org To: commits@eagle.apache.org Date: Wed, 22 Feb 2017 08:12:39 -0000 Message-Id: In-Reply-To: <82cba4fae38c473cabf5db20ac62b323@git.apache.org> References: <82cba4fae38c473cabf5db20ac62b323@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [3/3] eagle git commit: [EAGLE-918] Support auth annotations PermitAll/DenyAll/RolesAllowed and API archived-at: Wed, 22 Feb 2017 08:12:40 -0000 [EAGLE-918] Support auth annotations PermitAll/DenyAll/RolesAllowed and API * Improve eagle auth framework to support annotations under Jersey 1.9 and Dropwizard 0.7.1 PermitAll DenyAll RolesAllowed Auth * Add Authentication API GET /auth/principal GET /auth/validate GET /auth/login * Add password encryption and EncrytTool java ServerMain encrypt [text to encrypt] Author: Hao Chen Closes #831 from haoch/EnableAuthAPI. Project: http://git-wip-us.apache.org/repos/asf/eagle/repo Commit: http://git-wip-us.apache.org/repos/asf/eagle/commit/94b597b7 Tree: http://git-wip-us.apache.org/repos/asf/eagle/tree/94b597b7 Diff: http://git-wip-us.apache.org/repos/asf/eagle/diff/94b597b7 Branch: refs/heads/master Commit: 94b597b774464d33c30b290538a4231075a363e1 Parents: a7df69e Author: Hao Chen Authored: Wed Feb 22 16:12:10 2017 +0800 Committer: Hao Chen Committed: Wed Feb 22 16:12:10 2017 +0800 ---------------------------------------------------------------------- .../eagle/app/resource/ApplicationResource.java | 2 +- .../eagle/common/authentication/User.java | 46 ---- .../apache/eagle/common/rest/RESTResponse.java | 255 +++++++++++++++++++ .../apache/eagle/common/security/DenyAll.java | 27 ++ .../apache/eagle/common/security/PermitAll.java | 29 +++ .../eagle/common/security/RolesAllowed.java | 26 ++ .../org/apache/eagle/common/security/User.java | 176 +++++++++++++ .../apache/eagle/common/service/HadoopUser.java | 2 +- .../eagle-metadata/eagle-metadata-base/pom.xml | 4 + .../eagle/metadata/resource/RESTResponse.java | 246 ------------------ .../eagle/metadata/resource/SiteResource.java | 1 + .../entity/meta/EntityDefinitionManager.java | 2 +- .../storage/hbase/TestWithHBaseCoprocessor.java | 24 +- .../jpm/analyzer/resource/AnalyzerResource.java | 2 +- .../apache/eagle/jpm/analyzer/util/Utils.java | 2 +- .../history/crawl/JHFSparkEventReader.java | 2 +- .../app/apps/jpm/partials/queue/overview.html | 2 +- .../entity/HdfsUserCommandPatternEntity.java | 2 +- .../eagle/security/hive/ql/TestParser.java | 2 +- eagle-server/pom.xml | 9 + .../eagle/server/RESTExceptionMapper.java | 2 +- .../apache/eagle/server/ServerApplication.java | 29 ++- .../org/apache/eagle/server/ServerConfig.java | 8 +- .../org/apache/eagle/server/ServerMain.java | 46 +++- .../BasicAuthProviderBuilder.java | 82 ------ .../authenticator/LdapBasicAuthenticator.java | 106 -------- .../authenticator/SimpleBasicAuthenticator.java | 43 ---- .../config/AuthenticationSettings.java | 119 --------- .../authentication/config/LdapSettings.java | 96 ------- .../authentication/config/SimpleSettings.java | 46 ---- .../server/resource/AuthenticationResource.java | 65 +++++ .../eagle/server/security/BasicAuthBuilder.java | 99 +++++++ .../server/security/BasicAuthRequestFilter.java | 161 ++++++++++++ .../BasicAuthResourceFilterFactory.java | 53 ++++ .../authenticator/LdapBasicAuthenticator.java | 106 ++++++++ .../authenticator/SimpleBasicAuthenticator.java | 59 +++++ .../security/config/AuthenticationConfig.java | 95 +++++++ .../server/security/config/LdapConfig.java | 96 +++++++ .../server/security/config/SimpleConfig.java | 34 +++ .../server/security/config/UserAccount.java | 55 ++++ .../security/encrypt/EncryptorFactory.java | 23 ++ .../security/encrypt/PasswordEncryptor.java | 23 ++ .../security/encrypt/PasswordEncryptorImpl.java | 37 +++ .../apache/eagle/server/tool/EncryptTool.java | 42 +++ .../java/org/apache/eagle/server/tool/Tool.java | 21 ++ .../src/main/resources/configuration.yml | 151 ++++++----- .../eagle/server/ServerApplicationTest.java | 26 -- .../org/apache/eagle/server/ServerDebug.java | 2 + .../LdapBasicAuthenticatorTest.java | 168 ------------ .../SimpleBasicAuthenticatorTest.java | 71 ------ .../TestBasicAuthenticationResource.java | 39 --- .../LdapBasicAuthenticatorTest.java | 168 ++++++++++++ .../SimpleBasicAuthenticatorTest.java | 81 ++++++ .../resource/BasicAuthenticationTestCase.java | 164 ++++++++++++ .../TestBasicAuthenticationResource.java | 107 ++++++++ .../src/test/resources/configuration.yml | 34 ++- pom.xml | 11 + 57 files changed, 2215 insertions(+), 1214 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/resource/ApplicationResource.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/resource/ApplicationResource.java b/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/resource/ApplicationResource.java index f304768..3c62367 100644 --- a/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/resource/ApplicationResource.java +++ b/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/resource/ApplicationResource.java @@ -19,9 +19,9 @@ package org.apache.eagle.app.resource; import org.apache.eagle.app.service.ApplicationManagementService; import org.apache.eagle.app.service.ApplicationOperations; import org.apache.eagle.app.service.ApplicationProviderService; +import org.apache.eagle.common.rest.RESTResponse; import org.apache.eagle.metadata.model.ApplicationDesc; import org.apache.eagle.metadata.model.ApplicationEntity; -import org.apache.eagle.metadata.resource.RESTResponse; import org.apache.eagle.metadata.service.ApplicationEntityService; import com.google.inject.Inject; http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/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 deleted file mode 100644 index e967624..0000000 --- a/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/authentication/User.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 roles = null; - - public User() { - } - - public User(String username) { - this.username = username; - } - - public User(String username, Set roles) { - this.username = username; - this.roles = roles; - } - - public Set getRoles() { - return roles; - } - - public String getName() { - return username; - } -} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/rest/RESTResponse.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/rest/RESTResponse.java b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/rest/RESTResponse.java new file mode 100644 index 0000000..7aaade3 --- /dev/null +++ b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/rest/RESTResponse.java @@ -0,0 +1,255 @@ +/** + * 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.rest; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.eagle.common.function.ThrowableConsumer; +import org.apache.eagle.common.function.ThrowableSupplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; +import java.util.function.Supplier; + +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +public class RESTResponse { + private static final Logger LOGGER = LoggerFactory.getLogger(RESTResponse.class); + + @JsonProperty + private boolean success = false; + @JsonProperty + private String message; + @JsonProperty + private String exception; + @JsonProperty + private T data; + + public RESTResponse() { + } + + public RESTResponse(Throwable throwable) { + if (throwable.getMessage() == null || throwable.getMessage().isEmpty()) { + this.setMessage(throwable.getMessage()); + } else { + this.setMessage(ExceptionUtils.getMessage(throwable)); + } + this.setException(ExceptionUtils.getStackTrace(throwable)); + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static RestResponseBuilder builder() { + return new RestResponseBuilder<>(); + } + + public static RestResponseBuilder of(E data) { + return RESTResponse.builder().data(data); + } + + public static RestResponseBuilder of(Consumer> func) { + return RESTResponse.builder().of(func); + } + + public static RestResponseBuilder of(Supplier func) { + return RESTResponse.builder().of(func); + } + + public static RestResponseBuilder async(ThrowableSupplier func) { + return RESTResponse.builder().async(func); + } + + public static RestResponseBuilder async(ThrowableConsumer, Exception> func) { + return RESTResponse.builder().async(func); + } + + public String getException() { + return exception; + } + + public void setThrowable(Throwable exception) { + this.setException(ExceptionUtils.getStackTrace(exception)); + } + + public void setException(String exception) { + this.exception = exception; + } + + public static class RestResponseBuilder { + private RESTResponse current = new RESTResponse(); + private Response.Status status = Response.Status.OK; + private CompletableFuture future = null; + + public RestResponseBuilder success(boolean success) { + this.current.setSuccess(success); + return this; + } + + public RestResponseBuilder status(Response.Status status) { + this.status = status; + return this; + } + + public RestResponseBuilder status(boolean success, Response.Status status) { + this.success(success); + this.status(status); + return this; + } + + public RestResponseBuilder message(String message) { + this.current.setMessage(message); + return this; + } + + public RestResponseBuilder data(E data) { + this.current.setData(data); + return this; + } + + public RestResponseBuilder exception(Throwable exception) { + this.current.setThrowable(exception); + if (this.current.getMessage() == null) { + if (exception.getMessage() == null || exception.getMessage().isEmpty()) { + this.current.setMessage(ExceptionUtils.getMessage(exception)); + } else { + this.current.setMessage(exception.getMessage()); + } + } + return this; + } + + public RestResponseBuilder of(Consumer> func) { + try { + this.success(true).status(Response.Status.OK); + func.accept(this); + } catch (Exception ex) { + LOGGER.error("Exception: " + ex.getMessage(), ex); + this.success(false).data(null).status(Response.Status.BAD_REQUEST).exception(ex); + raiseWebAppException(ex); + } + return this; + } + + public RestResponseBuilder of(Supplier func) { + try { + this.success(true).status(Response.Status.OK).data(func.get()); + } catch (Throwable ex) { + LOGGER.error("Exception: " + ex.getMessage(), ex); + this.success(false).status(Response.Status.BAD_REQUEST).exception(ex); + raiseWebAppException(ex); + } + return this; + } + + public RestResponseBuilder async(ThrowableSupplier func) { + CompletableFuture future = CompletableFuture.runAsync(() -> { + try { + this.status(Response.Status.OK).success(true).data(func.get()); + } catch (Throwable e) { + LOGGER.error("Exception: " + e.getMessage(), e); + this.success(false).status(Response.Status.BAD_REQUEST).exception(e); + raiseWebAppException(e); + } + }); + runAsync(future); + return this; + } + + public RestResponseBuilder async(ThrowableConsumer, Exception> func) { + CompletableFuture future = CompletableFuture.runAsync(() -> { + try { + func.accept(this); + this.success(true); + } catch (Throwable ex) { + LOGGER.error("Exception: " + ex.getMessage(), ex); + this.success(false).status(Response.Status.BAD_REQUEST).exception(ex); + raiseWebAppException(ex); + } + }); + runAsync(future); + return this; + } + + private void runAsync(CompletableFuture future) { + try { + future.get(); + } catch (InterruptedException ex) { + LOGGER.error("InterruptedException: " + ex.getMessage(), ex); + Thread.currentThread().interrupt(); + future.cancel(true); + this.success(false).status(Response.Status.BAD_REQUEST).exception(ex.getCause()); + raiseWebAppException(ex); + } catch (ExecutionException ex) { + LOGGER.error("ExecutionException: " + ex.getMessage(), ex); + this.success(false).status(Response.Status.BAD_REQUEST).exception(ex.getCause()); + raiseWebAppException(ex); + } + } + + private void raiseWebAppException(Throwable ex) { + throw new WebApplicationException(ex, Response.status(this.status).entity(this.current).build()); + } + + + public RestResponseBuilder then(ThrowableConsumer, Exception> func) { + try { + func.accept(this); + } catch (Throwable ex) { + LOGGER.error("Exception: " + ex.getMessage(), ex); + this.success(false).status(Response.Status.BAD_REQUEST).exception(ex); + raiseWebAppException(ex); + } + return this; + } + + public RESTResponse get() { + return current; + } + + public Response build() { + return Response.status(status).entity(current).type(MediaType.APPLICATION_JSON).build(); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/DenyAll.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/DenyAll.java b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/DenyAll.java new file mode 100644 index 0000000..db5cc99 --- /dev/null +++ b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/DenyAll.java @@ -0,0 +1,27 @@ +/* + * 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.security; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface DenyAll { +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/PermitAll.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/PermitAll.java b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/PermitAll.java new file mode 100644 index 0000000..7975f67 --- /dev/null +++ b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/PermitAll.java @@ -0,0 +1,29 @@ +/** + * 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.security; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface PermitAll { + +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/RolesAllowed.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/RolesAllowed.java b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/RolesAllowed.java new file mode 100644 index 0000000..b3aae58 --- /dev/null +++ b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/RolesAllowed.java @@ -0,0 +1,26 @@ +/** + * 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.security; + +import java.lang.annotation.*; + +@Inherited +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface RolesAllowed { + User.Role[] value(); +} http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/User.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/User.java b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/User.java new file mode 100644 index 0000000..a99ba95 --- /dev/null +++ b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/security/User.java @@ -0,0 +1,176 @@ +/* + * 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.security; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.google.common.base.Preconditions; + +import java.io.Serializable; +import java.security.Principal; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +@JsonSerialize +public class User implements Principal, Serializable { + private String username; + private String firstName; + private String lastName; + private String email; + private String fullName; + + private Collection roles; + + public User() { + + } + + public User(User user) { + this.setName(user.getName()); + this.setFirstName(user.getFirstName()); + this.setLastName(user.getLastName()); + this.setEmail(user.getEmail()); + this.setRoles(user.getRoles()); + } + + public User(String username) { + this.username = username; + } + + public User(String username, Collection roles) { + this.username = username; + this.roles = roles; + } + + public Collection getRoles() { + return roles; + } + + public void setRoles(Collection roles) { + this.roles = roles; + } + + public String getFullName() { + if (this.fullName != null ) { + return this.fullName; + } + if (this.firstName == null && this.lastName == null) { + return this.username; + } else if (this.firstName != null && this.lastName == null ) { + return this.firstName; + } else if (this.firstName == null) { + return this.lastName; + } else { + return String.format("%s, %s", this.lastName, this.firstName); + } + } + + @Override + public String getName() { + return this.username; + } + + public void setName(String username) { + this.username = username; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + @Override + public String toString() { + return "User {" + + "name='" + username + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", email='" + email + '\'' + + ", fullName='" + fullName + '\'' + + ", roles=" + roles + + '}'; + } + + public enum Role implements Serializable { + USER("USER"), // USER role with user-level permissions + APPLICATION("APPLICATION"), // APPLICATION role with application-level permissions + ADMINISTRATOR("ADMINISTRATOR"); // ADMINISTRATOR role with admin-level permissions + + public static final Role[] ALL_ROLES = new Role[] { + USER,APPLICATION, ADMINISTRATOR + }; + + private static Map nameRoleMap = new HashMap() { + { + put(ADMINISTRATOR.roleName.toUpperCase(), ADMINISTRATOR); + put(APPLICATION.roleName.toUpperCase(), APPLICATION); + put(USER.roleName.toUpperCase(), USER); + } + }; + + Role(String roleName) { + this.roleName = roleName; + } + + @Override + public String toString() { + return roleName; + } + + public static Role locateCaseInsensitive(String roleName) { + Preconditions.checkArgument(nameRoleMap.containsKey(roleName.toUpperCase()), "Illegal role " + roleName); + return nameRoleMap.get(roleName.toUpperCase()); + } + + private final String roleName; + } + + public boolean isInRole(Role ... allowedRoles) { + Preconditions.checkNotNull(allowedRoles); + if (this.roles != null ) { + for (Role allowRole: allowedRoles) { + if (this.roles.contains(allowRole)) { + return true; + } + } + } + return false; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/service/HadoopUser.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/service/HadoopUser.java b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/service/HadoopUser.java index 5c9cf80..094b808 100644 --- a/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/service/HadoopUser.java +++ b/eagle-core/eagle-common/src/main/java/org/apache/eagle/common/service/HadoopUser.java @@ -19,7 +19,7 @@ package org.apache.eagle.common.service; import java.util.List; /** - * Hadoop User. + * Hadoop UserPrincipal. * @since : 7/11/14,2014 */ public class HadoopUser { http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-metadata/eagle-metadata-base/pom.xml ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-base/pom.xml b/eagle-core/eagle-metadata/eagle-metadata-base/pom.xml index ff3db18..88274c2 100644 --- a/eagle-core/eagle-metadata/eagle-metadata-base/pom.xml +++ b/eagle-core/eagle-metadata/eagle-metadata-base/pom.xml @@ -67,5 +67,9 @@ org.mockito mockito-all + + io.dropwizard + dropwizard-auth + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/resource/RESTResponse.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/resource/RESTResponse.java b/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/resource/RESTResponse.java deleted file mode 100644 index 5647458..0000000 --- a/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/resource/RESTResponse.java +++ /dev/null @@ -1,246 +0,0 @@ -/** - * 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.metadata.resource; - -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.apache.eagle.common.function.ThrowableConsumer; -import org.apache.eagle.common.function.ThrowableSupplier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; -import java.util.function.Supplier; - -@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) -public class RESTResponse { - private static final Logger LOGGER = LoggerFactory.getLogger(RESTResponse.class); - private boolean success = false; - private String message; - private String exception; - private T data; - - public RESTResponse() { - } - - public RESTResponse(Throwable throwable) { - if (throwable.getMessage() == null || throwable.getMessage().isEmpty()) { - this.setMessage(throwable.getMessage()); - } else { - this.setMessage(ExceptionUtils.getMessage(throwable)); - } - this.setException(ExceptionUtils.getStackTrace(throwable)); - } - - public T getData() { - return data; - } - - public void setData(T data) { - this.data = data; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return success; - } - - public void setSuccess(boolean success) { - this.success = success; - } - - public static RestResponseBuilder builder() { - return new RestResponseBuilder<>(); - } - - public static RestResponseBuilder of(E data) { - return RESTResponse.builder().data(data); - } - - public static RestResponseBuilder of(Consumer> func) { - return RESTResponse.builder().of(func); - } - - public static RestResponseBuilder of(Supplier func) { - return RESTResponse.builder().of(func); - } - - public static RestResponseBuilder async(ThrowableSupplier func) { - return RESTResponse.builder().async(func); - } - - public static RestResponseBuilder async(ThrowableConsumer, Exception> func) { - return RESTResponse.builder().async(func); - } - - public String getException() { - return exception; - } - - public void setThrowable(Throwable exception) { - this.setException(ExceptionUtils.getStackTrace(exception)); - } - - public void setException(String exception) { - this.exception = exception; - } - - - public static class RestResponseBuilder { - private RESTResponse current = new RESTResponse(); - private Response.Status status = Response.Status.OK; - private CompletableFuture future = null; - - public RestResponseBuilder success(boolean success) { - this.current.setSuccess(success); - return this; - } - - public RestResponseBuilder status(Response.Status status) { - this.status = status; - return this; - } - - public RestResponseBuilder status(boolean success, Response.Status status) { - this.success(success); - this.status(status); - return this; - } - - public RestResponseBuilder message(String message) { - this.current.setMessage(message); - return this; - } - - public RestResponseBuilder data(E data) { - this.current.setData(data); - return this; - } - - public RestResponseBuilder exception(Throwable exception) { - this.current.setThrowable(exception); - if (this.current.getMessage() == null) { - if (exception.getMessage() == null || exception.getMessage().isEmpty()) { - this.current.setMessage(ExceptionUtils.getMessage(exception)); - } else { - this.current.setMessage(exception.getMessage()); - } - } - return this; - } - - public RestResponseBuilder of(Consumer> func) { - try { - this.success(true).status(Response.Status.OK); - func.accept(this); - } catch (Exception ex) { - LOGGER.error("Exception: " + ex.getMessage(), ex); - this.success(false).data(null).status(Response.Status.BAD_REQUEST).exception(ex); - raiseWebAppException(ex); - } - return this; - } - - public RestResponseBuilder of(Supplier func) { - try { - this.success(true).status(Response.Status.OK).data(func.get()); - } catch (Throwable ex) { - LOGGER.error("Exception: " + ex.getMessage(), ex); - this.success(false).status(Response.Status.BAD_REQUEST).exception(ex); - raiseWebAppException(ex); - } - return this; - } - - public RestResponseBuilder async(ThrowableSupplier func) { - CompletableFuture future = CompletableFuture.runAsync(() -> { - try { - this.status(Response.Status.OK).success(true).data(func.get()); - } catch (Throwable e) { - LOGGER.error("Exception: " + e.getMessage(), e); - this.success(false).status(Response.Status.BAD_REQUEST).exception(e); - raiseWebAppException(e); - } - }); - runAsync(future); - return this; - } - - public RestResponseBuilder async(ThrowableConsumer, Exception> func) { - CompletableFuture future = CompletableFuture.runAsync(() -> { - try { - func.accept(this); - this.success(true); - } catch (Throwable ex) { - LOGGER.error("Exception: " + ex.getMessage(), ex); - this.success(false).status(Response.Status.BAD_REQUEST).exception(ex); - raiseWebAppException(ex); - } - }); - runAsync(future); - return this; - } - - private void runAsync(CompletableFuture future) { - try { - future.get(); - } catch (InterruptedException ex) { - LOGGER.error("InterruptedException: " + ex.getMessage(), ex); - Thread.currentThread().interrupt(); - future.cancel(true); - this.success(false).status(Response.Status.BAD_REQUEST).exception(ex.getCause()); - raiseWebAppException(ex); - } catch (ExecutionException ex) { - LOGGER.error("ExecutionException: " + ex.getMessage(), ex); - this.success(false).status(Response.Status.BAD_REQUEST).exception(ex.getCause()); - raiseWebAppException(ex); - } - } - - private void raiseWebAppException(Throwable ex) { - throw new WebApplicationException(ex, Response.status(this.status).entity(this.current).build()); - } - - - public RestResponseBuilder then(ThrowableConsumer, Exception> func) { - try { - func.accept(this); - } catch (Throwable ex) { - LOGGER.error("Exception: " + ex.getMessage(), ex); - this.success(false).status(Response.Status.BAD_REQUEST).exception(ex); - raiseWebAppException(ex); - } - return this; - } - - public RESTResponse get() { - return current; - } - - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/resource/SiteResource.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/resource/SiteResource.java b/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/resource/SiteResource.java index a5461b3..22a693a 100644 --- a/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/resource/SiteResource.java +++ b/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/resource/SiteResource.java @@ -16,6 +16,7 @@ */ package org.apache.eagle.metadata.resource; +import org.apache.eagle.common.rest.RESTResponse; import org.apache.eagle.metadata.exceptions.SiteDeleteException; import org.apache.eagle.metadata.model.SiteEntity; import org.apache.eagle.metadata.service.ApplicationEntityService; http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-query/eagle-entity-base/src/main/java/org/apache/eagle/log/entity/meta/EntityDefinitionManager.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-query/eagle-entity-base/src/main/java/org/apache/eagle/log/entity/meta/EntityDefinitionManager.java b/eagle-core/eagle-query/eagle-entity-base/src/main/java/org/apache/eagle/log/entity/meta/EntityDefinitionManager.java index 7b1010d..8795ba0 100755 --- a/eagle-core/eagle-query/eagle-entity-base/src/main/java/org/apache/eagle/log/entity/meta/EntityDefinitionManager.java +++ b/eagle-core/eagle-query/eagle-entity-base/src/main/java/org/apache/eagle/log/entity/meta/EntityDefinitionManager.java @@ -278,7 +278,7 @@ public class EntityDefinitionManager { } /** - * User can register their own field SerDeser + * UserPrincipal can register their own field SerDeser * @param clazz class of the the SerDeser * @param entitySerDeser entity or field SerDeser * @throws IllegalArgumentException http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-core/eagle-query/eagle-storage-hbase/src/test/java/org/apache/eagle/storage/hbase/TestWithHBaseCoprocessor.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-query/eagle-storage-hbase/src/test/java/org/apache/eagle/storage/hbase/TestWithHBaseCoprocessor.java b/eagle-core/eagle-query/eagle-storage-hbase/src/test/java/org/apache/eagle/storage/hbase/TestWithHBaseCoprocessor.java index b3d3cfa..b647173 100644 --- a/eagle-core/eagle-query/eagle-storage-hbase/src/test/java/org/apache/eagle/storage/hbase/TestWithHBaseCoprocessor.java +++ b/eagle-core/eagle-query/eagle-storage-hbase/src/test/java/org/apache/eagle/storage/hbase/TestWithHBaseCoprocessor.java @@ -25,6 +25,7 @@ import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,14 +47,27 @@ public class TestWithHBaseCoprocessor { conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, AggregateProtocolEndPoint.class.getName()); conf.setInt("hbase.master.info.port", -1);//avoid port clobbering conf.setInt("hbase.regionserver.info.port", -1);//avoid port clobbering + + int attempts = 0; hbase = new HBaseTestingUtility(); - try { - hbase.startMiniCluster(); - } catch (Exception e) { - LOG.error("Error to start mini cluster: " + e.getMessage(), e); - throw new IllegalStateException(e); + boolean successToStart = false; + while (attempts < 3) { + try { + attempts ++; + hbase.startMiniCluster(); + successToStart = true; + } catch (Exception e) { + LOG.error("Error to start mini cluster (tried {} times): {}", attempts, e.getMessage(), e); + try { + hbase.shutdownMiniCluster(); + } catch (Exception e1) { + LOG.warn(e.getMessage(), e); + } + } } + Assert.assertTrue("Failed to start mini cluster in " + attempts + " attempts", successToStart); + HTable table = hbase.createTable(String.valueOf("unittest"),"f"); HTableDescriptor descriptor = new HTableDescriptor(table.getTableDescriptor()); descriptor.addCoprocessor(AggregateProtocolEndPoint.class.getName()); http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-jpm/eagle-jpm-analyzer/src/main/java/org/apache/eagle/jpm/analyzer/resource/AnalyzerResource.java ---------------------------------------------------------------------- diff --git a/eagle-jpm/eagle-jpm-analyzer/src/main/java/org/apache/eagle/jpm/analyzer/resource/AnalyzerResource.java b/eagle-jpm/eagle-jpm-analyzer/src/main/java/org/apache/eagle/jpm/analyzer/resource/AnalyzerResource.java index dc09202..80d9fb7 100644 --- a/eagle-jpm/eagle-jpm-analyzer/src/main/java/org/apache/eagle/jpm/analyzer/resource/AnalyzerResource.java +++ b/eagle-jpm/eagle-jpm-analyzer/src/main/java/org/apache/eagle/jpm/analyzer/resource/AnalyzerResource.java @@ -18,10 +18,10 @@ package org.apache.eagle.jpm.analyzer.resource; import com.google.inject.Inject; +import org.apache.eagle.common.rest.RESTResponse; import org.apache.eagle.jpm.analyzer.meta.MetaManagementService; import org.apache.eagle.jpm.analyzer.meta.model.JobMetaEntity; import org.apache.eagle.jpm.analyzer.meta.model.PublisherEntity; -import org.apache.eagle.metadata.resource.RESTResponse; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-jpm/eagle-jpm-analyzer/src/main/java/org/apache/eagle/jpm/analyzer/util/Utils.java ---------------------------------------------------------------------- diff --git a/eagle-jpm/eagle-jpm-analyzer/src/main/java/org/apache/eagle/jpm/analyzer/util/Utils.java b/eagle-jpm/eagle-jpm-analyzer/src/main/java/org/apache/eagle/jpm/analyzer/util/Utils.java index 66f7622..a987bd8 100644 --- a/eagle-jpm/eagle-jpm-analyzer/src/main/java/org/apache/eagle/jpm/analyzer/util/Utils.java +++ b/eagle-jpm/eagle-jpm-analyzer/src/main/java/org/apache/eagle/jpm/analyzer/util/Utils.java @@ -19,9 +19,9 @@ package org.apache.eagle.jpm.analyzer.util; import com.typesafe.config.Config; +import org.apache.eagle.common.rest.RESTResponse; import org.apache.eagle.jpm.analyzer.meta.model.JobMetaEntity; import org.apache.eagle.jpm.util.resourcefetch.connection.InputStreamUtils; -import org.apache.eagle.metadata.resource.RESTResponse; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.map.ObjectMapper; import org.slf4j.Logger; http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-jpm/eagle-jpm-spark-history/src/main/java/org/apache/eagle/jpm/spark/history/crawl/JHFSparkEventReader.java ---------------------------------------------------------------------- diff --git a/eagle-jpm/eagle-jpm-spark-history/src/main/java/org/apache/eagle/jpm/spark/history/crawl/JHFSparkEventReader.java b/eagle-jpm/eagle-jpm-spark-history/src/main/java/org/apache/eagle/jpm/spark/history/crawl/JHFSparkEventReader.java index 2ef1bd9..d245f49 100644 --- a/eagle-jpm/eagle-jpm-spark-history/src/main/java/org/apache/eagle/jpm/spark/history/crawl/JHFSparkEventReader.java +++ b/eagle-jpm/eagle-jpm-spark-history/src/main/java/org/apache/eagle/jpm/spark/history/crawl/JHFSparkEventReader.java @@ -169,7 +169,7 @@ public class JHFSparkEventReader { // the second argument of getNormalizeName() is changed to null because the original code contains sensitive text // original second argument looks like: this.app.getConfig().getConfig().get("xxx"), "xxx" is the sensitive text entity.getTags().put(SparkJobTagName.SPARK_APP_NORM_NAME.toString(), this.getNormalizedName(JSONUtils.getString(event, "App Name"), null)); - entity.getTags().put(SparkJobTagName.SPARK_USER.toString(), JSONUtils.getString(event, "User")); + entity.getTags().put(SparkJobTagName.SPARK_USER.toString(), JSONUtils.getString(event, "UserPrincipal")); entity.setTimestamp(appStartTime); } http://git-wip-us.apache.org/repos/asf/eagle/blob/94b597b7/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/partials/queue/overview.html ---------------------------------------------------------------------- diff --git a/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/partials/queue/overview.html b/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/partials/queue/overview.html index 732fbb2..dfcf41c 100644 --- a/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/partials/queue/overview.html +++ b/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/partials/queue/overview.html @@ -42,7 +42,7 @@