Skip to content

Commit

Permalink
v2.0.0-rc.2
Browse files Browse the repository at this point in the history
  • Loading branch information
arnett, stu committed Jun 25, 2015
1 parent 9319c18 commit 2242d4b
Show file tree
Hide file tree
Showing 34 changed files with 976 additions and 775 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ buildscript {
apply from: "$commonBuildDir/ecs-publish.gradle"

dependencies {
compile 'com.emc.ecs:smart-client:1.0.2',
'com.emc.vipr:vipr-object-transformations:2.0.3',
compile 'com.emc.ecs:smart-client:2.0.0',
'com.emc.ecs:object-transform:1.0.0',
'org.jdom:jdom2:2.0.5'
testCompile 'junit:junit:4.11'
}
30 changes: 6 additions & 24 deletions src/main/java/com/emc/object/AbstractJerseyClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@
import com.sun.jersey.client.apache4.config.ApacheHttpClient4Config;
import org.apache.log4j.Logger;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.MessageBodyWriter;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.net.URI;
import java.util.Map;
Expand Down Expand Up @@ -71,30 +68,15 @@ protected ClientResponse executeRequest(Client client, ObjectRequest request) {

if (entityRequest.getEntity() != null) entity = entityRequest.getEntity();

// calculate and set content-length
Long size = entityRequest.getContentLength();
if (size == null) {
// try and find an entity writer that can determine the size
// TODO: can remove when chunked encoding is supported
MediaType mediaType = MediaType.valueOf(contentType);
MessageBodyWriter writer = client.getProviders().getMessageBodyWriter(entity.getClass(), entity.getClass(),
EMPTY_ANNOTATIONS, mediaType);
size = writer.getSize(entity, entity.getClass(), entity.getClass(), EMPTY_ANNOTATIONS, mediaType);
}
// if content-length is set (perhaps by user), force jersey to use it
if (entityRequest.getContentLength() != null) {
SizeOverrideWriter.setEntitySize(entityRequest.getContentLength());

// if size cannot be determined, enable buffering to let HttpClient set the content-length
// NOTE: if a non-apache client handler is used, this has no effect and chunked encoding will always be enabled
// NOTE2: if the entity is an input stream, it will be streamed into memory to determine its size. this
// may cause OutOfMemoryException if there is not enough memory to hold the data
// TODO: can remove when chunked encoding is supported
if (size < 0) {
l4j.info("entity size cannot be determined; enabling Apache client entity buffering...");
if (entity instanceof InputStream)
l4j.warn("set a content-length for input streams to save memory");
// otherwise chunked encoding will be used. if the request does not support it, turn on
// buffering in the apache client (will set content length from buffered write)
} else if (!entityRequest.isChunkable()) {
request.property(ApacheHttpClient4Config.PROPERTY_ENABLE_BUFFERING, Boolean.TRUE);
}

SizeOverrideWriter.setEntitySize(size);
} else {

// no entity, but make sure the apache handler doesn't mess up the content-length somehow
Expand Down
189 changes: 121 additions & 68 deletions src/main/java/com/emc/object/EncryptionConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,68 +26,45 @@
*/
package com.emc.object;

import com.emc.vipr.transform.TransformConstants;
import com.emc.vipr.transform.TransformException;
import com.emc.vipr.transform.encryption.*;
import com.emc.codec.compression.deflate.DeflateCodec;
import com.emc.codec.encryption.BasicKeyProvider;
import com.emc.codec.encryption.EncryptionCodec;
import com.emc.codec.encryption.KeyProvider;
import com.emc.codec.encryption.KeystoreKeyProvider;

import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
* Creates an encryption configuration for use with an object transform client.
* Both keystore keys and bare RSA KeyPairs are supported.
* Creates an encryption configuration for use with {@link com.emc.object.s3.jersey.S3EncryptionClient}.
* Both keystore keys and bare RSA KeyPairs are supported. You can optionally implement your own
* {@link KeyProvider} as well.
*/
public class EncryptionConfig {
private EncryptionTransformFactory<BasicEncryptionOutputTransform, BasicEncryptionInputTransform> factory;

public static String getEncryptionMode(Map<String, String> metadata) {
String transformModes = metadata.get(TransformConstants.META_TRANSFORM_MODE);

// During decode, we process transforms in reverse order.
String[] modes = transformModes.split("\\|");
for (int i = modes.length - 1; i >= 0; i--) {
if (modes[i].startsWith(TransformConstants.ENCRYPTION_CLASS)) return modes[i];
}

return null;
}

public static void setEncryptionMode(Map<String, String> metadata, String encryptionMode) {
metadata.put(TransformConstants.META_TRANSFORM_MODE, encryptionMode);
}
private String encryptionSpec = new EncryptionCodec().getDefaultEncodeSpec();
private boolean compressionEnabled = false;
private String compressionSpec = new DeflateCodec().getDefaultEncodeSpec();
private Map<String, Object> codecProperties = new HashMap<String, Object>();

/**
* Creates a new EncryptionConfig object that will retrieve keys from a Keystore
* object.
* object. Note that currently, only RSA keys are supported.
*
* @param keystore the Keystore containing the master encryption key and any
* additional decryption key(s).
* @param masterKeyPassword password for the master keys. Note that this
* implementation assumes that all master keys use the same password.
* @param masterKeyAlias name of the master encryption key in the Keystore object.
* @param provider (optional) if not-null, the Provider object to use for all
* encryption operations. If null, the default provider(s) will be used from your
* java.security file.
* @param keySize size of encryption key to use, either 128 or 256. Note that to use
* 256-bit AES keys, you will probably need the unlimited strength jurisdiction files
* installed in your JRE.
* @throws java.security.InvalidKeyException if the master encryption key cannot be loaded.
* @throws java.security.NoSuchAlgorithmException if the AES encryption algorithm is not available.
* @throws javax.crypto.NoSuchPaddingException if PKCS5Padding is not available.
* @throws TransformException if some other error occurred initializing the encryption.
* @throws java.security.KeyStoreException if the keystore has not been initialized properly.
* @throws java.security.NoSuchAlgorithmException if the master key's algorithm is not available.
* @throws java.security.InvalidKeyException if the master key alias is not found in the keystore.
* @throws java.security.UnrecoverableKeyException if the master key is not readable (e.g. bad password)
*/
public EncryptionConfig(KeyStore keystore, char[] masterKeyPassword,
String masterKeyAlias, Provider provider, int keySize)
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, TransformException {
if (provider == null) {
factory = new KeyStoreEncryptionFactory(keystore, masterKeyAlias, masterKeyPassword);
} else {
factory = new KeyStoreEncryptionFactory(keystore, masterKeyAlias, masterKeyPassword, provider);
}
factory.setEncryptionSettings(TransformConstants.DEFAULT_ENCRYPTION_TRANSFORM, keySize, provider);
public EncryptionConfig(KeyStore keystore, char[] masterKeyPassword, String masterKeyAlias)
throws KeyStoreException, NoSuchAlgorithmException, InvalidKeyException, UnrecoverableKeyException {
this(new KeystoreKeyProvider(keystore, masterKeyPassword, masterKeyAlias));
}

/**
Expand All @@ -96,37 +73,113 @@ public EncryptionConfig(KeyStore keystore, char[] masterKeyPassword,
* @param masterEncryptionKey the KeyPair to use for encryption.
* @param decryptionKeys (optional) additional KeyPair objects available to
* decrypt objects.
* @param provider (optional) if not-null, the Provider object to use for all
* encryption operations. If null, the default provider(s) will be used from your
* java.security file.
* @param keySize size of encryption key to use, either 128 or 256. Note that to use
* 256-bit AES keys, you will probably need the unlimited strength jurisdiction files
* installed in your JRE.
* @throws java.security.InvalidKeyException if the master encryption key is not valid
* @throws java.security.NoSuchAlgorithmException if the AES encryption algorithm is not available.
* @throws javax.crypto.NoSuchPaddingException if PKCS5Padding is not available.
* @throws TransformException if some other error occurred initializing the encryption.
*/
public EncryptionConfig(KeyPair masterEncryptionKey, Set<KeyPair> decryptionKeys,
Provider provider, int keySize)
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, TransformException {
public EncryptionConfig(KeyPair masterEncryptionKey, Set<KeyPair> decryptionKeys) {
this(new BasicKeyProvider(masterEncryptionKey, decryptionKeys.toArray(new KeyPair[decryptionKeys.size()])));
}

public EncryptionConfig(KeyProvider keyProvider) {
codecProperties.put(EncryptionCodec.PROP_KEY_PROVIDER, keyProvider);
}

public KeyProvider getKeyProvider() {
return EncryptionCodec.getKeyProvider(codecProperties);
}

public int getKeySize() {
return EncryptionCodec.getKeySize(codecProperties);
}

/**
* Set the size of encryption key to use, either 128 or 256. Note that to use
* 256-bit AES keys, you will probably need the unlimited strength jurisdiction files
* installed in your JRE.
*/
public void setKeySize(int keySize) {
EncryptionCodec.setKeySize(codecProperties, keySize);
}

public Provider getSecurityProvider() {
return EncryptionCodec.getSecurityProvider(codecProperties);
}

/**
* Set the Java security provider to use for all encryption operations. If not specified,
* the default provider(s) will be used from your java.security file.
*/
public void setSecurityProvider(Provider provider) {
EncryptionCodec.setPropSecurityProvider(codecProperties, provider);
}

public String getEncryptionSpec() {
return encryptionSpec;
}

public void setEncryptionSpec(String encryptionSpec) {
this.encryptionSpec = encryptionSpec;
}

public boolean isCompressionEnabled() {
return compressionEnabled;
}

/**
* If set to true, will enable compression for objects created with the encryption client.
*/
public void setCompressionEnabled(boolean compressionEnabled) {
this.compressionEnabled = compressionEnabled;
}

if (provider == null) {
factory = new BasicEncryptionTransformFactory(masterEncryptionKey, decryptionKeys);
} else {
factory = new BasicEncryptionTransformFactory(masterEncryptionKey, decryptionKeys, provider);
}
factory.setEncryptionSettings(TransformConstants.DEFAULT_ENCRYPTION_TRANSFORM, keySize, provider);
public String getCompressionSpec() {
return compressionSpec;
}

/**
* Returns the configured EncryptionTransformFactory.
* Sets the compression spec to use for compression. Defaults to Deflate, level 5.
*
* @return the configured EncryptionTransformFactory.
* @see DeflateCodec#encodeSpec(int)
* @see com.emc.codec.compression.lzma.LzmaCodec#encodeSpec(int)
*/
public EncryptionTransformFactory<BasicEncryptionOutputTransform, BasicEncryptionInputTransform> getFactory() {
return factory;
public void setCompressionSpec(String compressionSpec) {
this.compressionSpec = compressionSpec;
}

public Map<String, Object> getCodecProperties() {
return codecProperties;
}

public void setCodecProperties(Map<String, Object> codecProperties) {
this.codecProperties = codecProperties;
}

/**
* @see #setKeySize(int)
*/
public EncryptionConfig withKeySize(int keySize) {
setKeySize(keySize);
return this;
}

/**
* @see #setSecurityProvider(Provider)
*/
public EncryptionConfig withSecurityProvider(Provider provider) {
setSecurityProvider(provider);
return this;
}

public EncryptionConfig withEncryptionSpec(String encryptionSpec) {
setEncryptionSpec(encryptionSpec);
return this;
}

public EncryptionConfig withCompressionEnabled(boolean compressionEnabled) {
setCompressionEnabled(compressionEnabled);
return this;
}

public EncryptionConfig withCompressionSpec(String compressionSpec) {
setCompressionSpec(compressionSpec);
return this;
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/emc/object/EntityRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ public interface EntityRequest {
String getContentType();

Long getContentLength();

boolean isChunkable();
}
Loading

0 comments on commit 2242d4b

Please sign in to comment.