HDDS-134. SCM CA: OM sends CSR and uses certificate issued by SCM. Contributed by Ajay Kumar.
This commit is contained in:
parent
8b72aea5c7
commit
4a3cddea70
@ -109,7 +109,7 @@ boolean verifySignature(byte[] data, byte[] signature,
|
|||||||
*
|
*
|
||||||
* @return CertificateSignRequest.Builder
|
* @return CertificateSignRequest.Builder
|
||||||
*/
|
*/
|
||||||
CertificateSignRequest.Builder getCSRBuilder();
|
CertificateSignRequest.Builder getCSRBuilder() throws CertificateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the certificate of well-known entity from SCM.
|
* Get the certificate of well-known entity from SCM.
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
package org.apache.hadoop.hdds.security.x509.certificate.client;
|
package org.apache.hadoop.hdds.security.x509.certificate.client;
|
||||||
|
|
||||||
|
import org.apache.hadoop.hdds.security.x509.certificates.utils.CertificateSignRequest;
|
||||||
|
import org.apache.hadoop.hdds.security.x509.exceptions.CertificateException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -30,8 +32,22 @@ public class DNCertificateClient extends DefaultCertificateClient {
|
|||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
LoggerFactory.getLogger(DNCertificateClient.class);
|
LoggerFactory.getLogger(DNCertificateClient.class);
|
||||||
DNCertificateClient(SecurityConfig securityConfig, String component) {
|
public DNCertificateClient(SecurityConfig securityConfig) {
|
||||||
super(securityConfig, component, LOG);
|
super(securityConfig, LOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a CSR builder that can be used to creates a Certificate signing
|
||||||
|
* request.
|
||||||
|
*
|
||||||
|
* @return CertificateSignRequest.Builder
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CertificateSignRequest.Builder getCSRBuilder()
|
||||||
|
throws CertificateException {
|
||||||
|
return super.getCSRBuilder()
|
||||||
|
.setDigitalEncryption(false)
|
||||||
|
.setDigitalSignature(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Logger getLogger() {
|
public Logger getLogger() {
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
|
import org.apache.commons.validator.routines.DomainValidator;
|
||||||
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
|
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.certificate.utils.CertificateCodec;
|
||||||
import org.apache.hadoop.hdds.security.x509.certificates.utils.CertificateSignRequest;
|
import org.apache.hadoop.hdds.security.x509.certificates.utils.CertificateSignRequest;
|
||||||
@ -66,20 +67,16 @@ public abstract class DefaultCertificateClient implements CertificateClient {
|
|||||||
|
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private final SecurityConfig securityConfig;
|
private final SecurityConfig securityConfig;
|
||||||
private final String component;
|
|
||||||
private final KeyCodec keyCodec;
|
private final KeyCodec keyCodec;
|
||||||
private PrivateKey privateKey;
|
private PrivateKey privateKey;
|
||||||
private PublicKey publicKey;
|
private PublicKey publicKey;
|
||||||
private X509Certificate x509Certificate;
|
private X509Certificate x509Certificate;
|
||||||
|
|
||||||
|
|
||||||
DefaultCertificateClient(SecurityConfig securityConfig, String component,
|
DefaultCertificateClient(SecurityConfig securityConfig, Logger log) {
|
||||||
Logger log) {
|
|
||||||
Objects.requireNonNull(securityConfig);
|
Objects.requireNonNull(securityConfig);
|
||||||
Objects.requireNonNull(component);
|
|
||||||
this.component = component;
|
|
||||||
this.securityConfig = securityConfig;
|
this.securityConfig = securityConfig;
|
||||||
keyCodec = new KeyCodec(securityConfig, component);
|
keyCodec = new KeyCodec(securityConfig);
|
||||||
this.logger = log;
|
this.logger = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,15 +92,14 @@ public PrivateKey getPrivateKey() {
|
|||||||
return privateKey;
|
return privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path keyPath = securityConfig.getKeyLocation(component);
|
Path keyPath = securityConfig.getKeyLocation();
|
||||||
if (OzoneSecurityUtil.checkIfFileExist(keyPath,
|
if (OzoneSecurityUtil.checkIfFileExist(keyPath,
|
||||||
securityConfig.getPrivateKeyFileName())) {
|
securityConfig.getPrivateKeyFileName())) {
|
||||||
try {
|
try {
|
||||||
privateKey = keyCodec.readPrivateKey();
|
privateKey = keyCodec.readPrivateKey();
|
||||||
} catch (InvalidKeySpecException | NoSuchAlgorithmException
|
} catch (InvalidKeySpecException | NoSuchAlgorithmException
|
||||||
| IOException e) {
|
| IOException e) {
|
||||||
getLogger().error("Error while getting private key for {}",
|
getLogger().error("Error while getting private key.", e);
|
||||||
component, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return privateKey;
|
return privateKey;
|
||||||
@ -121,15 +117,14 @@ public PublicKey getPublicKey() {
|
|||||||
return publicKey;
|
return publicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path keyPath = securityConfig.getKeyLocation(component);
|
Path keyPath = securityConfig.getKeyLocation();
|
||||||
if (OzoneSecurityUtil.checkIfFileExist(keyPath,
|
if (OzoneSecurityUtil.checkIfFileExist(keyPath,
|
||||||
securityConfig.getPublicKeyFileName())) {
|
securityConfig.getPublicKeyFileName())) {
|
||||||
try {
|
try {
|
||||||
publicKey = keyCodec.readPublicKey();
|
publicKey = keyCodec.readPublicKey();
|
||||||
} catch (InvalidKeySpecException | NoSuchAlgorithmException
|
} catch (InvalidKeySpecException | NoSuchAlgorithmException
|
||||||
| IOException e) {
|
| IOException e) {
|
||||||
getLogger().error("Error while getting private key for {}",
|
getLogger().error("Error while getting public key.", e);
|
||||||
component, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return publicKey;
|
return publicKey;
|
||||||
@ -147,18 +142,18 @@ public X509Certificate getCertificate() {
|
|||||||
return x509Certificate;
|
return x509Certificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path certPath = securityConfig.getCertificateLocation(component);
|
Path certPath = securityConfig.getCertificateLocation();
|
||||||
if (OzoneSecurityUtil.checkIfFileExist(certPath,
|
if (OzoneSecurityUtil.checkIfFileExist(certPath,
|
||||||
securityConfig.getCertificateFileName())) {
|
securityConfig.getCertificateFileName())) {
|
||||||
CertificateCodec certificateCodec =
|
CertificateCodec certificateCodec =
|
||||||
new CertificateCodec(securityConfig, component);
|
new CertificateCodec(securityConfig);
|
||||||
try {
|
try {
|
||||||
X509CertificateHolder x509CertificateHolder =
|
X509CertificateHolder x509CertificateHolder =
|
||||||
certificateCodec.readCertificate();
|
certificateCodec.readCertificate();
|
||||||
x509Certificate =
|
x509Certificate =
|
||||||
CertificateCodec.getX509Certificate(x509CertificateHolder);
|
CertificateCodec.getX509Certificate(x509CertificateHolder);
|
||||||
} catch (java.security.cert.CertificateException | IOException e) {
|
} catch (java.security.cert.CertificateException | IOException e) {
|
||||||
getLogger().error("Error reading certificate for {}", component, e);
|
getLogger().error("Error reading certificate.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x509Certificate;
|
return x509Certificate;
|
||||||
@ -318,8 +313,26 @@ private boolean verifySignature(byte[] data, byte[] signature,
|
|||||||
* @return CertificateSignRequest.Builder
|
* @return CertificateSignRequest.Builder
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public CertificateSignRequest.Builder getCSRBuilder() {
|
public CertificateSignRequest.Builder getCSRBuilder()
|
||||||
return new CertificateSignRequest.Builder();
|
throws CertificateException {
|
||||||
|
CertificateSignRequest.Builder builder =
|
||||||
|
new CertificateSignRequest.Builder()
|
||||||
|
.setConfiguration(securityConfig.getConfiguration());
|
||||||
|
try {
|
||||||
|
DomainValidator validator = DomainValidator.getInstance();
|
||||||
|
// Add all valid ips.
|
||||||
|
OzoneSecurityUtil.getValidInetsForCurrentHost().forEach(
|
||||||
|
ip -> {
|
||||||
|
builder.addIpAddress(ip.getHostAddress());
|
||||||
|
if(validator.isValid(ip.getCanonicalHostName())) {
|
||||||
|
builder.addDnsName(ip.getCanonicalHostName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CertificateException("Error while adding ip to CSR builder",
|
||||||
|
e, CSR_ERROR);
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -345,8 +358,7 @@ public X509Certificate queryCertificate(String query) {
|
|||||||
@Override
|
@Override
|
||||||
public void storeCertificate(X509Certificate certificate)
|
public void storeCertificate(X509Certificate certificate)
|
||||||
throws CertificateException {
|
throws CertificateException {
|
||||||
CertificateCodec certificateCodec = new CertificateCodec(securityConfig,
|
CertificateCodec certificateCodec = new CertificateCodec(securityConfig);
|
||||||
component);
|
|
||||||
try {
|
try {
|
||||||
certificateCodec.writeCertificate(
|
certificateCodec.writeCertificate(
|
||||||
new X509CertificateHolder(certificate.getEncoded()));
|
new X509CertificateHolder(certificate.getEncoded()));
|
||||||
@ -595,7 +607,7 @@ protected boolean validateKeyPair(PublicKey pubKey)
|
|||||||
* location.
|
* location.
|
||||||
* */
|
* */
|
||||||
protected void bootstrapClientKeys() throws CertificateException {
|
protected void bootstrapClientKeys() throws CertificateException {
|
||||||
Path keyPath = securityConfig.getKeyLocation(component);
|
Path keyPath = securityConfig.getKeyLocation();
|
||||||
if (Files.notExists(keyPath)) {
|
if (Files.notExists(keyPath)) {
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(keyPath);
|
Files.createDirectories(keyPath);
|
||||||
@ -618,10 +630,9 @@ protected KeyPair createKeyPair() throws CertificateException {
|
|||||||
keyCodec.writePrivateKey(keyPair.getPrivate());
|
keyCodec.writePrivateKey(keyPair.getPrivate());
|
||||||
} catch (NoSuchProviderException | NoSuchAlgorithmException
|
} catch (NoSuchProviderException | NoSuchAlgorithmException
|
||||||
| IOException e) {
|
| IOException e) {
|
||||||
getLogger().error("Error while bootstrapping certificate client for {}",
|
getLogger().error("Error while bootstrapping certificate client.", e);
|
||||||
component, e);
|
throw new CertificateException("Error while bootstrapping certificate.",
|
||||||
throw new CertificateException("Error while bootstrapping certificate " +
|
BOOTSTRAP_ERROR);
|
||||||
"client for" + component, BOOTSTRAP_ERROR);
|
|
||||||
}
|
}
|
||||||
return keyPair;
|
return keyPair;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.hadoop.hdds.security.x509.certificate.client;
|
package org.apache.hadoop.hdds.security.x509.certificate.client;
|
||||||
|
|
||||||
|
import org.apache.hadoop.hdds.security.x509.certificates.utils.CertificateSignRequest;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -38,8 +39,8 @@ public class OMCertificateClient extends DefaultCertificateClient {
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
LoggerFactory.getLogger(OMCertificateClient.class);
|
LoggerFactory.getLogger(OMCertificateClient.class);
|
||||||
|
|
||||||
public OMCertificateClient(SecurityConfig securityConfig, String component) {
|
public OMCertificateClient(SecurityConfig securityConfig) {
|
||||||
super(securityConfig, component, LOG);
|
super(securityConfig, LOG);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected InitResponse handleCase(InitCase init) throws
|
protected InitResponse handleCase(InitCase init) throws
|
||||||
@ -96,6 +97,21 @@ protected InitResponse handleCase(InitCase init) throws
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a CSR builder that can be used to creates a Certificate signing
|
||||||
|
* request.
|
||||||
|
*
|
||||||
|
* @return CertificateSignRequest.Builder
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public CertificateSignRequest.Builder getCSRBuilder()
|
||||||
|
throws CertificateException {
|
||||||
|
return super.getCSRBuilder()
|
||||||
|
.setDigitalEncryption(true)
|
||||||
|
.setDigitalSignature(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Logger getLogger() {
|
public Logger getLogger() {
|
||||||
return LOG;
|
return LOG;
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,16 @@ public CertificateCodec(SecurityConfig config, String component) {
|
|||||||
this.location = securityConfig.getCertificateLocation(component);
|
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.
|
* Creates an CertificateCodec.
|
||||||
*
|
*
|
||||||
@ -167,6 +177,22 @@ public Path getLocation() {
|
|||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the X.509 Certificate from PEM encoded String.
|
||||||
|
*
|
||||||
|
* @param pemEncodedString - PEM encoded String.
|
||||||
|
* @return X509Certificate - Certificate.
|
||||||
|
* @throws CertificateException - Thrown on Failure.
|
||||||
|
* @throws IOException - Thrown on Failure.
|
||||||
|
*/
|
||||||
|
public static X509Certificate getX509Cert(String pemEncodedString)
|
||||||
|
throws CertificateException, IOException {
|
||||||
|
CertificateFactory fact = CertificateFactory.getInstance("X.509");
|
||||||
|
try (InputStream input = IOUtils.toInputStream(pemEncodedString, UTF_8)) {
|
||||||
|
return (X509Certificate) fact.generateCertificate(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the Certificate pointed to the location by the configs.
|
* Write the Certificate pointed to the location by the configs.
|
||||||
*
|
*
|
||||||
|
@ -144,6 +144,8 @@ public static class Builder {
|
|||||||
private SecurityConfig config;
|
private SecurityConfig config;
|
||||||
private List<GeneralName> altNames;
|
private List<GeneralName> altNames;
|
||||||
private Boolean ca = false;
|
private Boolean ca = false;
|
||||||
|
private boolean digitalSignature;
|
||||||
|
private boolean digitalEncryption;
|
||||||
|
|
||||||
public CertificateSignRequest.Builder setConfiguration(
|
public CertificateSignRequest.Builder setConfiguration(
|
||||||
Configuration configuration) {
|
Configuration configuration) {
|
||||||
@ -171,6 +173,16 @@ public CertificateSignRequest.Builder setScmID(String s) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setDigitalSignature(boolean dSign) {
|
||||||
|
this.digitalSignature = dSign;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setDigitalEncryption(boolean dEncryption) {
|
||||||
|
this.digitalEncryption = dEncryption;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// Support SAN extenion with DNS and RFC822 Name
|
// Support SAN extenion with DNS and RFC822 Name
|
||||||
// other name type will be added as needed.
|
// other name type will be added as needed.
|
||||||
public CertificateSignRequest.Builder addDnsName(String dnsName) {
|
public CertificateSignRequest.Builder addDnsName(String dnsName) {
|
||||||
@ -200,8 +212,13 @@ public CertificateSignRequest.Builder setCA(Boolean isCA) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Extension getKeyUsageExtension() throws IOException {
|
private Extension getKeyUsageExtension() throws IOException {
|
||||||
int keyUsageFlag = KeyUsage.digitalSignature | KeyUsage.keyEncipherment
|
int keyUsageFlag = KeyUsage.keyAgreement;
|
||||||
| KeyUsage.dataEncipherment | KeyUsage.keyAgreement;
|
if(digitalEncryption){
|
||||||
|
keyUsageFlag |= KeyUsage.keyEncipherment | KeyUsage.dataEncipherment;
|
||||||
|
}
|
||||||
|
if(digitalSignature) {
|
||||||
|
keyUsageFlag |= KeyUsage.digitalSignature;
|
||||||
|
}
|
||||||
|
|
||||||
if (ca) {
|
if (ca) {
|
||||||
keyUsageFlag |= KeyUsage.keyCertSign | KeyUsage.cRLSign;
|
keyUsageFlag |= KeyUsage.keyCertSign | KeyUsage.cRLSign;
|
||||||
|
@ -82,6 +82,7 @@ public enum ErrorCode {
|
|||||||
CRYPTO_SIGN_ERROR,
|
CRYPTO_SIGN_ERROR,
|
||||||
CERTIFICATE_ERROR,
|
CERTIFICATE_ERROR,
|
||||||
BOOTSTRAP_ERROR,
|
BOOTSTRAP_ERROR,
|
||||||
|
CSR_ERROR,
|
||||||
CRYPTO_SIGNATURE_VERIFICATION_ERROR
|
CRYPTO_SIGNATURE_VERIFICATION_ERROR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,17 @@ public KeyCodec(SecurityConfig config, String component) {
|
|||||||
this.location = securityConfig.getKeyLocation(component);
|
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.
|
* Creates an HDDS Key Writer.
|
||||||
*
|
*
|
||||||
|
@ -272,6 +272,8 @@ private OzoneConsts() {
|
|||||||
public static final Metadata.Key<String> USER_METADATA_KEY =
|
public static final Metadata.Key<String> USER_METADATA_KEY =
|
||||||
Metadata.Key.of(OZONE_USER, ASCII_STRING_MARSHALLER);
|
Metadata.Key.of(OZONE_USER, ASCII_STRING_MARSHALLER);
|
||||||
|
|
||||||
|
public static final String RPC_PORT = "RPC";
|
||||||
|
|
||||||
// Default OMServiceID for OM Ratis servers to use as RaftGroupId
|
// Default OMServiceID for OM Ratis servers to use as RaftGroupId
|
||||||
public static final String OM_SERVICE_ID_DEFAULT = "omServiceIdDefault";
|
public static final String OM_SERVICE_ID_DEFAULT = "omServiceIdDefault";
|
||||||
|
|
||||||
|
@ -21,13 +21,25 @@
|
|||||||
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_SECURITY_ENABLED_DEFAULT;
|
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_SECURITY_ENABLED_DEFAULT;
|
||||||
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_SECURITY_ENABLED_KEY;
|
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_SECURITY_ENABLED_KEY;
|
||||||
|
|
||||||
|
import org.apache.commons.validator.routines.InetAddressValidator;
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.classification.InterfaceStability;
|
import org.apache.hadoop.classification.InterfaceStability;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ozone security Util class.
|
* Ozone security Util class.
|
||||||
@ -36,6 +48,12 @@
|
|||||||
@InterfaceStability.Evolving
|
@InterfaceStability.Evolving
|
||||||
public final class OzoneSecurityUtil {
|
public final class OzoneSecurityUtil {
|
||||||
|
|
||||||
|
private final static Logger LOG =
|
||||||
|
LoggerFactory.getLogger(OzoneSecurityUtil.class);
|
||||||
|
// List of ip's not recommended to be added to CSR.
|
||||||
|
private final static Set<String> INVALID_IPS = new HashSet<>(Arrays.asList(
|
||||||
|
"0.0.0.0", "127.0.0.1"));
|
||||||
|
|
||||||
private OzoneSecurityUtil() {
|
private OzoneSecurityUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,4 +75,44 @@ public static boolean checkIfFileExist(Path path, String fileName) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates through network interfaces and return all valid ip's not
|
||||||
|
* listed in CertificateSignRequest#INVALID_IPS.
|
||||||
|
*
|
||||||
|
* @return List<InetAddress>
|
||||||
|
* @throws IOException if no network interface are found or if an error
|
||||||
|
* occurs.
|
||||||
|
*/
|
||||||
|
public static List<InetAddress> getValidInetsForCurrentHost()
|
||||||
|
throws IOException {
|
||||||
|
List<InetAddress> hostIps = new ArrayList<>();
|
||||||
|
InetAddressValidator ipValidator = InetAddressValidator.getInstance();
|
||||||
|
|
||||||
|
Enumeration<NetworkInterface> enumNI =
|
||||||
|
NetworkInterface.getNetworkInterfaces();
|
||||||
|
if (enumNI != null) {
|
||||||
|
while (enumNI.hasMoreElements()) {
|
||||||
|
NetworkInterface ifc = enumNI.nextElement();
|
||||||
|
if (ifc.isUp()) {
|
||||||
|
Enumeration<InetAddress> enumAdds = ifc.getInetAddresses();
|
||||||
|
while (enumAdds.hasMoreElements()) {
|
||||||
|
InetAddress addr = enumAdds.nextElement();
|
||||||
|
|
||||||
|
if (ipValidator.isValid(addr.getHostAddress())
|
||||||
|
&& !INVALID_IPS.contains(addr.getHostAddress())) {
|
||||||
|
LOG.info("Adding ip:{},host:{}", addr.getHostAddress(),
|
||||||
|
addr.getHostName());
|
||||||
|
hostIps.add(addr);
|
||||||
|
} else {
|
||||||
|
LOG.info("ip:{},host:{} not returned.", addr.getHostAddress(),
|
||||||
|
addr.getHostName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hostIps;
|
||||||
|
} else {
|
||||||
|
throw new IOException("Unable to get network interfaces.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1830,7 +1830,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property>
|
<property>
|
||||||
<name>ozone.scm.security.service.address</name>
|
<name>ozone.scm.security.service.address</name>
|
||||||
<value>0.0.0.0:9961</value>
|
<value/>
|
||||||
<tag>OZONE, HDDS, SECURITY</tag>
|
<tag>OZONE, HDDS, SECURITY</tag>
|
||||||
<description>Address of SCMSecurityProtocolServer.</description>
|
<description>Address of SCMSecurityProtocolServer.</description>
|
||||||
</property>
|
</property>
|
||||||
|
@ -61,7 +61,6 @@ public class TestCertificateClientInit {
|
|||||||
|
|
||||||
private CertificateClient dnCertificateClient;
|
private CertificateClient dnCertificateClient;
|
||||||
private CertificateClient omCertificateClient;
|
private CertificateClient omCertificateClient;
|
||||||
private static final String COMP = "test";
|
|
||||||
private HDDSKeyGenerator keyGenerator;
|
private HDDSKeyGenerator keyGenerator;
|
||||||
private Path metaDirPath;
|
private Path metaDirPath;
|
||||||
private SecurityConfig securityConfig;
|
private SecurityConfig securityConfig;
|
||||||
@ -97,11 +96,11 @@ public void setUp() throws Exception {
|
|||||||
metaDirPath = Paths.get(path, "test");
|
metaDirPath = Paths.get(path, "test");
|
||||||
config.set(HDDS_METADATA_DIR_NAME, metaDirPath.toString());
|
config.set(HDDS_METADATA_DIR_NAME, metaDirPath.toString());
|
||||||
securityConfig = new SecurityConfig(config);
|
securityConfig = new SecurityConfig(config);
|
||||||
dnCertificateClient = new DNCertificateClient(securityConfig, COMP);
|
dnCertificateClient = new DNCertificateClient(securityConfig);
|
||||||
omCertificateClient = new OMCertificateClient(securityConfig, COMP);
|
omCertificateClient = new OMCertificateClient(securityConfig);
|
||||||
keyGenerator = new HDDSKeyGenerator(securityConfig);
|
keyGenerator = new HDDSKeyGenerator(securityConfig);
|
||||||
keyCodec = new KeyCodec(securityConfig, COMP);
|
keyCodec = new KeyCodec(securityConfig);
|
||||||
Files.createDirectories(securityConfig.getKeyLocation(COMP));
|
Files.createDirectories(securityConfig.getKeyLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -118,7 +117,7 @@ public void testInitDatanode() throws Exception {
|
|||||||
if (pvtKeyPresent) {
|
if (pvtKeyPresent) {
|
||||||
keyCodec.writePrivateKey(keyPair.getPrivate());
|
keyCodec.writePrivateKey(keyPair.getPrivate());
|
||||||
} else {
|
} else {
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
|
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +126,7 @@ public void testInitDatanode() throws Exception {
|
|||||||
keyCodec.writePublicKey(keyPair.getPublic());
|
keyCodec.writePublicKey(keyPair.getPublic());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,11 +134,11 @@ public void testInitDatanode() throws Exception {
|
|||||||
X509Certificate x509Certificate = KeyStoreTestUtil.generateCertificate(
|
X509Certificate x509Certificate = KeyStoreTestUtil.generateCertificate(
|
||||||
"CN=Test", keyPair, 10, securityConfig.getSignatureAlgo());
|
"CN=Test", keyPair, 10, securityConfig.getSignatureAlgo());
|
||||||
|
|
||||||
CertificateCodec codec = new CertificateCodec(securityConfig, COMP);
|
CertificateCodec codec = new CertificateCodec(securityConfig);
|
||||||
codec.writeCertificate(new X509CertificateHolder(
|
codec.writeCertificate(new X509CertificateHolder(
|
||||||
x509Certificate.getEncoded()));
|
x509Certificate.getEncoded()));
|
||||||
} else {
|
} else {
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getCertificateFileName()).toFile());
|
.toString(), securityConfig.getCertificateFileName()).toFile());
|
||||||
}
|
}
|
||||||
InitResponse response = dnCertificateClient.init();
|
InitResponse response = dnCertificateClient.init();
|
||||||
@ -148,10 +147,10 @@ public void testInitDatanode() throws Exception {
|
|||||||
|
|
||||||
if (!response.equals(FAILURE)) {
|
if (!response.equals(FAILURE)) {
|
||||||
assertTrue(OzoneSecurityUtil.checkIfFileExist(
|
assertTrue(OzoneSecurityUtil.checkIfFileExist(
|
||||||
securityConfig.getKeyLocation(COMP),
|
securityConfig.getKeyLocation(),
|
||||||
securityConfig.getPrivateKeyFileName()));
|
securityConfig.getPrivateKeyFileName()));
|
||||||
assertTrue(OzoneSecurityUtil.checkIfFileExist(
|
assertTrue(OzoneSecurityUtil.checkIfFileExist(
|
||||||
securityConfig.getKeyLocation(COMP),
|
securityConfig.getKeyLocation(),
|
||||||
securityConfig.getPublicKeyFileName()));
|
securityConfig.getPublicKeyFileName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +161,7 @@ public void testInitOzoneManager() throws Exception {
|
|||||||
if (pvtKeyPresent) {
|
if (pvtKeyPresent) {
|
||||||
keyCodec.writePrivateKey(keyPair.getPrivate());
|
keyCodec.writePrivateKey(keyPair.getPrivate());
|
||||||
} else {
|
} else {
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
|
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +170,7 @@ public void testInitOzoneManager() throws Exception {
|
|||||||
keyCodec.writePublicKey(keyPair.getPublic());
|
keyCodec.writePublicKey(keyPair.getPublic());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,11 +178,11 @@ public void testInitOzoneManager() throws Exception {
|
|||||||
X509Certificate x509Certificate = KeyStoreTestUtil.generateCertificate(
|
X509Certificate x509Certificate = KeyStoreTestUtil.generateCertificate(
|
||||||
"CN=Test", keyPair, 10, securityConfig.getSignatureAlgo());
|
"CN=Test", keyPair, 10, securityConfig.getSignatureAlgo());
|
||||||
|
|
||||||
CertificateCodec codec = new CertificateCodec(securityConfig, COMP);
|
CertificateCodec codec = new CertificateCodec(securityConfig);
|
||||||
codec.writeCertificate(new X509CertificateHolder(
|
codec.writeCertificate(new X509CertificateHolder(
|
||||||
x509Certificate.getEncoded()));
|
x509Certificate.getEncoded()));
|
||||||
} else {
|
} else {
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getCertificateFileName()).toFile());
|
.toString(), securityConfig.getCertificateFileName()).toFile());
|
||||||
}
|
}
|
||||||
InitResponse response = omCertificateClient.init();
|
InitResponse response = omCertificateClient.init();
|
||||||
@ -196,10 +195,10 @@ public void testInitOzoneManager() throws Exception {
|
|||||||
|
|
||||||
if (!response.equals(FAILURE)) {
|
if (!response.equals(FAILURE)) {
|
||||||
assertTrue(OzoneSecurityUtil.checkIfFileExist(
|
assertTrue(OzoneSecurityUtil.checkIfFileExist(
|
||||||
securityConfig.getKeyLocation(COMP),
|
securityConfig.getKeyLocation(),
|
||||||
securityConfig.getPrivateKeyFileName()));
|
securityConfig.getPrivateKeyFileName()));
|
||||||
assertTrue(OzoneSecurityUtil.checkIfFileExist(
|
assertTrue(OzoneSecurityUtil.checkIfFileExist(
|
||||||
securityConfig.getKeyLocation(COMP),
|
securityConfig.getKeyLocation(),
|
||||||
securityConfig.getPublicKeyFileName()));
|
securityConfig.getPublicKeyFileName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,6 @@ public class TestDefaultCertificateClient {
|
|||||||
|
|
||||||
private OMCertificateClient omCertClient;
|
private OMCertificateClient omCertClient;
|
||||||
private DNCertificateClient dnCertClient;
|
private DNCertificateClient dnCertClient;
|
||||||
private static final String COMP = "test";
|
|
||||||
private HDDSKeyGenerator keyGenerator;
|
private HDDSKeyGenerator keyGenerator;
|
||||||
private Path metaDirPath;
|
private Path metaDirPath;
|
||||||
private SecurityConfig securityConfig;
|
private SecurityConfig securityConfig;
|
||||||
@ -81,13 +80,13 @@ public void setUp() throws Exception {
|
|||||||
securityConfig = new SecurityConfig(config);
|
securityConfig = new SecurityConfig(config);
|
||||||
getCertClient();
|
getCertClient();
|
||||||
keyGenerator = new HDDSKeyGenerator(securityConfig);
|
keyGenerator = new HDDSKeyGenerator(securityConfig);
|
||||||
keyCodec = new KeyCodec(securityConfig, COMP);
|
keyCodec = new KeyCodec(securityConfig);
|
||||||
Files.createDirectories(securityConfig.getKeyLocation(COMP));
|
Files.createDirectories(securityConfig.getKeyLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getCertClient() {
|
private void getCertClient() {
|
||||||
omCertClient = new OMCertificateClient(securityConfig, COMP);
|
omCertClient = new OMCertificateClient(securityConfig);
|
||||||
dnCertClient = new DNCertificateClient(securityConfig, COMP);
|
dnCertClient = new DNCertificateClient(securityConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -160,7 +159,7 @@ public void testSignDataStream() throws Exception {
|
|||||||
() -> omCertClient.signDataStream(IOUtils.toInputStream(data,
|
() -> omCertClient.signDataStream(IOUtils.toInputStream(data,
|
||||||
UTF)));
|
UTF)));
|
||||||
|
|
||||||
KeyPair keyPair = generateKeyPairFiles();
|
generateKeyPairFiles();
|
||||||
byte[] sign = omCertClient.signDataStream(IOUtils.toInputStream(data,
|
byte[] sign = omCertClient.signDataStream(IOUtils.toInputStream(data,
|
||||||
UTF));
|
UTF));
|
||||||
validateHash(sign, data.getBytes());
|
validateHash(sign, data.getBytes());
|
||||||
@ -247,11 +246,11 @@ public void testInitCertAndKeypairValidationFailures() throws Exception {
|
|||||||
omClientLog.clearOutput();
|
omClientLog.clearOutput();
|
||||||
|
|
||||||
// Case 1. Expect failure when keypair validation fails.
|
// Case 1. Expect failure when keypair validation fails.
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
|
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
|
||||||
keyCodec.writePrivateKey(keyPair.getPrivate());
|
keyCodec.writePrivateKey(keyPair.getPrivate());
|
||||||
|
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
||||||
keyCodec.writePublicKey(keyPair2.getPublic());
|
keyCodec.writePublicKey(keyPair2.getPublic());
|
||||||
|
|
||||||
@ -272,12 +271,12 @@ public void testInitCertAndKeypairValidationFailures() throws Exception {
|
|||||||
// Case 2. Expect failure when certificate is generated from different
|
// Case 2. Expect failure when certificate is generated from different
|
||||||
// private key and keypair validation fails.
|
// private key and keypair validation fails.
|
||||||
getCertClient();
|
getCertClient();
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getCertificateFileName()).toFile());
|
.toString(), securityConfig.getCertificateFileName()).toFile());
|
||||||
X509Certificate x509Certificate = KeyStoreTestUtil.generateCertificate(
|
X509Certificate x509Certificate = KeyStoreTestUtil.generateCertificate(
|
||||||
"CN=Test", keyGenerator.generateKey(), 10,
|
"CN=Test", keyGenerator.generateKey(), 10,
|
||||||
securityConfig.getSignatureAlgo());
|
securityConfig.getSignatureAlgo());
|
||||||
CertificateCodec codec = new CertificateCodec(securityConfig, COMP);
|
CertificateCodec codec = new CertificateCodec(securityConfig);
|
||||||
codec.writeCertificate(new X509CertificateHolder(
|
codec.writeCertificate(new X509CertificateHolder(
|
||||||
x509Certificate.getEncoded()));
|
x509Certificate.getEncoded()));
|
||||||
|
|
||||||
@ -299,7 +298,7 @@ public void testInitCertAndKeypairValidationFailures() throws Exception {
|
|||||||
|
|
||||||
// Re write the correct public key.
|
// Re write the correct public key.
|
||||||
getCertClient();
|
getCertClient();
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
||||||
keyCodec.writePublicKey(keyPair.getPublic());
|
keyCodec.writePublicKey(keyPair.getPublic());
|
||||||
|
|
||||||
@ -319,7 +318,7 @@ public void testInitCertAndKeypairValidationFailures() throws Exception {
|
|||||||
|
|
||||||
// Case 4. Failure when public key recovery fails.
|
// Case 4. Failure when public key recovery fails.
|
||||||
getCertClient();
|
getCertClient();
|
||||||
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation(COMP)
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
||||||
|
|
||||||
// Check for DN.
|
// Check for DN.
|
||||||
|
@ -80,7 +80,7 @@ public void setUp() throws Exception {
|
|||||||
|
|
||||||
private CertificateClient getCertificateClient(SecurityConfig secConf)
|
private CertificateClient getCertificateClient(SecurityConfig secConf)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
return new OMCertificateClient(secConf, "om"){
|
return new OMCertificateClient(secConf){
|
||||||
@Override
|
@Override
|
||||||
public X509Certificate getCertificate() {
|
public X509Certificate getCertificate() {
|
||||||
return x509Certificate;
|
return x509Certificate;
|
||||||
|
@ -80,7 +80,7 @@ private CertificateClient setupCertificateClient() throws Exception {
|
|||||||
X509Certificate cert = KeyStoreTestUtil
|
X509Certificate cert = KeyStoreTestUtil
|
||||||
.generateCertificate("CN=OzoneMaster", keyPair, 30, "SHA256withRSA");
|
.generateCertificate("CN=OzoneMaster", keyPair, 30, "SHA256withRSA");
|
||||||
|
|
||||||
return new OMCertificateClient(securityConfig, "test") {
|
return new OMCertificateClient(securityConfig) {
|
||||||
@Override
|
@Override
|
||||||
public X509Certificate getCertificate() {
|
public X509Certificate getCertificate() {
|
||||||
return cert;
|
return cert;
|
||||||
|
@ -392,7 +392,9 @@ public MiniOzoneCluster build() throws IOException {
|
|||||||
scm = createSCM();
|
scm = createSCM();
|
||||||
scm.start();
|
scm.start();
|
||||||
om = createOM();
|
om = createOM();
|
||||||
om.setCertClient(certClient);
|
if(certClient != null) {
|
||||||
|
om.setCertClient(certClient);
|
||||||
|
}
|
||||||
} catch (AuthenticationException ex) {
|
} catch (AuthenticationException ex) {
|
||||||
throw new IOException("Unable to build MiniOzoneCluster. ", ex);
|
throw new IOException("Unable to build MiniOzoneCluster. ", ex);
|
||||||
}
|
}
|
||||||
@ -476,6 +478,10 @@ void initializeOmStorage(OMStorage omStorage) throws IOException{
|
|||||||
omStorage.setClusterId(clusterId);
|
omStorage.setClusterId(clusterId);
|
||||||
omStorage.setScmId(scmId.get());
|
omStorage.setScmId(scmId.get());
|
||||||
omStorage.setOmId(omId.orElse(UUID.randomUUID().toString()));
|
omStorage.setOmId(omId.orElse(UUID.randomUUID().toString()));
|
||||||
|
// Initialize ozone certificate client if security is enabled.
|
||||||
|
if (OzoneSecurityUtil.isSecurityEnabled(conf)) {
|
||||||
|
OzoneManager.initializeSecurity(conf, omStorage);
|
||||||
|
}
|
||||||
omStorage.initialize();
|
omStorage.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
|
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
|
||||||
import org.apache.hadoop.hdds.scm.server.SCMStorageConfig;
|
import org.apache.hadoop.hdds.scm.server.SCMStorageConfig;
|
||||||
import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
|
import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
|
||||||
import org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient;
|
|
||||||
import org.apache.hadoop.hdds.security.x509.keys.HDDSKeyGenerator;
|
import org.apache.hadoop.hdds.security.x509.keys.HDDSKeyGenerator;
|
||||||
import org.apache.hadoop.hdds.security.x509.keys.KeyCodec;
|
import org.apache.hadoop.hdds.security.x509.keys.KeyCodec;
|
||||||
import org.apache.hadoop.io.Text;
|
import org.apache.hadoop.io.Text;
|
||||||
@ -65,6 +64,7 @@
|
|||||||
import org.apache.hadoop.minikdc.MiniKdc;
|
import org.apache.hadoop.minikdc.MiniKdc;
|
||||||
import org.apache.hadoop.net.NetUtils;
|
import org.apache.hadoop.net.NetUtils;
|
||||||
import org.apache.hadoop.ozone.client.CertificateClientTestImpl;
|
import org.apache.hadoop.ozone.client.CertificateClientTestImpl;
|
||||||
|
import org.apache.hadoop.ozone.common.Storage;
|
||||||
import org.apache.hadoop.ozone.om.OMConfigKeys;
|
import org.apache.hadoop.ozone.om.OMConfigKeys;
|
||||||
import org.apache.hadoop.ozone.om.OMStorage;
|
import org.apache.hadoop.ozone.om.OMStorage;
|
||||||
import org.apache.hadoop.ozone.om.OzoneManager;
|
import org.apache.hadoop.ozone.om.OzoneManager;
|
||||||
@ -80,6 +80,10 @@
|
|||||||
import org.apache.hadoop.test.GenericTestUtils;
|
import org.apache.hadoop.test.GenericTestUtils;
|
||||||
import org.apache.hadoop.test.GenericTestUtils.LogCapturer;
|
import org.apache.hadoop.test.GenericTestUtils.LogCapturer;
|
||||||
import org.apache.hadoop.test.LambdaTestUtils;
|
import org.apache.hadoop.test.LambdaTestUtils;
|
||||||
|
import org.bouncycastle.asn1.x500.RDN;
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
|
import org.bouncycastle.asn1.x500.style.BCStyle;
|
||||||
|
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@ -90,6 +94,12 @@
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class to for security enabled Ozone cluster.
|
* Test class to for security enabled Ozone cluster.
|
||||||
@ -97,7 +107,7 @@
|
|||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
public final class TestSecureOzoneCluster {
|
public final class TestSecureOzoneCluster {
|
||||||
|
|
||||||
private static final String TEST_USER = "testUgiUser";
|
private static final String TEST_USER = "testUgiUser@EXAMPLE.COM";
|
||||||
private static final int CLIENT_TIMEOUT = 2 * 1000;
|
private static final int CLIENT_TIMEOUT = 2 * 1000;
|
||||||
private Logger logger = LoggerFactory
|
private Logger logger = LoggerFactory
|
||||||
.getLogger(TestSecureOzoneCluster.class);
|
.getLogger(TestSecureOzoneCluster.class);
|
||||||
@ -118,6 +128,7 @@ public final class TestSecureOzoneCluster {
|
|||||||
private UserGroupInformation testKerberosUgi;
|
private UserGroupInformation testKerberosUgi;
|
||||||
private StorageContainerManager scm;
|
private StorageContainerManager scm;
|
||||||
private OzoneManager om;
|
private OzoneManager om;
|
||||||
|
private String host;
|
||||||
|
|
||||||
private static String clusterId;
|
private static String clusterId;
|
||||||
private static String scmId;
|
private static String scmId;
|
||||||
@ -137,10 +148,15 @@ public void init() {
|
|||||||
final String path = folder.newFolder().toString();
|
final String path = folder.newFolder().toString();
|
||||||
metaDirPath = Paths.get(path, "om-meta");
|
metaDirPath = Paths.get(path, "om-meta");
|
||||||
conf.set(OZONE_METADATA_DIRS, metaDirPath.toString());
|
conf.set(OZONE_METADATA_DIRS, metaDirPath.toString());
|
||||||
|
conf.setBoolean(OZONE_SECURITY_ENABLED_KEY, true);
|
||||||
|
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
|
||||||
|
KERBEROS.toString());
|
||||||
|
|
||||||
startMiniKdc();
|
startMiniKdc();
|
||||||
setSecureConfig(conf);
|
setSecureConfig(conf);
|
||||||
createCredentialsInKDC(conf, miniKdc);
|
createCredentialsInKDC(conf, miniKdc);
|
||||||
generateKeyPair(conf);
|
generateKeyPair(conf);
|
||||||
|
// OzoneManager.setTestSecureOmFlag(true);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.error("Failed to initialize TestSecureOzoneCluster", e);
|
logger.error("Failed to initialize TestSecureOzoneCluster", e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -198,7 +214,7 @@ private void stopMiniKdc() {
|
|||||||
private void setSecureConfig(Configuration configuration) throws IOException {
|
private void setSecureConfig(Configuration configuration) throws IOException {
|
||||||
configuration.setBoolean(OZONE_SECURITY_ENABLED_KEY, true);
|
configuration.setBoolean(OZONE_SECURITY_ENABLED_KEY, true);
|
||||||
configuration.setBoolean(OZONE_ENABLED, true);
|
configuration.setBoolean(OZONE_ENABLED, true);
|
||||||
String host = InetAddress.getLocalHost().getCanonicalHostName()
|
host = InetAddress.getLocalHost().getCanonicalHostName()
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
String realm = miniKdc.getRealm();
|
String realm = miniKdc.getRealm();
|
||||||
curUser = UserGroupInformation.getCurrentUser()
|
curUser = UserGroupInformation.getCurrentUser()
|
||||||
@ -417,6 +433,7 @@ public void testDelegationToken() throws Exception {
|
|||||||
RPC.getProtocolVersion(OzoneManagerProtocolPB.class);
|
RPC.getProtocolVersion(OzoneManagerProtocolPB.class);
|
||||||
try {
|
try {
|
||||||
// Start OM
|
// Start OM
|
||||||
|
om.setCertClient(new CertificateClientTestImpl(conf));
|
||||||
om.start();
|
om.start();
|
||||||
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
|
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
|
||||||
String username = ugi.getUserName();
|
String username = ugi.getUserName();
|
||||||
@ -564,6 +581,7 @@ public void testDelegationTokenRenewal() throws Exception {
|
|||||||
// Start OM
|
// Start OM
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
om.setCertClient(new CertificateClientTestImpl(conf));
|
||||||
om.start();
|
om.start();
|
||||||
|
|
||||||
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
|
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
|
||||||
@ -643,7 +661,94 @@ private void setupOm(OzoneConfiguration config) throws Exception {
|
|||||||
omStore.initialize();
|
omStore.initialize();
|
||||||
OzoneManager.setTestSecureOmFlag(true);
|
OzoneManager.setTestSecureOmFlag(true);
|
||||||
om = OzoneManager.createOm(null, config);
|
om = OzoneManager.createOm(null, config);
|
||||||
CertificateClient certClient = new CertificateClientTestImpl(config);
|
}
|
||||||
om.setCertClient(certClient);
|
|
||||||
|
/**
|
||||||
|
* Test functionality to get SCM signed certificate for OM.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSecureOmInitSuccess() throws Exception {
|
||||||
|
LogCapturer omLogs =
|
||||||
|
LogCapturer.captureLogs(OzoneManager.getLogger());
|
||||||
|
omLogs.clearOutput();
|
||||||
|
initSCM();
|
||||||
|
try {
|
||||||
|
scm = StorageContainerManager.createSCM(null, conf);
|
||||||
|
scm.start();
|
||||||
|
|
||||||
|
OMStorage omStore = new OMStorage(conf);
|
||||||
|
initializeOmStorage(omStore);
|
||||||
|
OzoneManager.setTestSecureOmFlag(true);
|
||||||
|
om = OzoneManager.createOm(null, conf);
|
||||||
|
|
||||||
|
Assert.assertNotNull(om.getCertificateClient());
|
||||||
|
Assert.assertNotNull(om.getCertificateClient().getPublicKey());
|
||||||
|
Assert.assertNotNull(om.getCertificateClient().getPrivateKey());
|
||||||
|
Assert.assertNotNull(om.getCertificateClient().getCertificate());
|
||||||
|
Assert.assertTrue(omLogs.getOutput().contains("Init response: GETCERT"));
|
||||||
|
Assert.assertTrue(omLogs.getOutput().contains("Successfully stored " +
|
||||||
|
"SCM signed certificate"));
|
||||||
|
X509Certificate certificate = om.getCertificateClient().getCertificate();
|
||||||
|
validateCertificate(certificate);
|
||||||
|
} finally {
|
||||||
|
if (scm != null) {
|
||||||
|
scm.stop();
|
||||||
|
}
|
||||||
|
if (om != null) {
|
||||||
|
om.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validateCertificate(X509Certificate cert) throws Exception {
|
||||||
|
|
||||||
|
// Assert that we indeed have a self signed certificate.
|
||||||
|
X500Name x500Issuer = new JcaX509CertificateHolder(cert).getIssuer();
|
||||||
|
RDN cn = x500Issuer.getRDNs(BCStyle.CN)[0];
|
||||||
|
String hostName = InetAddress.getLocalHost().getHostName();
|
||||||
|
String scmUser = "scm@" + hostName;
|
||||||
|
Assert.assertEquals(scmUser, cn.getFirst().getValue().toString());
|
||||||
|
|
||||||
|
// Subject name should be om login user in real world but in this test
|
||||||
|
// UGI has scm user context.
|
||||||
|
Assert.assertEquals(scmUser, cn.getFirst().getValue().toString());
|
||||||
|
|
||||||
|
LocalDate today = LocalDateTime.now().toLocalDate();
|
||||||
|
Date invalidDate;
|
||||||
|
|
||||||
|
// Make sure the end date is honored.
|
||||||
|
invalidDate = java.sql.Date.valueOf(today.plus(1, ChronoUnit.DAYS));
|
||||||
|
Assert.assertTrue(cert.getNotAfter().after(invalidDate));
|
||||||
|
|
||||||
|
invalidDate = java.sql.Date.valueOf(today.plus(400, ChronoUnit.DAYS));
|
||||||
|
Assert.assertTrue(cert.getNotAfter().before(invalidDate));
|
||||||
|
|
||||||
|
Assert.assertTrue(cert.getSubjectDN().toString().contains(scmId));
|
||||||
|
Assert.assertTrue(cert.getSubjectDN().toString().contains(clusterId));
|
||||||
|
|
||||||
|
Assert.assertTrue(cert.getIssuerDN().toString().contains(scmUser));
|
||||||
|
Assert.assertTrue(cert.getIssuerDN().toString().contains(scmId));
|
||||||
|
Assert.assertTrue(cert.getIssuerDN().toString().contains(clusterId));
|
||||||
|
|
||||||
|
// Verify that certificate matches the public key.
|
||||||
|
String encodedKey1 = cert.getPublicKey().toString();
|
||||||
|
String encodedKey2 = om.getCertificateClient().getPublicKey().toString();
|
||||||
|
Assert.assertEquals(encodedKey1, encodedKey2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeOmStorage(OMStorage omStorage) throws IOException {
|
||||||
|
if (omStorage.getState() == Storage.StorageState.INITIALIZED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
omStorage.setClusterId(clusterId);
|
||||||
|
omStorage.setScmId(scmId);
|
||||||
|
omStorage.setOmId(omId);
|
||||||
|
// Initialize ozone certificate client if security is enabled.
|
||||||
|
if (OzoneSecurityUtil.isSecurityEnabled(conf)) {
|
||||||
|
OzoneManager.initializeSecurity(conf, omStorage);
|
||||||
|
}
|
||||||
|
omStorage.initialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.hadoop.ozone.client;
|
package org.apache.hadoop.ozone.client;
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
||||||
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
|
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
|
||||||
import org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient;
|
import org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient;
|
||||||
@ -26,6 +27,7 @@
|
|||||||
import org.bouncycastle.cert.X509CertificateHolder;
|
import org.bouncycastle.cert.X509CertificateHolder;
|
||||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
@ -45,27 +47,14 @@ public class CertificateClientTestImpl implements CertificateClient {
|
|||||||
|
|
||||||
private final SecurityConfig securityConfig;
|
private final SecurityConfig securityConfig;
|
||||||
private final KeyPair keyPair;
|
private final KeyPair keyPair;
|
||||||
private final X509Certificate cert;
|
private final Configuration config;
|
||||||
|
|
||||||
public CertificateClientTestImpl(OzoneConfiguration conf) throws Exception{
|
public CertificateClientTestImpl(OzoneConfiguration conf) throws Exception{
|
||||||
securityConfig = new SecurityConfig(conf);
|
securityConfig = new SecurityConfig(conf);
|
||||||
HDDSKeyGenerator keyGen =
|
HDDSKeyGenerator keyGen =
|
||||||
new HDDSKeyGenerator(securityConfig.getConfiguration());
|
new HDDSKeyGenerator(securityConfig.getConfiguration());
|
||||||
keyPair = keyGen.generateKey();
|
keyPair = keyGen.generateKey();
|
||||||
|
config = conf;
|
||||||
SelfSignedCertificate.Builder builder =
|
|
||||||
SelfSignedCertificate.newBuilder()
|
|
||||||
.setBeginDate(LocalDate.now())
|
|
||||||
.setEndDate(LocalDate.now().plus(365, ChronoUnit.DAYS))
|
|
||||||
.setClusterID("cluster1")
|
|
||||||
.setKey(keyPair)
|
|
||||||
.setSubject("TestCertSub")
|
|
||||||
.setConfiguration(conf)
|
|
||||||
.setScmID("TestScmId1")
|
|
||||||
.makeCA();
|
|
||||||
|
|
||||||
X509CertificateHolder certificateHolder = builder.build();
|
|
||||||
cert = new JcaX509CertificateConverter().getCertificate(certificateHolder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -80,7 +69,24 @@ public PublicKey getPublicKey() {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public X509Certificate getCertificate() {
|
public X509Certificate getCertificate() {
|
||||||
return cert;
|
SelfSignedCertificate.Builder builder =
|
||||||
|
SelfSignedCertificate.newBuilder()
|
||||||
|
.setBeginDate(LocalDate.now())
|
||||||
|
.setEndDate(LocalDate.now().plus(365, ChronoUnit.DAYS))
|
||||||
|
.setClusterID("cluster1")
|
||||||
|
.setKey(keyPair)
|
||||||
|
.setSubject("TestCertSub")
|
||||||
|
.setConfiguration(config)
|
||||||
|
.setScmID("TestScmId1")
|
||||||
|
.makeCA();
|
||||||
|
X509CertificateHolder certificateHolder = null;
|
||||||
|
try {
|
||||||
|
certificateHolder = builder.build();
|
||||||
|
return new JcaX509CertificateConverter().getCertificate(
|
||||||
|
certificateHolder);
|
||||||
|
} catch (IOException | java.security.cert.CertificateException e) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -113,7 +119,7 @@ public boolean verifySignature(byte[] data, byte[] signature,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CertificateSignRequest.Builder getCSRBuilder() {
|
public CertificateSignRequest.Builder getCSRBuilder() {
|
||||||
return null;
|
return new CertificateSignRequest.Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,218 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* 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.ozone.om;
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.hadoop.hdds.HddsConfigKeys;
|
||||||
|
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
||||||
|
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
|
||||||
|
import org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient;
|
||||||
|
import org.apache.hadoop.hdds.security.x509.certificate.client.OMCertificateClient;
|
||||||
|
import org.apache.hadoop.hdds.security.x509.certificate.utils.CertificateCodec;
|
||||||
|
import org.apache.hadoop.hdds.security.x509.keys.KeyCodec;
|
||||||
|
import org.apache.hadoop.ozone.MiniOzoneCluster;
|
||||||
|
import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
|
||||||
|
import org.apache.hadoop.test.LambdaTestUtils;
|
||||||
|
import org.bouncycastle.cert.X509CertificateHolder;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.Timeout;
|
||||||
|
|
||||||
|
import java.net.ConnectException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION;
|
||||||
|
import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_NAMES;
|
||||||
|
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_ENABLED;
|
||||||
|
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_OPEN_KEY_EXPIRE_THRESHOLD_SECONDS;
|
||||||
|
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_SECURITY_ENABLED_KEY;
|
||||||
|
import static org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS;
|
||||||
|
import static org.apache.hadoop.test.GenericTestUtils.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test secure Ozone Manager operation in distributed handler scenario.
|
||||||
|
*/
|
||||||
|
public class TestSecureOzoneManager {
|
||||||
|
|
||||||
|
private MiniOzoneCluster cluster = null;
|
||||||
|
private OzoneConfiguration conf;
|
||||||
|
private String clusterId;
|
||||||
|
private String scmId;
|
||||||
|
private String omId;
|
||||||
|
private Path metaDir;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public Timeout timeout = new Timeout(1000 * 25);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a MiniDFSCluster for testing.
|
||||||
|
* <p>
|
||||||
|
* Ozone is made active by setting OZONE_ENABLED = true
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void init() throws Exception {
|
||||||
|
conf = new OzoneConfiguration();
|
||||||
|
clusterId = UUID.randomUUID().toString();
|
||||||
|
scmId = UUID.randomUUID().toString();
|
||||||
|
omId = UUID.randomUUID().toString();
|
||||||
|
conf.setBoolean(OZONE_ACL_ENABLED, true);
|
||||||
|
conf.setBoolean(OZONE_SECURITY_ENABLED_KEY, true);
|
||||||
|
conf.setInt(OZONE_OPEN_KEY_EXPIRE_THRESHOLD_SECONDS, 2);
|
||||||
|
conf.set(HADOOP_SECURITY_AUTHENTICATION, KERBEROS.toString());
|
||||||
|
conf.set(OZONE_SCM_NAMES, "localhost");
|
||||||
|
final String path = getTempPath(UUID.randomUUID().toString());
|
||||||
|
metaDir = Paths.get(path, "om-meta");
|
||||||
|
conf.set(HddsConfigKeys.OZONE_METADATA_DIRS, metaDir.toString());
|
||||||
|
OzoneManager.setTestSecureOmFlag(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown MiniDFSCluster.
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
public void shutdown() {
|
||||||
|
if (cluster != null) {
|
||||||
|
cluster.shutdown();
|
||||||
|
}
|
||||||
|
FileUtils.deleteQuietly(metaDir.toFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test failure cases for secure OM initialization.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSecureOmInitFailures() throws Exception {
|
||||||
|
PrivateKey privateKey;
|
||||||
|
PublicKey publicKey;
|
||||||
|
LogCapturer omLogs =
|
||||||
|
LogCapturer.captureLogs(OzoneManager.getLogger());
|
||||||
|
OMStorage omStorage = new OMStorage(conf);
|
||||||
|
omStorage.setClusterId(clusterId);
|
||||||
|
omStorage.setScmId(scmId);
|
||||||
|
omStorage.setOmId(omId);
|
||||||
|
omLogs.clearOutput();
|
||||||
|
|
||||||
|
// Case 1: When keypair as well as certificate is missing. Initial keypair
|
||||||
|
// boot-up. Get certificate will fail no SCM is not running.
|
||||||
|
LambdaTestUtils.intercept(ConnectException.class, "Connection " +
|
||||||
|
"refused; For more detail",
|
||||||
|
() -> OzoneManager.initializeSecurity(conf, omStorage));
|
||||||
|
SecurityConfig securityConfig = new SecurityConfig(conf);
|
||||||
|
CertificateClient client =
|
||||||
|
new OMCertificateClient(securityConfig);
|
||||||
|
privateKey = client.getPrivateKey();
|
||||||
|
publicKey = client.getPublicKey();
|
||||||
|
Assert.assertNotNull(client.getPrivateKey());
|
||||||
|
Assert.assertNotNull(client.getPublicKey());
|
||||||
|
Assert.assertNull(client.getCertificate());
|
||||||
|
Assert.assertTrue(omLogs.getOutput().contains("Init response: GETCERT"));
|
||||||
|
omLogs.clearOutput();
|
||||||
|
|
||||||
|
// Case 2: If key pair already exist than response should be RECOVER.
|
||||||
|
client = new OMCertificateClient(securityConfig);
|
||||||
|
LambdaTestUtils.intercept(RuntimeException.class, " OM security" +
|
||||||
|
" initialization failed",
|
||||||
|
() -> OzoneManager.initializeSecurity(conf, omStorage));
|
||||||
|
Assert.assertNotNull(client.getPrivateKey());
|
||||||
|
Assert.assertNotNull(client.getPublicKey());
|
||||||
|
Assert.assertNull(client.getCertificate());
|
||||||
|
Assert.assertTrue(omLogs.getOutput().contains("Init response: RECOVER"));
|
||||||
|
Assert.assertTrue(omLogs.getOutput().contains(" OM certificate is " +
|
||||||
|
"missing"));
|
||||||
|
omLogs.clearOutput();
|
||||||
|
|
||||||
|
// Case 3: When public key as well as certificate is missing.
|
||||||
|
client = new OMCertificateClient(securityConfig);
|
||||||
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
|
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
||||||
|
LambdaTestUtils.intercept(RuntimeException.class, " OM security" +
|
||||||
|
" initialization failed",
|
||||||
|
() -> OzoneManager.initializeSecurity(conf, omStorage));
|
||||||
|
Assert.assertNotNull(client.getPrivateKey());
|
||||||
|
Assert.assertNull(client.getPublicKey());
|
||||||
|
Assert.assertNull(client.getCertificate());
|
||||||
|
Assert.assertTrue(omLogs.getOutput().contains("Init response: FAILURE"));
|
||||||
|
omLogs.clearOutput();
|
||||||
|
|
||||||
|
// Case 4: When private key and certificate is missing.
|
||||||
|
client = new OMCertificateClient(securityConfig);
|
||||||
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
|
.toString(), securityConfig.getPrivateKeyFileName()).toFile());
|
||||||
|
KeyCodec keyCodec = new KeyCodec(securityConfig);
|
||||||
|
keyCodec.writePublicKey(publicKey);
|
||||||
|
LambdaTestUtils.intercept(RuntimeException.class, " OM security" +
|
||||||
|
" initialization failed",
|
||||||
|
() -> OzoneManager.initializeSecurity(conf, omStorage));
|
||||||
|
Assert.assertNull(client.getPrivateKey());
|
||||||
|
Assert.assertNotNull(client.getPublicKey());
|
||||||
|
Assert.assertNull(client.getCertificate());
|
||||||
|
Assert.assertTrue(omLogs.getOutput().contains("Init response: FAILURE"));
|
||||||
|
omLogs.clearOutput();
|
||||||
|
|
||||||
|
// Case 5: When only certificate is present.
|
||||||
|
client = new OMCertificateClient(securityConfig);
|
||||||
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
|
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
||||||
|
CertificateCodec certCodec = new CertificateCodec(securityConfig);
|
||||||
|
X509Certificate x509Certificate = KeyStoreTestUtil.generateCertificate(
|
||||||
|
"CN=Test", new KeyPair(publicKey, privateKey), 10,
|
||||||
|
securityConfig.getSignatureAlgo());
|
||||||
|
certCodec.writeCertificate(new X509CertificateHolder(
|
||||||
|
x509Certificate.getEncoded()));
|
||||||
|
LambdaTestUtils.intercept(RuntimeException.class, " OM security" +
|
||||||
|
" initialization failed",
|
||||||
|
() -> OzoneManager.initializeSecurity(conf, omStorage));
|
||||||
|
Assert.assertNull(client.getPrivateKey());
|
||||||
|
Assert.assertNull(client.getPublicKey());
|
||||||
|
Assert.assertNotNull(client.getCertificate());
|
||||||
|
Assert.assertTrue(omLogs.getOutput().contains("Init response: FAILURE"));
|
||||||
|
omLogs.clearOutput();
|
||||||
|
|
||||||
|
// Case 6: When private key and certificate is present.
|
||||||
|
client = new OMCertificateClient(securityConfig);
|
||||||
|
FileUtils.deleteQuietly(Paths.get(securityConfig.getKeyLocation()
|
||||||
|
.toString(), securityConfig.getPublicKeyFileName()).toFile());
|
||||||
|
keyCodec.writePrivateKey(privateKey);
|
||||||
|
OzoneManager.initializeSecurity(conf, omStorage);
|
||||||
|
Assert.assertNotNull(client.getPrivateKey());
|
||||||
|
Assert.assertNotNull(client.getPublicKey());
|
||||||
|
Assert.assertNotNull(client.getCertificate());
|
||||||
|
Assert.assertTrue(omLogs.getOutput().contains("Init response: SUCCESS"));
|
||||||
|
omLogs.clearOutput();
|
||||||
|
|
||||||
|
// Case 7 When keypair and certificate is present.
|
||||||
|
client = new OMCertificateClient(securityConfig);
|
||||||
|
OzoneManager.initializeSecurity(conf, omStorage);
|
||||||
|
Assert.assertNotNull(client.getPrivateKey());
|
||||||
|
Assert.assertNotNull(client.getPublicKey());
|
||||||
|
Assert.assertNotNull(client.getCertificate());
|
||||||
|
Assert.assertTrue(omLogs.getOutput().contains("Init response: SUCCESS"));
|
||||||
|
omLogs.clearOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -24,9 +24,14 @@
|
|||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.protobuf.BlockingService;
|
import com.google.protobuf.BlockingService;
|
||||||
|
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.crypto.key.KeyProvider;
|
import org.apache.hadoop.crypto.key.KeyProvider;
|
||||||
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
|
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
|
||||||
@ -38,6 +43,9 @@
|
|||||||
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
||||||
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
|
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
|
||||||
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
|
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
|
||||||
|
import org.apache.hadoop.hdds.protocol.SCMSecurityProtocol;
|
||||||
|
import org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolClientSideTranslatorPB;
|
||||||
|
import org.apache.hadoop.hdds.protocolPB.SCMSecurityProtocolPB;
|
||||||
import org.apache.hadoop.hdds.scm.ScmInfo;
|
import org.apache.hadoop.hdds.scm.ScmInfo;
|
||||||
import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList;
|
import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList;
|
||||||
import org.apache.hadoop.hdds.scm.protocol.ScmBlockLocationProtocol;
|
import org.apache.hadoop.hdds.scm.protocol.ScmBlockLocationProtocol;
|
||||||
@ -48,6 +56,9 @@
|
|||||||
import org.apache.hadoop.hdds.scm.protocolPB.StorageContainerLocationProtocolPB;
|
import org.apache.hadoop.hdds.scm.protocolPB.StorageContainerLocationProtocolPB;
|
||||||
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
|
import org.apache.hadoop.hdds.security.x509.SecurityConfig;
|
||||||
import org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient;
|
import org.apache.hadoop.hdds.security.x509.certificate.client.CertificateClient;
|
||||||
|
import org.apache.hadoop.hdds.security.x509.certificate.client.OMCertificateClient;
|
||||||
|
import org.apache.hadoop.hdds.security.x509.certificate.utils.CertificateCodec;
|
||||||
|
import org.apache.hadoop.hdds.security.x509.certificates.utils.CertificateSignRequest;
|
||||||
import org.apache.hadoop.hdds.server.ServiceRuntimeInfoImpl;
|
import org.apache.hadoop.hdds.server.ServiceRuntimeInfoImpl;
|
||||||
import org.apache.hadoop.hdds.tracing.TracingUtil;
|
import org.apache.hadoop.hdds.tracing.TracingUtil;
|
||||||
import org.apache.hadoop.hdfs.DFSUtil;
|
import org.apache.hadoop.hdfs.DFSUtil;
|
||||||
@ -126,6 +137,7 @@
|
|||||||
import org.apache.hadoop.util.StringUtils;
|
import org.apache.hadoop.util.StringUtils;
|
||||||
import org.apache.hadoop.utils.RetriableTask;
|
import org.apache.hadoop.utils.RetriableTask;
|
||||||
import org.apache.ratis.util.LifeCycle;
|
import org.apache.ratis.util.LifeCycle;
|
||||||
|
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -150,8 +162,9 @@
|
|||||||
|
|
||||||
import static org.apache.hadoop.hdds.HddsUtils.getScmAddressForBlockClients;
|
import static org.apache.hadoop.hdds.HddsUtils.getScmAddressForBlockClients;
|
||||||
import static org.apache.hadoop.hdds.HddsUtils.getScmAddressForClients;
|
import static org.apache.hadoop.hdds.HddsUtils.getScmAddressForClients;
|
||||||
import static org.apache.hadoop.hdds.HddsUtils.isHddsEnabled;
|
import static org.apache.hadoop.hdds.HddsUtils.getScmAddressForSecurityProtocol;
|
||||||
import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.HEALTHY;
|
import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.HEALTHY;
|
||||||
|
import static org.apache.hadoop.hdds.security.x509.certificates.utils.CertificateSignRequest.getEncodedString;
|
||||||
import static org.apache.hadoop.hdds.server.ServerUtils.updateRPCListenAddress;
|
import static org.apache.hadoop.hdds.server.ServerUtils.updateRPCListenAddress;
|
||||||
import static org.apache.hadoop.io.retry.RetryPolicies.retryUpToMaximumCountWithFixedSleep;
|
import static org.apache.hadoop.io.retry.RetryPolicies.retryUpToMaximumCountWithFixedSleep;
|
||||||
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_AUTHORIZER_CLASS;
|
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_AUTHORIZER_CLASS;
|
||||||
@ -159,8 +172,8 @@
|
|||||||
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_ENABLED_DEFAULT;
|
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_ENABLED_DEFAULT;
|
||||||
import static org.apache.hadoop.ozone.OzoneConsts.OM_METRICS_FILE;
|
import static org.apache.hadoop.ozone.OzoneConsts.OM_METRICS_FILE;
|
||||||
import static org.apache.hadoop.ozone.OzoneConsts.OM_METRICS_TEMP_FILE;
|
import static org.apache.hadoop.ozone.OzoneConsts.OM_METRICS_TEMP_FILE;
|
||||||
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ENABLED;
|
|
||||||
|
|
||||||
|
import static org.apache.hadoop.ozone.OzoneConsts.RPC_PORT;
|
||||||
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ADDRESS_KEY;
|
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ADDRESS_KEY;
|
||||||
import static org.apache.hadoop.ozone.om.OMConfigKeys
|
import static org.apache.hadoop.ozone.om.OMConfigKeys
|
||||||
.OZONE_OM_HANDLER_COUNT_DEFAULT;
|
.OZONE_OM_HANDLER_COUNT_DEFAULT;
|
||||||
@ -246,6 +259,7 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
|
|||||||
private final SecurityConfig secConfig;
|
private final SecurityConfig secConfig;
|
||||||
private final S3SecretManager s3SecretManager;
|
private final S3SecretManager s3SecretManager;
|
||||||
private volatile boolean isOmRpcServerRunning = false;
|
private volatile boolean isOmRpcServerRunning = false;
|
||||||
|
private String omComponent;
|
||||||
|
|
||||||
private KeyProviderCryptoExtension kmsProvider = null;
|
private KeyProviderCryptoExtension kmsProvider = null;
|
||||||
private static String keyProviderUriKeyName =
|
private static String keyProviderUriKeyName =
|
||||||
@ -291,12 +305,14 @@ private OzoneManager(OzoneConfiguration conf) throws IOException,
|
|||||||
omRpcAddressTxt = new Text(omNodeDetails.getRpcAddressString());
|
omRpcAddressTxt = new Text(omNodeDetails.getRpcAddressString());
|
||||||
|
|
||||||
secConfig = new SecurityConfig(configuration);
|
secConfig = new SecurityConfig(configuration);
|
||||||
|
if (secConfig.isSecurityEnabled()) {
|
||||||
|
omComponent = OM_DAEMON + "-" + omId;
|
||||||
|
certClient = new OMCertificateClient(new SecurityConfig(conf));
|
||||||
|
delegationTokenMgr = createDelegationTokenSecretManager(configuration);
|
||||||
|
}
|
||||||
if (secConfig.isBlockTokenEnabled()) {
|
if (secConfig.isBlockTokenEnabled()) {
|
||||||
blockTokenMgr = createBlockTokenSecretManager(configuration);
|
blockTokenMgr = createBlockTokenSecretManager(configuration);
|
||||||
}
|
}
|
||||||
if(secConfig.isSecurityEnabled()){
|
|
||||||
delegationTokenMgr = createDelegationTokenSecretManager(configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
omRpcServer = getRpcServer(conf);
|
omRpcServer = getRpcServer(conf);
|
||||||
omRpcAddress = updateRPCListenAddress(configuration,
|
omRpcAddress = updateRPCListenAddress(configuration,
|
||||||
@ -668,11 +684,17 @@ public void setCertClient(CertificateClient certClient) {
|
|||||||
*/
|
*/
|
||||||
private void readKeyPair() throws OzoneSecurityException {
|
private void readKeyPair() throws OzoneSecurityException {
|
||||||
try {
|
try {
|
||||||
keyPair = new KeyPair(certClient.getPublicKey(),
|
LOG.info("Reading keypair and certificate from file system.");
|
||||||
certClient.getPrivateKey());
|
PublicKey pubKey = certClient.getPublicKey();
|
||||||
|
PrivateKey pvtKey = certClient.getPrivateKey();
|
||||||
|
Objects.requireNonNull(pubKey);
|
||||||
|
Objects.requireNonNull(pvtKey);
|
||||||
|
Objects.requireNonNull(certClient.getCertificate());
|
||||||
|
|
||||||
|
keyPair = new KeyPair(pubKey, pvtKey);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new OzoneSecurityException("Error reading private file for "
|
throw new OzoneSecurityException("Error reading keypair & certificate "
|
||||||
+ "OzoneManager", e, OzoneSecurityException
|
+ "OzoneManager.", e, OzoneSecurityException
|
||||||
.ResultCodes.OM_PUBLIC_PRIVATE_KEY_FILE_NOT_EXIST);
|
.ResultCodes.OM_PUBLIC_PRIVATE_KEY_FILE_NOT_EXIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -730,6 +752,29 @@ private static ScmBlockLocationProtocol getScmBlockClient(
|
|||||||
.createProxy(scmBlockLocationClient, ScmBlockLocationProtocol.class);
|
.createProxy(scmBlockLocationClient, ScmBlockLocationProtocol.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a scm security client, used to get SCM signed certificate.
|
||||||
|
*
|
||||||
|
* @return {@link SCMSecurityProtocol}
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private static SCMSecurityProtocol getScmSecurityClient(
|
||||||
|
OzoneConfiguration conf) throws IOException {
|
||||||
|
RPC.setProtocolEngine(conf, SCMSecurityProtocolPB.class,
|
||||||
|
ProtobufRpcEngine.class);
|
||||||
|
long scmVersion =
|
||||||
|
RPC.getProtocolVersion(ScmBlockLocationProtocolPB.class);
|
||||||
|
InetSocketAddress scmSecurityProtoAdd =
|
||||||
|
getScmAddressForSecurityProtocol(conf);
|
||||||
|
SCMSecurityProtocolClientSideTranslatorPB scmSecurityClient =
|
||||||
|
new SCMSecurityProtocolClientSideTranslatorPB(
|
||||||
|
RPC.getProxy(SCMSecurityProtocolPB.class, scmVersion,
|
||||||
|
scmSecurityProtoAdd, UserGroupInformation.getCurrentUser(),
|
||||||
|
conf, NetUtils.getDefaultSocketFactory(conf),
|
||||||
|
Client.getRpcTimeout(conf)));
|
||||||
|
return scmSecurityClient;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a scm container client.
|
* Returns a scm container client.
|
||||||
*
|
*
|
||||||
@ -859,11 +904,6 @@ public static OzoneManager createOm(
|
|||||||
private static OzoneManager createOm(String[] argv,
|
private static OzoneManager createOm(String[] argv,
|
||||||
OzoneConfiguration conf, boolean printBanner)
|
OzoneConfiguration conf, boolean printBanner)
|
||||||
throws IOException, AuthenticationException {
|
throws IOException, AuthenticationException {
|
||||||
if (!isHddsEnabled(conf)) {
|
|
||||||
System.err.println("OM cannot be started in secure mode or when " +
|
|
||||||
OZONE_ENABLED + " is set to false");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
StartupOption startOpt = parseArguments(argv);
|
StartupOption startOpt = parseArguments(argv);
|
||||||
if (startOpt == null) {
|
if (startOpt == null) {
|
||||||
printUsage(System.err);
|
printUsage(System.err);
|
||||||
@ -928,6 +968,11 @@ static boolean omInit(OzoneConfiguration conf) throws IOException {
|
|||||||
"OM initialization succeeded.Current cluster id for sd="
|
"OM initialization succeeded.Current cluster id for sd="
|
||||||
+ omStorage.getStorageDir() + ";cid=" + omStorage
|
+ omStorage.getStorageDir() + ";cid=" + omStorage
|
||||||
.getClusterID());
|
.getClusterID());
|
||||||
|
|
||||||
|
if (OzoneSecurityUtil.isSecurityEnabled(conf)) {
|
||||||
|
initializeSecurity(conf, omStorage);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
LOG.error("Could not initialize OM version file", ioe);
|
LOG.error("Could not initialize OM version file", ioe);
|
||||||
@ -942,6 +987,41 @@ static boolean omInit(OzoneConfiguration conf) throws IOException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes secure OzoneManager.
|
||||||
|
* */
|
||||||
|
@VisibleForTesting
|
||||||
|
public static void initializeSecurity(OzoneConfiguration conf,
|
||||||
|
OMStorage omStore)
|
||||||
|
throws IOException {
|
||||||
|
LOG.info("Initializing secure OzoneManager.");
|
||||||
|
|
||||||
|
CertificateClient certClient =
|
||||||
|
new OMCertificateClient(new SecurityConfig(conf));
|
||||||
|
CertificateClient.InitResponse response = certClient.init();
|
||||||
|
LOG.info("Init response: {}", response);
|
||||||
|
switch (response) {
|
||||||
|
case SUCCESS:
|
||||||
|
LOG.info("Initialization successful.");
|
||||||
|
break;
|
||||||
|
case GETCERT:
|
||||||
|
getSCMSignedCert(certClient, conf, omStore);
|
||||||
|
LOG.info("Successfully stored SCM signed certificate.");
|
||||||
|
break;
|
||||||
|
case FAILURE:
|
||||||
|
LOG.error("OM security initialization failed.");
|
||||||
|
throw new RuntimeException("OM security initialization failed.");
|
||||||
|
case RECOVER:
|
||||||
|
LOG.error("OM security initialization failed. OM certificate is " +
|
||||||
|
"missing.");
|
||||||
|
throw new RuntimeException("OM security initialization failed.");
|
||||||
|
default:
|
||||||
|
LOG.error("OM security initialization failed. Init response: {}",
|
||||||
|
response);
|
||||||
|
throw new RuntimeException("OM security initialization failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static ScmInfo getScmInfo(OzoneConfiguration conf)
|
private static ScmInfo getScmInfo(OzoneConfiguration conf)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
try {
|
try {
|
||||||
@ -1266,6 +1346,65 @@ private void startSecretManagerIfNecessary() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SCM signed certificate and store it using certificate client.
|
||||||
|
* */
|
||||||
|
private static void getSCMSignedCert(CertificateClient client,
|
||||||
|
OzoneConfiguration config, OMStorage omStore) throws IOException {
|
||||||
|
CertificateSignRequest.Builder builder = client.getCSRBuilder();
|
||||||
|
KeyPair keyPair = new KeyPair(client.getPublicKey(),
|
||||||
|
client.getPrivateKey());
|
||||||
|
InetSocketAddress omRpcAdd;
|
||||||
|
|
||||||
|
omRpcAdd = OmUtils.getOmAddress(config);
|
||||||
|
// Get host name.
|
||||||
|
String hostname = omRpcAdd.getAddress().getHostName();
|
||||||
|
|
||||||
|
String subject = UserGroupInformation.getCurrentUser()
|
||||||
|
.getShortUserName() + "@" + hostname;
|
||||||
|
|
||||||
|
builder.setCA(false)
|
||||||
|
.setKey(keyPair)
|
||||||
|
.setConfiguration(config)
|
||||||
|
.setScmID(omStore.getScmId())
|
||||||
|
.setClusterID(omStore.getClusterID())
|
||||||
|
.setSubject(subject)
|
||||||
|
.addIpAddress(omRpcAdd.getAddress().getHostAddress());
|
||||||
|
|
||||||
|
LOG.info("Creating csr for OM->dns:{},ip:{},scmId:{},clusterId:{}," +
|
||||||
|
"subject:{}", hostname, omRpcAdd.getAddress().getHostAddress(),
|
||||||
|
omStore.getScmId(), omStore.getClusterID(), subject);
|
||||||
|
|
||||||
|
HddsProtos.OzoneManagerDetailsProto.Builder omDetailsProtoBuilder =
|
||||||
|
HddsProtos.OzoneManagerDetailsProto.newBuilder()
|
||||||
|
.setHostName(omRpcAdd.getHostName())
|
||||||
|
.setIpAddress(omRpcAdd.getAddress().getHostAddress())
|
||||||
|
.setUuid(omStore.getOmId())
|
||||||
|
.addPorts(HddsProtos.Port.newBuilder()
|
||||||
|
.setName(RPC_PORT)
|
||||||
|
.setValue(omRpcAdd.getPort())
|
||||||
|
.build());
|
||||||
|
|
||||||
|
PKCS10CertificationRequest csr = builder.build();
|
||||||
|
HddsProtos.OzoneManagerDetailsProto omDetailsProto =
|
||||||
|
omDetailsProtoBuilder.build();
|
||||||
|
LOG.info("OzoneManager ports added:{}", omDetailsProto.getPortsList());
|
||||||
|
SCMSecurityProtocol secureScmClient = getScmSecurityClient(config);
|
||||||
|
|
||||||
|
String pemEncodedCert = secureScmClient.getOMCertificate(omDetailsProto,
|
||||||
|
getEncodedString(csr));
|
||||||
|
|
||||||
|
try {
|
||||||
|
X509Certificate x509Certificate =
|
||||||
|
CertificateCodec.getX509Cert(pemEncodedCert);
|
||||||
|
client.storeCertificate(x509Certificate);
|
||||||
|
} catch (IOException | CertificateException e) {
|
||||||
|
LOG.error("Error while storing SCM signed certificate.", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return true if delegation token operation is allowed
|
* @return true if delegation token operation is allowed
|
||||||
@ -2469,4 +2608,13 @@ public List<OMNodeDetails> getPeerNodes() {
|
|||||||
public OMFailoverProxyProvider getOMFailoverProxyProvider() {
|
public OMFailoverProxyProvider getOMFailoverProxyProvider() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public CertificateClient getCertificateClient() {
|
||||||
|
return certClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComponent() {
|
||||||
|
return omComponent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user