// 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 com.cloud.api;

import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URLDecoder;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.Set;

import javax.inject.Inject;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.cloudstack.api.APICommand;
import com.cloud.api.auth.DefaultForgotPasswordAPIAuthenticatorCmd;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ApiServerService;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.auth.APIAuthenticationManager;
import org.apache.cloudstack.api.auth.APIAuthenticationType;
import org.apache.cloudstack.api.auth.APIAuthenticator;
import org.apache.cloudstack.api.command.user.consoleproxy.CreateConsoleEndpointCmd;
import org.apache.cloudstack.api.command.user.gui.theme.ListGuiThemesCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.managed.context.ManagedContext;
import org.apache.cloudstack.utils.consoleproxy.ConsoleAccessUtils;
import org.apache.commons.collections.MapUtils;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.commons.lang3.EnumUtils;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import com.cloud.api.auth.ListUserTwoFactorAuthenticatorProvidersCmd;
import com.cloud.api.auth.SetupUserTwoFactorAuthenticationCmd;
import com.cloud.api.auth.ValidateUserTwoFactorAuthenticationCodeCmd;
import com.cloud.projects.Project;
import com.cloud.projects.dao.ProjectDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManagerImpl;
import com.cloud.user.AccountService;
import com.cloud.user.User;
import com.cloud.user.UserAccount;

import com.cloud.utils.HttpUtils;
import com.cloud.utils.HttpUtils.ApiSessionKeySameSite;
import com.cloud.utils.HttpUtils.ApiSessionKeyCheckOption;
import com.cloud.utils.StringUtils;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.net.NetUtils;

@Component("apiServlet")
public class ApiServlet extends HttpServlet {
    protected static Logger LOGGER = LogManager.getLogger(ApiServlet.class);
    private static final Logger ACCESSLOGGER = LogManager.getLogger("apiserver." + ApiServlet.class.getName());
    private static final String REPLACEMENT = "_";
    private static final String LOGGER_REPLACEMENTS = "[\n\r\t]";
    private static final Pattern GET_REQUEST_COMMANDS = Pattern.compile("^(get|list|query|find)(\\w+)+$");
    private static final HashSet<String> GET_REQUEST_COMMANDS_LIST = new HashSet<>(Set.of("isaccountallowedtocreateofferingswithtags",
            "readyforshutdown", "cloudianisenabled", "quotabalance", "quotasummary", "quotatarifflist", "quotaisenabled", "quotastatement", "verifyoauthcodeandgetuser"));
    private static final HashSet<String> POST_REQUESTS_TO_DISABLE_LOGGING = new HashSet<>(Set.of(
            "login",
            "oauthlogin",
            "createaccount",
            "createuser",
            "updateuser",
            "forgotpassword",
            "resetpassword",
            "importrole",
            "updaterolepermission",
            "updateprojectrolepermission",
            "createstoragepool",
            "addhost",
            "updatehostpassword",
            "addcluster",
            "addvmwaredc",
            "configureoutofbandmanagement",
            "uploadcustomcertificate",
            "addciscovnmcresource",
            "addnetscalerloadbalancer",
            "createtungstenfabricprovider",
            "addnsxcontroller",
            "configtungstenfabricservice",
            "createnetworkacl",
            "updatenetworkaclitem",
            "quotavalidateactivationrule",
            "quotatariffupdate",
            "listandswitchsamlaccount",
            "uploadresourceicon"
    ));

    @Inject
    ApiServerService apiServer;
    @Inject
    AccountService accountMgr;
    @Inject
    EntityManager entityMgr;
    @Inject
    ManagedContext managedContext;
    @Inject
    APIAuthenticationManager authManager;
    @Inject
    private ProjectDao projectDao;

    public ApiServlet() {
    }

    @Override
    public void init(final ServletConfig config) throws ServletException {
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
    }

