private void apply0()

in src/main/java/org/opensearch/security/filter/SecurityFilter.java [162:378]


    private <Request extends ActionRequest, Response extends ActionResponse> void apply0(Task task, final String action, Request request,
            ActionListener<Response> listener, ActionFilterChain<Request, Response> chain) {
        try {

            if(threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_ORIGIN) == null) {
                threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_ORIGIN, Origin.LOCAL.toString());
            }

            final ComplianceConfig complianceConfig = auditLog.getComplianceConfig();
            if (complianceConfig != null && complianceConfig.isEnabled()) {
                attachSourceFieldContext(request);
            }
            final Set<String> injectedRoles = rolesInjector.injectUserAndRoles(request, action, task, threadContext);
            boolean enforcePrivilegesEvaluation = false;
            User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER);
            if(user == null && (user = backendRegistry.authenticate(request, null, task, action)) != null) {
                threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, user);
                enforcePrivilegesEvaluation = true;
            }

            final boolean userIsAdmin = isUserAdmin(user, adminDns);
            final boolean interClusterRequest = HeaderHelper.isInterClusterRequest(threadContext);
            final boolean trustedClusterRequest = HeaderHelper.isTrustedClusterRequest(threadContext);
            final boolean confRequest = "true".equals(HeaderHelper.getSafeFromHeader(threadContext, ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER));
            final boolean passThroughRequest = action.startsWith("indices:admin/seq_no")
                    || action.equals(WhoAmIAction.NAME);

            final boolean internalRequest =
                    (interClusterRequest || HeaderHelper.isDirectRequest(threadContext))
                    && action.startsWith("internal:")
                    && !action.startsWith("internal:transport/proxy");

            if (user != null) {
                org.apache.logging.log4j.ThreadContext.put("user", user.getName());
            }
                        
            if (isActionTraceEnabled()) {

                String count = "";
                if(request instanceof BulkRequest) {
                    count = ""+((BulkRequest) request).requests().size();
                }

                if(request instanceof MultiGetRequest) {
                    count = ""+((MultiGetRequest) request).getItems().size();
                }

                if(request instanceof MultiSearchRequest) {
                    count = ""+((MultiSearchRequest) request).requests().size();
                }

                traceAction("Node "+cs.localNode().getName()+" -> "+action+" ("+count+"): userIsAdmin="+userIsAdmin+"/conRequest="+confRequest+"/internalRequest="+internalRequest
                        +"origin="+threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_ORIGIN)+"/directRequest="+HeaderHelper.isDirectRequest(threadContext)+"/remoteAddress="+request.remoteAddress());


                threadContext.putHeader("_opendistro_security_trace"+System.currentTimeMillis()+"#"+UUID.randomUUID().toString(), Thread.currentThread().getName()+" FILTER -> "+"Node "+cs.localNode().getName()+" -> "+action+" userIsAdmin="+userIsAdmin+"/conRequest="+confRequest+"/internalRequest="+internalRequest
                        +"origin="+threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_ORIGIN)+"/directRequest="+HeaderHelper.isDirectRequest(threadContext)+"/remoteAddress="+request.remoteAddress()+" "+threadContext.getHeaders().entrySet().stream().filter(p->!p.getKey().startsWith("_opendistro_security_trace")).collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue())));


            }


            if(userIsAdmin
                    || confRequest
                    || internalRequest
                    || passThroughRequest){

                if(userIsAdmin && !confRequest && !internalRequest && !passThroughRequest) {
                    auditLog.logGrantedPrivileges(action, request, task);
                    auditLog.logIndexEvent(action, request, task);
                }

                chain.proceed(task, action, request, listener);
                return;
            }
            
            
            if(immutableIndicesMatcher != WildcardMatcher.NONE) {
            
                boolean isImmutable = false;
                
                if(request instanceof BulkShardRequest) {
                    for(BulkItemRequest bsr: ((BulkShardRequest) request).items()) {
                        isImmutable = checkImmutableIndices(bsr.request(), listener);
                        if(isImmutable) {
                            break;
                        }
                    }
                } else {
                    isImmutable = checkImmutableIndices(request, listener);
                }
    
                if(isImmutable) {
                    return;
                }

            }

            if(Origin.LOCAL.toString().equals(threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_ORIGIN))
                    && (interClusterRequest || HeaderHelper.isDirectRequest(threadContext))
                    && (injectedRoles == null)
                    && !enforcePrivilegesEvaluation
                    ) {

                chain.proceed(task, action, request, listener);
                return;
            }

            if(user == null) {

                if(action.startsWith("cluster:monitor/state")) {
                    chain.proceed(task, action, request, listener);
                    return;
                }

                boolean skipSecurityIfDualMode = threadContext.getTransient(ConfigConstants.SECURITY_SSL_DUAL_MODE_SKIP_SECURITY) == Boolean.TRUE;
                if((interClusterRequest || trustedClusterRequest || request.remoteAddress() == null) && !compatConfig.transportInterClusterAuthEnabled()) {
                    chain.proceed(task, action, request, listener);
                    return;
                } else if((interClusterRequest || trustedClusterRequest || request.remoteAddress() == null || skipSecurityIfDualMode) && compatConfig.transportInterClusterPassiveAuthEnabled()) {
                    log.info("Transport auth in passive mode and no user found. Injecting default user");
                    user = User.DEFAULT_TRANSPORT_USER;
                    threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, user);
                } else {
                    log.error("No user found for "+ action+" from "+request.remoteAddress()+" "+threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_ORIGIN)+" via "+threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_CHANNEL_TYPE)+" "+threadContext.getHeaders());
                    listener.onFailure(new OpenSearchSecurityException("No user found for "+action, RestStatus.INTERNAL_SERVER_ERROR));
                    return;
                }
            }

            final PrivilegesEvaluator eval = evalp;

            if (!eval.isInitialized()) {
                log.error("OpenSearch Security not initialized for {}", action);
                listener.onFailure(new OpenSearchSecurityException("OpenSearch Security not initialized for "
                + action, RestStatus.SERVICE_UNAVAILABLE));
                return;
            }

            if (log.isTraceEnabled()) {
                log.trace("Evaluate permissions for user: {}", user.getName());
            }

            final PrivilegesEvaluatorResponse pres = eval.evaluate(user, action, request, task, injectedRoles);
            
            if (log.isDebugEnabled()) {
                log.debug(pres.toString());
            }

            if (pres.isAllowed()) {
                auditLog.logGrantedPrivileges(action, request, task);
                auditLog.logIndexEvent(action, request, task);
                if(!dlsFlsValve.invoke(action, request, listener, pres.getAllowedFlsFields(), pres.getMaskedFields(), pres.getQueries())) {
                    return;
                }
                final CreateIndexRequestBuilder createIndexRequestBuilder = pres.getCreateIndexRequestBuilder();
                if (createIndexRequestBuilder == null) {
                    chain.proceed(task, action, request, listener);
                } else {
                    CreateIndexRequest createIndexRequest = createIndexRequestBuilder.request();
                    log.info("Request {} requires new tenant index {} with aliases {}",
                        request.getClass().getSimpleName(), createIndexRequest.index(), alias2Name(createIndexRequest.aliases()));
                    createIndexRequestBuilder.execute(new ActionListener<CreateIndexResponse>() {
                        @Override
                        public void onResponse(CreateIndexResponse createIndexResponse) {
                            if (createIndexResponse.isAcknowledged()) {
                                log.debug("Request to create index {} with aliases {} acknowledged, proceeding with {}",
                                    createIndexRequest.index(), alias2Name(createIndexRequest.aliases()), request.getClass().getSimpleName());
                                chain.proceed(task, action, request, listener);
                            } else {
                                String message = LoggerMessageFormat.format("Request to create index {} with aliases {} was not acknowledged, failing {}",
                                    createIndexRequest.index(), alias2Name(createIndexRequest.aliases()), request.getClass().getSimpleName());
                                log.error(message);
                                listener.onFailure(new OpenSearchException(message));
                            }
                        }

                        @Override
                        public void onFailure(Exception e) {
                            Throwable cause = ExceptionsHelper.unwrapCause(e);
                            if (cause instanceof ResourceAlreadyExistsException) {
                                log.warn("Request to create index {} with aliases {} failed as the resource already exists, proceeding with {}",
                                    createIndexRequest.index(), alias2Name(createIndexRequest.aliases()), request.getClass().getSimpleName(), e);
                                chain.proceed(task, action, request, listener);
                            } else {
                                log.error("Request to create index {} with aliases {} failed, failing {}",
                                    createIndexRequest.index(), alias2Name(createIndexRequest.aliases()), request.getClass().getSimpleName(), e);
                                listener.onFailure(e);
                            }
                        }
                    });
                }
            } else {
                auditLog.logMissingPrivileges(action, request, task);
                String err;
                if(!pres.getMissingSecurityRoles().isEmpty()) {
                    err = String.format("No mapping for %s on roles %s", user, pres.getMissingSecurityRoles());
                } else {
                    err = (injectedRoles != null) ?
                            String.format("no permissions for %s and associated roles %s", pres.getMissingPrivileges(), pres.getResolvedSecurityRoles()) :
                            String.format("no permissions for %s and %s", pres.getMissingPrivileges(), user);
                }
                log.debug(err);
                listener.onFailure(new OpenSearchSecurityException(err, RestStatus.FORBIDDEN));
            }
        } catch (OpenSearchException e) {
            if (task != null) {
                log.debug("Failed to apply filter. Task id: {} ({}). Action: {}", task.getId(), task.getDescription(), action, e);
            } else {
                log.debug("Failed to apply filter. Action: {}", action, e);
            }
            listener.onFailure(e);
        } catch (Throwable e) {
            log.error("Unexpected exception "+e, e);
            listener.onFailure(new OpenSearchSecurityException("Unexpected exception " + action, RestStatus.INTERNAL_SERVER_ERROR));
        }
    }