HADOOP-11096. KMS: KeyAuthorizationKeyProvider should verify the keyversion belongs to the keyname on decrypt. (tucu)
This commit is contained in:
parent
0e7d1dbf9a
commit
e14e71d5fe
|
@ -815,6 +815,9 @@ Release 2.6.0 - UNRELEASED
|
|||
HADOOP-11088. Unittest TestKeyShell, TestCredShell and TestKMS assume UNIX
|
||||
path separator for JECKS key store path. (Xiaoyu Yao via cnauroth)
|
||||
|
||||
HADOOP-11096. KMS: KeyAuthorizationKeyProvider should verify the keyversion
|
||||
belongs to the keyname on decrypt. (tucu)
|
||||
|
||||
Release 2.5.1 - 2014-09-05
|
||||
|
||||
INCOMPATIBLE CHANGES
|
||||
|
|
|
@ -91,6 +91,8 @@ public class KeyProviderCryptoExtension extends
|
|||
* returned EncryptedKeyVersion will only partially be populated; it is not
|
||||
* necessarily suitable for operations besides decryption.
|
||||
*
|
||||
* @param keyName Key name of the encryption key use to encrypt the
|
||||
* encrypted key.
|
||||
* @param encryptionKeyVersionName Version name of the encryption key used
|
||||
* to encrypt the encrypted key.
|
||||
* @param encryptedKeyIv Initialization vector of the encrypted
|
||||
|
@ -100,12 +102,12 @@ public class KeyProviderCryptoExtension extends
|
|||
* @param encryptedKeyMaterial Key material of the encrypted key.
|
||||
* @return EncryptedKeyVersion suitable for decryption.
|
||||
*/
|
||||
public static EncryptedKeyVersion createForDecryption(String
|
||||
encryptionKeyVersionName, byte[] encryptedKeyIv,
|
||||
public static EncryptedKeyVersion createForDecryption(String keyName,
|
||||
String encryptionKeyVersionName, byte[] encryptedKeyIv,
|
||||
byte[] encryptedKeyMaterial) {
|
||||
KeyVersion encryptedKeyVersion = new KeyVersion(null, EEK,
|
||||
encryptedKeyMaterial);
|
||||
return new EncryptedKeyVersion(null, encryptionKeyVersionName,
|
||||
return new EncryptedKeyVersion(keyName, encryptionKeyVersionName,
|
||||
encryptedKeyIv, encryptedKeyVersion);
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ public class TestKeyProviderCryptoExtension {
|
|||
|
||||
// Test the createForDecryption factory method
|
||||
EncryptedKeyVersion eek2 =
|
||||
EncryptedKeyVersion.createForDecryption(
|
||||
EncryptedKeyVersion.createForDecryption(eek.getEncryptionKeyName(),
|
||||
eek.getEncryptionKeyVersionName(), eek.getEncryptedKeyIv(),
|
||||
eek.getEncryptedKeyVersion().getMaterial());
|
||||
|
||||
|
|
|
@ -192,9 +192,21 @@ public class KeyAuthorizationKeyProvider extends KeyProviderCryptoExtension {
|
|||
return provider.generateEncryptedKey(encryptionKeyName);
|
||||
}
|
||||
|
||||
private void verifyKeyVersionBelongsToKey(EncryptedKeyVersion ekv)
|
||||
throws IOException {
|
||||
String kn = ekv.getEncryptionKeyName();
|
||||
String kvn = ekv.getEncryptionKeyVersionName();
|
||||
KeyVersion kv = provider.getKeyVersion(kvn);
|
||||
if (!kv.getName().equals(kn)) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"KeyVersion '%s' does not belong to the key '%s'", kvn, kn));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyVersion decryptEncryptedKey(EncryptedKeyVersion encryptedKeyVersion)
|
||||
throws IOException, GeneralSecurityException {
|
||||
verifyKeyVersionBelongsToKey(encryptedKeyVersion);
|
||||
doAccessCheck(
|
||||
encryptedKeyVersion.getEncryptionKeyName(), KeyOpType.DECRYPT_EEK);
|
||||
return provider.decryptEncryptedKey(encryptedKeyVersion);
|
||||
|
|
|
@ -215,4 +215,57 @@ public class TestKeyAuthorizationKeyProvider {
|
|||
return options;
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testDecryptWithKeyVersionNameKeyMismatch() throws Exception {
|
||||
final Configuration conf = new Configuration();
|
||||
KeyProvider kp =
|
||||
new UserProvider.Factory().createProvider(new URI("user:///"), conf);
|
||||
KeyACLs mock = mock(KeyACLs.class);
|
||||
when(mock.isACLPresent("testKey", KeyOpType.MANAGEMENT)).thenReturn(true);
|
||||
when(mock.isACLPresent("testKey", KeyOpType.GENERATE_EEK)).thenReturn(true);
|
||||
when(mock.isACLPresent("testKey", KeyOpType.DECRYPT_EEK)).thenReturn(true);
|
||||
when(mock.isACLPresent("testKey", KeyOpType.ALL)).thenReturn(true);
|
||||
UserGroupInformation u1 = UserGroupInformation.createRemoteUser("u1");
|
||||
UserGroupInformation u2 = UserGroupInformation.createRemoteUser("u2");
|
||||
UserGroupInformation u3 = UserGroupInformation.createRemoteUser("u3");
|
||||
UserGroupInformation sudo = UserGroupInformation.createRemoteUser("sudo");
|
||||
when(mock.hasAccessToKey("testKey", u1,
|
||||
KeyOpType.MANAGEMENT)).thenReturn(true);
|
||||
when(mock.hasAccessToKey("testKey", u2,
|
||||
KeyOpType.GENERATE_EEK)).thenReturn(true);
|
||||
when(mock.hasAccessToKey("testKey", u3,
|
||||
KeyOpType.DECRYPT_EEK)).thenReturn(true);
|
||||
when(mock.hasAccessToKey("testKey", sudo,
|
||||
KeyOpType.ALL)).thenReturn(true);
|
||||
final KeyProviderCryptoExtension kpExt =
|
||||
new KeyAuthorizationKeyProvider(
|
||||
KeyProviderCryptoExtension.createKeyProviderCryptoExtension(kp),
|
||||
mock);
|
||||
|
||||
sudo.doAs(
|
||||
new PrivilegedExceptionAction<Void>() {
|
||||
@Override
|
||||
public Void run() throws Exception {
|
||||
Options opt = newOptions(conf);
|
||||
Map<String, String> m = new HashMap<String, String>();
|
||||
m.put("key.acl.name", "testKey");
|
||||
opt.setAttributes(m);
|
||||
KeyVersion kv =
|
||||
kpExt.createKey("foo", SecureRandom.getSeed(16), opt);
|
||||
kpExt.rollNewVersion(kv.getName());
|
||||
kpExt.rollNewVersion(kv.getName(), SecureRandom.getSeed(16));
|
||||
EncryptedKeyVersion ekv = kpExt.generateEncryptedKey(kv.getName());
|
||||
ekv = EncryptedKeyVersion.createForDecryption(
|
||||
ekv.getEncryptionKeyName() + "x",
|
||||
ekv.getEncryptionKeyVersionName(),
|
||||
ekv.getEncryptedKeyIv(),
|
||||
ekv.getEncryptedKeyVersion().getMaterial());
|
||||
kpExt.decryptEncryptedKey(ekv);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1321,7 +1321,8 @@ public class DFSClient implements java.io.Closeable, RemotePeerFactory,
|
|||
" an encrypted file");
|
||||
}
|
||||
EncryptedKeyVersion ekv = EncryptedKeyVersion.createForDecryption(
|
||||
feInfo.getEzKeyVersionName(), feInfo.getIV(),
|
||||
//TODO: here we have to put the keyName to be provided by HDFS-6987
|
||||
null, feInfo.getEzKeyVersionName(), feInfo.getIV(),
|
||||
feInfo.getEncryptedDataEncryptionKey());
|
||||
try {
|
||||
return provider.decryptEncryptedKey(ekv);
|
||||
|
|
Loading…
Reference in New Issue