"Signature not yet current" in AWS signature 4 - WSO2 class mediator

201 Views Asked by At

I am currently trying to list all users using AWS IAM api and facing some difficulties. When after invoking the API through the WSO2 micro integrator it shows following error,

XML Response from AWS

I have set the time zone to UTC in the deployed docker pod. To generate the signature I had to implement a custom class mediator and used the AWS recommended java implementation to generate the key.

package test;

import java.util.Calendar;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class IamConfigMediator extends AbstractMediator {

    private static final String ACCESS_KEY = "XXXX";
    private static final String SECRET_KEY = "XXXXXX";
    private static final String region = "us-east-1";
    private static final String serviceName = "iam";
    private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
    
    
    public boolean mediate(MessageContext context) {
        log.info("[IamConfigMediator] Generating SIGNATURE_HEADER and EXPIRE_TIME ##############################");
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.HOUR_OF_DAY, 24);
        long time = cal.getTimeInMillis();
        String expireTime = formatTimestamp(time);
    
        context.setProperty("EXPIRE_TIME", expireTime);
    
        try {
            byte[] signature = getSignatureKey(SECRET_KEY, expireTime, region, serviceName);
            String header = "AWS4-HMAC-SHA256 Credential=" + ACCESS_KEY + "/" + expireTime + "/" + region + "/" + serviceName + "/aws4_request, SignedHeaders=host;x-amz-date, Signature=" + bytesToHex(signature);
            context.setProperty("SIGNATURE_HEADER", header);
        } catch (Exception e) {
            e.printStackTrace();
        }
    
        return true;
    }
    
    static byte[] HmacSHA256(String data, byte[] key) throws Exception {
        String algorithm = "HmacSHA256";
        Mac mac = Mac.getInstance(algorithm);
        mac.init(new SecretKeySpec(key, algorithm));
        return mac.doFinal(data.getBytes("UTF-8"));
    }
    
    static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception {
        byte[] kSecret = ("AWS4" + key).getBytes("UTF-8");
        byte[] kDate = HmacSHA256(dateStamp, kSecret);
        byte[] kRegion = HmacSHA256(regionName, kDate);
        byte[] kService = HmacSHA256(serviceName, kRegion);
        byte[] kSigning = HmacSHA256("aws4_request", kService);
        return kSigning;
    }
    
    private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }
        return new String(hexChars);
    }
    
    private static final DateTimeFormatter dateFormatter = DateTimeFormat
        .forPattern("yyyyMMdd").withZoneUTC();
    
    private static final DateTimeFormatter timeFormatter = DateTimeFormat
        .forPattern("yyyyMMdd'T'HHmmss'Z'").withZoneUTC();
    
    public static String formatTimestamp(long timeMilli) {
        return timeFormatter.print(timeMilli);
    }

}

Above implementation was used to generate the signature header("SIGNATURE_HEADER").

0

There are 0 best solutions below