AmbariAuthorizationFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; String requestURI = httpRequest.getRequestURI(); SecurityContext context = getSecurityContext(); Authentication authentication = context.getAuthentication(); AuditEvent auditEvent = null; if (authentication == null || authentication instanceof AnonymousAuthenticationToken) { Authentication defaultAuthentication = getDefaultAuthentication(); if (defaultAuthentication != null) { context.setAuthentication(defaultAuthentication); authentication = defaultAuthentication; } } if (authentication == null || authentication instanceof AnonymousAuthenticationToken || !authentication.isAuthenticated()) { String token = httpRequest.getHeader(INTERNAL_TOKEN_HEADER); if (token != null) { InternalAuthenticationToken internalAuthenticationToken = new InternalAuthenticationToken(token); context.setAuthentication(internalAuthenticationToken); if(auditLogger.isEnabled()) { LoginAuditEvent loginAuditEvent = LoginAuditEvent.builder() .withUserName(internalAuthenticationToken.getName()) .withRemoteIp(RequestUtils.getRemoteAddress(httpRequest)) .withRoles(permissionHelper.getPermissionLabels(authentication)) .withTimestamp(System.currentTimeMillis()).build(); auditLogger.log(loginAuditEvent); } } else { if (requestURI.matches(VIEWS_CONTEXT_ALL_PATTERN)) { String queryString = httpRequest.getQueryString(); String requestedURL = queryString == null ? requestURI : (requestURI + '?' + queryString); String redirectURL = httpResponse.encodeRedirectURL(LOGIN_REDIRECT_BASE + requestedURL); httpResponse.sendRedirect(redirectURL); } else { entryPoint.commence(httpRequest, httpResponse, new AuthenticationCredentialsNotFoundException("Missing authentication token")); } return; } } else if (!authorizationPerformedInternally(requestURI)) { boolean authorized = false; if (requestURI.matches(API_BOOTSTRAP_PATTERN_ALL)) { authorized = AuthorizationHelper.isAuthorized(authentication, ResourceType.CLUSTER, null, EnumSet.of(RoleAuthorization.HOST_ADD_DELETE_HOSTS)); } else { for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) { if (grantedAuthority instanceof AmbariGrantedAuthority) { AmbariGrantedAuthority ambariGrantedAuthority = (AmbariGrantedAuthority) grantedAuthority; PrivilegeEntity privilegeEntity = ambariGrantedAuthority.getPrivilegeEntity(); Integer permissionId = privilegeEntity.getPermission().getId(); if (permissionId.equals(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION)) { authorized = true; break; } if (!"GET".equalsIgnoreCase(httpRequest.getMethod()) && requestURI.matches(API_CREDENTIALS_AMBARI_PATTERN)) { if (permissionId.equals(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION)) { authorized = true; break; } } else if (requestURI.matches(API_CLUSTERS_ALL_PATTERN)) { if (permissionId.equals(PermissionEntity.CLUSTER_USER_PERMISSION) || permissionId.equals(PermissionEntity.CLUSTER_ADMINISTRATOR_PERMISSION)) { authorized = true; break; } } else if (STACK_ADVISOR_REGEX.matcher(requestURI).matches()) { if (permissionId.equals(PermissionEntity.CLUSTER_USER_PERMISSION) || permissionId.equals(PermissionEntity.CLUSTER_ADMINISTRATOR_PERMISSION)) { authorized = true; break; } } else if (requestURI.matches(API_VIEWS_ALL_PATTERN)) { if (permissionId.equals(PermissionEntity.VIEW_USER_PERMISSION)) { authorized = true; break; } } } } authorized = authorized || (httpRequest.getMethod().equals("GET") && !requestURI.matches(API_LDAP_SYNC_EVENTS_ALL_PATTERN)); } if (!authorized) { if(auditLogger.isEnabled()) { auditEvent = AccessUnauthorizedAuditEvent.builder() .withHttpMethodName(httpRequest.getMethod()) .withRemoteIp(RequestUtils.getRemoteAddress(httpRequest)) .withResourcePath(httpRequest.getRequestURI()) .withUserName(AuthorizationHelper.getAuthenticatedName()) .withTimestamp(System.currentTimeMillis()) .build(); auditLogger.log(auditEvent); } httpResponse.setHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\""); httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "You do not have permissions to access this resource."); httpResponse.flushBuffer(); return; } } if (AuthorizationHelper.getAuthenticatedName() != null) { httpResponse.setHeader("User", AuthorizationHelper.getAuthenticatedName()); if (auditLogger.isEnabled() && httpResponse.getStatus() == HttpServletResponse.SC_FORBIDDEN) { auditEvent = AccessUnauthorizedAuditEvent.builder() .withHttpMethodName(httpRequest.getMethod()) .withRemoteIp(RequestUtils.getRemoteAddress(httpRequest)) .withResourcePath(httpRequest.getRequestURI()) .withUserName(AuthorizationHelper.getAuthenticatedName()) .withTimestamp(System.currentTimeMillis()) .build(); auditLogger.log(auditEvent); } } chain.doFilter(request, response); } AmbariAuthorizationFilter(AmbariEntryPoint entryPoint,
                                   Configuration configuration,
                                   Users users,
                                   AuditLogger auditLogger,
                                   PermissionHelper permissionHelper); @Override void init(FilterConfig filterConfig); @Override void doFilter(ServletRequest request, ServletResponse response, FilterChain chain); @Override void destroy(); static final String API_VERSION_PREFIX; static final String VIEWS_CONTEXT_PATH_PREFIX; }
