This is an automated email from the ASF dual-hosted git repository.
dhavalshah9131 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new 605de3c RANGER-3580 : add TencentKMS as MasterKeyProvider
new 1135aaf Merge branch 'master' of
https://gitbox.apache.org/repos/asf/ranger
605de3c is described below
commit 605de3cba8d311e983f0aee3490e67266f6668a9
Author: ZhouTianling <[email protected]>
AuthorDate: Sat Jan 22 01:51:15 2022 +0800
RANGER-3580 : add TencentKMS as MasterKeyProvider
---
distro/src/main/assembly/kms.xml | 4 +
kms/config/kms-webapp/dbks-site.xml | 35 ++++-
kms/pom.xml | 5 +
kms/scripts/install.properties | 7 +
kms/scripts/setup.sh | 82 ++++++++----
.../key/AzureKeyVaultClientAuthenticator.java | 33 ++---
.../hadoop/crypto/key/DBToAzureKeyVault.java | 2 +-
.../apache/hadoop/crypto/key/JKS2RangerUtil.java | 4 +-
...r.java => RangerAzureKeyVaultKeyGenerator.java} | 78 +++++++++--
.../apache/hadoop/crypto/key/RangerKeyStore.java | 23 ++--
.../hadoop/crypto/key/RangerKeyStoreProvider.java | 148 ++++++++-------------
.../crypto/key/RangerTencentKMSProvider.java | 135 +++++++++++++++++++
pom.xml | 6 +-
13 files changed, 402 insertions(+), 160 deletions(-)
diff --git a/distro/src/main/assembly/kms.xml b/distro/src/main/assembly/kms.xml
index 983a43e..f760507 100755
--- a/distro/src/main/assembly/kms.xml
+++ b/distro/src/main/assembly/kms.xml
@@ -195,6 +195,10 @@
<include>io.grpc:grpc-xds</include>
<include>io.grpc:grpc-services</include>
<include>io.opencensus:opencensus-proto</include>
+ <!-- TencentKMS -->
+
<include>com.tencentcloudapi:tencentcloud-sdk-java</include>
+ <include>com.squareup.okhttp:logging-interceptor</include>
+ <include>com.squareup.okhttp:okhttp</include>
</includes>
</binaries>
</moduleSet>
diff --git a/kms/config/kms-webapp/dbks-site.xml
b/kms/config/kms-webapp/dbks-site.xml
index 07de4d4..258d331 100755
--- a/kms/config/kms-webapp/dbks-site.xml
+++ b/kms/config/kms-webapp/dbks-site.xml
@@ -327,7 +327,40 @@
</property>
<!-- Google Cloud KMS end -->
- <!-- HSM Config -->
+ <!--Tencent KMS START-->
+ <property>
+ <name>ranger.kms.tencentkms.enabled</name>
+ <value>false</value>
+ <description>Flag for Tencent KMS</description>
+ </property>
+ <property>
+ <name>ranger.kms.tencent.client.id</name>
+ <value></value>
+ <description>Tencent Client Id</description>
+ </property>
+ <property>
+ <name>ranger.kms.tencent.client.secret</name>
+ <value></value>
+ <description>Tencent Client Secret</description>
+ </property>
+ <property>
+ <name>ranger.kms.tencent.client.secret.alias</name>
+ <value>ranger.ks.tencent.client.secret</value>
+ <description>Tencent Client Secret Alias</description>
+ </property>
+ <property>
+ <name>ranger.kms.tencent.client.region</name>
+ <value>ap-beijing</value>
+ <description>Tencent Client Id</description>
+ </property>
+ <property>
+ <name>ranger.kms.tencent.masterkey.id</name>
+ <value></value>
+ <description>Tencent master key name</description>
+ </property>
+ <!--Tencent KMS END-->
+
+ <!-- HSM Config -->
<property>
<name>ranger.ks.hsm.type</name>
<value>LunaProvider</value>
diff --git a/kms/pom.xml b/kms/pom.xml
index 7a4f98d..ade563f 100644
--- a/kms/pom.xml
+++ b/kms/pom.xml
@@ -456,6 +456,11 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>com.tencentcloudapi</groupId>
+ <artifactId>tencentcloud-sdk-java</artifactId>
+ <version>${com.tencentcloudapi.sdk.version}</version>
+ </dependency>
+ <dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
<version>${io.reactivex.rxjava.version}</version>
diff --git a/kms/scripts/install.properties b/kms/scripts/install.properties
index 31143d3..780509d 100755
--- a/kms/scripts/install.properties
+++ b/kms/scripts/install.properties
@@ -132,6 +132,13 @@ GCP_PROJECT_ID=
GCP_LOCATION_ID=
GCP_MASTER_KEY_NAME=MyMasterKeyNameChangeIt
+#------------------------- Ranger Tencent KMS ------------------------------
+TENCENT_KMS_ENABLED=false
+TENCENT_MASTERKEY_ID=b756b016-6e11-11ec-a735-525400fe0300
+TENCENT_CLIENT_ID=AKIDrXx6ybx2qNdiaBWaNs76pGQJvFJ6crpW
+TENCENT_CLIENT_SECRET=<TencentSecretKey>
+TENCENT_CLIENT_REGION=ap-beijing
+
# ------- UNIX User CONFIG ----------------
#
unix_user=kms
diff --git a/kms/scripts/setup.sh b/kms/scripts/setup.sh
index 2051df5..448042e 100755
--- a/kms/scripts/setup.sh
+++ b/kms/scripts/setup.sh
@@ -121,6 +121,12 @@ GCP_PROJECT_ID=$(get_prop 'GCP_PROJECT_ID' $PROPFILE)
GCP_LOCATION_ID=$(get_prop 'GCP_LOCATION_ID' $PROPFILE)
GCP_MASTER_KEY_NAME=$(get_prop 'GCP_MASTER_KEY_NAME' $PROPFILE)
+TENCENT_KMS_ENABLED=$(get_prop 'TENCENT_KMS_ENABLED' $PROPFILE)
+TENCENT_MASTERKEY_ID=$(get_prop 'TENCENT_MASTERKEY_ID' $PROPFILE)
+TENCENT_CLIENT_ID=$(get_prop 'TENCENT_CLIENT_ID' $PROPFILE)
+TENCENT_CLIENT_SECRET=$(get_prop 'TENCENT_CLIENT_SECRET' $PROPFILE)
+TENCENT_CLIENT_REGION=$(get_prop 'TENCENT_CLIENT_REGION' $PROPFILE)
+
kms_principal=$(get_prop 'kms_principal' $PROPFILE)
kms_keytab=$(get_prop 'kms_keytab' $PROPFILE)
hadoop_conf=$(get_prop 'hadoop_conf' $PROPFILE)
@@ -235,26 +241,6 @@ password_validation(){
fi
}
-password_validation_safenet_keysecure(){
- if [ -z "$1" ]
- then
- log "[I] Blank password is not allowed for" $2". Please enter
valid password."
- exit 1
- else
- log "[I]" $2 "password validated."
- fi
-}
-
-azure_client_secret_validation(){
- if [ -z "$1" ]
- then
- log "[I] Blank password is not allowed for" $2". Please enter
valid password."
- exit 1
- else
- log "[I]" $2 "password validated."
- fi
-}
-
init_variables(){
curDt=`date '+%Y%m%d%H%M%S'`
@@ -481,8 +467,10 @@ setup_kms(){
checkIfEmpty() {
if [ -z "$1" ]
then
- echo "Error - Since GCP is enabled, Please provide valid value
for '$2', Found : '$1'";
+ log "[I] - Please provide valid value for '$2', Found : '$1'";
exit 1
+ else
+ log "[I] - '$2' validated";
fi
}
@@ -654,11 +642,15 @@ update_properties() {
AZURE_CLIENT_SEC="ranger.kms.azure.client.secret"
AZURE_CLIENT_SECRET_ALIAS="ranger.ks.azure.client.secret"
+ TENCENT_CLIENT_SEC="ranger.kms.tencent.client.secret"
+ TENCENT_CLIENT_SECRET_ALIAS="ranger.ks.tencent.client.secret"
+
HSM_ENABLED=`echo $HSM_ENABLED | tr '[:lower:]' '[:upper:]'`
KEYSECURE_ENABLED=`echo $KEYSECURE_ENABLED | tr '[:lower:]'
'[:upper:]'`
AZURE_KEYVAULT_ENABLED=`echo $AZURE_KEYVAULT_ENABLED | tr '[:lower:]'
'[:upper:]'`
IS_GCP_ENABLED=`echo $IS_GCP_ENABLED | tr '[:lower:]' '[:upper:]'`
+ TENCENT_KMS_ENABLED=`echo $TENCENT_KMS_ENABLED | tr '[:lower:]'
'[:upper:]'`
if [ "${keystore}" != "" ]
then
@@ -686,7 +678,7 @@ update_properties() {
if [ "${KEYSECURE_ENABLED}" == "TRUE" ]
then
- password_validation_safenet_keysecure
"$KEYSECURE_PASSWORD" "KEYSECURE User Password"
+ checkIfEmpty "$KEYSECURE_PASSWORD" "KEYSECURE User
Password"
$PYTHON_COMMAND_INVOKER ranger_credential_helper.py -l
"cred/lib/*" -f "$keystore" -k "${KEYSECURE_PASSWORD_ALIAS}" -v
"${KEYSECURE_PASSWORD}" -c 1
propertyName=ranger.kms.keysecure.login.password.alias
@@ -700,7 +692,7 @@ update_properties() {
if [ "${AZURE_KEYVAULT_ENABLED}" == "TRUE" ]
then
- azure_client_secret_validation "$AZURE_CLIENT_SECRET"
"Azure Client Secret"
+ checkIfEmpty "$AZURE_CLIENT_SECRET" "Azure Client
Secret"
$PYTHON_COMMAND_INVOKER ranger_credential_helper.py -l
"cred/lib/*" -f "$keystore" -k "${AZURE_CLIENT_SECRET_ALIAS}" -v
"${AZURE_CLIENT_SECRET}" -c 1
propertyName=ranger.kms.azure.client.secret.alias
@@ -712,6 +704,19 @@ update_properties() {
updatePropertyToFilePy $propertyName $newPropertyValue
$to_file
fi
+ if [ "$TENCENT_KMS_ENABLED" == "TRUE" ]
+ then
+ checkIfEmpty "$TENCENT_CLIENT_SECRET" "Tencent Client
Secret"
+ $PYTHON_COMMAND_INVOKER ranger_credential_helper.py -l
"cred/lib/*" -f "$keystore" -k "${TENCENT_CLIENT_SECRET_ALIAS}" -v
"${TENCENT_CLIENT_SECRET}" -c 1
+
+ propertyName=ranger.kms.tencent.client.secret.alias
+ newPropertyValue="${TENCENT_CLIENT_SECRET_ALIAS}"
+ updatePropertyToFilePy $propertyName $newPropertyValue
$to_file
+
+ propertyName=ranger.kms.tencent.client.secret
+ newPropertyValue="_"
+ updatePropertyToFilePy $propertyName $newPropertyValue
$to_file
+ fi
propertyName=ranger.ks.jpa.jdbc.credential.alias
newPropertyValue="${DB_CREDENTIAL_ALIAS}"
@@ -753,6 +758,10 @@ update_properties() {
newPropertyValue="${AZURE_CLIENT_SECRET}"
updatePropertyToFilePy $propertyName $newPropertyValue $to_file
+ propertyName="${TENCENT_CLIENT_SEC}"
+ newPropertyValue="${TENCENT_CLIENT_SECRET}"
+ updatePropertyToFilePy $propertyName $newPropertyValue $to_file
+
fi
if test -f $keystore; then
@@ -945,6 +954,33 @@ update_properties() {
updatePropertyToFilePy $propertyName $newPropertyValue
$to_file
fi
+ ########### TENCENT KEY VAULT #################
+
+
+ if [ "${TENCENT_KMS_ENABLED}" != "TRUE" ]
+ then
+ propertyName=ranger.kms.tencentkms.enabled
+ newPropertyValue="false"
+ updatePropertyToFilePy $propertyName $newPropertyValue $to_file
+ else
+ propertyName=ranger.kms.tencentkms.enabled
+ newPropertyValue="true"
+ updatePropertyToFilePy $propertyName $newPropertyValue $to_file
+
+ propertyName=ranger.kms.tencent.client.id
+ newPropertyValue="${TENCENT_CLIENT_ID}"
+ updatePropertyToFilePy $propertyName $newPropertyValue $to_file
+
+ propertyName=ranger.kms.client.region
+ newPropertyValue="${TENCENT_CLIENT_REGION}"
+ updatePropertyToFilePy $propertyName $newPropertyValue $to_file
+
+ propertyName=ranger.kms.tencent.masterkey.id
+ newPropertyValue="${TENCENT_MASTERKEY_ID}"
+ updatePropertyToFilePy $propertyName $newPropertyValue $to_file
+
+ fi
+
to_file_kms_site=$PWD/ews/webapp/WEB-INF/classes/conf/ranger-kms-site.xml
if test -f $to_file_kms_site; then
log "[I] $to_file_kms_site file found"
diff --git
a/kms/src/main/java/org/apache/hadoop/crypto/key/AzureKeyVaultClientAuthenticator.java
b/kms/src/main/java/org/apache/hadoop/crypto/key/AzureKeyVaultClientAuthenticator.java
index f96cbb7..13897ac 100644
---
a/kms/src/main/java/org/apache/hadoop/crypto/key/AzureKeyVaultClientAuthenticator.java
+++
b/kms/src/main/java/org/apache/hadoop/crypto/key/AzureKeyVaultClientAuthenticator.java
@@ -236,26 +236,27 @@ public class AzureKeyVaultClientAuthenticator extends
KeyVaultCredentials {
return keyCert;
}
}
-}
-class KeyCert {
+ static class KeyCert {
- X509Certificate certificate;
- PrivateKey key;
+ X509Certificate certificate;
+ PrivateKey key;
- public X509Certificate getCertificate() {
- return certificate;
- }
+ public X509Certificate getCertificate() {
+ return certificate;
+ }
- public void setCertificate(X509Certificate certificate) {
- this.certificate = certificate;
- }
+ public void setCertificate(X509Certificate certificate) {
+ this.certificate = certificate;
+ }
- public PrivateKey getKey() {
- return key;
- }
+ public PrivateKey getKey() {
+ return key;
+ }
- public void setKey(PrivateKey key) {
- this.key = key;
+ public void setKey(PrivateKey key) {
+ this.key = key;
+ }
}
-}
\ No newline at end of file
+}
+
diff --git
a/kms/src/main/java/org/apache/hadoop/crypto/key/DBToAzureKeyVault.java
b/kms/src/main/java/org/apache/hadoop/crypto/key/DBToAzureKeyVault.java
index bacc928..39de0a5 100644
--- a/kms/src/main/java/org/apache/hadoop/crypto/key/DBToAzureKeyVault.java
+++ b/kms/src/main/java/org/apache/hadoop/crypto/key/DBToAzureKeyVault.java
@@ -178,7 +178,7 @@ public class DBToAzureKeyVault {
System.err.println("Key Vault is null. Please
check the azure related configs.");
System.exit(1);
}
- RangerKeyVaultKeyGenerator rangerKVKeyGenerator = new
RangerKeyVaultKeyGenerator(
+ RangerKMSMKI rangerKVKeyGenerator = new
RangerAzureKeyVaultKeyGenerator(
conf, kvClient);
boolean azureMKSuccess =
rangerKVKeyGenerator.generateMasterKey(mKeyPass);
if (azureMKSuccess) {
diff --git a/kms/src/main/java/org/apache/hadoop/crypto/key/JKS2RangerUtil.java
b/kms/src/main/java/org/apache/hadoop/crypto/key/JKS2RangerUtil.java
index 4324439..a1a6f34 100644
--- a/kms/src/main/java/org/apache/hadoop/crypto/key/JKS2RangerUtil.java
+++ b/kms/src/main/java/org/apache/hadoop/crypto/key/JKS2RangerUtil.java
@@ -159,7 +159,7 @@ public class JKS2RangerUtil {
}
String azureClientSecret =
conf.get(AZURE_CLIENT_SECRET);
AzureKeyVaultClientAuthenticator
azureKVClientAuthenticator;
- RangerKeyVaultKeyGenerator rangerKVKeyGenerator
= null;
+ RangerKMSMKI rangerKVKeyGenerator = null;
KeyVaultClient kvClient = null;
if (conf != null
&&
StringUtils.isNotEmpty(conf.get(AZURE_KEYVAULT_SSL_ENABLED))
@@ -201,7 +201,7 @@ public class JKS2RangerUtil {
if (kvClient != null) {
try {
dbStore = new
RangerKeyStore(daoManager, conf, kvClient);
- rangerKVKeyGenerator = new
RangerKeyVaultKeyGenerator(
+ rangerKVKeyGenerator = new
RangerAzureKeyVaultKeyGenerator(
conf, kvClient);
if (rangerKVKeyGenerator !=
null) {
success =
rangerKVKeyGenerator
diff --git
a/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyVaultKeyGenerator.java
b/kms/src/main/java/org/apache/hadoop/crypto/key/RangerAzureKeyVaultKeyGenerator.java
similarity index 63%
rename from
kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyVaultKeyGenerator.java
rename to
kms/src/main/java/org/apache/hadoop/crypto/key/RangerAzureKeyVaultKeyGenerator.java
index c661268..138a897 100644
---
a/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyVaultKeyGenerator.java
+++
b/kms/src/main/java/org/apache/hadoop/crypto/key/RangerAzureKeyVaultKeyGenerator.java
@@ -28,19 +28,25 @@ import com.microsoft.azure.keyvault.webkey.JsonWebKeyType;
import java.security.Key;
+import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.joda.time.DateTime;
-public class RangerKeyVaultKeyGenerator implements RangerKMSMKI {
+public class RangerAzureKeyVaultKeyGenerator implements RangerKMSMKI {
static final Logger logger = LoggerFactory
- .getLogger(RangerKeyVaultKeyGenerator.class);
- private static final String AZURE_KEYVAULT_URL =
"ranger.kms.azurekeyvault.url";
- private static final String AZURE_MASTER_KEY_ALIAS =
"ranger.kms.azure.masterkey.name";
- private static final String AZURE_MASTER_KEY_TYPE =
"ranger.kms.azure.masterkey.type";
- private static final String ZONE_KEY_ENCRYPTION_ALGO =
"ranger.kms.azure.zonekey.encryption.algorithm";
+ .getLogger(RangerAzureKeyVaultKeyGenerator.class);
+ static final String AZURE_KEYVAULT_URL = "ranger.kms.azurekeyvault.url";
+ static final String AZURE_MASTER_KEY_ALIAS =
"ranger.kms.azure.masterkey.name";
+ static final String AZURE_MASTER_KEY_TYPE =
"ranger.kms.azure.masterkey.type";
+ static final String ZONE_KEY_ENCRYPTION_ALGO =
"ranger.kms.azure.zonekey.encryption.algorithm";
+ static final String AZURE_KEYVAULT_SSL_ENABLED =
"ranger.kms.azure.keyvault.ssl.enabled";
+ static final String AZURE_CLIENT_ID = "ranger.kms.azure.client.id";
+ static final String AZURE_CLIENT_SECRET =
"ranger.kms.azure.client.secret";
+ static final String AZURE_KEYVAULT_CERTIFICATE_PATH =
"ranger.kms.azure.keyvault.certificate.path";
+ static final String AZURE_KEYVAULT_CERTIFICATE_PASSWORD =
"ranger.kms.azure.keyvault.certificate.password";
private String keyVaultURL;
private String azureMasterKey;
private String azureMasterKeyType;
@@ -48,8 +54,8 @@ public class RangerKeyVaultKeyGenerator implements
RangerKMSMKI {
private KeyVaultClient keyVaultClient;
private KeyBundle masterKeyBundle;
- public RangerKeyVaultKeyGenerator(Configuration conf,
- KeyVaultClient kvClient) {
+ public RangerAzureKeyVaultKeyGenerator(Configuration conf,
+
KeyVaultClient kvClient) {
this.keyVaultURL = conf.get(AZURE_KEYVAULT_URL);
this.azureMasterKey = conf.get(AZURE_MASTER_KEY_ALIAS);
this.azureMasterKeyType = conf.get(AZURE_MASTER_KEY_TYPE);
@@ -57,6 +63,62 @@ public class RangerKeyVaultKeyGenerator implements
RangerKMSMKI {
this.keyVaultClient = kvClient;
}
+ public RangerAzureKeyVaultKeyGenerator(Configuration conf) throws
Exception {
+ this(conf, createKeyVaultClient(conf));
+ }
+
+ public static KeyVaultClient createKeyVaultClient(Configuration conf)
throws Exception {
+ AzureKeyVaultClientAuthenticator azureKVClientAuthenticator;
+ String azureClientId = conf.get(AZURE_CLIENT_ID);
+ if (StringUtils.isEmpty(azureClientId)) {
+ throw new Exception(
+ "Azure Key Vault is enabled and client
id is not configured");
+ }
+ String azureClientSecret = conf.get(AZURE_CLIENT_SECRET);
+ KeyVaultClient kvClient;
+ if (conf != null
+ &&
StringUtils.isNotEmpty(conf.get(AZURE_KEYVAULT_SSL_ENABLED))
+ &&
conf.get(AZURE_KEYVAULT_SSL_ENABLED).equalsIgnoreCase("false")) {
+ try {
+ if (StringUtils.isEmpty(azureClientSecret)) {
+ throw new Exception(
+ "Azure Key Vault is
enabled in non SSL mode and client password/secret is not configured");
+ }
+ azureKVClientAuthenticator = new
AzureKeyVaultClientAuthenticator(
+ azureClientId,
azureClientSecret);
+ kvClient = new
KeyVaultClient(azureKVClientAuthenticator);
+ } catch (Exception ex) {
+ throw new Exception(
+ "Error while getting key vault
client object with client id and client secret : "
+ + ex);
+ }
+ } else {
+ try {
+ azureKVClientAuthenticator = new
AzureKeyVaultClientAuthenticator(
+ azureClientId);
+ String keyVaultCertPath = conf
+
.get(AZURE_KEYVAULT_CERTIFICATE_PATH);
+ if (StringUtils.isEmpty(keyVaultCertPath)) {
+ throw new Exception(
+ "Azure Key Vault is
enabled in SSL mode. Please provide certificate path for authentication.");
+ }
+ String keyVaultCertPassword = conf
+
.get(AZURE_KEYVAULT_CERTIFICATE_PASSWORD);
+
+ kvClient =
!StringUtils.isEmpty(keyVaultCertPassword) ? azureKVClientAuthenticator
+
.getAuthentication(keyVaultCertPath,
+
keyVaultCertPassword)
+ :
azureKVClientAuthenticator.getAuthentication(
+ keyVaultCertPath, "");
+ } catch (Exception ex) {
+ throw new Exception(
+ "Error while getting key vault
client object with client id and certificate. Error : : "
+ + ex);
+ }
+ }
+ return kvClient;
+ }
+
@Override
public boolean generateMasterKey(String password) throws Exception {
if (keyVaultClient == null) {
diff --git a/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyStore.java
b/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyStore.java
index 5234dc7..8dc1290 100644
--- a/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyStore.java
+++ b/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyStore.java
@@ -91,8 +91,7 @@ public class RangerKeyStore extends KeyStoreSpi {
private static final String KEY_NAME_VALIDATION =
"[a-z,A-Z,0-9](?!.*--)(?!.*__)(?!.*-_)(?!.*_-)[\\w\\-\\_]*";
private static final Pattern pattern =
Pattern.compile(KEY_NAME_VALIDATION);
private static final String AZURE_KEYVAULT_ENABLED =
"ranger.kms.azurekeyvault.enabled";
- private boolean azureKeyVaultEnabled = false;
- private boolean isGCPHSMEnabled = false;
+ private boolean keyVaultEnabled = false;
private DaoManager daoManager;
private RangerKMSMKI masterKeyProvider;
@@ -126,7 +125,7 @@ public class RangerKeyStore extends KeyStoreSpi {
private Map<String, Object> keyEntries = new ConcurrentHashMap<>();
private Map<String, Object> deltaEntries = new ConcurrentHashMap<>();
- RangerKeyStore() {
+ public RangerKeyStore() {
}
public RangerKeyStore(DaoManager daoManager) {
@@ -135,20 +134,20 @@ public class RangerKeyStore extends KeyStoreSpi {
public RangerKeyStore(DaoManager daoManager, Configuration conf,
KeyVaultClient kvClient) {
this.daoManager = daoManager;
- this.masterKeyProvider = new RangerKeyVaultKeyGenerator(conf,
kvClient);
+ this.masterKeyProvider = new RangerAzureKeyVaultKeyGenerator(conf,
kvClient);
if(conf != null
&& StringUtils.isNotEmpty(conf
.get(AZURE_KEYVAULT_ENABLED))
&&
conf.get(AZURE_KEYVAULT_ENABLED).equalsIgnoreCase(
"true")){
- azureKeyVaultEnabled = true;
+ keyVaultEnabled = true;
}
}
- public RangerKeyStore(DaoManager daoManager, boolean isGcpEnabled,
RangerKMSMKI rangerGCPProvider) {
+ public RangerKeyStore(DaoManager daoManager, boolean keyVaultEnabled,
RangerKMSMKI masterKeyProvider) {
this.daoManager = daoManager;
- this.masterKeyProvider = rangerGCPProvider;
- this.isGCPHSMEnabled = isGcpEnabled;
+ this.masterKeyProvider = masterKeyProvider;
+ this.keyVaultEnabled = keyVaultEnabled;
}
String convertAlias(String alias) {
@@ -404,7 +403,7 @@ public class RangerKeyStore extends KeyStoreSpi {
logger.debug("==> RangerKeyStore.engineStore()");
}
synchronized (deltaEntries) {
- if (azureKeyVaultEnabled || isGCPHSMEnabled) {
+ if (keyVaultEnabled) {
for (Entry<String, Object> entry :
deltaEntries.entrySet()) {
Long creationDate =
((SecretKeyByteEntry) entry.getValue()).date
.getTime();
@@ -536,7 +535,7 @@ public class RangerKeyStore extends KeyStoreSpi {
}
keyEntries.clear();
- if (azureKeyVaultEnabled || isGCPHSMEnabled) {
+ if (keyVaultEnabled) {
for (XXRangerKeyStore rangerKey :
rangerKeyDetails) {
String encodedStr =
rangerKey.getEncoded();
byte[] encodedByte = DatatypeConverter
@@ -739,7 +738,7 @@ public class RangerKeyStore extends KeyStoreSpi {
}
synchronized (deltaEntries) {
KeyStore ks;
- if (azureKeyVaultEnabled || isGCPHSMEnabled) {
+ if (keyVaultEnabled) {
try {
ks = KeyStore.getInstance(fileFormat);
ks.load(stream, storePass);
@@ -929,7 +928,7 @@ public class RangerKeyStore extends KeyStoreSpi {
Key key;
while (e.hasMoreElements()) {
alias = e.nextElement();
- if(azureKeyVaultEnabled || isGCPHSMEnabled) {
+ if(keyVaultEnabled){
key = engineGetDecryptedZoneKey(alias);
} else {
key =
engineGetKey(alias, masterKey);
diff --git
a/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyStoreProvider.java
b/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyStoreProvider.java
index 74c54a7..18a6bee 100755
--- a/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyStoreProvider.java
+++ b/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyStoreProvider.java
@@ -17,7 +17,6 @@
package org.apache.hadoop.crypto.key;
-import com.microsoft.azure.keyvault.KeyVaultClient;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@@ -42,7 +41,6 @@ import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
-import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.ranger.plugin.util.JsonUtilsV2;
@@ -75,12 +73,11 @@ public class RangerKeyStoreProvider extends KeyProvider {
private static final String KEYSECURE_PASSWORD =
"ranger.kms.keysecure.login.password";
private static final String KEYSECURE_LOGIN =
"ranger.kms.keysecure.login";
private static final String AZURE_KEYVAULT_ENABLED =
"ranger.kms.azurekeyvault.enabled";
- private static final String AZURE_KEYVAULT_SSL_ENABLED =
"ranger.kms.azure.keyvault.ssl.enabled";
- private static final String AZURE_CLIENT_ID =
"ranger.kms.azure.client.id";
private static final String AZURE_CLIENT_SECRET_ALIAS =
"ranger.kms.azure.client.secret.alias";
private static final String AZURE_CLIENT_SECRET =
"ranger.kms.azure.client.secret";
- private static final String AZURE_KEYVAULT_CERTIFICATE_PATH =
"ranger.kms.azure.keyvault.certificate.path";
- private static final String AZURE_KEYVAULT_CERTIFICATE_PASSWORD =
"ranger.kms.azure.keyvault.certificate.password";
+ private static final String TENCENT_KMS_ENABLED =
"ranger.kms.tencentkms.enabled";
+ private static final String TENCENT_CLIENT_SECRET =
RangerTencentKMSProvider.TENCENT_CLIENT_SECRET;
+ private static final String TENCENT_CLIENT_SECRET_ALIAS =
"ranger.kms.tencent.client.secret.alias";
private static final String IS_GCP_ENABLED = "ranger.kms.gcp.enabled";
private RangerKeyStore dbStore;
private char[] masterKey;
@@ -88,10 +85,7 @@ public class RangerKeyStoreProvider extends KeyProvider {
private final Map<String, Metadata> cache = new HashMap<String,
Metadata>();
private DaoManager daoManager;
private Lock readLock;
- private boolean isHSMEnabled = false;
- private boolean azureKeyVaultEnabled = false;
- private boolean isGCPEnabled = false;
- private boolean isKeySecureEnabled = false;
+ private boolean keyVaultEnabled = false;
public RangerKeyStoreProvider(Configuration conf) throws Throwable {
super(conf);
@@ -115,12 +109,14 @@ public class RangerKeyStoreProvider extends KeyProvider {
"The Ranger MasterKey Password is empty
or not a valid Password");
}
- this.isHSMEnabled = conf.getBoolean(HSM_ENABLED, false);
- this.azureKeyVaultEnabled =
conf.getBoolean(AZURE_KEYVAULT_ENABLED, false);
- this.isGCPEnabled = conf.getBoolean(IS_GCP_ENABLED, false);
- this.isKeySecureEnabled = conf.getBoolean(KEYSECURE_ENABLED,
false);
+ boolean isHSMEnabled = conf.getBoolean(HSM_ENABLED, false);
+ boolean isKeySecureEnabled = conf.getBoolean(KEYSECURE_ENABLED,
false);
+ boolean isAzureKeyVaultEnabled =
conf.getBoolean(AZURE_KEYVAULT_ENABLED, false);
+ boolean isGCPEnabled = conf.getBoolean(IS_GCP_ENABLED, false);
+ boolean isTencentKMSEnabled =
conf.getBoolean(TENCENT_KMS_ENABLED, false);
+ this.keyVaultEnabled = isAzureKeyVaultEnabled || isGCPEnabled
|| isTencentKMSEnabled;
- if(this.isHSMEnabled) {
+ if (isHSMEnabled) {
logger.info("Ranger KMS HSM is enabled for storing
master key.");
masterKeyProvider = new RangerHSM(conf);
String partitionPasswd =
conf.get(HSM_PARTITION_PASSWORD);
@@ -129,7 +125,18 @@ public class RangerKeyStoreProvider extends KeyProvider {
||
partitionPasswd.trim().equals("crypted")) {
throw new IOException("Partition Password
doesn't exists");
}
- } else if (this.isKeySecureEnabled) {
+ dbStore = new RangerKeyStore(daoManager);
+ // generate master key on HSM
+ masterKeyProvider.generateMasterKey(password);
+ try {
+ masterKey =
masterKeyProvider.getMasterKey(password)
+ .toCharArray();
+ } catch (Exception ex) {
+ throw new Exception(
+ "Error while getting Safenet
KeySecure master key "
+ + ex);
+ }
+ } else if (isKeySecureEnabled) {
logger.info("KeySecure is enabled for storing the
master key.");
getFromJceks(conf, CREDENTIAL_PATH,
KEYSECURE_PASSWORD_ALIAS,
KEYSECURE_PASSWORD);
@@ -151,93 +158,42 @@ public class RangerKeyStoreProvider extends KeyProvider {
+ ex);
}
- } else if (this.azureKeyVaultEnabled) {
+ } else if (isAzureKeyVaultEnabled) {
logger.info("Azure Key Vault is enabled for storing the
master key.");
- azureKeyVaultEnabled = true;
getFromJceks(conf, CREDENTIAL_PATH,
AZURE_CLIENT_SECRET_ALIAS,
AZURE_CLIENT_SECRET);
- String azureClientId = conf.get(AZURE_CLIENT_ID);
- if (StringUtils.isEmpty(azureClientId)) {
+ try {
+ masterKeyProvider = new
RangerAzureKeyVaultKeyGenerator(conf);
+ masterKeyProvider.onInitialization();
+ dbStore = new RangerKeyStore(daoManager, true,
masterKeyProvider);
+ // ensure master key exist
+ masterKeyProvider.generateMasterKey(password);
+ } catch (Exception ex) {
throw new Exception(
- "Azure Key Vault is enabled and
client id is not configured");
- }
- String azureClientSecret =
conf.get(AZURE_CLIENT_SECRET);
- AzureKeyVaultClientAuthenticator
azureKVClientAuthenticator;
- KeyVaultClient kvClient = null;
- if (conf != null
- &&
StringUtils.isNotEmpty(conf.get(AZURE_KEYVAULT_SSL_ENABLED))
- &&
conf.get(AZURE_KEYVAULT_SSL_ENABLED).equalsIgnoreCase("false")) {
- try {
- if
(StringUtils.isEmpty(azureClientSecret)) {
- throw new Exception(
- "Azure Key
Vault is enabled in non SSL mode and client password/secret is not configured");
- }
- azureKVClientAuthenticator = new
AzureKeyVaultClientAuthenticator(
- azureClientId,
azureClientSecret);
- kvClient = new
KeyVaultClient(azureKVClientAuthenticator);
- } catch (Exception ex) {
- throw new Exception(
- "Error while getting
key vault client object with client id and client secret : "
- + ex);
- }
- } else {
- try {
- azureKVClientAuthenticator = new
AzureKeyVaultClientAuthenticator(
- azureClientId);
- String keyVaultCertPath = conf
-
.get(AZURE_KEYVAULT_CERTIFICATE_PATH);
- if
(StringUtils.isEmpty(keyVaultCertPath)) {
- throw new Exception(
- "Azure Key
Vault is enabled in SSL mode. Please provide certificate path for
authentication.");
- }
- String keyVaultCertPassword = conf
-
.get(AZURE_KEYVAULT_CERTIFICATE_PASSWORD);
-
- kvClient =
!StringUtils.isEmpty(keyVaultCertPassword) ? azureKVClientAuthenticator
-
.getAuthentication(keyVaultCertPath,
-
keyVaultCertPassword)
- :
azureKVClientAuthenticator.getAuthentication(
-
keyVaultCertPath, "");
- } catch (Exception ex) {
- throw new Exception(
- "Error while getting
key vault client object with client id and certificate. Error : : "
- + ex);
- }
+ "Error while generating master
key and master key secret in Azure Key Vault. Error : "
+ + ex);
}
- boolean success = false;
- if (kvClient != null) {
- try {
- dbStore = new
RangerKeyStore(daoManager, conf, kvClient);
- masterKeyProvider = new
RangerKeyVaultKeyGenerator(conf,
- kvClient);
- if (masterKeyProvider != null) {
- success =
masterKeyProvider.generateMasterKey(password);
- }
- } catch (Exception ex) {
- throw new Exception(
- "Error while generating
master key and master key secret in Azure key vault. Error : : "
- + ex);
- }
- } else {
+ } else if (isTencentKMSEnabled) {
+ logger.info("Ranger KMS Tencent KMS is enabled for
storing master key.");
+ getFromJceks(conf, CREDENTIAL_PATH,
TENCENT_CLIENT_SECRET_ALIAS,
+ TENCENT_CLIENT_SECRET);
+ try {
+ masterKeyProvider = new
RangerTencentKMSProvider(conf);
+ masterKeyProvider.onInitialization();
+ dbStore = new RangerKeyStore(daoManager, true,
masterKeyProvider);
+ // ensure master key exist
+ masterKeyProvider.generateMasterKey(password);
+ } catch (Exception ex) {
throw new Exception(
- "Unable to get Key Vault
Client. Please check the azure credentials.");
- }
- if (success) {
- try {
- /* Master key not exportable from key
vault */
- masterKey = null;
- } catch (Exception ex) {
- throw new Exception(
- "Error while getting
Azure Master key Secret. Error : "
- + ex);
- }
+ "Error while generating master
key and master key secret in Tencent KMS. Error : "
+ + ex);
}
- } else if(this.isGCPEnabled) {
+ } else if (isGCPEnabled) {
logger.info("Google Cloud HSM is enabled for storing
the master key.");
masterKeyProvider = new RangerGoogleCloudHSMProvider(conf);
masterKeyProvider.onInitialization();
if(masterKeyProvider != null) {
- this.dbStore = new RangerKeyStore(daoManager,
this.isGCPEnabled, masterKeyProvider);
+ this.dbStore = new RangerKeyStore(daoManager, true,
masterKeyProvider);
masterKeyProvider.generateMasterKey(password);
}
} else {
@@ -346,7 +302,7 @@ public class RangerKeyStoreProvider extends KeyProvider {
}
try {
String attribute = JsonUtilsV2.mapToJson(attributes);
- if (azureKeyVaultEnabled || this.isGCPEnabled) {
+ if (keyVaultEnabled) {
dbStore.addSecureKeyByteEntry(versionName, new
SecretKeySpec(
material, cipher), cipher,
bitLength, description,
version, attribute);
@@ -409,7 +365,7 @@ public class RangerKeyStoreProvider extends KeyProvider {
Metadata metadata = entry.getValue();
String attributes =
JsonUtilsV2.mapToJson(metadata
.getAttributes());
- if (azureKeyVaultEnabled ||
this.isGCPEnabled) {
+ if (keyVaultEnabled) {
Key ezkey = new
KeyMetadata(metadata);
if (ezkey.getEncoded().length
== 0) {
KeyGenerator
keyGenerator = KeyGenerator
@@ -457,7 +413,7 @@ public class RangerKeyStoreProvider extends KeyProvider {
readLock.lock();
try {
- if (azureKeyVaultEnabled || this.isGCPEnabled) {
+ if (keyVaultEnabled) {
byte[] decryptKeyByte = null;
try {
if
(!dbStore.engineContainsAlias(versionName)) {
@@ -570,7 +526,7 @@ public class RangerKeyStoreProvider extends KeyProvider {
return null;
}
}
- if (azureKeyVaultEnabled || this.isGCPEnabled) {
+ if (keyVaultEnabled) {
Metadata meta =
dbStore.engineGetKeyMetadata(name);
if (meta != null) {
cache.put(name, meta);
diff --git
a/kms/src/main/java/org/apache/hadoop/crypto/key/RangerTencentKMSProvider.java
b/kms/src/main/java/org/apache/hadoop/crypto/key/RangerTencentKMSProvider.java
new file mode 100644
index 0000000..1f01259
--- /dev/null
+++
b/kms/src/main/java/org/apache/hadoop/crypto/key/RangerTencentKMSProvider.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.hadoop.crypto.key;
+
+import com.tencentcloudapi.common.Credential;
+import com.tencentcloudapi.common.exception.TencentCloudSDKException;
+import com.tencentcloudapi.kms.v20190118.KmsClient;
+import com.tencentcloudapi.kms.v20190118.models.*;
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.charset.StandardCharsets;
+import java.security.Key;
+import java.util.Base64;
+
+public class RangerTencentKMSProvider implements RangerKMSMKI {
+
+ static final Logger logger =
LoggerFactory.getLogger(RangerTencentKMSProvider.class);
+ static final String TENCENT_MASTER_KEY_ID =
"ranger.kms.tencent.masterkey.id";
+ static final String TENCENT_CLIENT_ID = "ranger.kms.tencent.client.id";
+ static final String TENCENT_CLIENT_SECRET =
"ranger.kms.tencent.client.secret";
+ static final String TENCENT_CLIENT_REGION =
"ranger.kms.tencent.client.region";
+ private String masterKeyId;
+ private KeyMetadata masterKeyMetadata;
+ private KmsClient keyVaultClient;
+
+ protected RangerTencentKMSProvider(Configuration conf,
+
KmsClient client) {
+ this.masterKeyId = conf.get(TENCENT_MASTER_KEY_ID);
+ this.keyVaultClient = client;
+ }
+
+ public RangerTencentKMSProvider(Configuration conf) throws Exception {
+ this(conf, createKMSClient(conf));
+ }
+
+ public static KmsClient createKMSClient(Configuration conf) throws
Exception {
+ String tencentClientId = conf.get(TENCENT_CLIENT_ID);
+ if (StringUtils.isEmpty(tencentClientId)) {
+ throw new Exception(
+ "Tencent KMS is enabled, but client id
is not configured");
+ }
+ String tencentClientSecret = conf.get(TENCENT_CLIENT_SECRET);
+ String tencentClientRegion = conf.get(TENCENT_CLIENT_REGION);
+ return new KmsClient(
+ new Credential(tencentClientId,
tencentClientSecret),
+ tencentClientRegion);
+ }
+
+ @Override
+ public boolean generateMasterKey(String password) throws Exception {
+ if (keyVaultClient == null) {
+ throw new Exception(
+ "Key Vault Client is null. Please check
the azure related configuration.");
+ }
+ try {
+
+ DescribeKeyRequest desckey_req = new
DescribeKeyRequest();
+ desckey_req.setKeyId(masterKeyId);
+ DescribeKeyResponse desckey_resp =
keyVaultClient.DescribeKey(desckey_req);
+ if (desckey_resp == null ||
!desckey_resp.getKeyMetadata().getKeyId().equals(masterKeyId)) {
+ throw new Exception("KetMetadata is invalid");
+ }
+ masterKeyMetadata = desckey_resp.getKeyMetadata();
+ } catch (TencentCloudSDKException ex) {
+ throw new Exception(
+ "Error while getting existing master
key from Tencent. Master Key Id : "
+ + masterKeyId + " .
Error : " + ex.getMessage());
+ }
+ if (masterKeyMetadata == null) {
+ throw new NoSuchMethodException("generateMasterKey is
not implemented for Tencent KMS");
+ } else {
+ logger.info("Tencent Master key exist with KeyId :" +
masterKeyId
+ + " with Alias: " +
masterKeyMetadata.getAlias()
+ + " with Description : " +
masterKeyMetadata.getDescription()
+ + " with ResourceId : " +
masterKeyMetadata.getResourceId());
+ return true;
+ }
+ }
+
+ @Override
+ public byte[] encryptZoneKey(Key zoneKey) throws Exception {
+ try {
+ EncryptRequest req = new EncryptRequest();
+ req.setKeyId(this.masterKeyId);
+
req.setPlaintext(Base64.getEncoder().encodeToString(zoneKey.getEncoded()));
+ EncryptResponse resp = keyVaultClient.Encrypt(req);
+ // resp.getCiphertextBlob() returns something looks
like base64 encoded.
+ // It is actually a concatenation of several base64
encoded fragments.
+ // Maybe Tencent KMS will use the separation
information of fragments.
+ // So we MUST NOT decode base64 here.
+ return
resp.getCiphertextBlob().getBytes(StandardCharsets.US_ASCII);
+ } catch (TencentCloudSDKException e) {
+ throw (Exception)new Exception("Error while encrypting
zone key.").initCause(e);
+ }
+ }
+
+ @Override
+ public byte[] decryptZoneKey(byte[] encryptedByte) throws Exception {
+ try {
+ DecryptRequest req = new DecryptRequest();
+ req.setCiphertextBlob(new String(encryptedByte,
StandardCharsets.US_ASCII));
+ DecryptResponse resp = keyVaultClient.Decrypt(req);
+ return Base64.getDecoder().decode(resp.getPlaintext());
+ } catch (TencentCloudSDKException e) {
+ throw (Exception)new Exception("Error while decrypting
zone key.").initCause(e);
+ }
+ }
+
+ @Override
+ public String getMasterKey(String masterKeySecretName) {
+ /*
+ * This method is not require for Tencent KMS because we can't
get
+ * key outside of KMS
+ */
+ return null;
+ }
+}
diff --git a/pom.xml b/pom.xml
index 8a19c2d..5e844ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -217,7 +217,7 @@
<presto.validation-api.version>2.0.1.Final</presto.validation-api.version>
<presto.re2j.version>1.1</presto.re2j.version>
- <!-- Azure Key Vault dependencies -->
+ <!-- Azure Key Vault dependencies -->
<com.microsoft.azure.version>1.22.0</com.microsoft.azure.version>
<com.microsoft.azure.azure-keyvault.version>1.2.1</com.microsoft.azure.azure-keyvault.version>
<com.microsoft.azure.azure-mgmt-keyvault.version>1.22.0</com.microsoft.azure.azure-mgmt-keyvault.version>
@@ -234,6 +234,7 @@
<jsonsmart.version>2.3.1</jsonsmart.version>
<nimbus-jose-jwt.version>8.22.1</nimbus-jose-jwt.version>
<com.amazonaws.aws-java-sdk-bom.version>1.12.125</com.amazonaws.aws-java-sdk-bom.version>
+
<!-- GCP HSM -->
<google.cloud.kms>2.3.0</google.cloud.kms>
@@ -242,6 +243,9 @@
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.language>java</sonar.language>
+
+ <!-- Tencent KMS depencies -->
+
<com.tencentcloudapi.sdk.version>3.1.322</com.tencentcloudapi.sdk.version>
</properties>
<profiles>
<profile>