ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jonathanhur...@apache.org
Subject [27/50] [abbrv] ambari git commit: AMBARI-18821. Logsearch support KNOX SSO (oleewere)
Date Thu, 17 Nov 2016 17:13:43 GMT
AMBARI-18821. Logsearch support KNOX SSO (oleewere)

Change-Id: I7d275de0ed17f02234ca290811236b2211653bae


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7d2fa09e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7d2fa09e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7d2fa09e

Branch: refs/heads/branch-feature-AMBARI-18456
Commit: 7d2fa09ebea5eaf1617e2661ae5691fa3ba7cf76
Parents: 7b54b9a
Author: oleewere <oleewere@gmail.com>
Authored: Thu Nov 10 12:12:04 2016 +0100
Committer: oleewere <oleewere@gmail.com>
Committed: Wed Nov 16 16:48:10 2016 +0100

----------------------------------------------------------------------
 .../ambari-logsearch-portal/pom.xml             |   6 +
 .../ambari/logsearch/conf/AuthPropsConfig.java  |  62 +++++++
 .../ambari/logsearch/conf/SecurityConfig.java   |  55 ++++--
 .../web/filters/LogsearchJWTFilter.java         | 181 +++++++++++++++++++
 ...LogsearchSecurityContextFormationFilter.java |   3 +-
 ...rchUsernamePasswordAuthenticationFilter.java |   1 -
 .../web/model/JWTAuthenticationToken.java       |  53 ++++++
 .../configuration/logsearch-properties.xml      |  63 +++++++
 .../LOGSEARCH/0.5.0/themes/theme.json           |  87 ++++++++-
 ambari-web/app/data/HDP2/site_properties.js     |  21 +++
 10 files changed, 515 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7d2fa09e/ambari-logsearch/ambari-logsearch-portal/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/pom.xml b/ambari-logsearch/ambari-logsearch-portal/pom.xml
index 5485ca1..5096481 100755
--- a/ambari-logsearch/ambari-logsearch-portal/pom.xml
+++ b/ambari-logsearch/ambari-logsearch-portal/pom.xml
@@ -37,6 +37,7 @@
     <jetty-version>9.2.11.v20150529</jetty-version>
     <swagger.version>1.5.8</swagger.version>
     <spring-data-solr.version>2.0.2.RELEASE</spring-data-solr.version>
+    <jjwt.version>0.6.0</jjwt.version>
   </properties>
   <profiles>
     <!-- Dev Profile Start -->
@@ -767,5 +768,10 @@
       <artifactId>freemarker</artifactId>
       <version>2.3.20</version>
     </dependency>
+    <dependency>
+      <groupId>io.jsonwebtoken</groupId>
+      <artifactId>jjwt</artifactId>
+      <version>${jjwt.version}</version>
+    </dependency>
   </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d2fa09e/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/conf/AuthPropsConfig.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/conf/AuthPropsConfig.java
b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/conf/AuthPropsConfig.java
index 67ddd1f..54cc10c 100644
--- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/conf/AuthPropsConfig.java
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/conf/AuthPropsConfig.java
@@ -21,6 +21,8 @@ package org.apache.ambari.logsearch.conf;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
 
