in ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java [157:300]
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 no explicit authenticated user is set, set it to the default user (if one is specified)
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())
.withProxyUserName(AuthorizationHelper.getProxyUserName(internalAuthenticationToken))
.withRemoteIp(RequestUtils.getRemoteAddress(httpRequest))
.withRoles(permissionHelper.getPermissionLabels(authentication))
.withTimestamp(System.currentTimeMillis()).build();
auditLogger.log(loginAuditEvent);
}
} else {
// for view access, we should redirect to the Ambari login
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();
// admin has full access
if (permissionId.equals(PermissionEntity.AMBARI_ADMINISTRATOR_PERMISSION)) {
authorized = true;
break;
}
// clusters require permission
if (!"GET".equalsIgnoreCase(httpRequest.getMethod()) && requestURI.matches(API_CREDENTIALS_AMBARI_PATTERN)) {
// Only the administrator can operate on credentials where the alias starts with "ambari."
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()) {
//TODO permissions model doesn't manage stacks api, but we need access to stack advisor to save configs
if (permissionId.equals(PermissionEntity.CLUSTER_USER_PERMISSION) ||
permissionId.equals(PermissionEntity.CLUSTER_ADMINISTRATOR_PERMISSION)) {
authorized = true;
break;
}
} else if (requestURI.matches(API_VIEWS_ALL_PATTERN)) {
// views require permission
if (permissionId.equals(PermissionEntity.VIEW_USER_PERMISSION)) {
authorized = true;
break;
}
} else if (requestURI.matches(API_AUTH_PATTERN) && "POST".equalsIgnoreCase(httpRequest.getMethod())) {
// all are able to login
authorized = true;
break;
}
}
}
// Allow all GETs that are not LDAP sync events...
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())
.withProxyUserName(AuthorizationHelper.getProxyUserName())
.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())
.withProxyUserName(AuthorizationHelper.getProxyUserName())
.withTimestamp(System.currentTimeMillis())
.build();
auditLogger.log(auditEvent);
}
}
chain.doFilter(request, response);
}