Repository: ranger Updated Branches: refs/heads/ranger-0.7 98da92207 -> 50ef5f0fd
RANGER-1639 : Ranger KMS should validate key name before importing into DB Project: http://git-wip-us.apache.org/repos/asf/ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/ranger/commit/50ef5f0f Tree: http://git-wip-us.apache.org/repos/asf/ranger/tree/50ef5f0f Diff: http://git-wip-us.apache.org/repos/asf/ranger/diff/50ef5f0f Branch: refs/heads/ranger-0.7 Commit: 50ef5f0fd94f29debb81bffb15d2aefe6dad4381 Parents: 98da922 Author: Ankita Sinha <[email protected]> Authored: Fri Jun 23 10:44:51 2017 +0530 Committer: Ankita Sinha <[email protected]> Committed: Mon Jul 10 15:40:06 2017 +0530 ---------------------------------------------------------------------- .../hadoop/crypto/key/RangerKeyStore.java | 20 ++- .../crypto/key/kms/TestRangerKeyStore.java | 156 +++++++++++++++++++ 2 files changed, 173 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ranger/blob/50ef5f0f/kms/src/main/java/org/apache/hadoop/crypto/key/RangerKeyStore.java ---------------------------------------------------------------------- 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 a001c08..4b1b9bb 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 @@ -42,11 +42,12 @@ import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; -import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.crypto.SealedObject; import javax.xml.bind.DatatypeConverter; @@ -64,6 +65,8 @@ import org.apache.ranger.kms.dao.RangerKMSDao; public class RangerKeyStore extends KeyStoreSpi { static final Logger logger = Logger.getLogger(RangerKeyStore.class); + 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 DaoManager daoManager; @@ -89,7 +92,7 @@ public class RangerKeyStore extends KeyStoreSpi { RangerKeyStore() { } - RangerKeyStore(DaoManager daoManager) { + public RangerKeyStore(DaoManager daoManager) { this.daoManager = daoManager; } @@ -526,6 +529,7 @@ public class RangerKeyStore extends KeyStoreSpi { entry.cipher_field = k.getAlgorithm(); } String keyName = alias.split("@")[0]; + validateKeyName(keyName); entry.attributes = "{\"key.acl.name\":\"" + keyName + "\"}"; Class<?> c = null; Object o = null; @@ -581,7 +585,17 @@ public class RangerKeyStore extends KeyStoreSpi { } } } - + + private void validateKeyName(String name) { + Matcher matcher = pattern.matcher(name); + if (!matcher.matches()) { + throw new IllegalArgumentException( + "Key Name : " + + name + + ", should start with alpha/numeric letters and can have special characters - (hypen) or _ (underscore)"); + } + } + public void clearDeltaEntires(){ deltaEntries.clear(); } http://git-wip-us.apache.org/repos/asf/ranger/blob/50ef5f0f/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerKeyStore.java ---------------------------------------------------------------------- diff --git a/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerKeyStore.java b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerKeyStore.java new file mode 100644 index 0000000..f366964 --- /dev/null +++ b/kms/src/test/java/org/apache/hadoop/crypto/key/kms/TestRangerKeyStore.java @@ -0,0 +1,156 @@ +/* + * 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.kms; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +import javax.crypto.KeyGenerator; + +import org.apache.hadoop.crypto.key.RangerKeyStore; +import org.apache.ranger.kms.dao.DaoManager; +import org.junit.After; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestRangerKeyStore { + + String fileFormat = "jceks"; + String keyStoreFileName = "KmsKeyStoreFile"; + char[] storePass = "none".toCharArray(); + char[] keyPass = "none".toCharArray(); + char[] masterKey = "MasterPassword".toCharArray(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void checkFileIfExists() { + deleteKeyStoreFile(); + } + + @After + public void cleanKeystoreFile() { + deleteKeyStoreFile(); + } + + @Test(expected=IOException.class) + public void testInvalidKey1() throws NoSuchAlgorithmException, + CertificateException, IOException, KeyStoreException { + + DaoManager daoManager = Mockito.mock(DaoManager.class); + RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager); + String keyValue = "enckey:1"; + rangerKeyStore.engineLoadKeyStoreFile(generateKeyStoreFile(keyValue),storePass, keyPass, masterKey, fileFormat); + } + + @Test(expected=IOException.class) + public void testInvalidKey2() throws NoSuchAlgorithmException, + CertificateException, IOException, KeyStoreException { + + DaoManager daoManager = Mockito.mock(DaoManager.class); + RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager); + String keyValue = "1%enckey"; + rangerKeyStore.engineLoadKeyStoreFile(generateKeyStoreFile(keyValue),storePass, keyPass, masterKey, fileFormat); + } + + @Test(expected=IOException.class) + public void testInvalidKey3() throws NoSuchAlgorithmException, + CertificateException, IOException, KeyStoreException { + + DaoManager daoManager = Mockito.mock(DaoManager.class); + RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager); + String keyValue = "1 enckey"; + rangerKeyStore.engineLoadKeyStoreFile(generateKeyStoreFile(keyValue),storePass, keyPass, masterKey, fileFormat); + } + + @Test(expected=IOException.class) + public void testInvalidKey4() throws NoSuchAlgorithmException, + CertificateException, IOException, KeyStoreException { + + DaoManager daoManager = Mockito.mock(DaoManager.class); + RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager); + String keyValue = "_1-enckey"; + rangerKeyStore.engineLoadKeyStoreFile(generateKeyStoreFile(keyValue),storePass, keyPass, masterKey, fileFormat); + } + + @Test + public void testValidKey1() throws NoSuchAlgorithmException, + CertificateException, IOException, KeyStoreException { + + DaoManager daoManager = Mockito.mock(DaoManager.class); + RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager); + String keyValue = "enckey_1-test"; + rangerKeyStore.engineLoadKeyStoreFile(generateKeyStoreFile(keyValue),storePass, keyPass, masterKey, fileFormat); + } + + @Test + public void testValidKey2() throws NoSuchAlgorithmException, + CertificateException, IOException, KeyStoreException { + + DaoManager daoManager = Mockito.mock(DaoManager.class); + RangerKeyStore rangerKeyStore = new RangerKeyStore(daoManager); + String keyValue = "1-enckey_test"; + rangerKeyStore.engineLoadKeyStoreFile(generateKeyStoreFile(keyValue),storePass, keyPass, masterKey, fileFormat); + } + + private InputStream generateKeyStoreFile(String keyValue) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { + FileOutputStream stream = new FileOutputStream(new File(keyStoreFileName)); + KeyStore ks; + try { + ks = KeyStore.getInstance(fileFormat); + if (ks != null) { + ks.load(null, storePass); + String alias = keyValue; + + KeyGenerator kg = KeyGenerator.getInstance("AES"); + kg.init(256); + Key key = kg.generateKey(); + ks.setKeyEntry(alias, key, keyPass, null); + ks.store(stream, storePass); + } + return new FileInputStream(new File(keyStoreFileName)); + } catch (Throwable t) { + throw new IOException(t); + } + } + + private void deleteKeyStoreFile() { + File f = new File(keyStoreFileName); + if (f.exists()) { + f.delete(); + } + } +}
