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

io.warp10.quasar.encoder.QuasarTokenEncoder Maven / Gradle / Ivy

There is a newer version: 3.4.1
Show newest version
//
//   Copyright 2018-2023  SenX S.A.S.
//
//   Licensed 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 io.warp10.quasar.encoder;

import org.apache.thrift.TBase;
import org.apache.thrift.TException;
import org.apache.thrift.TSerializer;
import org.apache.thrift.protocol.TCompactProtocol;
import org.bouncycastle.util.encoders.Hex;

import io.warp10.crypto.CryptoUtils;
import io.warp10.crypto.KeyStore;
import io.warp10.crypto.OrderPreservingBase64;
import io.warp10.crypto.SipHashInline;
import io.warp10.quasar.token.thrift.data.ReadToken;
import io.warp10.quasar.token.thrift.data.TokenType;
import io.warp10.quasar.token.thrift.data.WriteToken;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class QuasarTokenEncoder {

  public String deliverReadToken(String appName, String producerUID, String ownerUID, List apps, long ttl, KeyStore keystore) throws TException {
    ReadToken token = getReadToken(appName, producerUID, Arrays.asList(ownerUID), null, apps, null, null, ttl);
    return cypherToken(token, keystore);
  }

  public String deliverReadToken(String appName, String producerUID, String ownerUID, List apps, Map labels, long ttl, KeyStore keystore) throws TException {
    ReadToken token = getReadToken(appName, producerUID, Arrays.asList(ownerUID), null, apps, labels, null, ttl);
    return cypherToken(token, keystore);
  }

  public String deliverReadToken(String appName, String producerUID, List owners, List apps, Map hooks, long ttl, KeyStore keystore) throws TException {
    ReadToken token = getReadToken(appName, producerUID, owners, null, apps, null, hooks, ttl);
    return cypherToken(token, keystore);
  }

  public String deliverReadToken(String appName, String producerUID, List owners, List apps,  Map labels, Map hooks, long ttl, KeyStore keystore) throws TException {
    ReadToken token = getReadToken(appName, producerUID, owners, null, apps, labels, hooks, ttl);
    return cypherToken(token, keystore);
  }

  public String deliverReadToken(String appName, String producerUID, List owners, List producers, List apps,  Map labels, Map hooks, long ttl, KeyStore keystore) throws TException {
    ReadToken token = getReadToken(appName, producerUID, owners, producers, apps, labels, hooks, ttl);
    return cypherToken(token, keystore);
  }

  /**
   * @param appName     this token belongs to this application
   * @param producerUID this token belongs to this producer
   * @param owners      this token can access time series owned to these owners
   * @param producers   this token can access time series pushed by these producers
   * @param apps        this token can access time series stored in these applications
   * @param labels      this token can access time series with the given labels
   * @param hooks       tokens Warpscript hooks
   * @param ttl         Time to live (ms)
   * @return ReadToken thrift structure
   * @throws TException
   */
  public ReadToken getReadToken(String appName, String producerUID, List owners, List producers, List apps,  Map labels, Map hooks, long ttl) throws TException {
    long currentTime = System.currentTimeMillis();

    // Generate the READ Tokens
    ReadToken token = new ReadToken();
    token.setAppName(appName);
    token.setIssuanceTimestamp(currentTime);
    token.setExpiryTimestamp(currentTime + ttl);
    token.setTokenType(TokenType.READ);

    // applications
    token.setApps(apps);

    // owners
    if (null != owners && owners.size() > 0) {
      for (String owner : owners) {
        token.addToOwners(toByteBuffer(owner));
      }
    } else {
      token.setOwners(new ArrayList());
    }

    // producers
    if (null != producers && producers.size() > 0) {
      for (String producer : producers) {
        token.addToProducers(toByteBuffer(producer));
      }
    } else {
      token.setProducers(new ArrayList());
    }


    // hooks
    if (null != labels && labels.size() > 0) {
      token.setLabels(labels);
    }

    // hooks
    if (null != hooks && hooks.size() > 0) {
      token.setHooks(hooks);
    }

    // Billing
    token.setBilledId(toByteBuffer(producerUID));
    return token;
  }


  /**
   * Classic Write token owner = producer
   *
   * @param appName  Warp10 application's name
   * @param uuid     producer and owner uuid
   * @param ttl      token time to live (ms)
   * @param keystore
   * @return Warp10 writes token
   * @throws TException
   */
  public String deliverWriteToken(String appName, String uuid, long ttl, KeyStore keystore) throws TException {
    WriteToken token = getWriteToken(appName, uuid, uuid, null, null, ttl);
    return cypherToken(token, keystore);
  }

  public String deliverWriteToken(String appName, String producerUID, String ownerUID, long ttl, KeyStore keystore) throws TException {
    WriteToken token = getWriteToken(appName, producerUID, ownerUID, null, null, ttl);
    return cypherToken(token, keystore);
  }

  public String deliverWriteToken(String appName, String producerUID, String ownerUID, Map labels, long ttl, KeyStore keystore) throws TException {
    WriteToken token = getWriteToken(appName, producerUID, ownerUID, labels, null, ttl);
    return cypherToken(token, keystore);
  }

  public WriteToken getWriteToken(String appName, String producerUID, String ownerUID, Map labels, List indices, long ttl) throws TException {
    long currentTime = System.currentTimeMillis();

    WriteToken token = new WriteToken();
    token.setAppName(appName);
    token.setIssuanceTimestamp(currentTime);
    token.setExpiryTimestamp(currentTime + ttl);
    token.setTokenType(TokenType.WRITE);

    if (null != labels && labels.size() > 0) {
      token.setLabels(labels);
    }

    if (null != indices && indices.size() > 0) {
      token.setIndices(indices);
    }

    token.setProducerId(toByteBuffer(producerUID));
    token.setOwnerId(toByteBuffer(ownerUID));
    return token;
  }

  public String cypherToken(TBase token, KeyStore keyStore) throws TException {
    return encryptToken(token, keyStore.getKey(KeyStore.AES_TOKEN), keyStore.getKey(KeyStore.SIPHASH_TOKEN));
  }

  public String encryptToken(TBase token, byte[] tokenAESKey, byte[] tokenSipHashKey) throws TException {
    // TSerializer is not thread-safe so we initialize one each time.
    TSerializer serializer = new TSerializer(new TCompactProtocol.Factory());

    // Serialize the  thrift token into byte array
    byte[] serialized = serializer.serialize(token);

    // Calculate the SIP
    long sip = SipHashInline.hash24_palindromic(tokenSipHashKey, serialized);

    //Create the token byte buffer
    ByteBuffer buffer = ByteBuffer.allocate(8 + serialized.length);
    buffer.order(ByteOrder.BIG_ENDIAN);
    // adds the sip
    buffer.putLong(sip);
    // adds the thrift token
    buffer.put(serialized);

    // Wrap the TOKEN
    byte[] wrappedData = CryptoUtils.wrap(tokenAESKey, buffer.array());

    String accessToken = new String(OrderPreservingBase64.encode(wrappedData));

    return accessToken;
  }

  public String getTokenIdent(String token, KeyStore keystore) {
    byte[] tokenSipHashkey = keystore.getKey(KeyStore.SIPHASH_TOKEN);
    return getTokenIdent(token, tokenSipHashkey);
  }

  public String getTokenIdent(String token, byte[] tokenSipHashkey) {
    long ident = SipHashInline.hash24_palindromic(tokenSipHashkey, token.getBytes());

    ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
    buffer.order(ByteOrder.BIG_ENDIAN);
    buffer.putLong(ident);
    return Hex.toHexString(buffer.array());
  }

  public ByteBuffer toByteBuffer(String strUUID) {
    ByteBuffer buffer = ByteBuffer.allocate(16);
    buffer.order(ByteOrder.BIG_ENDIAN);

    UUID uuid = UUID.fromString(strUUID);

    buffer.putLong(uuid.getMostSignificantBits());
    buffer.putLong(uuid.getLeastSignificantBits());

    buffer.position(0);
    return buffer;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy