Javascript-Beispiel für Absicherung eines Requests mittels STS Token

Wie in meinem Artikel angekündigt hier also ein Codebeispiel für die Absicherung eines REST Requests zum Anlegen einer Area mittels eines STS Token:

function newArea() {
  var areaName;
  var areaNameLbl;
  var areaNameTxt;
  var body;
  var bodyHash;

  var date;
  var header;
  var request;
  var requestHash;
  var signature;
  var signatureKey;
  var shaObj;
  var stringToSign;
  
  var now = new Date(); 

  var day = now.getDate() < 10 ? '0' + now.getDate() : now.getDate();
  var mon = now.getMonth() < 9 ? '0' + (now.getMonth()+1) : (now.getMonth()+1);
  var year = now.getFullYear();
  var hour = now.getUTCHours() < 10 ? '0' + now.getUTCHours() : now.getUTCHours();
  var min = now.getMinutes() < 10 ? '0' + now.getMinutes() : now.getMinutes();
  var sec = now.getSeconds() < 10 ? '0' + now.getSeconds() : now.getSeconds();
  
  var date = year+mon+day
  var datetime = date + "T" + hour + min + sec + "Z";

  formObject  = document.forms['new-area-form'];
  
  areaNameTxt = formObject.elements['new-area-area-name-text'];

  areaNameLbl = document.getElementById('new-area-area-name-label');

  areaName    = areaNameTxt.value;
  
  if (!areaName || areaName.length < 6) {
    areaNameLbl.innerHTML = 'Der Areaname muss mindestens 6 Zeichen lang sein';
    areaNameLbl.style.color = '#FF0000';
    areaNameTxt.focus();
    
    return;
  }

  sessionStorage.setItem ('areaName', areaName);
  
  console.log('add new area [' + areaName + ']');

  // der Body ist der Content den es abzusichern gilt
  body = '{"atos":[{"id":null, "name":"' + areaName + '", "folder":null, "number":0, "size":0, "date":null, "version":null}]}';
  
  shaObj = new jsSHA("SHA-256", "TEXT");
  shaObj.update(body);
  bodyHash = shaObj.getHash("HEX");

  request = 'POST\n' +
        '/prd/content/area\n' +
        '\n' +
        'content-type:application/json; charset=utf-8\n' +
        'host:a4sbwzghm9.execute-api.eu-central-1.amazonaws.com\n' +
        'x-amz-date:' + datetime + '\n' +
        '\n' +
        'content-type;host;x-amz-date\n' +
        bodyHash;
  
  shaObj = new jsSHA("SHA-256", "TEXT");
  shaObj.update(request);
  requestHash = shaObj.getHash("HEX");

  stringToSign = 'AWS4-HMAC-SHA256\n' + datetime + '\n' + date + '/eu-central-1/execute-api/aws4_request\n' + requestHash;

  signatureKey = getSignatureKey(secretAccessKey, date, "eu-central-1", "execute-api");

  shaObj = new jsSHA("SHA-256", "TEXT");
  shaObj.setHMACKey(signatureKey, "HEX");
  shaObj.update(stringToSign);
  signature = shaObj.getHMAC("HEX");
  
  header = 'AWS4-HMAC-SHA256 Credential=' + accessKeyID + '/' + date + '/eu-central-1/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=' + signature;

  $.ajax({
    async: false,
    data: body,
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    error: function(xhr, status, error) {
      alert(status);
    },
    headers: {
      'authorization':header,
      'content-type':'application/json; charset=utf-8',
      'x-amz-date':datetime,
      'x-amz-security-token':sessionToken
    },  
    success: function(data, status, xhr){
      if (xhr.status == 200) {
        $.mobile.changePage('#new-area-dialog', 'pop', true, true);
      }
    },
    type: 'POST',
    url: srvURL + '/area'
  });
}


