All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.networknt.soap.SoapSecurityTransformAction Maven / Gradle / Ivy

Go to download

A yaml rule action implementation to inject a soap security section on the light-gateway to access Cannex API in the request transform interceptor.

The newest version!
package com.networknt.soap;

import com.networknt.rule.IAction;
import com.networknt.rule.RuleActionValue;
import com.networknt.rule.RuleConstants;
import com.networknt.config.Config;
import com.networknt.utility.ModuleRegistry;
import java.nio.charset.StandardCharsets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Transform a soap request to call the external service with a security section with username, password, nonce and
 * timestamp. The original request body, username and password will be passed from the yaml rule instead of hardcoded
 * in the action class here.
 *
 * We don't want to introduce some third party XML library to manipulate the request body to inject the security section,
 * so only regex replacement is used. It depends on the original request body has a string soap:Header to be matched.
 *
 * Please be aware that we are dealing with XML content here instead of JSON.
 *
 * @author Steve Hu
 */
public class SoapSecurityTransformAction implements IAction {
    private static final String CONFIG_NAME = "cannex";
    private static final String USERNAME = "username";
    private static final String PASSWORD = "password";
    private static final Logger logger = LoggerFactory.getLogger(SoapSecurityTransformAction.class);
    private static final Map config = Config.getInstance().getJsonMapConfigNoCache(CONFIG_NAME);
    String pattern = "(.*?)";

    public SoapSecurityTransformAction() {
        if(logger.isInfoEnabled()) logger.info("SoapSecurityTransformAction is constructed.");
        List masks = new ArrayList<>();
        masks.add("password");
        ModuleRegistry.registerPlugin(
                SoapSecurityTransformAction.class.getPackage().getImplementationTitle(),
                SoapSecurityTransformAction.class.getPackage().getImplementationVersion(),
                "cannex",
                SoapSecurityTransformAction.class.getName(),
                Config.getNoneDecryptedInstance().getJsonMapConfigNoCache(CONFIG_NAME),
                masks);
    }

    @Override
    public void performAction(Map objMap, Map resultMap, Collection actionValues) {
        // get the body from the objMap and create a new body in the resultMap. Both in string format.
        resultMap.put(RuleConstants.RESULT, true);
        String requestBody = (String)objMap.get("requestBody");
        String username = (String)config.get(USERNAME);
        String password = (String)config.get(PASSWORD);
        if(logger.isTraceEnabled()) logger.debug("username = " + username + " password = " + password + " original request body = " + requestBody);
        String modifiedBody = transform(requestBody, username, password);
        if(logger.isTraceEnabled()) logger.trace("transformed request body = " + modifiedBody);
        resultMap.put("requestBody", modifiedBody);
    }

    private String transform(String requestBody, String username, String password) {
        // the source input is a string of XML, we will replace the header with security with regex.
        String output = requestBody.replaceAll(pattern, "" + generateSecurity(username, password) + "");
        return output;
    }

    private String generateSecurity(String username, String password) {
        String nonce = generateNonce();
        if(logger.isTraceEnabled()) logger.trace("Nonce = " + nonce);
        System.out.println("Nonce = " + nonce);

        // created date/time in UTC format
        DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date today = Calendar.getInstance().getTime();
        String created = dateFormatter.format(today);
        if(logger.isTraceEnabled()) logger.trace("Created = " + created);

        // generate the password digest from the nonce + created + fixed password
        String passwordDigest = createPasswordDigest(nonce, created, password);
        if(logger.isTraceEnabled()) logger.trace("Password Digest = " + passwordDigest);

        // SOAP header security section.
        String security =
                "   \n"
                + "      \n"
                + "         %Username%\n"
                + "         %PasswordDigest%\n"
                + "         %Nonce%\n"
                + "         %Created%\n"
                + "      \n"
                + "   \n";


        security = security.replaceAll("%Username%", username);
        security = security.replaceAll("%PasswordDigest%", passwordDigest);
        security = security.replaceAll("%Nonce%", nonce);
        security = security.replaceAll("%Created%", created);
        return security;
    }

    private String createPasswordDigest(String nonce, String created, String password) {
        MessageDigest sha1;
        String passwordDigest = null;
        try {
            sha1 = MessageDigest.getInstance("SHA-1");
            sha1.update(Base64.getDecoder().decode(nonce));
            sha1.update(created.getBytes("UTF-8"));
            passwordDigest = new String(Base64.getEncoder().encode(sha1.digest(password.getBytes("UTF-8"))));
            sha1.reset();
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            logger.error("Exception: ", e);
        }
        return passwordDigest;
    }

    private String generateNonce() {
        String dateTimeString = Long.toString(new Date().getTime());
        byte[] nonceByte = dateTimeString.getBytes(StandardCharsets.UTF_8);
        return Base64.getEncoder().encodeToString(nonceByte);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy