blob: dfcab8b9c957055f4e5ae2995095b919c3705d3d [file] [log] [blame]
/*
* 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.knox.gateway.services.security;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.services.ServiceLifecycleException;
import org.apache.knox.gateway.services.security.impl.ConfigurableEncryptor;
import org.apache.knox.gateway.services.security.impl.DefaultCryptoService;
import org.apache.knox.test.category.ManualTests;
import org.apache.knox.test.category.MediumTests;
import org.easymock.EasyMock;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import java.nio.charset.StandardCharsets;
import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.assertEquals;
@Category( { ManualTests.class, MediumTests.class } )
public class CryptoServiceTest {
private static CryptoService cs;
private static AliasService as;
@BeforeClass
public static void setupSuite() throws Exception {
as = new AliasService() {
@Override
public void init(GatewayConfig config, Map<String, String> options)
throws ServiceLifecycleException {
}
@Override
public void start() throws ServiceLifecycleException {
}
@Override
public void stop() throws ServiceLifecycleException {
}
@Override
public void addAliasForCluster(String clusterName, String alias,
String value) {
}
@Override
public void addAliasesForCluster(String clusterName, Map<String, String> credentials) throws AliasServiceException {
for (Map.Entry<String, String> credential : credentials.entrySet()) {
addAliasForCluster(clusterName, credential.getKey(), credential.getValue());
}
}
@Override
public char[] getPasswordFromAliasForCluster(String clusterName,
String alias) {
return "password".toCharArray();
}
@Override
public char[] getPasswordFromAliasForCluster(String clusterName,
String alias, boolean generate) {
return null;
}
@Override
public void generateAliasForCluster(String clusterName, String alias) {
}
@Override
public char[] getPasswordFromAliasForGateway(String alias) {
return null;
}
@Override
public void generateAliasForGateway(String alias) {
}
@Override
public Certificate getCertificateForGateway(String alias) {
return null;
}
@Override
public void removeAliasForCluster(String clusterName, String alias) {
}
@Override
public void removeAliasesForCluster(String clusterName, Set<String> aliases) throws AliasServiceException {
}
@Override
public List<String> getAliasesForCluster(String clusterName) {
return null;
}
@Override
public char[] getGatewayIdentityPassphrase() throws AliasServiceException {
return null;
}
@Override
public char[] getGatewayIdentityKeystorePassword() throws AliasServiceException {
return null;
}
@Override
public char[] getSigningKeyPassphrase() throws AliasServiceException {
return new char[0];
}
@Override
public char[] getSigningKeystorePassword() throws AliasServiceException {
return new char[0];
}
};
cs = new DefaultCryptoService();
((DefaultCryptoService)cs).setAliasService(as);
}
@Test
public void testCryptoServiceAES() throws Exception {
GatewayConfig config = EasyMock.createNiceMock( GatewayConfig.class );
EasyMock.expect(config.getAlgorithm()).andReturn("AES");
EasyMock.expect(config.getPBEAlgorithm()).andReturn("PBKDF2WithHmacSHA1");
EasyMock.expect(config.getSaltSize()).andReturn("16");
EasyMock.expect(config.getIterationCount()).andReturn("65536");
EasyMock.expect(config.getKeyLength()).andReturn("128");
EasyMock.expect(config.getTransformation()).andReturn("AES/CBC/PKCS5Padding");
EasyMock.replay(config);
// password to create key - same Encryptor
String queryString = "url=http://localhost:50070/api/v1/blahblah";
ConfigurableEncryptor aes0 = new ConfigurableEncryptor("password");
aes0.init(config);
cs.init(config, new HashMap<>());
EncryptionResult result0 = cs.encryptForCluster("Test", "encrypt_url", queryString.getBytes(StandardCharsets.UTF_8));
byte[] decrypted0 = cs.decryptForCluster("Test", "encrypt_url", result0.cipher, result0.iv, result0.salt);
assertEquals(queryString, new String(decrypted0, StandardCharsets.UTF_8));
assertEquals(queryString.getBytes(StandardCharsets.UTF_8).length, decrypted0.length);
assertEquals(queryString.getBytes(StandardCharsets.UTF_8).length, new String(decrypted0, StandardCharsets.UTF_8).toCharArray().length);
}
@Test
public void testCryptoServiceDES() throws Exception {
GatewayConfig config = EasyMock.createNiceMock( GatewayConfig.class );
EasyMock.expect(config.getAlgorithm()).andReturn("DES");
EasyMock.expect(config.getPBEAlgorithm()).andReturn("PBKDF2WithHmacSHA1");
EasyMock.expect(config.getSaltSize()).andReturn("16");
EasyMock.expect(config.getIterationCount()).andReturn("65536");
EasyMock.expect(config.getKeyLength()).andReturn("128");
EasyMock.expect(config.getTransformation()).andReturn("DES");
EasyMock.replay(config);
// password to create key - same Encryptor
String queryString = "url=http://localhost:50070/api/v1/blahblah";
ConfigurableEncryptor aes0 = new ConfigurableEncryptor("password");
aes0.init(config);
cs.init(config, new HashMap<>());
EncryptionResult result0 = cs.encryptForCluster("Test", "encrypt_url", queryString.getBytes(StandardCharsets.UTF_8));
byte[] decrypted0 = cs.decryptForCluster("Test", "encrypt_url", result0.cipher, result0.iv, result0.salt);
assertEquals(queryString, new String(decrypted0, StandardCharsets.UTF_8));
assertEquals(queryString.getBytes(StandardCharsets.UTF_8).length, decrypted0.length);
assertEquals(queryString.getBytes(StandardCharsets.UTF_8).length, new String(decrypted0, StandardCharsets.UTF_8).toCharArray().length);
}
@Test
public void testConfigurableEncryptor() throws Exception {
GatewayConfig config = EasyMock.createNiceMock( GatewayConfig.class );
EasyMock.expect(config.getAlgorithm()).andReturn("AES");
EasyMock.expect(config.getPBEAlgorithm()).andReturn("PBKDF2WithHmacSHA1");
EasyMock.expect(config.getSaltSize()).andReturn("16");
EasyMock.expect(config.getIterationCount()).andReturn("65536");
EasyMock.expect(config.getKeyLength()).andReturn("128");
EasyMock.expect(config.getTransformation()).andReturn("AES/CBC/PKCS5Padding");
EasyMock.replay(config);
// password to create key - same Encryptor
ConfigurableEncryptor aes = new ConfigurableEncryptor("Test");
aes.init(config);
EncryptionResult result = aes.encrypt("larry".getBytes(StandardCharsets.UTF_8));
byte[] decrypted = aes.decrypt(result.salt, result.iv, result.cipher);
assertEquals(new String(decrypted, StandardCharsets.UTF_8), "larry");
// password to create key - different Encryptor
ConfigurableEncryptor aes2 = new ConfigurableEncryptor("Test");
aes2.init(config);
decrypted = aes2.decrypt(result.salt, result.iv, result.cipher);
assertEquals(new String(decrypted, StandardCharsets.UTF_8), "larry");
// password to create key resolved from alias - same Encryptor
ConfigurableEncryptor aes3 = new ConfigurableEncryptor(new String(as.getPasswordFromAliasForCluster("test", "encrypt_url")));
aes3.init(config);
result = aes3.encrypt("larry".getBytes(StandardCharsets.UTF_8));
decrypted = aes3.decrypt(result.salt, result.iv, result.cipher);
assertEquals(new String(decrypted, StandardCharsets.UTF_8), "larry");
// password to create key resolved from alias - different Encryptor
ConfigurableEncryptor aes4 = new ConfigurableEncryptor(new String(as.getPasswordFromAliasForCluster("test", "encrypt_url")));
aes4.init(config);
decrypted = aes4.decrypt(result.salt, result.iv, result.cipher);
assertEquals(new String(decrypted, StandardCharsets.UTF_8), "larry");
}
@Test
//@Ignore
public void testEncryptionOfQueryStrings() throws Exception {
String alias = "encrypt-url";
String queryString = "url=http://localhost:50070/api/v1/blahblah";
EncryptionResult result = cs.encryptForCluster("Test", alias, queryString.getBytes(StandardCharsets.UTF_8));
assertEquals("Resulted cipertext length should be a multiple of 16", 0, (result.cipher.length % 16));
byte[] decryptedQueryString = cs.decryptForCluster("Test", alias, result.cipher, result.iv, result.salt);
assertEquals(queryString.getBytes(StandardCharsets.UTF_8).length, decryptedQueryString.length);
}
}