+import java.util.List;
+
 @Configuration
 public class AuthPropsConfig {
 
@@ -38,6 +40,18 @@ public class AuthPropsConfig {
   private String externalAuthLoginUrl;
   @Value("${logsearch.login.credentials.file:user_pass.json}")
   private String credentialsFile;
+  @Value("${logsearch.auth.jwt.enabled:false}")
+  private boolean authJwtEnabled;
+  @Value("${logsearch.auth.jwt.provider_url:}")
+  private String providedUrl;
+  @Value("${logsearch.auth.jwt.public_key:}")
+  private String publicKey;
+  @Value("${logsearch.auth.jwt.cookie.name:hadoop-jwt}")
+  private String cookieName;
+  @Value("${logsearch.auth.jwt.query.param.original_url:originalUrl=}")
+  private String originalUrlQueryParam;
+  @Value("#{'${logsearch.auth.jwt.audiances:}'.split(',')}")
+  private List<String> audiences;
 
   public boolean isAuthFileEnabled() {
     return authFileEnabled;
@@ -94,4 +108,52 @@ public class AuthPropsConfig {
   public void setAuthExternalEnabled(boolean authExternalEnabled) {
     this.authExternalEnabled = authExternalEnabled;
   }
+
+  public boolean isAuthJwtEnabled() {
+    return authJwtEnabled;
+  }
+
+  public void setAuthJwtEnabled(boolean authJwtEnabled) {
+    this.authJwtEnabled = authJwtEnabled;
+  }
+
+  public String getProvidedUrl() {
+    return providedUrl;
+  }
+
+  public void setProvidedUrl(String providedUrl) {
+    this.providedUrl = providedUrl;
+  }
+
+  public String getPublicKey() {
+    return publicKey;
+  }
+
+  public void setPublicKey(String publicKey) {
+    this.publicKey = publicKey;
+  }
+
+  public String getCookieName() {
+    return cookieName;
+  }
+
+  public void setCookieName(String cookieName) {
+    this.cookieName = cookieName;
+  }
+
+  public String getOriginalUrlQueryParam() {
+    return originalUrlQueryParam;
+  }
+
+  public void setOriginalUrlQueryParam(String originalUrlQueryParam) {
+    this.originalUrlQueryParam = originalUrlQueryParam;
+  }
+
+  public List<String> getAudiences() {
+    return audiences;
+  }
+
+  public void setAudiences(List<String> audiences) {
+    this.audiences = audiences;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d2fa09e/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/conf/SecurityConfig.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/conf/SecurityConfig.java
b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/conf/SecurityConfig.java
index d3db110..7a6c69c 100644
--- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/conf/SecurityConfig.java
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/conf/SecurityConfig.java
@@ -18,11 +18,13 @@
  */
 package org.apache.ambari.logsearch.conf;
 
+import com.google.common.collect.Lists;
 import org.apache.ambari.logsearch.web.authenticate.LogsearchAuthFailureHandler;
 import org.apache.ambari.logsearch.web.authenticate.LogsearchAuthSuccessHandler;
 import org.apache.ambari.logsearch.web.authenticate.LogsearchLogoutSuccessHandler;
 import org.apache.ambari.logsearch.web.filters.LogsearchAuthenticationEntryPoint;
 import org.apache.ambari.logsearch.web.filters.LogsearchKRBAuthenticationFilter;
+import org.apache.ambari.logsearch.web.filters.LogsearchJWTFilter;
 import org.apache.ambari.logsearch.web.filters.LogsearchSecurityContextFormationFilter;
 import org.apache.ambari.logsearch.web.filters.LogsearchUsernamePasswordAuthenticationFilter;
 import org.apache.ambari.logsearch.web.security.LogsearchAuthenticationProvider;
@@ -34,11 +36,21 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
 import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
+import org.springframework.security.web.util.matcher.OrRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+import javax.inject.Inject;
+import java.util.List;
 
 @Configuration
 @EnableWebSecurity
 public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
+  @Inject
+  private AuthPropsConfig authPropsConfig;
+
   @Override
   protected void configure(HttpSecurity http) throws Exception {
     http
@@ -46,20 +58,10 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
       .sessionManagement()
          .sessionFixation()
          .newSession()
-         .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
+         .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
       .and()
       .authorizeRequests()
-        .antMatchers("/login.html").permitAll()
-        .antMatchers("/styles/**").permitAll()
-        .antMatchers("/fonts/**").permitAll()
-        .antMatchers("/fonts/**").permitAll()
-        .antMatchers("/scripts/**").permitAll()
-        .antMatchers("/libs/**").permitAll()
-        .antMatchers("/images/**").permitAll()
-        .antMatchers("/templates/**").permitAll()
-        .antMatchers("/favicon.ico").permitAll()
-        .antMatchers("/api/v1/public/**").permitAll()
-        .antMatchers("/api/v1/swagger.json").permitAll()
+        .requestMatchers(requestMatcher()).permitAll()
         .antMatchers("/**").authenticated()
       .and()
       .authenticationProvider(logsearchAuthenticationProvider())
@@ -70,8 +72,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
         .authenticationEntryPoint(logsearchAuthenticationEntryPoint())
       .and()
       .addFilterBefore(logsearchUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
-      .addFilterBefore(new LogsearchKRBAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
+      .addFilterBefore(logsearchKRBAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
       .addFilterAfter(securityContextFormationFilter(), FilterSecurityInterceptor.class)
+      .addFilterBefore(logsearchJwtFilter(), LogsearchSecurityContextFormationFilter.class)
       .logout()
         .logoutUrl("/logout.html")
         .deleteCookies("JSESSIONID")
@@ -94,6 +97,15 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
   }
 
   @Bean
+  public LogsearchJWTFilter logsearchJwtFilter() throws Exception {
+    LogsearchJWTFilter filter = new LogsearchJWTFilter(requestMatcher(), authPropsConfig);
+    filter.setAuthenticationManager(authenticationManagerBean());
+    filter.setAuthenticationSuccessHandler(new LogsearchAuthSuccessHandler());
+    filter.setAuthenticationFailureHandler(new LogsearchAuthFailureHandler());
+    return filter;
+  }
+
+  @Bean
   public LogsearchAuthenticationEntryPoint logsearchAuthenticationEntryPoint() {
     LogsearchAuthenticationEntryPoint entryPoint = new LogsearchAuthenticationEntryPoint("/login.html");
     entryPoint.setForceHttps(false);
@@ -109,4 +121,21 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
     return filter;
   }
 
+  @Bean
+  public RequestMatcher requestMatcher() {
+    List<RequestMatcher> matchers = Lists.newArrayList();
+    matchers.add(new AntPathRequestMatcher("/login.html"));
+    matchers.add(new AntPathRequestMatcher("/logout.html"));
+    matchers.add(new AntPathRequestMatcher("/styles/**"));
+    matchers.add(new AntPathRequestMatcher("/fonts/**"));
+    matchers.add(new AntPathRequestMatcher("/scripts/**"));
+    matchers.add(new AntPathRequestMatcher("/libs/**"));
+    matchers.add(new AntPathRequestMatcher("/templates/**"));
+    matchers.add(new AntPathRequestMatcher("/favicon.ico"));
+    matchers.add(new AntPathRequestMatcher("/api/v1/public/**"));
+    matchers.add(new AntPathRequestMatcher("/api/v1/swagger.json"));
+    matchers.add(new AntPathRequestMatcher("/api/v1/swagger.yaml"));
+    return new OrRequestMatcher(matchers);
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d2fa09e/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchJWTFilter.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchJWTFilter.java
b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchJWTFilter.java
new file mode 100644
index 0000000..1bc7231
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchJWTFilter.java
@@ -0,0 +1,181 @@
+/*
+ * 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.ambari.logsearch.web.filters;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.MalformedJwtException;
+import io.jsonwebtoken.SignatureException;
+import org.apache.ambari.logsearch.conf.AuthPropsConfig;
+import org.apache.ambari.logsearch.web.model.JWTAuthenticationToken;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
+import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+
+public class LogsearchJWTFilter extends AbstractAuthenticationProcessingFilter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(LogsearchJWTFilter.class);
+
+  private static final String PEM_HEADER = "-----BEGIN CERTIFICATE-----\n";
+  private static final String PEM_FOOTER = "\n-----END CERTIFICATE-----";
+
+  private AuthPropsConfig authPropsConfig;
+
+  public LogsearchJWTFilter(RequestMatcher requestMatcher, AuthPropsConfig authPropsConfig)
{
+    super(new NegatedRequestMatcher(requestMatcher));
+    this.authPropsConfig = authPropsConfig;
+  }
+
+  @Override
+  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse
response) throws AuthenticationException, IOException, ServletException {
+    if (StringUtils.isEmpty(authPropsConfig.getProvidedUrl())) {
+      throw new BadCredentialsException("Authentication provider URL must not be null or
empty.");
+    }
+    if (StringUtils.isEmpty(authPropsConfig.getPublicKey())) {
+      throw new BadCredentialsException("Public key for signature validation must be provisioned.");
+    }
+
+    try {
+      Claims claims = Jwts
+        .parser()
+        .setSigningKey(parseRSAPublicKey(authPropsConfig.getPublicKey()))
+        .parseClaimsJws(getJWTFromCookie(request))
+        .getBody();
+
+      String userName  = claims.getSubject();
+      LOG.info("USERNAME: " + userName);
+      LOG.info("URL = " + request.getRequestURL());
+      if (StringUtils.isNotEmpty(claims.getAudience()) && !authPropsConfig.getAudiences().contains(claims.getAudience()))
{
+        throw new IllegalArgumentException(String.format("Audience validation failed. (Not
found: %s)", claims.getAudience()));
+      }
+      Authentication authentication = new JWTAuthenticationToken(userName, authPropsConfig.getPublicKey());
+      authentication.setAuthenticated(true);
+      SecurityContextHolder.getContext().setAuthentication(authentication);
+      return authentication;
+    } catch (ExpiredJwtException | MalformedJwtException | SignatureException | IllegalArgumentException
e) {
+      LOG.info("URL = " + request.getRequestURL());
+      LOG.warn("Error during JWT authentication: ", e.getMessage());
+      throw new BadCredentialsException(e.getMessage(), e);
+    }
+  }
+
+  @Override
+  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws
IOException, ServletException {
+    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+    if (!authPropsConfig.isAuthJwtEnabled() || isAuthenticated(authentication)) {
+      chain.doFilter(req, res);
+      return;
+    }
+    super.doFilter(req, res, chain);
+  }
+
+  @Override
+  protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse
response, FilterChain chain, Authentication authResult) throws IOException, ServletException
{
+    super.successfulAuthentication(request, response, chain, authResult);
+    response.sendRedirect(request.getRequestURL().toString() + getOriginalQueryString(request));
+  }
+
+  @Override
+  protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse
response, AuthenticationException failed) throws IOException, ServletException {
+    super.unsuccessfulAuthentication(request, response, failed);
+    String loginUrl = constructLoginURL(request);
+    response.sendRedirect(loginUrl);
+  }
+
+  private String getJWTFromCookie(HttpServletRequest req) {
+    String serializedJWT = null;
+    Cookie[] cookies = req.getCookies();
+    if (cookies != null) {
+      for (Cookie cookie : cookies) {
+        if (authPropsConfig.getCookieName().equals(cookie.getName())) {
+          LOG.info(authPropsConfig.getCookieName() + " cookie has been found and is being
processed");
+          serializedJWT = cookie.getValue();
+          break;
+        }
+      }
+    }
+    return serializedJWT;
+  }
+
+  private RSAPublicKey parseRSAPublicKey(String pem) throws ServletException {
+    String fullPem = PEM_HEADER + pem + PEM_FOOTER;
+    try {
+      CertificateFactory fact = CertificateFactory.getInstance("X.509");
+      ByteArrayInputStream is = new ByteArrayInputStream(fullPem.getBytes("UTF8"));
+
+      X509Certificate cer = (X509Certificate) fact.generateCertificate(is);
+      return (RSAPublicKey) cer.getPublicKey();
+    } catch (CertificateException ce) {
+      String message;
+      if (pem.startsWith(PEM_HEADER)) {
+        message = "CertificateException - be sure not to include PEM header "
+          + "and footer in the PEM configuration element.";
+      } else {
+        message = "CertificateException - PEM may be corrupt";
+      }
+      throw new ServletException(message, ce);
+    } catch (UnsupportedEncodingException uee) {
+      throw new ServletException(uee);
+    }
+  }
+
+  private String constructLoginURL(HttpServletRequest request) {
+    String delimiter = "?";
+    if (authPropsConfig.getProvidedUrl().contains("?")) {
+      delimiter = "&";
+    }
+    return authPropsConfig.getProvidedUrl() + delimiter
+      + authPropsConfig.getOriginalUrlQueryParam() + "="
+      + request.getRequestURL().toString() + getOriginalQueryString(request);
+  }
+
+  private String getOriginalQueryString(HttpServletRequest request) {
+    String originalQueryString = request.getQueryString();
+    return (originalQueryString == null) ? "" : "?" + originalQueryString;
+  }
+
+  private boolean isAuthenticated(Authentication authentication) {
+    return authentication != null && !(authentication instanceof AnonymousAuthenticationToken)
&& authentication.isAuthenticated();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d2fa09e/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchSecurityContextFormationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchSecurityContextFormationFilter.java
b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchSecurityContextFormationFilter.java
index 1320278..b427749 100644
--- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchSecurityContextFormationFilter.java
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchSecurityContextFormationFilter.java
@@ -88,8 +88,7 @@ public class LogsearchSecurityContextFormationFilter extends GenericFilterBean
{
           httpResponse.addCookie(cookie);
         }
         // [1]get the context from session
-        LogSearchContext context = (LogSearchContext) httpSession
-          .getAttribute(LOGSEARCH_SC_SESSION_KEY);
+        LogSearchContext context = (LogSearchContext) httpSession.getAttribute(LOGSEARCH_SC_SESSION_KEY);
         if (context == null) {
           context = new LogSearchContext();
           httpSession.setAttribute(LOGSEARCH_SC_SESSION_KEY, context);

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d2fa09e/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchUsernamePasswordAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchUsernamePasswordAuthenticationFilter.java
b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchUsernamePasswordAuthenticationFilter.java
index 85688a2..24ec2d4 100644
--- a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchUsernamePasswordAuthenticationFilter.java
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/filters/LogsearchUsernamePasswordAuthenticationFilter.java
@@ -36,7 +36,6 @@ public class LogsearchUsernamePasswordAuthenticationFilter extends UsernamePassw
 
   public void setRememberMeServices(RememberMeServices rememberMeServices) {
     super.setRememberMeServices(rememberMeServices);
-
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d2fa09e/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/model/JWTAuthenticationToken.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/model/JWTAuthenticationToken.java
b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/model/JWTAuthenticationToken.java
new file mode 100644
index 0000000..35175b6
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-portal/src/main/java/org/apache/ambari/logsearch/web/model/JWTAuthenticationToken.java
@@ -0,0 +1,53 @@
+/*
+ * 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.ambari.logsearch.web.model;
+
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.Collection;
+
+public class JWTAuthenticationToken extends AbstractAuthenticationToken {
+
+  private String credential;
+
+  private String principal;
+
+  public JWTAuthenticationToken(String principal, String credential) {
+    super((Collection)null);
+    this.principal = principal;
+    this.credential = credential;
+  }
+
+  public JWTAuthenticationToken(String principal, String credential, Collection<? extends
GrantedAuthority> authorities) {
+    super(authorities);
+    this.principal = principal;
+    this.credential = credential;
+  }
+
+  @Override
+  public Object getCredentials() {
+    return credential;
+  }
+
+  @Override
+  public Object getPrincipal() {
+    return principal;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d2fa09e/ambari-server/src/main/resources/common-services/LOGSEARCH/0.5.0/configuration/logsearch-properties.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/LOGSEARCH/0.5.0/configuration/logsearch-properties.xml
b/ambari-server/src/main/resources/common-services/LOGSEARCH/0.5.0/configuration/logsearch-properties.xml
index febeffd..9dcd5cf 100644
--- a/ambari-server/src/main/resources/common-services/LOGSEARCH/0.5.0/configuration/logsearch-properties.xml
+++ b/ambari-server/src/main/resources/common-services/LOGSEARCH/0.5.0/configuration/logsearch-properties.xml
@@ -173,4 +173,67 @@
     <description>The path and query of the external server used to authenticate</description>
     <on-ambari-upgrade add="true"/>
   </property>
+  <property>
+    <name>logsearch.auth.jwt.enabled</name>
+    <value>false</value>
+    <display-name>JWT authentication enabled</display-name>
+    <description>Enable JWT based authentication for Log Search portal</description>
+    <value-attributes>
+      <type>value-list</type>
+      <overridable>false</overridable>
+      <entries>
+        <entry>
+          <value>true</value>
+          <label>ON</label>
+        </entry>
+        <entry>
+          <value>false</value>
+          <label>OFF</label>
+        </entry>
+      </entries>
+      <selection-cardinality>1</selection-cardinality>
+    </value-attributes>
+    <on-ambari-upgrade add="true"/>
+  </property>
+  <property>
+    <name>logsearch.auth.jwt.provider_url</name>
+    <value/>
+    <display-name>JWT authentication provider url</display-name>
+    <description>URL to the JWT authentication server</description>
+    <on-ambari-upgrade add="true"/>
+  </property>
+  <property>
+    <name>logsearch.auth.jwt.query.param.original_url</name>
+    <value>originalUrl</value>
+    <display-name>JWT original url query param</display-name>
+    <description>Name of the original request URL which is used to redirect to Log
Search Portal</description>
+    <on-ambari-upgrade add="true"/>
+  </property>
+  <property>
+    <name>logsearch.auth.jwt.cookie.name</name>
+    <value>hadoop-jwt</value>
+    <display-name>JWT cookie name</display-name>
+    <description>The name of the cookie that contains the JWT token</description>
+    <on-ambari-upgrade add="true"/>
+  </property>
+  <property>
+    <name>logsearch.auth.jwt.audiances</name>
+    <value/>
+    <display-name>JWT expected audiances</display-name>
+    <description>Comma separated list of acceptable audiences for the JWT token</description>
+    <value-attributes>
+      <empty-value-valid>true</empty-value-valid>
+    </value-attributes>
+    <on-ambari-upgrade add="true"/>
+  </property>
+  <property>
+    <name>logsearch.auth.jwt.public_key</name>
+    <value/>
+    <display-name>JWT authentication signing key</display-name>
+    <description>PEM formatted public key for JWT token without the header and the
footer</description>
+    <value-attributes>
+      <type>content</type>
+    </value-attributes>
+    <on-ambari-upgrade add="true"/>
+  </property>
 </configuration>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d2fa09e/ambari-server/src/main/resources/common-services/LOGSEARCH/0.5.0/themes/theme.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/LOGSEARCH/0.5.0/themes/theme.json
b/ambari-server/src/main/resources/common-services/LOGSEARCH/0.5.0/themes/theme.json
index 2ed6474..0193689 100644
--- a/ambari-server/src/main/resources/common-services/LOGSEARCH/0.5.0/themes/theme.json
+++ b/ambari-server/src/main/resources/common-services/LOGSEARCH/0.5.0/themes/theme.json
@@ -11,7 +11,7 @@
             "display-name": "Settings",
             "layout": {
               "tab-columns": "2",
-              "tab-rows": "1",
+              "tab-rows": "2",
               "sections": [
                 {
                   "name": "section-logsearch-server",
@@ -38,6 +38,25 @@
                       "column-span": "1"
                     }
                   ]
+                },
+                {
+                  "name": "section-logsearch-sso",
+                  "display-name": "Single Sign-On",
+                  "row-index": "1",
+                  "column-index": "1",
+                  "row-span": "3",
+                  "column-span": "1",
+                  "section-columns": "1",
+                  "section-rows": "5",
+                  "subsections": [
+                    {
+                      "name": "subsection-logsearch-server-sso-col1",
+                      "row-index": "1",
+                      "column-index": "0",
+                      "row-span": "3",
+                      "column-span": "1"
+                    }
+                  ]
                 }
               ]
             }
@@ -71,6 +90,54 @@
         {
           "config": "logsearch-properties/logsearch.collection.audit.logs.replication.factor",
           "subsection-name": "subsection-logsearch-server-col2"
+        },
+        {
+          "config": "logsearch-properties/logsearch.auth.jwt.enabled",
+          "subsection-name": "subsection-logsearch-server-sso-col1"
+        },
+        {
+          "config": "logsearch-properties/logsearch.auth.jwt.provider_url",
+          "subsection-name": "subsection-logsearch-server-sso-col1",
+          "depends-on": [
+            {
+              "configs":[
+                "logsearch-properties/logsearch.auth.jwt.enabled"
+              ],
+              "if": "${logsearch-properties/logsearch.auth.jwt.enabled}",
+              "then": {
+                "property_value_attributes": {
+                  "visible": true
+                }
+              },
+              "else": {
+                "property_value_attributes": {
+                  "visible": false
+                }
+              }
+            }
+          ]
+        },
+        {
+          "config": "logsearch-properties/logsearch.auth.jwt.public_key",
+          "subsection-name": "subsection-logsearch-server-sso-col1",
+          "depends-on": [
+            {
+              "configs":[
+                "logsearch-properties/logsearch.auth.jwt.enabled"
+              ],
+              "if": "${logsearch-properties/logsearch.auth.jwt.enabled}",
+              "then": {
+                "property_value_attributes": {
+                  "visible": true
+                }
+              },
+              "else": {
+                "property_value_attributes": {
+                  "visible": false
+                }
+              }
+            }
+          ]
         }
       ]
     },
@@ -135,6 +202,24 @@
             }
           ]
         }
+      },
+      {
+        "config": "logsearch-properties/logsearch.auth.jwt.enabled",
+        "widget": {
+          "type": "toggle"
+        }
+      },
+      {
+        "config": "logsearch-properties/logsearch.auth.jwt.provider_url",
+        "widget": {
+          "type": "text-field"
+        }
+      },
+      {
+        "config": "logsearch-properties/logsearch.auth.jwt.public_key",
+        "widget": {
+          "type": "directories"
+        }
       }
     ]
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/7d2fa09e/ambari-web/app/data/HDP2/site_properties.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/data/HDP2/site_properties.js b/ambari-web/app/data/HDP2/site_properties.js
index 5be3b5a..d61d4aa 100644
--- a/ambari-web/app/data/HDP2/site_properties.js
+++ b/ambari-web/app/data/HDP2/site_properties.js
@@ -2264,6 +2264,27 @@ var hdp2properties = [
     "category": "Advanced logsearch-properties",
     "index": 11
   },
+  {
+    "name": "logsearch.auth.jwt.audiances",
+    "serviceName": "LOGSEARCH",
+    "filename": "logsearch-properties.xml",
+    "category": "Advanced logsearch-properties",
+    "index": 12
+  },
+  {
+    "name": "logsearch.auth.jwt.cookie.name",
+    "serviceName": "LOGSEARCH",
+    "filename": "logsearch-properties.xml",
+    "category": "Advanced logsearch-properties",
+    "index": 13
+  },
+  {
+    "name": "logsearch.auth.jwt.query.param.original_url",
+    "serviceName": "LOGSEARCH",
+    "filename": "logsearch-properties.xml",
+    "category": "Advanced logsearch-properties",
+    "index": 14
+  },
   /*infra-solr-client-log4j*/
   {
     "name": "infra_solr_client_log_dir",


Mime
View raw message