Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8806ceb
general code refactor
saxenapranav Oct 7, 2022
ef092dd
general refactor
saxenapranav Oct 7, 2022
fec93f4
Made ABFSKey final
saxenapranav Oct 7, 2022
c2d35d8
added javadocs
saxenapranav Oct 7, 2022
1e987a5
refactors
saxenapranav Oct 7, 2022
6364cfb
added javadocs.
saxenapranav Oct 10, 2022
a1b1906
small refactors + javadocs
saxenapranav Oct 10, 2022
d35a276
removed null handling of encryptionAdapter in abfsclient.addEncryptio…
saxenapranav Oct 11, 2022
450324a
refactored how encryptionAdapter was created in case of versionFileSt…
saxenapranav Oct 11, 2022
183f1bc
small refactors
saxenapranav Oct 12, 2022
d0a16bd
fixed tests
saxenapranav Oct 12, 2022
a69ee4a
refactored condition in openFileForRead
saxenapranav Oct 17, 2022
061930b
getIsNamespace in abfsclient
saxenapranav Nov 17, 2022
00bd8c3
Added NamespaceUtil
saxenapranav Nov 17, 2022
a642ef3
ListResultEntrySchema to have value for x-ms-encryption-context: http…
saxenapranav Nov 21, 2022
56f3efa
added test for the listPath
saxenapranav Nov 21, 2022
adc82f6
test for: using result of listStatus to open a file in case the file …
saxenapranav Dec 8, 2022
241fb9b
Remove public documentation for Encryption Options.
saxenapranav Dec 12, 2022
9daea68
remove non required import in abfsOutputStream; itestAbfsCustomEncryp…
saxenapranav Dec 12, 2022
2313790
small refactors
saxenapranav Dec 12, 2022
aee1c7b
refactor mock verification so that parameter can be null
saxenapranav Dec 12, 2022
bb45ae9
assertions changed for abfsclient namespaceEnabled check
saxenapranav Dec 13, 2022
3c6eddb
Revert "assertions changed for abfsclient namespaceEnabled check"
saxenapranav Dec 13, 2022
a231592
AbfsClientUtils to set certain fields for test. AbfsClient to have pa…
saxenapranav Dec 13, 2022
6ab375c
added javadocs; indentation; comments on https://github.com/sumangala…
saxenapranav Dec 22, 2022
aaf1582
minor change
saxenapranav Dec 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.io.IOException;
import java.lang.reflect.Field;

import org.apache.hadoop.fs.azurebfs.extensions.EncryptionContextProvider;
import org.apache.hadoop.classification.VisibleForTesting;
import org.apache.hadoop.util.Preconditions;

