com.ibm.og.s3.v4.AWSV4Auth.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.og.s3.v4.AWSV4Auth.java

Source

/* Copyright (c) IBM Corporation 2016. All Rights Reserved.
 * Project name: Object Generator
 * This project is licensed under the Apache License 2.0, see LICENSE.
 */

package com.ibm.og.s3.v4;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import javax.inject.Inject;
import javax.inject.Named;

import com.ibm.og.http.AuthenticatedHttpRequest;
import com.ibm.og.http.HttpAuth;
import com.ibm.og.util.Context;
import com.ibm.og.util.io.Streams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.amazonaws.SignableRequest;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.ibm.og.api.AuthenticatedRequest;
import com.ibm.og.api.DataType;
import com.ibm.og.api.Request;
import com.ibm.og.http.Bodies;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.hash.Hashing;
import com.google.common.hash.HashingInputStream;

/**
 * An http auth implementation which authenticates using the aws v4 algorithm
 * 
 * @since 1.0
 */
public class AWSV4Auth implements HttpAuth {
    private static Logger _logger = LoggerFactory.getLogger(AWSV4Auth.class);
    private final boolean chunkedEncoding;
    private final int cacheSize;
    private final DataType data;
    private final LoadingCache<Long, byte[]> digestCache;

    @Inject
    public AWSV4Auth(@Named("authentication.awsChunked") final boolean chunkedEncoding,
            @Named("authentication.awsCacheSize") final int cacheSize, final DataType data) {
        this.chunkedEncoding = chunkedEncoding;
        checkArgument(cacheSize >= 0, "cacheSize must be >= 0 [%s]", cacheSize);
        this.cacheSize = cacheSize;
        this.data = checkNotNull(data);
        checkArgument(data != DataType.NONE, "data must not be NONE");

        if (cacheSize > 0) {
            checkArgument(data == DataType.ZEROES, "If cacheSize > 0, data must be ZEROES [%s]", data);
            this.digestCache = CacheBuilder.newBuilder().maximumSize(cacheSize).build(new DigestLoader());
        } else {
            this.digestCache = null;
        }
    }

    static class DigestLoader extends CacheLoader<Long, byte[]> {
        @Override
        public byte[] load(final Long key) throws Exception {
            checkNotNull(key);
            _logger.debug("Loading digest for size [{}]", key);

            final HashingInputStream hashStream = new HashingInputStream(Hashing.sha256(),
                    Streams.create(Bodies.zeroes(key)));
            final byte[] buffer = new byte[4096];
            while (hashStream.read(buffer) != -1) {
            }
            // should never throw an exception since the source is from Streams.create
            hashStream.close();

            return hashStream.hash().asBytes();
        }
    }

    @Override
    public AuthenticatedRequest authenticate(final Request request) {
        checkNotNull(request);
        final String accessKeyId = checkNotNull(request.getContext().get(Context.X_OG_USERNAME));
        final String secretAccessKey = checkNotNull(request.getContext().get(Context.X_OG_PASSWORD));
        final AWSCredentials credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey);

        final AWSS3V4Signer signer = new AWSS3V4Signer(this.chunkedEncoding, this.digestCache);
        signer.setServiceName("s3");

        final AuthenticatedHttpRequest authenticatedRequest = new AuthenticatedHttpRequest(request);
        final SignableRequest<Request> signableRequest = new SignableRequestAdapter(authenticatedRequest);

        signer.sign(signableRequest, credentials);

        return authenticatedRequest;
    }

    @Override
    public String toString() {
        return String.format("AWSV4Auth [chunkedEncoding=%s, cacheSize=%s, data=%s]", this.chunkedEncoding,
                this.cacheSize, this.data);
    }
}