function getSignatureKey(secretAccessKey, date, region, service) {
  var kDate;
  var kRegion;
  var kService;
  var kSigning;
  var shaObj;
  
  
  shaObj = new jsSHA("SHA-256", "TEXT");
  shaObj.setHMACKey("AWS4" + secretAccessKey, "TEXT");
  shaObj.update(date);
  kDate = shaObj.getHMAC("HEX")
  
  shaObj = new jsSHA("SHA-256", "TEXT");
  shaObj.setHMACKey(kDate, "HEX");
  shaObj.update(region);
  kRegion = shaObj.getHMAC("HEX")

  shaObj = new jsSHA("SHA-256", "TEXT");
  shaObj.setHMACKey(kRegion, "HEX");
  shaObj.update(service);
  kService = shaObj.getHMAC("HEX")

  shaObj = new jsSHA("SHA-256", "TEXT");
  shaObj.setHMACKey(kService, "HEX");
  shaObj.update("aws4_request");
  kSigning = shaObj.getHMAC("HEX")

  return kSigning;
}

Importclient für DynamoDB

Der erste Teil meiner Artikelserie zu AWS Lambda ist nun im Jaxenter erschienen unter Spring-Boot vs. AWS Lambda. In diesem Artikel habe ich auch einen Client für den Import von Jason basierten Datensätzen für die Area sowie die Pictures angesprochen. Im Grund möchte ich in meine DynamoDB die folgenden Datensätze importieren:

Areas:

[
{"id":"1", "name":"Architektur", "folder":"0100000000000000000", "number":50, "size":6422, "date":"2016-01-01T12:00:00.000Z", "version":1},
{"id":"2", "name":"Audio", "folder":"0200000000000000000", "number":17, "size":1655, "date":"2016-01-01T12:00:00.000Z", "version":1},
{"id":"3", "name":"Auto", "folder":"0300000000000000000", "number":70, "size":8459, "date":"2016-01-01T12:00:00.000Z", "version":1},
usw.

Pictures:

[
{"id":"1", "areaId":"1", "name":"5878385598646124113", "size":112, "date":"2012-10-11T12:00:00.000Z", "version":1},
{"id":"2", "areaId":"1", "name":"7655519180858176879", "size":109, "date":"2012-10-11T12:00:00.000Z", "version":1},
{"id":"3", "areaId":"1", "name":"8086031961797504572", "size":98, "date":"2012-10-11T12:00:00.000Z", "version":1},

Der zugehörige Code sieht dann wie folgt aus:

package com.axxessio.axx2sls.content;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import org.junit.Test;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class LoadDB {

    @Test
    public void test() throws JsonParseException, IOException {
    Table table;
    JsonParser parser;
    JsonNode rootNode;

    
    AmazonDynamoDBClient client = new AmazonDynamoDBClient().withEndpoint("https://dynamodb.eu-central-1.amazonaws.com");
    DynamoDB dynamoDB = new DynamoDB(client);

    table = dynamoDB.getTable("area");

    parser = new JsonFactory().createParser(new File("./src/main/resources/areas.json"));
    
    rootNode = new ObjectMapper().readTree(parser);

    loadTable (rootNode, table);
    
    parser.close();    

    table = dynamoDB.getTable("picture");

    parser = new JsonFactory().createParser(new File("./src/main/resources/pictures.json"));
    
    rootNode = new ObjectMapper().readTree(parser);

    loadTable (rootNode, table);
    
    parser.close();
  }

  private void loadTable (JsonNode rootNode, Table table) {
    Iterator iter = rootNode.iterator();

    ObjectNode currentNode;

    while (iter.hasNext()) {
      currentNode = (ObjectNode) iter.next();

      String id = currentNode.path("id").asText();

      try {
        table.putItem(Item.fromJSON(currentNode.toString()).withPrimaryKey("id", id));
        System.out.println("PutItem succeeded [" + id + "] into table [" + table.getTableName() + "]");

      } catch (Exception e) {
        System.err.println("Unable to add data set [" + id + "] into table [" + table.getTableName() + "]");
        System.err.println(e.getMessage());
        break;
      }
    }
  }
}