HDDS-1946. CertificateClient should not persist keys/certs to ozone.m… (#1311)

This commit is contained in:
Vivek Ratnavel Subramanian 2019-08-27 17:29:27 -07:00 committed by Xiaoyu Yao
parent 6e37d65b03
commit b1eee8b52e
15 changed files with 240 additions and 192 deletions

View File

@ -70,6 +70,7 @@ import java.util.concurrent.TimeoutException;
*/
public class XceiverClientGrpc extends XceiverClientSpi {
static final Logger LOG = LoggerFactory.getLogger(XceiverClientGrpc.class);
private static final String COMPONENT = "dn";
private final Pipeline pipeline;
private final Configuration config;
private Map<UUID, XceiverClientProtocolServiceStub> asyncStubs;
@ -150,9 +151,9 @@ public class XceiverClientGrpc extends XceiverClientSpi {
.intercept(new ClientCredentialInterceptor(userName, encodedToken),
new GrpcClientInterceptor());
if (secConfig.isGrpcTlsEnabled()) {
File trustCertCollectionFile = secConfig.getTrustStoreFile();
File privateKeyFile = secConfig.getClientPrivateKeyFile();
File clientCertChainFile = secConfig.getClientCertChainFile();
File trustCertCollectionFile = secConfig.getTrustStoreFile(COMPONENT);
File privateKeyFile = secConfig.getClientPrivateKeyFile(COMPONENT);
File clientCertChainFile = secConfig.getClientCertChainFile(COMPONENT);
SslContextBuilder sslContextBuilder = GrpcSslContexts.forClient();
if (trustCertCollectionFile != null) {

View File

@ -20,6 +20,7 @@
package org.apache.hadoop.hdds.security.x509;
import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ozone.OzoneConfigKeys;
import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider;
@ -246,23 +247,12 @@ public class SecurityConfig {
return privateKeyFileName;
}
/**
* Returns the File path to where keys are stored.
*
* @return path Key location.
*/
public Path getKeyLocation() {
Preconditions.checkNotNull(this.metadatDir, "Metadata directory can't be"
+ " null. Please check configs.");
return Paths.get(metadatDir, keyDir);
}
/**
* Returns the File path to where keys are stored with an additional component
* name inserted in between.
*
* @param component - Component Name - String.
* @return Path location.
* @return Path Key location.
*/
public Path getKeyLocation(String component) {
Preconditions.checkNotNull(this.metadatDir, "Metadata directory can't be"
@ -271,18 +261,8 @@ public class SecurityConfig {
}
/**
* Returns the File path to where keys are stored.
*
* @return path Key location.
*/
public Path getCertificateLocation() {
Preconditions.checkNotNull(this.metadatDir, "Metadata directory can't be"
+ " null. Please check configs.");
return Paths.get(metadatDir, certificateDir);
}
/**
* Returns the File path to where keys are stored with an addition component
* Returns the File path to where certificates are stored with an addition
* component
* name inserted in between.
*
* @param component - Component Name - String.
@ -379,14 +359,35 @@ public class SecurityConfig {
return this.grpcMutualTlsRequired;
}
/**
* Returns the TLS-enabled gRPC client private key file(Only needed for mutual
* authentication) for the given component.
* @param component name of the component.
* @return the TLS-enabled gRPC client private key file.
*/
public File getClientPrivateKeyFile(String component) {
return Paths.get(getKeyLocation(component).toString(),
"client." + privateKeyFileName).toFile();
}
/**
* Returns the TLS-enabled gRPC client private key file(Only needed for mutual
* authentication).
* @return the TLS-enabled gRPC client private key file.
*/
public File getClientPrivateKeyFile() {
return Paths.get(getKeyLocation().toString(),
"client." + privateKeyFileName).toFile();
return getClientPrivateKeyFile(StringUtils.EMPTY);
}
/**
* Returns the TLS-enabled gRPC server private key file for the given
* component.
* @param component name of the component.
* @return the TLS-enabled gRPC server private key file.
*/
public File getServerPrivateKeyFile(String component) {
return Paths.get(getKeyLocation(component).toString(),
"server." + privateKeyFileName).toFile();
}
/**
@ -394,8 +395,19 @@ public class SecurityConfig {
* @return the TLS-enabled gRPC server private key file.
*/
public File getServerPrivateKeyFile() {
return Paths.get(getKeyLocation().toString(),
"server." + privateKeyFileName).toFile();
return getServerPrivateKeyFile(StringUtils.EMPTY);
}
/**
* Get the trusted CA certificate file for the given component. (CA
* certificate)
* @param component name of the component.
* @return the trusted CA certificate.
*/
public File getTrustStoreFile(String component) {
return Paths.get(getKeyLocation(component).toString(),
trustStoreFileName).
toFile();
}
/**
@ -403,7 +415,19 @@ public class SecurityConfig {
* @return the trusted CA certificate.
*/
public File getTrustStoreFile() {
return Paths.get(getKeyLocation().toString(), trustStoreFileName).
return getTrustStoreFile(StringUtils.EMPTY);
}
/**
* Get the TLS-enabled gRPC Client certificate chain file for the given
* component (only needed for
* mutual authentication).
* @param component name of the component.
* @return the TLS-enabled gRPC Server certificate chain file.
*/
public File getClientCertChainFile(String component) {
return Paths.get(getKeyLocation(component).toString(),
clientCertChainFileName).
toFile();
}
@ -413,7 +437,18 @@ public class SecurityConfig {
* @return the TLS-enabled gRPC Server certificate chain file.
*/
public File getClientCertChainFile() {
return Paths.get(getKeyLocation().toString(), clientCertChainFileName).
return getClientCertChainFile(StringUtils.EMPTY);
}
/**
* Get the TLS-enabled gRPC Server certificate chain file for the given
* component.
* @param component name of the component.
* @return the TLS-enabled gRPC Server certificate chain file.
*/
public File getServerCertChainFile(String component) {
return Paths.get(getKeyLocation(component).toString(),
serverCertChainFileName).
toFile();
}
@ -422,8 +457,7 @@ public class SecurityConfig {
* @return the TLS-enabled gRPC Server certificate chain file.
*/
public File getServerCertChainFile() {
return Paths.get(getKeyLocation().toString(), serverCertChainFileName).
toFile();
return getServerCertChainFile(StringUtils.EMPTY);
}
/**
@ -437,7 +471,7 @@ public class SecurityConfig {
/**
* Return true if using test certificates with authority as localhost.
* This should be used only for unit test where certifiates are generated
* This should be used only for unit test where certificates are generated
* by openssl with localhost as DN and should never use for production as it
* will bypass the hostname/ip matching verification.
* @return true if using test certificates.
@ -464,7 +498,7 @@ public class SecurityConfig {
/**
* Returns max date for which S3 tokens will be valid.
* */
*/
public long getS3TokenMaxDate() {
return getConfiguration().getTimeDuration(
OzoneConfigKeys.OZONE_S3_TOKEN_MAX_LIFETIME_KEY,

View File

@ -25,6 +25,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
/**
* Certificate client for DataNodes.
*/
@ -32,13 +33,16 @@ public class DNCertificateClient extends DefaultCertificateClient {
private static final Logger LOG =
LoggerFactory.getLogger(DNCertificateClient.class);
public static final String COMPONENT_NAME = "dn";
public DNCertificateClient(SecurityConfig securityConfig,
String certSerialId) {
super(securityConfig, LOG, certSerialId);
super(securityConfig, LOG, certSerialId, COMPONENT_NAME);
}
public DNCertificateClient(SecurityConfig securityConfig) {
super(securityConfig, LOG, null);
super(securityConfig, LOG, null, COMPONENT_NAME);
}
/**

View File

@ -89,16 +89,18 @@ public abstract class DefaultCertificateClient implements CertificateClient {
private X509Certificate x509Certificate;
private Map<String, X509Certificate> certificateMap;
private String certSerialId;
private String component;
DefaultCertificateClient(SecurityConfig securityConfig, Logger log,
String certSerialId) {
String certSerialId, String component) {
Objects.requireNonNull(securityConfig);
this.securityConfig = securityConfig;
keyCodec = new KeyCodec(securityConfig);
keyCodec = new KeyCodec(securityConfig, component);
this.logger = log;
this.certificateMap = new ConcurrentHashMap<>();
this.certSerialId = certSerialId;
this.component = component;
loadAllCertificates();
}
@ -108,7 +110,7 @@ public abstract class DefaultCertificateClient implements CertificateClient {
* */
private void loadAllCertificates() {
// See if certs directory exists in file system.
Path certPath = securityConfig.getCertificateLocation();
Path certPath = securityConfig.getCertificateLocation(component);
if (Files.exists(certPath) && Files.isDirectory(certPath)) {
getLogger().info("Loading certificate from location:{}.",
certPath);
@ -116,7 +118,7 @@ public abstract class DefaultCertificateClient implements CertificateClient {
if (certFiles != null) {
CertificateCodec certificateCodec =
new CertificateCodec(securityConfig);
new CertificateCodec(securityConfig, component);
for (File file : certFiles) {
if (file.isFile()) {
try {
@ -158,7 +160,7 @@ public abstract class DefaultCertificateClient implements CertificateClient {
return privateKey;
}
Path keyPath = securityConfig.getKeyLocation();
Path keyPath = securityConfig.getKeyLocation(component);
if (OzoneSecurityUtil.checkIfFileExist(keyPath,
securityConfig.getPrivateKeyFileName())) {
try {
@ -182,7 +184,7 @@ public abstract class DefaultCertificateClient implements CertificateClient {
return publicKey;
}
Path keyPath = securityConfig.getKeyLocation();
Path keyPath = securityConfig.getKeyLocation(component);
if (OzoneSecurityUtil.checkIfFileExist(keyPath,
securityConfig.getPublicKeyFileName())) {
try {
@ -477,9 +479,10 @@ public abstract class DefaultCertificateClient implements CertificateClient {
@Override
public void storeCertificate(String pemEncodedCert, boolean force,
boolean caCert) throws CertificateException {
CertificateCodec certificateCodec = new CertificateCodec(securityConfig);
CertificateCodec certificateCodec = new CertificateCodec(securityConfig,
component);
try {
Path basePath = securityConfig.getCertificateLocation();
Path basePath = securityConfig.getCertificateLocation(component);
X509Certificate cert =
CertificateCodec.getX509Certificate(pemEncodedCert);
@ -738,7 +741,7 @@ public abstract class DefaultCertificateClient implements CertificateClient {
* location.
* */
protected void bootstrapClientKeys() throws CertificateException {
Path keyPath = securityConfig.getKeyLocation();
Path keyPath = securityConfig.getKeyLocation(component);
if (Files.notExists(keyPath)) {
try {
Files.createDirectories(keyPath);

View File

@ -39,13 +39,15 @@ public class OMCertificateClient extends DefaultCertificateClient {
private static final Logger LOG =
LoggerFactory.getLogger(OMCertificateClient.class);
public static final String COMPONENT_NAME = "om";
public OMCertificateClient(SecurityConfig securityConfig,
String certSerialId) {
super(securityConfig, LOG, certSerialId);
super(securityConfig, LOG, certSerialId, COMPONENT_NAME);
}
public OMCertificateClient(SecurityConfig securityConfig) {
super(securityConfig, LOG, null);
super(securityConfig, LOG, null, COMPONENT_NAME);
}
protected InitResponse handleCase(InitCase init) throws

View File

@ -19,9 +19,7 @@
package org.apache.hadoop.hdds.security.x509.certificate.utils;
import com.google.common.base.Preconditions;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdds.security.exception.SCMSecurityException;
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
import org.bouncycastle.cert.X509CertificateHolder;
@ -70,7 +68,7 @@ public class CertificateCodec {
Stream.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE)
.collect(Collectors.toSet());
/**
* Creates an CertificateCodec.
* Creates a CertificateCodec with component name.
*
* @param config - Security Config.
* @param component - Component String.
@ -80,27 +78,6 @@ public class CertificateCodec {
this.location = securityConfig.getCertificateLocation(component);
}
/**
* Creates an CertificateCodec.
*
* @param config - Security Config.
*/
public CertificateCodec(SecurityConfig config) {
this.securityConfig = config;
this.location = securityConfig.getCertificateLocation();
}
/**
* Creates an CertificateCodec.
*
* @param configuration - Configuration
*/
public CertificateCodec(Configuration configuration) {
Preconditions.checkNotNull(configuration, "Config cannot be null");
this.securityConfig = new SecurityConfig(configuration);
this.location = securityConfig.getCertificateLocation();
}
/**
* Returns a X509 Certificate from the Certificate Holder.
*

View File

@ -22,7 +22,6 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.FileWriterWithEncoding;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
@ -76,7 +75,7 @@ public class KeyCodec {
private Supplier<Boolean> isPosixFileSystem;
/**
* Creates an KeyCodec.
* Creates a KeyCodec with component name.
*
* @param config - Security Config.
* @param component - Component String.
@ -87,29 +86,6 @@ public class KeyCodec {
this.location = securityConfig.getKeyLocation(component);
}
/**
* Creates an KeyCodec.
*
* @param config - Security Config.
*/
public KeyCodec(SecurityConfig config) {
this.securityConfig = config;
isPosixFileSystem = KeyCodec::isPosix;
this.location = securityConfig.getKeyLocation();
}
/**
* Creates an HDDS Key Writer.
*
* @param configuration - Configuration
*/
public KeyCodec(Configuration configuration) {
Preconditions.checkNotNull(configuration, "Config cannot be null");
this.securityConfig = new SecurityConfig(configuration);
isPosixFileSystem = KeyCodec::isPosix;
this.location = securityConfig.getKeyLocation();
}
/**
* Checks if File System supports posix style security permissions.
*

View File

@ -66,8 +66,11 @@ public class TestCertificateClientInit {
private HDDSKeyGenerator keyGenerator;
private Path metaDirPath;
private SecurityConfig securityConfig;
private KeyCodec keyCodec;
private KeyCodec dnKeyCodec;
private KeyCodec omKeyCodec;
private X509Certificate x509Certificate;
private final static String DN_COMPONENT = DNCertificateClient.COMPONENT_NAME;
private final static String OM_COMPONENT = OMCertificateClient.COMPONENT_NAME;
@Parameter
public boolean pvtKeyPresent;
@ -107,9 +110,11 @@ public class TestCertificateClientInit {
certSerialId);
omCertificateClient = new OMCertificateClient(securityConfig,
certSerialId);
keyCodec = new KeyCodec(securityConfig);
dnKeyCodec = new KeyCodec(securityConfig, DN_COMPONENT);
omKeyCodec = new KeyCodec(securityConfig, OM_COMPONENT);
Files.createDirectories(securityConfig.getKeyLocation());
Files.createDirectories(securityConfig.getKeyLocation(DN_COMPONENT));
Files.createDirectories(securityConfig.getKeyLocation(OM_COMPONENT));
}
@After
@ -123,28 +128,32 @@ public class TestCertificateClientInit {
@Test
public void testInitDatanode() throws Exception {
if (pvtKeyPresent) {
keyCodec.writePrivateKey(keyPair.getPrivate());
dnKeyCodec.writePrivateKey(keyPair.getPrivate());
} else {
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
securityConfig.getKeyLocation(DN_COMPONENT).toString(),
securityConfig.getPrivateKeyFileName()).toFile());
}
if (pubKeyPresent) {
if (dnCertificateClient.getPublicKey() == null) {
keyCodec.writePublicKey(keyPair.getPublic());
dnKeyCodec.writePublicKey(keyPair.getPublic());
}
} else {
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
.toString(), securityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(
Paths.get(securityConfig.getKeyLocation(DN_COMPONENT).toString(),
securityConfig.getPublicKeyFileName()).toFile());
}
if (certPresent) {
CertificateCodec codec = new CertificateCodec(securityConfig);
CertificateCodec codec = new CertificateCodec(securityConfig,
DN_COMPONENT);
codec.writeCertificate(new X509CertificateHolder(
x509Certificate.getEncoded()));
} else {
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
.toString(), securityConfig.getCertificateFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
securityConfig.getKeyLocation(DN_COMPONENT).toString(),
securityConfig.getCertificateFileName()).toFile());
}
InitResponse response = dnCertificateClient.init();
@ -152,10 +161,10 @@ public class TestCertificateClientInit {
if (!response.equals(FAILURE)) {
assertTrue(OzoneSecurityUtil.checkIfFileExist(
securityConfig.getKeyLocation(),
securityConfig.getKeyLocation(DN_COMPONENT),
securityConfig.getPrivateKeyFileName()));
assertTrue(OzoneSecurityUtil.checkIfFileExist(
securityConfig.getKeyLocation(),
securityConfig.getKeyLocation(DN_COMPONENT),
securityConfig.getPublicKeyFileName()));
}
}
@ -163,28 +172,32 @@ public class TestCertificateClientInit {
@Test
public void testInitOzoneManager() throws Exception {
if (pvtKeyPresent) {
keyCodec.writePrivateKey(keyPair.getPrivate());
omKeyCodec.writePrivateKey(keyPair.getPrivate());
} else {
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
securityConfig.getKeyLocation(OM_COMPONENT).toString(),
securityConfig.getPrivateKeyFileName()).toFile());
}
if (pubKeyPresent) {
if (omCertificateClient.getPublicKey() == null) {
keyCodec.writePublicKey(keyPair.getPublic());
omKeyCodec.writePublicKey(keyPair.getPublic());
}
} else {
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
.toString(), securityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
securityConfig.getKeyLocation(OM_COMPONENT).toString(),
securityConfig.getPublicKeyFileName()).toFile());
}
if (certPresent) {
CertificateCodec codec = new CertificateCodec(securityConfig);
CertificateCodec codec = new CertificateCodec(securityConfig,
OM_COMPONENT);
codec.writeCertificate(new X509CertificateHolder(
x509Certificate.getEncoded()));
} else {
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
.toString(), securityConfig.getCertificateFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
securityConfig.getKeyLocation(OM_COMPONENT).toString(),
securityConfig.getCertificateFileName()).toFile());
}
InitResponse response = omCertificateClient.init();
@ -196,10 +209,10 @@ public class TestCertificateClientInit {
if (!response.equals(FAILURE)) {
assertTrue(OzoneSecurityUtil.checkIfFileExist(
securityConfig.getKeyLocation(),
securityConfig.getKeyLocation(OM_COMPONENT),
securityConfig.getPrivateKeyFileName()));
assertTrue(OzoneSecurityUtil.checkIfFileExist(
securityConfig.getKeyLocation(),
securityConfig.getKeyLocation(OM_COMPONENT),
securityConfig.getPublicKeyFileName()));
}
}

View File

@ -76,6 +76,8 @@ public class TestDefaultCertificateClient {
private SecurityConfig omSecurityConfig;
private SecurityConfig dnSecurityConfig;
private final static String UTF = "UTF-8";
private final static String DN_COMPONENT = DNCertificateClient.COMPONENT_NAME;
private final static String OM_COMPONENT = OMCertificateClient.COMPONENT_NAME;
private KeyCodec omKeyCodec;
private KeyCodec dnKeyCodec;
@ -99,11 +101,11 @@ public class TestDefaultCertificateClient {
keyGenerator = new HDDSKeyGenerator(omSecurityConfig);
omKeyCodec = new KeyCodec(omSecurityConfig);
dnKeyCodec = new KeyCodec(dnSecurityConfig);
omKeyCodec = new KeyCodec(omSecurityConfig, OM_COMPONENT);
dnKeyCodec = new KeyCodec(dnSecurityConfig, DN_COMPONENT);
Files.createDirectories(omSecurityConfig.getKeyLocation());
Files.createDirectories(dnSecurityConfig.getKeyLocation());
Files.createDirectories(omSecurityConfig.getKeyLocation(OM_COMPONENT));
Files.createDirectories(dnSecurityConfig.getKeyLocation(DN_COMPONENT));
x509Certificate = generateX509Cert(null);
certSerialId = x509Certificate.getSerialNumber().toString();
getCertClient();
@ -156,14 +158,18 @@ public class TestDefaultCertificateClient {
}
private void cleanupOldKeyPair() {
FileUtils.deleteQuietly(Paths.get(omSecurityConfig.getKeyLocation()
.toString(), omSecurityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(omSecurityConfig.getKeyLocation()
.toString(), omSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(dnSecurityConfig.getKeyLocation()
.toString(), dnSecurityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(dnSecurityConfig.getKeyLocation()
.toString(), dnSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
omSecurityConfig.getKeyLocation(OM_COMPONENT).toString(),
omSecurityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
omSecurityConfig.getKeyLocation(OM_COMPONENT).toString(),
omSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
dnSecurityConfig.getKeyLocation(DN_COMPONENT).toString(),
dnSecurityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
dnSecurityConfig.getKeyLocation(DN_COMPONENT).toString(),
dnSecurityConfig.getPublicKeyFileName()).toFile());
}
/**
@ -196,10 +202,12 @@ public class TestDefaultCertificateClient {
@Test
public void testSignDataStream() throws Exception {
String data = RandomStringUtils.random(100, UTF);
FileUtils.deleteQuietly(Paths.get(omSecurityConfig.getKeyLocation()
.toString(), omSecurityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(omSecurityConfig.getKeyLocation()
.toString(), omSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
omSecurityConfig.getKeyLocation(OM_COMPONENT).toString(),
omSecurityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
omSecurityConfig.getKeyLocation(OM_COMPONENT).toString(),
omSecurityConfig.getPublicKeyFileName()).toFile());
// Expect error when there is no private key to sign.
LambdaTestUtils.intercept(IOException.class, "Error while " +
@ -285,8 +293,9 @@ public class TestDefaultCertificateClient {
X509Certificate cert2 = generateX509Cert(keyPair);
X509Certificate cert3 = generateX509Cert(keyPair);
Path certPath = dnSecurityConfig.getCertificateLocation();
CertificateCodec codec = new CertificateCodec(dnSecurityConfig);
Path certPath = dnSecurityConfig.getCertificateLocation(DN_COMPONENT);
CertificateCodec codec = new CertificateCodec(dnSecurityConfig,
DN_COMPONENT);
// Certificate not found.
LambdaTestUtils.intercept(CertificateException.class, "Error while" +
@ -308,7 +317,7 @@ public class TestDefaultCertificateClient {
codec.writeCertificate(certPath, "3.crt",
getPEMEncodedString(cert3), true);
// Re instentiate DN client which will load certificates from filesystem.
// Re instantiate DN client which will load certificates from filesystem.
dnCertClient = new DNCertificateClient(dnSecurityConfig, certSerialId);
assertNotNull(dnCertClient.getCertificate(cert1.getSerialNumber()
@ -352,16 +361,20 @@ public class TestDefaultCertificateClient {
omClientLog.clearOutput();
// Case 1. Expect failure when keypair validation fails.
FileUtils.deleteQuietly(Paths.get(omSecurityConfig.getKeyLocation()
.toString(), omSecurityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(omSecurityConfig.getKeyLocation()
.toString(), omSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
omSecurityConfig.getKeyLocation(OM_COMPONENT).toString(),
omSecurityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
omSecurityConfig.getKeyLocation(OM_COMPONENT).toString(),
omSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(dnSecurityConfig.getKeyLocation()
.toString(), dnSecurityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(dnSecurityConfig.getKeyLocation()
.toString(), dnSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
dnSecurityConfig.getKeyLocation(DN_COMPONENT).toString(),
dnSecurityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
dnSecurityConfig.getKeyLocation(DN_COMPONENT).toString(),
dnSecurityConfig.getPublicKeyFileName()).toFile());
omKeyCodec.writePrivateKey(keyPair.getPrivate());
omKeyCodec.writePublicKey(keyPair2.getPublic());
@ -387,16 +400,20 @@ public class TestDefaultCertificateClient {
// Case 2. Expect failure when certificate is generated from different
// private key and keypair validation fails.
getCertClient();
FileUtils.deleteQuietly(Paths.get(omSecurityConfig.getKeyLocation()
.toString(), omSecurityConfig.getCertificateFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(dnSecurityConfig.getKeyLocation()
.toString(), dnSecurityConfig.getCertificateFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
omSecurityConfig.getKeyLocation(OM_COMPONENT).toString(),
omSecurityConfig.getCertificateFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
dnSecurityConfig.getKeyLocation(DN_COMPONENT).toString(),
dnSecurityConfig.getCertificateFileName()).toFile());
CertificateCodec omCertCodec = new CertificateCodec(omSecurityConfig);
CertificateCodec omCertCodec = new CertificateCodec(omSecurityConfig,
OM_COMPONENT);
omCertCodec.writeCertificate(new X509CertificateHolder(
x509Certificate.getEncoded()));
CertificateCodec dnCertCodec = new CertificateCodec(dnSecurityConfig);
CertificateCodec dnCertCodec = new CertificateCodec(dnSecurityConfig,
DN_COMPONENT);
dnCertCodec.writeCertificate(new X509CertificateHolder(
x509Certificate.getEncoded()));
// Check for DN.
@ -416,10 +433,12 @@ public class TestDefaultCertificateClient {
// private key and certificate validation fails.
// Re write the correct public key.
FileUtils.deleteQuietly(Paths.get(omSecurityConfig.getKeyLocation()
.toString(), omSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(dnSecurityConfig.getKeyLocation()
.toString(), dnSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
omSecurityConfig.getKeyLocation(OM_COMPONENT).toString(),
omSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
dnSecurityConfig.getKeyLocation(DN_COMPONENT).toString(),
dnSecurityConfig.getPublicKeyFileName()).toFile());
getCertClient();
omKeyCodec.writePublicKey(keyPair.getPublic());
dnKeyCodec.writePublicKey(keyPair.getPublic());
@ -440,10 +459,12 @@ public class TestDefaultCertificateClient {
// Case 4. Failure when public key recovery fails.
getCertClient();
FileUtils.deleteQuietly(Paths.get(omSecurityConfig.getKeyLocation()
.toString(), omSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(dnSecurityConfig.getKeyLocation()
.toString(), dnSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
omSecurityConfig.getKeyLocation(OM_COMPONENT).toString(),
omSecurityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
dnSecurityConfig.getKeyLocation(DN_COMPONENT).toString(),
dnSecurityConfig.getPublicKeyFileName()).toFile());
// Check for DN.
assertEquals(dnCertClient.init(), FAILURE);

View File

@ -22,6 +22,7 @@ package org.apache.hadoop.hdds.security.x509.certificate.utils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.security.exception.SCMSecurityException;
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
import org.apache.hadoop.hdds.security.x509.certificates.utils.SelfSignedCertificate;
import org.apache.hadoop.hdds.security.x509.keys.HDDSKeyGenerator;
import org.bouncycastle.cert.X509CertificateHolder;
@ -50,12 +51,15 @@ import static org.junit.Assert.assertTrue;
*/
public class TestCertificateCodec {
private static OzoneConfiguration conf = new OzoneConfiguration();
private static final String COMPONENT = "test";
private SecurityConfig securityConfig;
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Before
public void init() throws IOException {
conf.set(OZONE_METADATA_DIRS, temporaryFolder.newFolder().toString());
securityConfig = new SecurityConfig(conf);
}
/**
@ -88,7 +92,7 @@ public class TestCertificateCodec {
.setKey(keyGenerator.generateKey())
.makeCA()
.build();
CertificateCodec codec = new CertificateCodec(conf);
CertificateCodec codec = new CertificateCodec(securityConfig, COMPONENT);
String pemString = codec.getPEMEncodedString(cert);
assertTrue(pemString.startsWith(CertificateCodec.BEGIN_CERT));
assertTrue(pemString.endsWith(CertificateCodec.END_CERT + "\n"));
@ -131,7 +135,7 @@ public class TestCertificateCodec {
.setKey(keyGenerator.generateKey())
.makeCA()
.build();
CertificateCodec codec = new CertificateCodec(conf);
CertificateCodec codec = new CertificateCodec(securityConfig, COMPONENT);
String pemString = codec.getPEMEncodedString(cert);
File basePath = temporaryFolder.newFolder();
if (!basePath.exists()) {
@ -172,7 +176,7 @@ public class TestCertificateCodec {
.setKey(keyGenerator.generateKey())
.makeCA()
.build();
CertificateCodec codec = new CertificateCodec(conf);
CertificateCodec codec = new CertificateCodec(securityConfig, COMPONENT);
codec.writeCertificate(cert);
X509CertificateHolder certHolder = codec.readCertificate();
assertNotNull(certHolder);

View File

@ -57,6 +57,8 @@ public class TestKeyCodec {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private OzoneConfiguration configuration;
private SecurityConfig securityConfig;
private String component;
private HDDSKeyGenerator keyGenerator;
private String prefix;
@ -66,6 +68,8 @@ public class TestKeyCodec {
prefix = temporaryFolder.newFolder().toString();
configuration.set(HDDS_METADATA_DIR_NAME, prefix);
keyGenerator = new HDDSKeyGenerator(configuration);
securityConfig = new SecurityConfig(configuration);
component = "test_component";
}
/**
@ -83,11 +87,11 @@ public class TestKeyCodec {
throws NoSuchProviderException, NoSuchAlgorithmException,
IOException, InvalidKeySpecException {
KeyPair keys = keyGenerator.generateKey();
KeyCodec pemWriter = new KeyCodec(configuration);
KeyCodec pemWriter = new KeyCodec(securityConfig, component);
pemWriter.writeKey(keys);
// Assert that locations have been created.
Path keyLocation = pemWriter.getSecurityConfig().getKeyLocation();
Path keyLocation = pemWriter.getSecurityConfig().getKeyLocation(component);
Assert.assertTrue(keyLocation.toFile().exists());
// Assert that locations are created in the locations that we specified
@ -172,7 +176,7 @@ public class TestKeyCodec {
public void testReWriteKey()
throws Exception {
KeyPair kp = keyGenerator.generateKey();
KeyCodec pemWriter = new KeyCodec(configuration);
KeyCodec pemWriter = new KeyCodec(securityConfig, component);
SecurityConfig secConfig = pemWriter.getSecurityConfig();
pemWriter.writeKey(kp);
@ -181,13 +185,13 @@ public class TestKeyCodec {
.intercept(IOException.class, "Private Key file already exists.",
() -> pemWriter.writeKey(kp));
FileUtils.deleteQuietly(Paths.get(
secConfig.getKeyLocation().toString() + "/" + secConfig
secConfig.getKeyLocation(component).toString() + "/" + secConfig
.getPrivateKeyFileName()).toFile());
LambdaTestUtils
.intercept(IOException.class, "Public Key file already exists.",
() -> pemWriter.writeKey(kp));
FileUtils.deleteQuietly(Paths.get(
secConfig.getKeyLocation().toString() + "/" + secConfig
secConfig.getKeyLocation(component).toString() + "/" + secConfig
.getPublicKeyFileName()).toFile());
// Should succeed now as both public and private key are deleted.
@ -206,7 +210,7 @@ public class TestKeyCodec {
public void testWriteKeyInNonPosixFS()
throws Exception {
KeyPair kp = keyGenerator.generateKey();
KeyCodec pemWriter = new KeyCodec(configuration);
KeyCodec pemWriter = new KeyCodec(securityConfig, component);
pemWriter.setIsPosixFileSystem(() -> false);
// Assert key rewrite fails in non Posix file system.
@ -221,7 +225,7 @@ public class TestKeyCodec {
InvalidKeySpecException {
KeyPair kp = keyGenerator.generateKey();
KeyCodec keycodec = new KeyCodec(configuration);
KeyCodec keycodec = new KeyCodec(securityConfig, component);
keycodec.writeKey(kp);
PublicKey pubKey = keycodec.readPublicKey();

View File

@ -64,6 +64,7 @@ import java.util.concurrent.TimeUnit;
public final class XceiverServerGrpc extends XceiverServer {
private static final Logger
LOG = LoggerFactory.getLogger(XceiverServerGrpc.class);
private static final String COMPONENT = "dn";
private int port;
private UUID id;
private Server server;
@ -111,11 +112,12 @@ public final class XceiverServerGrpc extends XceiverServer {
}
if (getSecConfig().isGrpcTlsEnabled()) {
File privateKeyFilePath = getSecurityConfig().getServerPrivateKeyFile();
File privateKeyFilePath =
getSecurityConfig().getServerPrivateKeyFile(COMPONENT);
File serverCertChainFilePath =
getSecurityConfig().getServerCertChainFile();
getSecurityConfig().getServerCertChainFile(COMPONENT);
File clientCertChainFilePath =
getSecurityConfig().getClientCertChainFile();
getSecurityConfig().getClientCertChainFile(COMPONENT);
try {
SslContextBuilder sslClientContextBuilder = SslContextBuilder.forServer(
serverCertChainFilePath, privateKeyFilePath);

View File

@ -66,6 +66,7 @@ public class TestHddsSecureDatanodeInit {
private static KeyCodec keyCodec;
private static CertificateCodec certCodec;
private static X509CertificateHolder certHolder;
private final static String DN_COMPONENT = DNCertificateClient.COMPONENT_NAME;
@BeforeClass
public static void setUp() throws Exception {
@ -93,8 +94,8 @@ public class TestHddsSecureDatanodeInit {
service.initializeCertificateClient(conf);
return null;
});
certCodec = new CertificateCodec(securityConfig);
keyCodec = new KeyCodec(securityConfig);
certCodec = new CertificateCodec(securityConfig, DN_COMPONENT);
keyCodec = new KeyCodec(securityConfig, DN_COMPONENT);
dnLogs.clearOutput();
privateKey = service.getCertificateClient().getPrivateKey();
publicKey = service.getCertificateClient().getPublicKey();
@ -115,12 +116,14 @@ public class TestHddsSecureDatanodeInit {
@Before
public void setUpDNCertClient(){
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
.toString(), securityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
securityConfig.getKeyLocation(DN_COMPONENT).toString(),
securityConfig.getPrivateKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(
securityConfig.getKeyLocation(DN_COMPONENT).toString(),
securityConfig.getPublicKeyFileName()).toFile());
FileUtils.deleteQuietly(Paths.get(securityConfig
.getCertificateLocation().toString(),
.getCertificateLocation(DN_COMPONENT).toString(),
securityConfig.getCertificateFileName()).toFile());
dnLogs.clearOutput();
client = new DNCertificateClient(securityConfig,

View File

@ -41,6 +41,7 @@ import org.apache.hadoop.hdds.scm.ScmInfo;
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
import org.apache.hadoop.hdds.scm.server.SCMStorageConfig;
import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
import org.apache.hadoop.hdds.security.x509.certificate.utils.CertificateCodec;
import org.apache.hadoop.hdds.security.x509.keys.HDDSKeyGenerator;
import org.apache.hadoop.hdds.security.x509.keys.KeyCodec;
@ -114,6 +115,7 @@ import static org.slf4j.event.Level.INFO;
public final class TestSecureOzoneCluster {
private static final String TEST_USER = "testUgiUser@EXAMPLE.COM";
private static final String COMPONENT = "test";
private static final int CLIENT_TIMEOUT = 2 * 1000;
private Logger logger = LoggerFactory
.getLogger(TestSecureOzoneCluster.class);
@ -559,7 +561,7 @@ public final class TestSecureOzoneCluster {
private void generateKeyPair(OzoneConfiguration config) throws Exception {
HDDSKeyGenerator keyGenerator = new HDDSKeyGenerator(conf);
keyPair = keyGenerator.generateKey();
KeyCodec pemWriter = new KeyCodec(config);
KeyCodec pemWriter = new KeyCodec(new SecurityConfig(config), COMPONENT);
pemWriter.writeKey(keyPair, true);
}

View File

@ -60,6 +60,7 @@ import static org.apache.hadoop.test.GenericTestUtils.*;
*/
public class TestSecureOzoneManager {
private static final String COMPONENT = "om";
private MiniOzoneCluster cluster = null;
private OzoneConfiguration conf;
private String clusterId;
@ -151,7 +152,7 @@ public class TestSecureOzoneManager {
// Case 3: When public key as well as certificate is missing.
client = new OMCertificateClient(securityConfig);
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMPONENT)
.toString(), securityConfig.getPublicKeyFileName()).toFile());
LambdaTestUtils.intercept(RuntimeException.class, " OM security" +
" initialization failed",
@ -164,9 +165,9 @@ public class TestSecureOzoneManager {
// Case 4: When private key and certificate is missing.
client = new OMCertificateClient(securityConfig);
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMPONENT)
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
KeyCodec keyCodec = new KeyCodec(securityConfig);
KeyCodec keyCodec = new KeyCodec(securityConfig, COMPONENT);
keyCodec.writePublicKey(publicKey);
LambdaTestUtils.intercept(RuntimeException.class, " OM security" +
" initialization failed",
@ -178,9 +179,10 @@ public class TestSecureOzoneManager {
omLogs.clearOutput();
// Case 5: When only certificate is present.
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMPONENT)
.toString(), securityConfig.getPublicKeyFileName()).toFile());
CertificateCodec certCodec = new CertificateCodec(securityConfig);
CertificateCodec certCodec =
new CertificateCodec(securityConfig, COMPONENT);
X509Certificate x509Certificate = KeyStoreTestUtil.generateCertificate(
"CN=Test", new KeyPair(publicKey, privateKey), 10,
securityConfig.getSignatureAlgo());
@ -201,7 +203,7 @@ public class TestSecureOzoneManager {
// Case 6: When private key and certificate is present.
client = new OMCertificateClient(securityConfig,
x509Certificate.getSerialNumber().toString());
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMPONENT)
.toString(), securityConfig.getPublicKeyFileName()).toFile());
keyCodec.writePrivateKey(privateKey);
OzoneManager.initializeSecurity(conf, omStorage);