@Test public void testDoFilter_NotLoggedIn_UseDefaultUser() throws Exception { final FilterChain chain = EasyMock.createStrictMock(FilterChain.class); final HttpServletResponse response = createNiceMock(HttpServletResponse.class); final HttpServletRequest request = createNiceMock(HttpServletRequest.class); expect(request.getRequestURI()).andReturn("/uri").anyTimes(); expect(request.getQueryString()).andReturn(null).anyTimes(); expect(request.getMethod()).andReturn("GET").anyTimes(); chain.doFilter(EasyMock.<ServletRequest>anyObject(), EasyMock.<ServletResponse>anyObject()); EasyMock.expectLastCall().once(); final Configuration configuration = EasyMock.createMock(Configuration.class); expect(configuration.getDefaultApiAuthenticatedUser()).andReturn("user1").once(); User user = EasyMock.createMock(User.class); expect(user.getUserName()).andReturn("user1").anyTimes(); expect(user.getUserType()).andReturn(UserType.LOCAL).anyTimes(); final Users users = EasyMock.createMock(Users.class); expect(users.getUser("user1", UserType.LOCAL)).andReturn(user).once(); expect(users.getUserAuthorities("user1", UserType.LOCAL)).andReturn(Collections.<AmbariGrantedAuthority>emptyList()).once(); replay(request, response, chain, configuration, users, user); Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(Configuration.class).toInstance(configuration); bind(Users.class).toInstance(users); bind(EntityManager.class).toInstance(EasyMock.createMock(EntityManager.class)); bind(UserDAO.class).toInstance(EasyMock.createMock(UserDAO.class)); bind(DBAccessor.class).toInstance(EasyMock.createMock(DBAccessor.class)); bind(PasswordEncoder.class).toInstance(EasyMock.createMock(PasswordEncoder.class)); bind(OsFamily.class).toInstance(EasyMock.createMock(OsFamily.class)); bind(AuditLogger.class).toInstance(EasyMock.createNiceMock(AuditLogger.class)); bind(HookService.class).toInstance(EasyMock.createMock(HookService.class)); bind(HookContextFactory.class).toInstance(EasyMock.createMock(HookContextFactory.class)); } }); AmbariAuthorizationFilter filter = new AmbariAuthorizationFilter(createNiceMock(AmbariEntryPoint.class), injector.getInstance(Configuration.class), injector.getInstance(Users.class), injector.getInstance(AuditLogger.class), injector.getInstance(PermissionHelper.class)); injector.injectMembers(filter); filter.doFilter(request, response, chain); Assert.assertEquals("user1", SecurityContextHolder.getContext().getAuthentication().getName()); }