blob: 973de1522c0a854febebadb627dc1edc15d4d8b3 [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.sqoop.tools.tool;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.log4j.Logger;
import org.apache.sqoop.cli.SqoopGnuParser;
import org.apache.sqoop.common.MapContext;
import org.apache.sqoop.common.SqoopException;
import org.apache.sqoop.connector.ConnectorManager;
import org.apache.sqoop.core.SqoopConfiguration;
import org.apache.sqoop.repository.MasterKeyManager;
import org.apache.sqoop.repository.Repository;
import org.apache.sqoop.repository.RepositoryManager;
import org.apache.sqoop.repository.RepositoryTransaction;
import org.apache.sqoop.security.SecurityConstants;
import org.apache.sqoop.security.SecurityError;
import org.apache.sqoop.tools.ConfiguredTool;
import org.apache.sqoop.utils.PasswordUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class RepositoryEncryptionTool extends ConfiguredTool {
public static final Logger LOG = Logger.getLogger(RepositoryDumpTool.class);
private static String FROM_OPTION = "F";
private static String TO_OPTION = "T";
private static String USE_CONFIGURATION = "useConf";
@Override
public boolean runToolWithConfiguration(String[] arguments) {
Options options = new Options();
options.addOption(OptionBuilder.hasArgs().withValueSeparator().create(FROM_OPTION));
options.addOption(OptionBuilder.hasArgs().withValueSeparator().create(TO_OPTION));
CommandLineParser parser = new SqoopGnuParser();
SqoopConfiguration.getInstance().initialize();
RepositoryManager.getInstance().initialize();
ConnectorManager.getInstance().initialize();
Repository repository = RepositoryManager.getInstance().getRepository();
CommandLine line;
try {
line = parser.parse(options, arguments);
} catch (ParseException e) {
LOG.error("Error parsing command line arguments:", e);
System.out.println("Error parsing command line arguments. Please check Server logs for details.");
return false;
}
Properties fromProperties = line.getOptionProperties(FROM_OPTION);
Properties toProperties = line.getOptionProperties(TO_OPTION);
RepositoryTransaction repositoryTransaction = null;
boolean successful = true;
try {
repositoryTransaction = repository.getTransaction();
repositoryTransaction.begin();
MasterKeyManager fromMasterKeyManager = null;
MasterKeyManager toMasterKeyManager = null;
if (!fromProperties.isEmpty()) {
fromMasterKeyManager = initializeMasterKeyManagerFromProperties(fromProperties, false, repositoryTransaction);
} else {
// Check to make sure there is no master key to prevent corruption
if (repository.getMasterKey(repositoryTransaction) != null) {
System.out.println("Repository is encrypted, need configuration to decrypt");
throw new SqoopException(SecurityError.ENCRYPTION_0013);
}
}
if (!toProperties.isEmpty()) {
toMasterKeyManager = initializeMasterKeyManagerFromProperties(toProperties, true, repositoryTransaction);
}
repository.changeMasterKeyManager(fromMasterKeyManager, toMasterKeyManager, repositoryTransaction);
if (fromMasterKeyManager != null) {
fromMasterKeyManager.deleteMasterKeyFromRepository();
fromMasterKeyManager.destroy();
}
repositoryTransaction.commit();
System.out.println("Changes committed");
} catch (Exception ex) {
if (repositoryTransaction != null) {
repositoryTransaction.rollback();
}
System.out.println("Error running tool. Please check Server logs for details.");
LOG.error(new SqoopException(SecurityError.ENCRYPTION_0012, ex));
successful = false;
} finally {
if (repositoryTransaction != null) {
repositoryTransaction.close();
}
}
return successful;
}
private MasterKeyManager initializeMasterKeyManagerFromProperties(Properties properties, boolean readFromRepository, RepositoryTransaction transaction) {
MasterKeyManager masterKeyManager = new MasterKeyManager();
if (properties.getProperty(USE_CONFIGURATION) != null) {
masterKeyManager.initialize(true, readFromRepository, transaction);
} else {
String hmacAlgorithm = properties.getProperty(SecurityConstants.REPO_ENCRYPTION_HMAC_ALGORITHM);
String cipherAlgorithm = properties.getProperty(SecurityConstants.REPO_ENCRYPTION_CIPHER_ALGORITHM);
String cipherSpec = properties.getProperty(SecurityConstants.REPO_ENCRYPTION_CIPHER_SPEC);
int cipherKeySize = Integer.parseInt(properties.getProperty(SecurityConstants.REPO_ENCRYPTION_CIPHER_KEY_SIZE));
int ivLength = Integer.parseInt(properties.getProperty(SecurityConstants.REPO_ENCRYPTION_INITIALIZATION_VECTOR_SIZE));
String pbkdf2Algorithm = properties.getProperty(SecurityConstants.REPO_ENCRYPTION_PBKDF2_ALGORITHM);
int pbkdf2Rounds = Integer.parseInt(properties.getProperty(SecurityConstants.REPO_ENCRYPTION_PBKDF2_ROUNDS));
// We need to create a MapContext to make reading the password simpler here
Map<String, String> passwordProperties = new HashMap<>();
passwordProperties.put(SecurityConstants.REPO_ENCRYPTION_PASSWORD, properties.getProperty(SecurityConstants.REPO_ENCRYPTION_PASSWORD));
passwordProperties.put(SecurityConstants.REPO_ENCRYPTION_PASSWORD_GENERATOR, properties.getProperty(SecurityConstants.REPO_ENCRYPTION_PASSWORD_GENERATOR));
String password = PasswordUtils.readPassword(new MapContext(passwordProperties), SecurityConstants.REPO_ENCRYPTION_PASSWORD, SecurityConstants.REPO_ENCRYPTION_PASSWORD_GENERATOR);
masterKeyManager.initialize(true, hmacAlgorithm, cipherAlgorithm, cipherSpec, cipherKeySize, ivLength, pbkdf2Algorithm, pbkdf2Rounds, password, readFromRepository, transaction);
}
return masterKeyManager;
}
}