    @Override
    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) {
        processRequest(req, resp);
    }

    @Override
    protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) {
        processRequest(req, resp);
    }

    /**
     * For HTTP GET requests, it seems that HttpServletRequest.getParameterMap() actually tries
     * to unwrap URL encoded content from ISO-9959-1.
     * After failed in using setCharacterEncoding() to control it, end up with following hacking:
     * for all GET requests, we will override it with our-own way of UTF-8 based URL decoding.
     * @param req request containing parameters
     * @param params output of "our" map of parameters/values
     */
    void utf8Fixup(final HttpServletRequest req, final Map<String, Object[]> params) {
        if (req.getQueryString() == null) {
            return;
        }

        final String[] paramsInQueryString = req.getQueryString().split("&");
        if (paramsInQueryString != null) {
            for (final String param : paramsInQueryString) {
                final String[] paramTokens = param.split("=", 2);
                if (paramTokens.length == 2) {
                    String name = decodeUtf8(paramTokens[0]);
                    String value = decodeUtf8(paramTokens[1]);
                    params.put(name, new String[] {value});
                } else {
                    LOGGER.debug("Invalid parameter in URL found. param: " + param);
                }
            }
        }
    }

    private String decodeUtf8(final String value) {
        try {
            return URLDecoder.decode(value, "UTF-8");
        } catch (final UnsupportedEncodingException e) {
            //should never happen
            return null;
        }
    }

    private void processRequest(final HttpServletRequest req, final HttpServletResponse resp) {
        managedContext.runWithContext(new Runnable() {
            @Override
            public void run() {
                processRequestInContext(req, resp);
            }
        });
    }

    private void checkSingleQueryParameterValue(Map<String, String[]> params) {
        params.forEach((k, v) -> {
            if (v.length > 1) {
                String message = String.format("Query parameter '%s' has multiple values %s. Only the last value will be respected." +
                    "It is advised to pass only a single parameter", k, Arrays.toString(v));
                LOGGER.warn(message);
            }
        });
    }

    void processRequestInContext(final HttpServletRequest req, final HttpServletResponse resp) {
        InetAddress remoteAddress = null;
        try {
            remoteAddress = getClientAddress(req);
        } catch (UnknownHostException e) {
            LOGGER.warn("UnknownHostException when trying to lookup remote IP-Address. This should never happen. Blocking request.", e);
            final String response = apiServer.getSerializedApiError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                    "UnknownHostException when trying to lookup remote IP-Address", null,
                    HttpUtils.RESPONSE_TYPE_XML);
            HttpUtils.writeHttpResponse(resp, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                    HttpUtils.RESPONSE_TYPE_XML, ApiServer.JSONContentType.value());
            return;
        }

        final StringBuilder auditTrailSb = new StringBuilder(128);
        auditTrailSb.append(" ").append(remoteAddress.getHostAddress());
        auditTrailSb.append(" -- ").append(req.getMethod()).append(' ');
        // get the response format since we'll need it in a couple of places
        String responseType = HttpUtils.RESPONSE_TYPE_XML;
        final Map<String, Object[]> params = new HashMap<String, Object[]>();
        Map<String, String[]> reqParams = req.getParameterMap();
        checkSingleQueryParameterValue(reqParams);
        params.putAll(reqParams);

        utf8Fixup(req, params);

        final Object[] commandObj = params.get(ApiConstants.COMMAND);
        final String command = commandObj == null ? null : (String) commandObj[0];

        // logging the request start and end in management log for easy debugging
        String reqStr = "";
        String cleanQueryString = StringUtils.cleanString(req.getQueryString());
        if (LOGGER.isDebugEnabled()) {
            reqStr = auditTrailSb.toString() + " " + cleanQueryString;
            if (req.getMethod().equalsIgnoreCase("POST") && org.apache.commons.lang3.StringUtils.isNotBlank(command)) {
                if (!POST_REQUESTS_TO_DISABLE_LOGGING.contains(command.toLowerCase()) && !reqParams.containsKey(ApiConstants.USER_DATA)) {
                    String cleanParamsString = getCleanParamsString(reqParams);
                    if (org.apache.commons.lang3.StringUtils.isNotBlank(cleanParamsString)) {
                        reqStr += "\n" + cleanParamsString;
                    }
                } else {
                    reqStr += " " + command;
                }
            }
            LOGGER.debug("===START=== " + reqStr);
        }

        try {
            resp.setContentType(HttpUtils.XML_CONTENT_TYPE);

            HttpSession session = req.getSession(false);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace(String.format("session found: %s", session));
            }
            final Object[] responseTypeParam = params.get(ApiConstants.RESPONSE);
            if (responseTypeParam != null) {
                responseType = (String)responseTypeParam[0];
            }

            final Object[] userObj = params.get(ApiConstants.USERNAME);
            String username = userObj == null ? null : (String)userObj[0];
            if (LOGGER.isTraceEnabled()) {
                String logCommand = saveLogString(command);
                String logName = saveLogString(username);
                LOGGER.trace(String.format("command %s processing for user \"%s\"",
                        logCommand,
                        logName));
            }

            if (command != null && !command.equals(ValidateUserTwoFactorAuthenticationCodeCmd.APINAME)) {
                APIAuthenticator apiAuthenticator = authManager.getAPIAuthenticator(command);
                if (apiAuthenticator != null) {
                    auditTrailSb.append("command=");
                    auditTrailSb.append(command);

                    int httpResponseCode = HttpServletResponse.SC_OK;
                    String responseString = null;

                    if (apiAuthenticator.getAPIType() == APIAuthenticationType.LOGIN_API) {
                        if (session != null) {
                            invalidateHttpSession(session, "invalidating session for login call");
                        }
                        session = req.getSession(true);

                        if (ApiServer.EnableSecureSessionCookie.value()) {
                            resp.setHeader("SET-COOKIE", String.format("JSESSIONID=%s;Secure;HttpOnly;Path=/client", session.getId()));
                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug("Session cookie is marked secure!");
                            }
                        }
                    }

                    try {
                        if (LOGGER.isTraceEnabled()) {
                            LOGGER.trace(String.format("apiAuthenticator.authenticate(%s, params[%d], %s, %s, %s, %s, %s,%s)",
                                    saveLogString(command), params.size(), session.getId(), remoteAddress.getHostAddress(), saveLogString(responseType), "auditTrailSb", "req", "resp"));
                        }
                        responseString = apiAuthenticator.authenticate(command, params, session, remoteAddress, responseType, auditTrailSb, req, resp);
                        if (session != null && session.getAttribute(ApiConstants.SESSIONKEY) != null) {
                            String sameSite = getApiSessionKeySameSite();
                            resp.addHeader("SET-COOKIE", String.format("%s=%s;HttpOnly;%s", ApiConstants.SESSIONKEY, session.getAttribute(ApiConstants.SESSIONKEY), sameSite));
                        }
                    } catch (ServerApiException e) {
                        httpResponseCode = e.getErrorCode().getHttpCode();
                        responseString = e.getMessage();
                        if (!DefaultForgotPasswordAPIAuthenticatorCmd.APINAME.equalsIgnoreCase(command) || StringUtils.isNotBlank(username)) {
                            LOGGER.debug("Authentication failure: {}", e.getMessage());
                        }
                    }

                    if (apiAuthenticator.getAPIType() == APIAuthenticationType.LOGOUT_API) {
                        if (session == null) {
                            throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Session not found for the logout process.");
                        }

                        final Long userId = (Long) session.getAttribute("userid");
                        final Account account = (Account) session.getAttribute("accountobj");
                        Long accountId = null;
                        if (account != null) {
                            accountId = account.getId();
                        }
                        auditTrailSb.insert(0, "(userId=" + userId + " accountId=" + accountId + " sessionId=" + session.getId() + ")");
                        if (userId != null) {
                            apiServer.logoutUser(userId);
                        }
                        invalidateHttpSession(session, "invalidating session after logout call");

                        final Cookie[] cookies = req.getCookies();
                        if (cookies != null) {
                            for (final Cookie cookie : cookies) {
                                cookie.setValue("");
                                cookie.setMaxAge(0);
                                resp.addCookie(cookie);
                            }
                        }
                    }
                    HttpUtils.writeHttpResponse(resp, responseString, httpResponseCode, responseType, ApiServer.JSONContentType.value());
                    return;
                }
            } else {
                LOGGER.trace("no command available");
            }
            auditTrailSb.append(cleanQueryString);
            final boolean isNew = ((session == null) ? true : session.isNew());

            // Initialize an empty context and we will update it after we have verified the request below,
            // we no longer rely on web-session here, verifyRequest will populate user/account information
            // if a API key exists

            if (isNew && LOGGER.isTraceEnabled()) {
                LOGGER.trace(String.format("new session: %s", session));
            }

            if (!isNew && (command.equalsIgnoreCase(ValidateUserTwoFactorAuthenticationCodeCmd.APINAME) || (!skip2FAcheckForAPIs(command) && !skip2FAcheckForUser(session)))) {
                LOGGER.debug("Verifying two factor authentication");
                boolean success = verify2FA(session, command, auditTrailSb, params, remoteAddress, responseType, req, resp);
                if (!success) {
                    LOGGER.debug("Verification of two factor authentication failed");
                    return;
                }
            }

            if (apiServer.isPostRequestsAndTimestampsEnforced() && !isStateChangingCommandUsingPOST(command, req.getMethod(), params)) {
                String errorText = String.format("State changing command %s needs to be sent using POST request", command);
                if (command.equalsIgnoreCase("updateConfiguration") && params.containsKey("name")) {
                    errorText = String.format("Changes for configuration %s needs to be sent using POST request", params.get("name")[0]);
                }
                auditTrailSb.append(" " + HttpServletResponse.SC_BAD_REQUEST + " " + errorText);
                final String serializedResponse =
                        apiServer.getSerializedApiError(new ServerApiException(ApiErrorCode.BAD_REQUEST, errorText), params,
                                responseType);
                HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_BAD_REQUEST, responseType, ApiServer.JSONContentType.value());
                return;
            }

            Long userId = null;
            if (!isNew) {
                userId = (Long)session.getAttribute("userid");
                final String account = (String) session.getAttribute("account");
                final Object accountObj = session.getAttribute("accountobj");
                if (account != null) {
                    if (invalidateHttpSessionIfNeeded(req, resp, auditTrailSb, responseType, params, session, account)) return;
                } else {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("no account, this request will be validated through apikey(%s)/signature");
                    }
                }

                if (!requestChecksoutAsSane(resp, auditTrailSb, responseType, params, session, command, userId, account, accountObj))
                    return;
            } else {
                CallContext.register(accountMgr.getSystemUser(), accountMgr.getSystemAccount());
            }
            setProjectContext(params);
            setGuiThemeParameterIfApiCallIsUnauthenticated(userId, command, req, params);

            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace(String.format("verifying request for user %s from %s with %d parameters",
                        userId, remoteAddress.getHostAddress(), params.size()));
            }
            if (apiServer.verifyRequest(params, userId, remoteAddress)) {
                auditTrailSb.insert(0, "(userId=" + CallContext.current().getCallingUserId() + " accountId=" + CallContext.current().getCallingAccount().getId() +
                        " sessionId=" + (session != null ? session.getId() : null) + ")");

                // Add the HTTP method (GET/POST/PUT/DELETE) as well into the params map.
                params.put("httpmethod", new String[]{req.getMethod()});
                setProjectContext(params);
                setClientAddressForConsoleEndpointAccess(command, params, req);
                final String response = apiServer.handleRequest(params, responseType, auditTrailSb);
                HttpUtils.writeHttpResponse(resp, response != null ? response : "", HttpServletResponse.SC_OK, responseType, ApiServer.JSONContentType.value());
            } else {
                if (session != null) {
                    invalidateHttpSession(session, String.format("request verification failed for %s from %s", userId, remoteAddress.getHostAddress()));
                }

                auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user credentials and/or request signature");
                final String serializedResponse =
                        apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to verify user credentials and/or request signature", params,
                                responseType);
                HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType, ApiServer.JSONContentType.value());
            }
        } catch (final ServerApiException se) {
            final String serializedResponseText = apiServer.getSerializedApiError(se, params, responseType);
            resp.setHeader("X-Description", se.getDescription());
            HttpUtils.writeHttpResponse(resp, serializedResponseText, se.getErrorCode().getHttpCode(), responseType, ApiServer.JSONContentType.value());
            auditTrailSb.append(" " + se.getErrorCode() + " " + se.getDescription());
        } catch (final Exception ex) {
            LOGGER.error("unknown exception writing api response", ex);
            auditTrailSb.append(" unknown exception writing api response");
        } finally {
            ACCESSLOGGER.info(auditTrailSb.toString());
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("===END=== " + reqStr);
            }
            // cleanup user context to prevent from being peeked in other request context
            CallContext.unregister();
        }
    }

    public static String getApiSessionKeySameSite() {
        ApiSessionKeySameSite sameSite = EnumUtils.getEnumIgnoreCase(ApiSessionKeySameSite.class,
                ApiServer.ApiSessionKeyCookieSameSiteSetting.value(), ApiSessionKeySameSite.Lax);
        switch (sameSite) {
            case Strict:
                return "SameSite=Strict";
            case NoneAndSecure:
                return "SameSite=None;Secure";
            case Null:
                return "";
            case Lax:
            default:
                return "SameSite=Lax";
        }
    }

    private void setGuiThemeParameterIfApiCallIsUnauthenticated(Long userId, String command, HttpServletRequest req, Map<String, Object[]> params) {
        String listGuiThemesApiName = ListGuiThemesCmd.class.getAnnotation(APICommand.class).name();

        if (userId != null || !listGuiThemesApiName.equalsIgnoreCase(command)) {
            return;
        }

        String serverName = req.getServerName();
        LOGGER.info("Unauthenticated call to {} API, thus, the `commonName` parameter will be inferred as {}.", listGuiThemesApiName, serverName);
        params.put(ApiConstants.COMMON_NAME, new String[]{serverName});
    }


    private boolean checkIfAuthenticatorIsOf2FA(String command) {
        boolean verify2FA = false;
        APIAuthenticator apiAuthenticator = authManager.getAPIAuthenticator(command);
        if (apiAuthenticator != null && apiAuthenticator.getAPIType().equals(APIAuthenticationType.LOGIN_2FA_API)) {
            verify2FA = true;
        } else {
            verify2FA = false;
        }
        return verify2FA;
    }

    private boolean isStateChangingCommandUsingPOST(String command, String method, Map<String, Object[]> params) {
        if (command == null || (!GET_REQUEST_COMMANDS.matcher(command.toLowerCase()).matches() && !GET_REQUEST_COMMANDS_LIST.contains(command.toLowerCase())
                && !command.equalsIgnoreCase("updateConfiguration") && !method.equals("POST"))) {
            return false;
        }
        return !command.equalsIgnoreCase("updateConfiguration") || method.equals("POST") || (params.containsKey("name")
                && params.get("name")[0].toString().equalsIgnoreCase(ApiServer.EnforcePostRequestsAndTimestamps.key()));
    }

    protected boolean skip2FAcheckForAPIs(String command) {
        boolean skip2FAcheck = false;

        if (command.equalsIgnoreCase(ApiConstants.LIST_IDPS)
                || command.equalsIgnoreCase(ApiConstants.LIST_APIS)
                || command.equalsIgnoreCase(ListUserTwoFactorAuthenticatorProvidersCmd.APINAME)
                || command.equalsIgnoreCase(SetupUserTwoFactorAuthenticationCmd.APINAME)) {
            skip2FAcheck = true;
        }
        return skip2FAcheck;
    }

    protected boolean skip2FAcheckForUser(HttpSession session) {
        boolean skip2FAcheck = false;
        Long userId = (Long) session.getAttribute("userid");
        boolean is2FAverified = (boolean) session.getAttribute(ApiConstants.IS_2FA_VERIFIED);
        if (is2FAverified) {
            LOGGER.debug(String.format("Two factor authentication is already verified for the user %d, so skipping", userId));
            skip2FAcheck = true;
        } else {
            UserAccount userAccount = accountMgr.getUserAccountById(userId);
            boolean is2FAenabled = userAccount.isUser2faEnabled();
            if (is2FAenabled) {
                skip2FAcheck = false;
            } else {
                Long domainId = userAccount.getDomainId();
                boolean is2FAmandated = Boolean.TRUE.equals(AccountManagerImpl.enableUserTwoFactorAuthentication.valueIn(domainId)) && Boolean.TRUE.equals(AccountManagerImpl.mandateUserTwoFactorAuthentication.valueIn(domainId));
                if (is2FAmandated) {
                    skip2FAcheck = false;
                } else {
                    skip2FAcheck = true;
                }
            }
        }
        return skip2FAcheck;
    }

    protected boolean verify2FA(HttpSession session, String command, StringBuilder auditTrailSb, Map<String, Object[]> params,
                                InetAddress remoteAddress, String responseType, HttpServletRequest req, HttpServletResponse resp) {
        boolean verify2FA = false;
        if (command.equals(ValidateUserTwoFactorAuthenticationCodeCmd.APINAME)) {
            APIAuthenticator apiAuthenticator = authManager.getAPIAuthenticator(command);
            if (apiAuthenticator != null) {
                String responseString = apiAuthenticator.authenticate(command, params, session, remoteAddress, responseType, auditTrailSb, req, resp);
                session.setAttribute(ApiConstants.IS_2FA_VERIFIED, true);
                HttpUtils.writeHttpResponse(resp, responseString, HttpServletResponse.SC_OK, responseType, ApiServer.JSONContentType.value());
                verify2FA = true;
            } else {
                LOGGER.error("Cannot find API authenticator while verifying 2FA");
                auditTrailSb.append(" Cannot find API authenticator while verifying 2FA");
                verify2FA = false;
            }
        } else {
            // invalidate the session
            Long userId = (Long) session.getAttribute("userid");
            UserAccount userAccount = accountMgr.getUserAccountById(userId);
            boolean is2FAenabled = userAccount.isUser2faEnabled();
            String keyFor2fa = userAccount.getKeyFor2fa();
            String providerFor2fa = userAccount.getUser2faProvider();
            String errorMsg;
            if (is2FAenabled) {
                if (org.apache.commons.lang3.StringUtils.isEmpty(keyFor2fa) || org.apache.commons.lang3.StringUtils.isEmpty(providerFor2fa)) {
                    errorMsg = "Two factor authentication is mandated by admin, user needs to setup 2FA using setupUserTwoFactorAuthentication API and" +
                            " then verify 2FA using validateUserTwoFactorAuthenticationCode API before calling other APIs. Existing session is invalidated.";
                } else {
                    errorMsg = "Two factor authentication 2FA is enabled but not verified, please verify 2FA using validateUserTwoFactorAuthenticationCode API before calling other APIs. Existing session is invalidated.";
                }
            } else {
                // when (is2FAmandated) is true
                errorMsg = "Two factor authentication is mandated by admin, user needs to setup 2FA using setupUserTwoFactorAuthentication API and" +
                        " then verify 2FA using validateUserTwoFactorAuthenticationCode API before calling other APIs. Existing session is invalidated.";
            }
            LOGGER.error(errorMsg);

            invalidateHttpSession(session, String.format("Unable to process the API request for %s from %s due to %s", userId, remoteAddress.getHostAddress(), errorMsg));
            auditTrailSb.append(" " + ApiErrorCode.UNAUTHORIZED2FA + " " + errorMsg);
            final String serializedResponse = apiServer.getSerializedApiError(ApiErrorCode.UNAUTHORIZED2FA.getHttpCode(), "Unable to process the API request due to :" + errorMsg, params, responseType);
            HttpUtils.writeHttpResponse(resp, serializedResponse, ApiErrorCode.UNAUTHORIZED2FA.getHttpCode(), responseType, ApiServer.JSONContentType.value());
            verify2FA = false;
        }

        return verify2FA;
    }
    protected void setClientAddressForConsoleEndpointAccess(String command, Map<String, Object[]> params, HttpServletRequest req) throws UnknownHostException {
        if (org.apache.commons.lang3.StringUtils.isNotBlank(command) &&
                command.equalsIgnoreCase(BaseCmd.getCommandNameByClass(CreateConsoleEndpointCmd.class))) {
            InetAddress addr = getClientAddress(req);
            String clientAddress = addr != null ? addr.getHostAddress() : null;
            params.put(ConsoleAccessUtils.CLIENT_INET_ADDRESS_KEY, new String[] {clientAddress});
        }
    }

    @Nullable
    private String saveLogString(String stringToLog) {
        return stringToLog == null ? null : stringToLog.replace(LOGGER_REPLACEMENTS, REPLACEMENT);
    }

    /**
     * Do a sanity check here to make sure the user hasn't already been deleted
     */
    private boolean requestChecksoutAsSane(HttpServletResponse resp, StringBuilder auditTrailSb, String responseType, Map<String, Object[]> params, HttpSession session, String command, Long userId, String account, Object accountObj) {
        if ((userId != null) && (account != null) && (accountObj != null) && apiServer.verifyUser(userId)) {
            if (command == null) {
                LOGGER.info("missing command, ignoring request...");
                auditTrailSb.append(" " + HttpServletResponse.SC_BAD_REQUEST + " " + "no command specified");
                final String serializedResponse = apiServer.getSerializedApiError(HttpServletResponse.SC_BAD_REQUEST, "no command specified", params, responseType);
                HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_BAD_REQUEST, responseType, ApiServer.JSONContentType.value());
                return true;
            }
            final User user = entityMgr.findById(User.class, userId);
            CallContext.register(user, (Account) accountObj);
        } else {
            invalidateHttpSession(session, "Invalidate the session to ensure we won't allow a request across management server restarts if the userId was serialized to the stored session");

            auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user credentials");
            final String serializedResponse =
                    apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to verify user credentials", params, responseType);
            HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType, ApiServer.JSONContentType.value());
            return false;
        }
        return true;
    }

    private boolean invalidateHttpSessionIfNeeded(HttpServletRequest req, HttpServletResponse resp, StringBuilder auditTrailSb, String responseType, Map<String, Object[]> params, HttpSession session, String account) {
        ApiSessionKeyCheckOption sessionKeyCheckOption = EnumUtils.getEnumIgnoreCase(ApiSessionKeyCheckOption.class,
                ApiServer.ApiSessionKeyCheckLocations.value(), ApiSessionKeyCheckOption.CookieAndParameter);
        if (!HttpUtils.validateSessionKey(session, params, req.getCookies(), ApiConstants.SESSIONKEY, sessionKeyCheckOption)) {
            String msg = String.format("invalidating session %s for account %s", session.getId(), account);
            invalidateHttpSession(session, msg);
            auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user credentials");
            final String serializedResponse =
                    apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to verify user credentials", params, responseType);
            HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED, responseType, ApiServer.JSONContentType.value());
            return true;
        }
        return false;
    }

    public static void invalidateHttpSession(HttpSession session, String msg) {
        try {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace(msg);
            }
            if (session == null) {
                return;
            }
            session.invalidate();
        } catch (final IllegalStateException ise) {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace(String.format("failed to invalidate session %s", session.getId()));
            }
        }
    }

    private void setProjectContext(Map<String, Object[]> requestParameters) {
        final String[] command = (String[])requestParameters.get(ApiConstants.COMMAND);
        if (command == null) {
            LOGGER.info("missing command, ignoring request...");
            return;
        }

        final String commandName = command[0];
        CallContext.current().setApiName(commandName);
        for (Map.Entry<String, Object[]> entry: requestParameters.entrySet()) {
            if (entry.getKey().equals(ApiConstants.PROJECT_ID) || isSpecificAPI(commandName)) {
                String projectId = null;
                if (isSpecificAPI(commandName)) {
                    projectId = String.valueOf(requestParameters.entrySet().stream()
                            .filter(e -> e.getKey().equals(ApiConstants.ID))
                            .map(Map.Entry::getValue).findFirst().get()[0]);
                } else {
                    projectId = String.valueOf(entry.getValue()[0]);
                }
                Project project = projectDao.findByUuid(projectId);
                if (project != null) {
                    CallContext.current().setProject(project);
                }
            }
        }
    }

    private boolean isSpecificAPI(String commandName) {
        List<String> commands = Arrays.asList("suspendProject", "updateProject", "activateProject", "deleteProject");
        if (commands.contains(commandName)) {
            return true;
        }
        return false;
    }
    static boolean doUseForwardHeaders() {
        return Boolean.TRUE.equals(ApiServer.useForwardHeader.value());
    }

    static String[] proxyNets() {
        return ApiServer.proxyForwardList.value().split(",");
    }
    //This method will try to get login IP of user even if servlet is behind reverseProxy or loadBalancer
    public static InetAddress getClientAddress(final HttpServletRequest request) throws UnknownHostException {
        final String remote = request.getRemoteAddr();
        if (doUseForwardHeaders()) {
            final InetAddress remoteAddr = InetAddress.getByName(remote);
            if (NetUtils.isIpInCidrList(remoteAddr, proxyNets())) {
                for (String header : getClientAddressHeaders()) {
                    header = header.trim();
                    final String ip = getCorrectIPAddress(request.getHeader(header));
                    if (StringUtils.isNotBlank(ip)) {
                        LOGGER.debug("found ip {} in header {}", ip, header);
                        return InetAddress.getByName(ip);
                    }
                }
            }
        }
        LOGGER.trace("no ip found in headers, returning remote address {}.", remote);
        return InetAddress.getByName(remote);
    }

    private static String[] getClientAddressHeaders() {
        return ApiServer.listOfForwardHeaders.value().split(",");
    }

    private static String getCorrectIPAddress(String ip) {
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            return null;
        }
        if(NetUtils.isValidIp4(ip) || NetUtils.isValidIp6(ip)) {
            return ip;
        }
        //it could be possible to have multiple IPs in HTTP header, this happens if there are multiple proxy in between
        //the client and the servlet, so parse the client IP
        String[] ips = ip.split(",");
        for(String i : ips) {
            if(NetUtils.isValidIp4(i.trim()) || NetUtils.isValidIp6(i.trim())) {
                return i.trim();
            }
        }
        return null;
    }

    private String getCleanParamsString(Map<String, String[]> reqParams) {
        if (MapUtils.isEmpty(reqParams)) {
            return "";
        }

        StringBuilder cleanParamsString = new StringBuilder();
        for (Map.Entry<String, String[]> reqParam : reqParams.entrySet()) {
            if (org.apache.commons.lang3.StringUtils.isBlank(reqParam.getKey())) {
                continue;
            }

            cleanParamsString.append(reqParam.getKey());
            cleanParamsString.append("=");

            if (reqParam.getKey().toLowerCase().contains("password")
                    || reqParam.getKey().toLowerCase().contains("privatekey")
                    || reqParam.getKey().toLowerCase().contains("accesskey")
                    || reqParam.getKey().toLowerCase().contains("secretkey")) {
                cleanParamsString.append("\n");
                continue;
            }

            if (reqParam.getValue() == null || reqParam.getValue().length == 0) {
                cleanParamsString.append("\n");
                continue;
            }

            for (String param : reqParam.getValue()) {
                if (org.apache.commons.lang3.StringUtils.isBlank(param)) {
                    continue;
                }
                String cleanParamString = StringUtils.cleanString(param.trim());
                cleanParamsString.append(cleanParamString);
                cleanParamsString.append(" ");
            }
            cleanParamsString.append("\n");
        }

        return cleanParamsString.toString();
    }
}
