Merge branch '1.7' into 1.8
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/da695f60 Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/da695f60 Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/da695f60 Branch: refs/heads/master Commit: da695f60483b4f1fd9e8082c0a5f84e9a7350e90 Parents: 116da38 4effd0e Author: Christopher Tubbs <ctubb...@apache.org> Authored: Thu Jun 8 22:03:13 2017 -0400 Committer: Christopher Tubbs <ctubb...@apache.org> Committed: Thu Jun 8 22:03:13 2017 -0400 ---------------------------------------------------------------------- .../accumulo/core/conf/SiteConfiguration.java | 20 +++++--------------- .../accumulo/core/file/rfile/PrintInfo.java | 4 +--- .../core/file/rfile/bcfile/PrintInfo.java | 3 +-- .../server/conf/ServerConfigurationFactory.java | 2 +- .../java/org/apache/accumulo/shell/Shell.java | 6 +++--- .../apache/accumulo/shell/ShellOptionsJC.java | 3 +-- .../accumulo/shell/commands/FateCommand.java | 3 +-- .../apache/accumulo/test/util/CertUtils.java | 4 ++-- 8 files changed, 15 insertions(+), 30 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/da695f60/core/src/main/java/org/apache/accumulo/core/file/rfile/PrintInfo.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/da695f60/server/base/src/main/java/org/apache/accumulo/server/conf/ServerConfigurationFactory.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/da695f60/shell/src/main/java/org/apache/accumulo/shell/Shell.java ---------------------------------------------------------------------- diff --cc shell/src/main/java/org/apache/accumulo/shell/Shell.java index 3e838e0,cdd177e..05d85cf --- a/shell/src/main/java/org/apache/accumulo/shell/Shell.java +++ b/shell/src/main/java/org/apache/accumulo/shell/Shell.java @@@ -53,8 -53,8 +53,7 @@@ import org.apache.accumulo.core.client. import org.apache.accumulo.core.client.NamespaceNotFoundException; import org.apache.accumulo.core.client.TableNotFoundException; import org.apache.accumulo.core.client.ZooKeeperInstance; - import org.apache.accumulo.core.client.impl.ClientContext; import org.apache.accumulo.core.client.impl.Tables; -import org.apache.accumulo.core.client.mock.MockInstance; import org.apache.accumulo.core.client.security.tokens.AuthenticationToken; import org.apache.accumulo.core.client.security.tokens.PasswordToken; import org.apache.accumulo.core.conf.AccumuloConfiguration; http://git-wip-us.apache.org/repos/asf/accumulo/blob/da695f60/shell/src/main/java/org/apache/accumulo/shell/ShellOptionsJC.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/da695f60/shell/src/main/java/org/apache/accumulo/shell/commands/FateCommand.java ---------------------------------------------------------------------- diff --cc shell/src/main/java/org/apache/accumulo/shell/commands/FateCommand.java index 88eeefd,94b83fc..9f8ee09 --- a/shell/src/main/java/org/apache/accumulo/shell/commands/FateCommand.java +++ b/shell/src/main/java/org/apache/accumulo/shell/commands/FateCommand.java @@@ -30,15 -26,11 +30,14 @@@ import java.util.Set import org.apache.accumulo.core.Constants; import org.apache.accumulo.core.client.Instance; import org.apache.accumulo.core.conf.AccumuloConfiguration; - import org.apache.accumulo.core.conf.DefaultConfiguration; import org.apache.accumulo.core.conf.Property; import org.apache.accumulo.core.conf.SiteConfiguration; +import org.apache.accumulo.core.util.Base64; import org.apache.accumulo.core.zookeeper.ZooUtil; import org.apache.accumulo.fate.AdminUtil; +import org.apache.accumulo.fate.ReadOnlyRepo; import org.apache.accumulo.fate.ReadOnlyTStore.TStatus; +import org.apache.accumulo.fate.Repo; import org.apache.accumulo.fate.ZooStore; import org.apache.accumulo.fate.zookeeper.IZooReaderWriter; import org.apache.accumulo.fate.zookeeper.ZooReaderWriter; http://git-wip-us.apache.org/repos/asf/accumulo/blob/da695f60/test/src/main/java/org/apache/accumulo/test/util/CertUtils.java ---------------------------------------------------------------------- diff --cc test/src/main/java/org/apache/accumulo/test/util/CertUtils.java index 95042d2,0000000..a49e1cd mode 100644,000000..100644 --- a/test/src/main/java/org/apache/accumulo/test/util/CertUtils.java +++ b/test/src/main/java/org/apache/accumulo/test/util/CertUtils.java @@@ -1,348 -1,0 +1,348 @@@ +/* + * 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.accumulo.test.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.util.Calendar; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +import org.apache.accumulo.core.cli.Help; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.conf.AccumuloConfiguration; +import org.apache.accumulo.core.conf.DefaultConfiguration; +import org.apache.accumulo.core.conf.Property; +import org.apache.accumulo.core.conf.SiteConfiguration; +import org.apache.commons.io.FileExistsException; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x500.style.IETFUtils; +import org.bouncycastle.asn1.x500.style.RFC4519Style; +import org.bouncycastle.asn1.x509.BasicConstraints; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.KeyUsage; +import org.bouncycastle.cert.CertIOException; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.provider.X509CertificateObject; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import com.google.common.base.Predicate; + +public class CertUtils { + private static final Logger log = LoggerFactory.getLogger(CertUtils.class); + static { + Security.addProvider(new BouncyCastleProvider()); + } + + static class Opts extends Help { + @Parameter(description = "generate-all | generate-local | generate-self-trusted", required = true, arity = 1) + List<String> operation = null; + + @Parameter(names = {"--local-keystore"}, description = "Target path for generated keystore") + String localKeystore = null; + + @Parameter(names = {"--root-keystore"}, description = "Path to root truststore, generated with generate-all, or used for signing with generate-local") + String rootKeystore = null; + + @Parameter(names = {"--root-truststore"}, description = "Target path for generated public root truststore") + String truststore = null; + + @Parameter(names = {"--keystore-type"}, description = "Type of keystore file to use") + String keystoreType = "JKS"; + + @Parameter(names = {"--root-keystore-password"}, description = "Password for root keystore, falls back to --keystore-password if not provided") + String rootKeystorePassword = null; + + @Parameter( + names = {"--keystore-password"}, + description = "Password used to encrypt keystores. If omitted, the instance-wide secret will be used. If specified, the password must also be explicitly configured in Accumulo.") + String keystorePassword = null; + + @Parameter(names = {"--truststore-password"}, description = "Password used to encrypt the truststore. If omitted, empty password is used") + String truststorePassword = ""; + + @Parameter(names = {"--key-name-prefix"}, description = "Prefix for names of generated keys") + String keyNamePrefix = CertUtils.class.getSimpleName(); + + @Parameter(names = {"--issuer-rdn"}, description = "RDN string for issuer, for example: 'c=US,o=My Organization,cn=My Name'") + String issuerDirString = "o=Apache Accumulo"; + + @Parameter(names = "--site-file", description = "Load configuration from the given site file") + public String siteFile = null; + + @Parameter(names = "--signing-algorithm", description = "Algorithm used to sign certificates") + public String signingAlg = "SHA256WITHRSA"; + + @Parameter(names = "--encryption-algorithm", description = "Algorithm used to encrypt private keys") + public String encryptionAlg = "RSA"; + + @Parameter(names = "--keysize", description = "Key size used by encryption algorithm") + public int keysize = 2048; + + public AccumuloConfiguration getConfiguration() { + if (siteFile == null) { - return SiteConfiguration.getInstance(DefaultConfiguration.getInstance()); ++ return SiteConfiguration.getInstance(); + } else { + return new AccumuloConfiguration() { + Configuration xml = new Configuration(); + { + xml.addResource(new Path(siteFile)); + } + + @Override + public Iterator<Entry<String,String>> iterator() { + TreeMap<String,String> map = new TreeMap<>(); + for (Entry<String,String> props : DefaultConfiguration.getInstance()) + map.put(props.getKey(), props.getValue()); + for (Entry<String,String> props : xml) + map.put(props.getKey(), props.getValue()); + return map.entrySet().iterator(); + } + + @Override + public String get(Property property) { + String value = xml.get(property.getKey()); + if (value != null) + return value; + return DefaultConfiguration.getInstance().get(property); + } + + @Override + public void getProperties(Map<String,String> props, Predicate<String> filter) { + for (Entry<String,String> entry : this) + if (filter.apply(entry.getKey())) + props.put(entry.getKey(), entry.getValue()); + } + }; + } + } + } + + public static void main(String[] args) throws Exception { + Opts opts = new Opts(); + opts.parseArgs(CertUtils.class.getName(), args); + String operation = opts.operation.get(0); + + String keyPassword = opts.keystorePassword; + if (keyPassword == null) + keyPassword = getDefaultKeyPassword(); + + String rootKeyPassword = opts.rootKeystorePassword; + if (rootKeyPassword == null) { + rootKeyPassword = keyPassword; + } + + CertUtils certUtils = new CertUtils(opts.keystoreType, opts.issuerDirString, opts.encryptionAlg, opts.keysize, opts.signingAlg); + + if ("generate-all".equals(operation)) { + certUtils.createAll(new File(opts.rootKeystore), new File(opts.localKeystore), new File(opts.truststore), opts.keyNamePrefix, rootKeyPassword, + keyPassword, opts.truststorePassword); + } else if ("generate-local".equals(operation)) { + certUtils.createSignedCert(new File(opts.localKeystore), opts.keyNamePrefix + "-local", keyPassword, opts.rootKeystore, rootKeyPassword); + } else if ("generate-self-trusted".equals(operation)) { + certUtils.createSelfSignedCert(new File(opts.truststore), opts.keyNamePrefix + "-selfTrusted", keyPassword); + } else { + JCommander jcommander = new JCommander(opts); + jcommander.setProgramName(CertUtils.class.getName()); + jcommander.usage(); + System.err.println("Unrecognized operation: " + opts.operation); + System.exit(0); + } + } + + private static String getDefaultKeyPassword() { - return SiteConfiguration.getInstance(DefaultConfiguration.getInstance()).get(Property.INSTANCE_SECRET); ++ return SiteConfiguration.getInstance().get(Property.INSTANCE_SECRET); + } + + private String issuerDirString; + private String keystoreType; + private String encryptionAlgorithm; + private int keysize; + private String signingAlgorithm; + + public CertUtils(String keystoreType, String issuerDirString, String encryptionAlgorithm, int keysize, String signingAlgorithm) { + super(); + this.keystoreType = keystoreType; + this.issuerDirString = issuerDirString; + this.encryptionAlgorithm = encryptionAlgorithm; + this.keysize = keysize; + this.signingAlgorithm = signingAlgorithm; + } + + public void createAll(File rootKeystoreFile, File localKeystoreFile, File trustStoreFile, String keyNamePrefix, String rootKeystorePassword, + String keystorePassword, String truststorePassword) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, + OperatorCreationException, AccumuloSecurityException, NoSuchProviderException, UnrecoverableKeyException, FileNotFoundException { + createSelfSignedCert(rootKeystoreFile, keyNamePrefix + "-root", rootKeystorePassword); + createSignedCert(localKeystoreFile, keyNamePrefix + "-local", keystorePassword, rootKeystoreFile.getAbsolutePath(), rootKeystorePassword); + createPublicCert(trustStoreFile, keyNamePrefix + "-public", rootKeystoreFile.getAbsolutePath(), rootKeystorePassword, truststorePassword); + } + + public void createPublicCert(File targetKeystoreFile, String keyName, String rootKeystorePath, String rootKeystorePassword, String truststorePassword) + throws NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, KeyStoreException, UnrecoverableKeyException { + KeyStore signerKeystore = KeyStore.getInstance(keystoreType); + char[] signerPasswordArray = rootKeystorePassword.toCharArray(); + try (FileInputStream fis = new FileInputStream(rootKeystorePath)) { + signerKeystore.load(fis, signerPasswordArray); + } + Certificate rootCert = findCert(signerKeystore); + + KeyStore keystore = KeyStore.getInstance(keystoreType); + keystore.load(null, null); + keystore.setCertificateEntry(keyName + "Cert", rootCert); + try (FileOutputStream fos = new FileOutputStream(targetKeystoreFile)) { + keystore.store(fos, truststorePassword.toCharArray()); + } + } + + public void createSignedCert(File targetKeystoreFile, String keyName, String keystorePassword, String signerKeystorePath, String signerKeystorePassword) + throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, OperatorCreationException, AccumuloSecurityException, + UnrecoverableKeyException, NoSuchProviderException { + KeyStore signerKeystore = KeyStore.getInstance(keystoreType); + char[] signerPasswordArray = signerKeystorePassword.toCharArray(); + try (FileInputStream fis = new FileInputStream(signerKeystorePath)) { + signerKeystore.load(fis, signerPasswordArray); + } + Certificate signerCert = findCert(signerKeystore); + PrivateKey signerKey = findPrivateKey(signerKeystore, signerPasswordArray); + + KeyPair kp = generateKeyPair(); + X509CertificateObject cert = generateCert(keyName, kp, false, signerCert.getPublicKey(), signerKey); + + char[] password = keystorePassword.toCharArray(); + KeyStore keystore = KeyStore.getInstance(keystoreType); + keystore.load(null, null); + keystore.setCertificateEntry(keyName + "Cert", cert); + keystore.setKeyEntry(keyName + "Key", kp.getPrivate(), password, new Certificate[] {cert, signerCert}); + try (FileOutputStream fos = new FileOutputStream(targetKeystoreFile)) { + keystore.store(fos, password); + } + } + + public void createSelfSignedCert(File targetKeystoreFile, String keyName, String keystorePassword) throws KeyStoreException, CertificateException, + NoSuchAlgorithmException, IOException, OperatorCreationException, AccumuloSecurityException, NoSuchProviderException { + if (targetKeystoreFile.exists()) { + throw new FileExistsException(targetKeystoreFile); + } + + KeyPair kp = generateKeyPair(); + + X509CertificateObject cert = generateCert(keyName, kp, true, kp.getPublic(), kp.getPrivate()); + + char[] password = keystorePassword.toCharArray(); + KeyStore keystore = KeyStore.getInstance(keystoreType); + keystore.load(null, null); + keystore.setCertificateEntry(keyName + "Cert", cert); + keystore.setKeyEntry(keyName + "Key", kp.getPrivate(), password, new Certificate[] {cert}); + try (FileOutputStream fos = new FileOutputStream(targetKeystoreFile)) { + keystore.store(fos, password); + } + } + + private KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException { + KeyPairGenerator gen = KeyPairGenerator.getInstance(encryptionAlgorithm); + gen.initialize(keysize); + return gen.generateKeyPair(); + } + + private X509CertificateObject generateCert(String keyName, KeyPair kp, boolean isCertAuthority, PublicKey signerPublicKey, PrivateKey signerPrivateKey) + throws IOException, CertIOException, OperatorCreationException, CertificateException, NoSuchAlgorithmException { + Calendar startDate = Calendar.getInstance(); + Calendar endDate = Calendar.getInstance(); + endDate.add(Calendar.YEAR, 100); + + BigInteger serialNumber = BigInteger.valueOf((startDate.getTimeInMillis())); + X500Name issuer = new X500Name(IETFUtils.rDNsFromString(issuerDirString, RFC4519Style.INSTANCE)); + JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(issuer, serialNumber, startDate.getTime(), endDate.getTime(), issuer, kp.getPublic()); + JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils(); + certGen.addExtension(Extension.subjectKeyIdentifier, false, extensionUtils.createSubjectKeyIdentifier(kp.getPublic())); + certGen.addExtension(Extension.basicConstraints, false, new BasicConstraints(isCertAuthority)); + certGen.addExtension(Extension.authorityKeyIdentifier, false, extensionUtils.createAuthorityKeyIdentifier(signerPublicKey)); + if (isCertAuthority) { + certGen.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign)); + } + X509CertificateHolder cert = certGen.build(new JcaContentSignerBuilder(signingAlgorithm).build(signerPrivateKey)); + return new X509CertificateObject(cert.toASN1Structure()); + } + + static Certificate findCert(KeyStore keyStore) throws KeyStoreException { + Enumeration<String> aliases = keyStore.aliases(); + Certificate cert = null; + while (aliases.hasMoreElements()) { + String alias = aliases.nextElement(); + if (keyStore.isCertificateEntry(alias)) { + if (cert == null) { + cert = keyStore.getCertificate(alias); + } else { + log.warn("Found multiple certificates in keystore. Ignoring " + alias); + } + } + } + if (cert == null) { + throw new KeyStoreException("Could not find cert in keystore"); + } + return cert; + } + + static PrivateKey findPrivateKey(KeyStore keyStore, char[] keystorePassword) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException { + Enumeration<String> aliases = keyStore.aliases(); + PrivateKey key = null; + while (aliases.hasMoreElements()) { + String alias = aliases.nextElement(); + if (keyStore.isKeyEntry(alias)) { + if (key == null) { + key = (PrivateKey) keyStore.getKey(alias, keystorePassword); + } else { + log.warn("Found multiple keys in keystore. Ignoring " + alias); + } + } + } + if (key == null) { + throw new KeyStoreException("Could not find private key in keystore"); + } + return key; + } +}