Expand Down Expand Up @@ -50,6 +49,7 @@
import org.apache.hadoop.fs.azurebfs.diagnostics.StringConfigurationBasicValidator;
import org.apache.hadoop.fs.azurebfs.enums.Trilean;
import org.apache.hadoop.fs.azurebfs.extensions.CustomTokenProviderAdaptee;
import org.apache.hadoop.fs.azurebfs.extensions.EncryptionContextProvider;
import org.apache.hadoop.fs.azurebfs.extensions.SASTokenProvider;
import org.apache.hadoop.fs.azurebfs.oauth2.AccessTokenProvider;
import org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider;
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ public final class AbfsHttpConstants {
public static final char CHAR_EQUALS = '=';
public static final char CHAR_STAR = '*';
public static final char CHAR_PLUS = '+';
public static final String DECEMBER_2019_API_VERSION = "2019-12-12";
public static final String APRIL_2021_API_VERSION = "2021-04-10";

private AbfsHttpConstants() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ public final class ConfigurationKeys {
public static final String AZURE_KEY_ACCOUNT_SHELLKEYPROVIDER_SCRIPT = "fs.azure.shellkeyprovider.script";
/** Setting this true will make the driver use it's own RemoteIterator implementation */
public static final String FS_AZURE_ENABLE_ABFS_LIST_ITERATOR = "fs.azure.enable.abfslistiterator";
/** Server side encryption key encoded in Base6format */
/** Server side encryption key encoded in Base6format {@value}.*/
public static final String FS_AZURE_ENCRYPTION_ENCODED_CLIENT_PROVIDED_KEY =
"fs.azure.encryption.encoded.client-provided-key";
/** SHA256 hash of encryption key encoded in Base64format */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ public class ListResultEntrySchema {
@JsonProperty(value = "permissions")
private String permissions;

/**
* The encryption context property
*/
@JsonProperty(value = "EncryptionContext")
private String xMsEncryptionContext;

/**
* The customer-provided encryption-256 value
* */
@JsonProperty(value = "CustomerProvidedKeySha256")
private String customerProvidedKeySha256;

/**
* Get the name value.
*
Expand Down Expand Up @@ -238,4 +250,19 @@ public ListResultEntrySchema withPermissions(final String permissions) {
return this;
}

}
/**
* Get the x-ms-encryption-context value.
* @return the x-ms-encryption-context value.
* */
public String getXMsEncryptionContext() {
return xMsEncryptionContext;
}

/**
* Get the customer-provided sha-256 key
* @return the x-ms-encryption-key-sha256 value used by client.
* */
public String getCustomerProvidedKeySha256() {
return customerProvidedKeySha256;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.azurebfs.security.ABFSKey;

/**
* This interface has two roles:<br>
* <ul>
* <li>
* To create new encryptionContext from a given path: To be used in case of
* create file as there is no encryptionContext in remote server to refer to
* for encryptionKey creation.
* </li>
* <li>To create encryptionKey using encryptionContext.</li>
* </ul>
* */
public interface EncryptionContextProvider extends Destroyable {
/**
* Initialize instance
Expand Down Expand Up @@ -53,6 +64,4 @@ public interface EncryptionContextProvider extends Destroyable {
* @throws IOException error in fetching encryption key
*/
ABFSKey getEncryptionKey(String path, ABFSKey encryptionContext) throws IOException;

void destroy();
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,44 @@
import javax.crypto.SecretKey;
import java.util.Arrays;

public class ABFSKey implements SecretKey {
private byte[] bytes;
/**
* Implementation of SecretKey that would be used by EncryptionAdapter object,
* implementations of encryptionContextProvider to maintain the byteArrays of
* encryptionContext and encryptionKey.
* */
public final class ABFSKey implements SecretKey {
private byte[] bytes;

public ABFSKey(byte[] bytes) {
if (bytes != null) {
this.bytes = bytes.clone();
}
public ABFSKey(byte[] bytes) {
if (bytes != null) {
this.bytes = bytes.clone();
}
}

@Override
public String getAlgorithm() {
return null;
}
@Override
public String getAlgorithm() {
return null;
}

@Override
public String getFormat() {
return null;
}
@Override
public String getFormat() {
return null;
}

/**
* This method to be called by implementations of EncryptionContextProvider interface.
* Method returns clone of the original bytes array to prevent findbugs flags.
* */
@Override
public byte[] getEncoded() {
if (bytes == null) {
return null;
}
return bytes.clone();
/**
* This method to be called by implementations of EncryptionContextProvider interface.
* Method returns clone of the original bytes array to prevent findbugs flags.
* */
@Override
public byte[] getEncoded() {
if (bytes == null) {
return null;
}
return bytes.clone();
}

@Override
public void destroy() {
Arrays.fill(bytes, (byte) 0);
}
@Override
public void destroy() {
Arrays.fill(bytes, (byte) 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,25 @@
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class EncodingHelper {
/**
* Utility class for managing encryption of bytes or base64String conversion of
* bytes.
* */
public final class EncodingHelper {

public static byte[] getSHA256Hash(byte[] key) {
try {
final MessageDigest digester = MessageDigest.getInstance("SHA-256");
return digester.digest(key);
} catch (NoSuchAlgorithmException ignored) {
/**
* This exception can be ignored. Reason being SHA-256 is a valid algorithm, and it is constant for all
* method calls.
*/
return null;
}
public static byte[] getSHA256Hash(byte[] key) {
try {
final MessageDigest digester = MessageDigest.getInstance("SHA-256");
return digester.digest(key);
} catch (NoSuchAlgorithmException noSuchAlgorithmException) {
/*This exception can be ignored. Reason being SHA-256 is a valid algorithm,
and it is constant for all method calls.*/
throw new RuntimeException("SHA-256 algorithm not found in MessageDigest",
noSuchAlgorithmException);
}
}

public static String getBase64EncodedString(byte[] bytes) {
return Base64.getEncoder().encodeToString(bytes);
}
public static String getBase64EncodedString(byte[] bytes) {
return Base64.getEncoder().encodeToString(bytes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,62 +21,81 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import javax.security.auth.DestroyFailedException;
import javax.security.auth.Destroyable;

import org.apache.hadoop.util.Preconditions;
import java.util.Objects;

import org.apache.hadoop.fs.azurebfs.extensions.EncryptionContextProvider;

public class EncryptionAdapter implements Destroyable {
import static org.apache.hadoop.fs.azurebfs.security.EncodingHelper.getBase64EncodedString;

/**
* Class manages the encryptionContext and encryptionKey that needs to be added
* to the headers to server request if Customer-Encryption-Context is enabled in
* the configuration.
* <br>
* For fileCreation, the object helps in creating encryptionContext through the
* implementation of EncryptionContextProvider.
* <br>
* For all operations, the object helps in converting encryptionContext to
* encryptionKey through the implementation of EncryptionContextProvider.
* */
public class EncryptionAdapter {
private final String path;
private ABFSKey encryptionContext;
private final ABFSKey encryptionContext;
private ABFSKey encryptionKey;
private final EncryptionContextProvider provider;

/**
* Following constructor called when the encryptionContext of file is known.
* The server shall send encryptionContext as a String, the constructor shall
* convert the string into a byte-array. The converted byte-array would be used
* by the implementation of EncryptionContextProvider to create byte-array of
* encryptionKey.
* */
public EncryptionAdapter(EncryptionContextProvider provider, String path,
byte[] encryptionContext) throws IOException {
this(provider, path);
Preconditions.checkNotNull(encryptionContext,
this.provider = provider;
this.path = path;
Objects.requireNonNull(encryptionContext,
"Encryption context should not be null.");
this.encryptionContext = new ABFSKey(Base64.getDecoder().decode(encryptionContext));
Arrays.fill(encryptionContext, (byte) 0);
computeKeys();
}

/**
* Following constructor called in case of createPath. Since, the path is not
* on the server, encryptionContext is not there for the path. Implementation
* of the EncryptionContextProvider would be used to create encryptionContext
* from the path.
* */
public EncryptionAdapter(EncryptionContextProvider provider, String path)
throws IOException {
this.provider = provider;
this.path = path;
encryptionContext = provider.getEncryptionContext(path);
Objects.requireNonNull(encryptionContext,
"Encryption context should not be null.");
computeKeys();
}

private void computeKeys() throws IOException {
if (encryptionContext == null) {
encryptionContext = provider.getEncryptionContext(path);
}
Preconditions.checkNotNull(encryptionContext,
"Encryption context should not be null.");
if (encryptionKey == null) {
encryptionKey = provider.getEncryptionKey(path, encryptionContext);
}
Preconditions.checkNotNull(encryptionKey, "Encryption key should not be null.");
encryptionKey = provider.getEncryptionKey(path, encryptionContext);
Objects.requireNonNull(encryptionKey, "Encryption key should not be null.");
}

public String getEncodedKey() throws IOException {
computeKeys();
return EncodingHelper.getBase64EncodedString(encryptionKey.getEncoded());
return getBase64EncodedString(encryptionKey.getEncoded());
}

public String getEncodedKeySHA() throws IOException {
computeKeys();
return EncodingHelper.getBase64EncodedString(EncodingHelper.getSHA256Hash(encryptionKey.getEncoded()));
return getBase64EncodedString(EncodingHelper.getSHA256Hash(encryptionKey.getEncoded()));
}

public String getEncodedContext() throws IOException {
computeKeys();
return EncodingHelper.getBase64EncodedString(encryptionContext.getEncoded());
return getBase64EncodedString(encryptionContext.getEncoded());
}

public void destroy() throws DestroyFailedException {
public void destroy() {
if (encryptionContext != null) {
encryptionContext.destroy();
}
Expand Down
Loading