密钥相关命令
环境准备:下载安装Win64OpenSSL-1_1_0i.exe和jdk_1.8
一、生成.ssh文件(用于远程登陆)
生成 id_rsa 和 id_rsa.pub 文件
ssh-keygen -t rsa -C "message"
将公钥发送到目标主机
ssh-copy-id [ip]
执行成功之后,我们在目标机器上查看/root/.ssh目录已经生成,并且多了一个名为authorized_keys的文件,里面保存的正是原机器上ssh-keygen生成的id_rsa.pub的内容。
- id_rsa:私钥
- id_rsa.pub:公钥
- authorized_keys:存储了可以远程登陆本机的节点的公钥
- known_hosts:连接到本机的节点的信息,包括远程机器ip、远程机器公钥。
二、openssl的证书指令
2.1 基本命令
生成私钥
openssl genrsa -aes256 -out rsaprivatekey.pem 2048
- 生成rsa私钥,aes256算法,2048位强度,密钥文件为server.key。
生成公钥
openssl rsa -in rsaprivatekey.pem -out rsapublickey.pem -pubout
将私钥进行pkcs8编码给java用
openssl pkcs8 -topk8 -inform PEM -in rsaprivatekey.pem -outform PEM -out rsaprivatekey_pkcs8.pem -nocrypt
2.2 生成证书
2.2.1 创建自签名证书
-
生成私钥
openssl genrsa -aes256 -out server.key 2048
-
生成CSR(证书签名请求)
Csr是证书请求文件,用于申请证书。openssl req -new -key server.key -out server.csr
如果要支持https,Common Name应该与域名保持一致,否则会引起浏览器警告。
-
删除私钥中的密码
在第1步创建私钥的过程中,由于必须要指定一个密码。而这个密码会带来一个副作用,那就是在每次启动Web服务器时,都会要求输入密码,这显然非常不方便。
要删除私钥中的密码,操作如下:openssl rsa -in server.key -out server.key
-
生成自签名证书CRT
crt是CA认证后的证书。用私钥server.key给csr签名后得到crt证书。openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
2.2.2 私有CA签名证书(推荐)
-
创建root CA私钥
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 365 -out ca.crt
CN输入ca.rancher.com
-
为服务端生成证书签名请求文件
openssl req -newkey rsa:4096 -nodes -sha256 -keyout demo.rancher.com.key -out demo.rancher.com.csr
CN输入demo.rancher.com;
注意:Commone Name一定要是你要授予证书的FQDN域名或主机名,并且不能与生成root CA设置的Commone Name相同
-
用第一步创建的CA证书给第二步生成的签名请求进行签名
openssl x509 -req -days 365 -in demo.rancher.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out demo.rancher.com.crt
4.如果您使用IP,例如192.168.1.101来连接,则可以改为运行以下命令:
echo 'subjectAltName = IP:192.168.1.101' > extfile.cnf
openssl x509 -req -days 365 -in demo.rancher.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile extfile.cnf -out demo.rancher.com.crt
2.3 验证证书
注意: 因为使用的是自签名证书,浏览器会提示证书的颁发机构是未知的。
把生成的ca证书和去除密码的私钥文件部署到web服务器后,执行以下命令验证:
openssl s_client -connect demo.rancher.com:443 -servername demo.rancher.com -CAfile server-ca.crt
三、java库的证书指令指令
3.1 基础命令
3.1.1 增
使用JDK自带工具keytool生成keystore和自签名证书
keytool -genkeypair -keystore ./keystore -storepass hxrhxr123 -alias hxr -keypass hxrhxr123 -keyalg RSA -keysize 1024 -validity 365
- -keystore:秘钥库文件名,保存了生成的证书
- -storepass:秘钥库的访问密码
- -alias:秘钥别名,默认 "mykey"
- -keypass:秘钥的访问密码
- -keyalg:使用的hash算法,默认"DSA"
- -keysize:密钥长度,默认1024
- -validity:有效期,默认365天
创建新的密钥
keytool -genkeypair -alias jetty2 -keypass bigdata123 -keyalg RSA -keysize 1024 -validity 365 -dname "CN=www.chenjie.asia,OU=,L=,ST=,C=" -keystore ./keystore -storepass hxrhxr123
- -dname:指定证书拥有者信息 "CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名称,ST=州或省份名称,C=单位的两字母国家代码"
导入证书文件到密钥库中
keytool -import -alias jetty3 -file ./test.cer -keystore ./keystore -storepass hxrhxr123
导出密钥库中的证书密钥
keytool -export [-rfc] -file ./jwt.crt -keystore ./keystore -storepass hxrhxr123 -alias jetty -keypass hxrhxr123
查看导出的crt证书信息
keytool -printcert -file "test.crt"
3.1.2 查
查看密钥库中所有密钥
keytool -list [-v] -keystore jwtstore -storepass hxrhxr123
- -v:打印所有密钥的详细信息
查看别名是hxr 的证书信息
keytool -list [-v] [-rfc] -alias hxr -keystore jwtstore -storepass hxrhxr123
指定了 -v 选项,将以可读格式打印证书,如果指定了 -rfc 选项,将以可打印的编码格式输出证书。
openssl查看公钥
keytool -list -rfc --keystore uaacenter.jks | openssl x509 -inform pem -pubkey
3.1.3 改
修改密钥库密码
keytool -keypasswd -new test1 -keystore ./keystore -storepass hxrhxr123
修改秘钥库中秘钥的密码
keytool -keypasswd -new testtest1 -keystore jwtstore -storepass hxrhxr123 -alias hxr -keypass hxrhxr123
修改密钥库中密钥的信息
keytool -selfcert -dname "cn=chenjie.asia,ou=,o=,c=" -keystore ./keystore -storepass hxrhxr123 -alias jetty -keypass hxrhxr123
3.1.4 删
删除别名是hxr的证书信息
keytool -delete -alias hxr -keystore jwtstore -storepass hxrhxr123
3.1.5 jar包签名
对InetAddress-1.0-SNAPSHOT.jar包进行签名
jarsigner -verbose -signedjar ./InetAddress-1.0-SNAPSHOT.jar.signed -keystore ./keystore -storepass hxrhxr123 -keypass bigdata123 ./InetAddress-1.0-SNAPSHOT.jar jetty
- -verbose 打印详细信息
- -signedjar 签名后文件存放的路径
对签名后的文件进行验证
jarsigner -verbose -verify InetAddress-1.0-SNAPSHOT.jar.signed
如果jar包中的文件被篡改,则验证不通过。
如我们修改了jar包中的pom.xml文件的内容,再进行验证,报错如下
D:\>jarsigner -verify InetAddress-1.0-SNAPSHOT.jar
jarsigner: java.lang.SecurityException: SHA-256 digest error for META-INF/maven/org.example/InetAddress/pom.xml
3.2 使自签名证书受信任
3.2.1 将证书导出
keytool -export -rfc -file ./hxr.cer -alias jetty -keystore ./keystore -storepass hxrhxr123
3.2.2 使客户端信任服务器
- 使chrome浏览器信任
进入浏览器的【设置】-【隐私设置和安全性】-【安全】-【管理证书】中,添加证书到 "受信任的根证书颁发机构"即可。
也可以直接双击证书安装到电脑中。
重启浏览器,再次访问网页发现证书已被信任。
可是还是不被信任 NET::ERR_CERT_COMMON_NAME_INVALID???奇怪!!!
- 使centos7.x服务器信任
将导出的证书内容追加到/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem文件中
cat /etc/security/keytab/cos-bigdata-test-hadoop-01.cer >> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
再次请求就不会报证书不受信任。
- 使jdk信任证书
将证书添加到jdk的信任库中,jdk的信任库文件是cacerts。
这种情况的使用场景就是,有框架是java编写的程序,在框架中请求一个自签名证书配置的https服务,如果不配置证书信任就会导致请求失败。如hadoop框架中,如果配置了Https-only且证书是自签名证书,那么默认每分钟Secondarynamenode会发起fetchImage的https请求,如果不配置自签名证书可信任,就会导致请求失败,Secondarynamenode功能失效。keytool -import -v -trustcacerts -alias cos-bigdata-test-hadoop-01 -file /etc/security/keytab/cos-bigdata-test-hadoop-01.crt -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
keytool和openssl的区别:keytool没办法签发证书,而openssl能够进行签发和证书链的管理。
因此,keytool 签发的所谓证书只是一种自签名证书。所谓自签名就是指证书只能保证自己是完整的,没有经过非法修改的。但是无法保证这个证书是属于谁的。
自签名证书有个很麻烦地方:对于每一个要链接的服务器,都要保存一个证书的验证副本。而且一旦服务器更换证书,所有客户端就需要重新部署这些副本。
也就是说,你可以用自签名证书让承认你的人承认你。但如果你做了一丁点变化,你需要让所有之前承认你的人再次承认你。
对于比较大型的应用来说,这一点是不可接受的。所以就需要证书链进行 双向认证。而 证书链,keytool自己就没办法做了,需要用到 openssl.
四、通过代码获取秘钥库的公私钥并对jwt进行签名和验签
public class KeyPairTest {
@Test
public void testCreateToken(){
String location = "uaacenter.jks";
String storepass = "uaacenter";
String keypass = "uaacenter";
String alias = "uaacenter";
//加载证书
ClassPathResource resource = new ClassPathResource(location);
//读取证书
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resource,storepass.toCharArray());
//获取证书中的一对秘钥
KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias,keypass.toCharArray());
//获取私钥
RSAPrivateKey aPrivate = (RSAPrivateKey)keyPair.getPrivate();
System.out.println(Base64.encode(aPrivate.getEncoded()));
//创建令牌,需要私钥加盐[RSA算法]
Jwt jwt = JwtHelper.encode("abcdefg", new RsaSigner(aPrivate));
//将令牌用base64编码得到token
String token = jwt.getEncoded();
System.out.println(token);
}
@Test
public void testParseToken(){
//TODO 获取公钥方式一:通过代码从证书库获得公钥
String location = "uaacenter.jks";
String storepass = "uaacenter";
String keypass = "uaacenter";
String alias = "uaacenter";
//加载证书
ClassPathResource resource = new ClassPathResource(location);
//读取证书
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resource,storepass.toCharArray());
//获取证书中的一对秘钥
KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias,keypass.toCharArray());
//获取公钥
RSAPublicKey aPublic = (RSAPublicKey)keyPair.getPublic();
System.out.println(Base64.encode(aPublic.getEncoded()));
//TODO 获取公钥方式二:通过openssl指令获取公钥
//需要带上begin和end信息,并且去掉换行符
// String aPublic= "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo668mNH7H86PzBCHsMsm7/Hxg4tK6YVWBWt74faDVrew6AzHfXz1S74ZoG5ftWt7hsQh2cFzpbnuMIYrhZatTEhnYNJA6T47meSb476WSc70/59w+21EIeQTbWUNhBZeA9r/M2u5ItBBJksyWSmMM6c2YRCeF7HC/KHFFGhWc46y9x6r3iqOrwnCAsrSjz9cIEvlCVgewLMxU5x9H/INZoqH3ZR8jUv/fIxFfju11izUrpxTb16SYC/t46Lb5l0Kynmrv4OOolGk0yJgeH3vgDnS/3OhlD08vGujnI6os7acCcXwEq3SDHvtOfd/Q/CBbUcDSQuk9ecyvtgFVRvOEwIDAQAB-----END PUBLIC KEY-----";
//解析之前得到的token
String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.YWJjZGVmZw.n1xeWFHjmh634MBzmC5aY9Q0Jo_EKRPPfjNf9eT6dguv3ivBHkBrFCVrVDMsM-f4Gy7ObrSCt-aR18tWySfmHgv9zp30YeXYbCg2sV_-pCPLJVE8wYuFYuuqnXINYNudAhp2rfhPApjh-jJxjVIdUB9NyMlWamAF7y-y3r2ox_32y0vqGQtNc6M6d9JR_MifVQWink8rGvhs-FVJlwDbhMt88kxsB9dOWhTspeQk9exfJIV_hDFhYiXLdQapG4t6FscEDeZjCRsuTfadj5KaJ3QwiWa711pZF50MBozCtE2NLSR_2UHtt_rmCMQcqDI3FphOHXN3GjadJn_gnfjpoQ";
//解码后获得jwt并通过公钥验证是否有效
Jwt jwt = JwtHelper.decodeAndVerify(token, new RsaVerifier(aPublic));
String claims = jwt.getClaims();
System.out.println(claims);
}
}
打印的privateKey为
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCjrryY0fsfzo/MEIewyybv8fGDi0rphVYFa3vh9oNWt7DoDMd9fPVLvhmgbl+1a3uGxCHZwXOlue4whiuFlq1MSGdg0kDpPjuZ5JvjvpZJzvT/n3D7bUQh5BNtZQ2EFl4D2v8za7ki0EEmSzJZKYwzpzZhEJ4XscL8ocUUaFZzjrL3HqveKo6vCcICytKPP1wgS+UJWB7AszFTnH0f8g1miofdlHyNS/98jEV+O7XWLNSunFNvXpJgL+3jotvmXQrKeau/g46iUaTTImB4fe+AOdL/c6GUPTy8a6OcjqiztpwJxfASrdIMe+05939D8IFtRwNJC6T15zK+2AVVG84TAgMBAAECggEAN/2DwfrCHkU4ZyOYZt93OEjYxpiVTYAwxrXXsJn0n2tCdn44lzJxbjFe7sQStSpJHPZmZeiIuL37PloG9TFvolJ6GmKRlbeWB7RtpuAA5MqIgBB4Q2lDDxzHkHoqv24vRr5Y4awNrlzyjDjYxisyLFEchuN6ULyb6HMlyS9Ps0Mm2KyqmTErgMdedDveWQXl/76xlKEWRDvx8xXmH/ThrOrWhFT9TXGAshL1/ifyW+eeB/xEI2WhrqYRD/nLCl4wMQ2ZiJ0bdDDcDhhyzX6GGjJ0T9scQVDh1TEqdjRwQwP22xXPPwUPoeVQw23/7eaKpCDzlJPxn2+ZdMqxRjGPoQKBgQDSNteMuvLccJaOCYaJYMUc5pTknEzkxCYI1u8/AwoGgDqA5WtJmBHOOqVYfvgH9tzLD7K4dkNWTrvXOR3uh2IQgkqt9kjBv5V0JUWBjQMkY9Z0Boefh/wZCpKdIbNmymHWgagT096/yD4rpryQ8kQo3Bk6/XXALxJkBsVMhfVzyQKBgQDHVWAAWj0llJaFQvDlEab0IrVRvWISe7FJejBkWMFddgInRd039GVbK+OukOKbw0orMsR30/kfvrBFpR6ZDGGb2ivmwxoAyI7rvaN9TrjOKb4UsnKv5FG66NUIUG8/XBfuN+wLjs9E+wg26Y1XMiZ7TBidOgcmICPL83mh+60I+wKBgQDRZKGHZD1AScIeT+y8cTFHXYPYyLxrb9s3GOoNyTg2S4p7FIuvLhQmahKDuU3VmRhMCSIMTnk6woinlRR0olSTf0VmTZohrHXx0KKQrmb/25cl0c9MoMcEJpzuekBa1qNoaZSD05rhTFRpZNgWRcyRKtTTBuBBBGJ8UqY7WICryQKBgFXq3q5INwLzwM0/xUV3Dlc8fpr03kjJN+lL2X/nIbF/I/55hpiPpwBdMo4TtRkeW+GyyCw+GastLh1WxpGBXLEooLOedJ7R04iY/NcOD2oNY/jX0ccuymud3/TtdoYA0+/B+uQgcgZxjWDd2iYzX5LVgeaDFIHCaKuIDm1bZYHxAoGBAI1tVE6ZqgIXuRMRCTRXxYgfASMuVqGOJ1IokYrC7aCq1G2VvFz8SLxYKIUUNOOaAj7aazZ6Nu6m97aECOdkQO/ATt3ha4r/GrieEUK801BbgWvTvb668WKLRgJoo9cLbDS5ZxRN1o11FNuivWzah0ih+C+3iALwO6d/HMYMKEu+
打印的publicKey如下,通过java代码获得的publicKey和openssl获得的publicKey是一致的。需要注意的是直接使用公钥字符串需要带上begin和end前后缀。
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo668mNH7H86PzBCHsMsm7/Hxg4tK6YVWBWt74faDVrew6AzHfXz1S74ZoG5ftWt7hsQh2cFzpbnuMIYrhZatTEhnYNJA6T47meSb476WSc70/59w+21EIeQTbWUNhBZeA9r/M2u5ItBBJksyWSmMM6c2YRCeF7HC/KHFFGhWc46y9x6r3iqOrwnCAsrSjz9cIEvlCVgewLMxU5x9H/INZoqH3ZR8jUv/fIxFfju11izUrpxTb16SYC/t46Lb5l0Kynmrv4OOolGk0yJgeH3vgDnS/3OhlD08vGujnI6os7acCcXwEq3SDHvtOfd/Q/CBbUcDSQuk9ecyvtgFVRvOEwIDAQAB
public class ExportCert {
//导出证书 base64格式
public static void exportCert(KeyStore keyStore, String alias, String exportFile) throws Exception {
Certificate certificate = keyStore.getCertificate(alias);
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(certificate.getEncoded());
FileWriter fw = new FileWriter(exportFile);
fw.write("------Begin Certificate----- \r\n ");//非必须
fw.write(encoded);
fw.write("\r\n-----End Certificate-----");//非必须
fw.close();
}
//得到KeyPair
public static KeyPair getKeyPair(KeyStore keyStore, String alias, char[] password){
try{
Key key = keyStore.getKey(alias, password);
if (key instanceof PrivateKey){
Certificate certificate = keyStore.getCertificate(alias);
PublicKey publicKey = certificate.getPublicKey();
return new KeyPair(publicKey, (PrivateKey) key);
}
}catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e){
e.printStackTrace();
}
return null;
}
//导出私钥
public static void exportPrivateKey(PrivateKey privateKey, String exportFile) throws Exception {
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(privateKey.getEncoded());
FileWriter fileWriter = new FileWriter(exportFile);
fileWriter.write("-----Begin Private Key-----\r\n");//非必须
fileWriter.write(encoded);
fileWriter.write("\r\n-----End Private Key-----");//非必须
fileWriter.close();
}
//导出公钥
public static void exportPublicKey(PublicKey publicKey, String exportFile) throws Exception {
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(publicKey.getEncoded());
FileWriter fileWriter = new FileWriter(exportFile);
fileWriter.write("-----Begin Public Key-----\r\n");//非必须
fileWriter.write(encoded);
fileWriter.write("\r\n-----End Public Key-----");//非必须
fileWriter.close();
}
public static void main(String[] args) throws Exception{
String keyStoreType = "jks";
String keystoreFile = "D:\\project\\workspace\\HelloWorld\\out\\production\\HelloWorld\\kunpu\\ijvmkeys";
String password = "ijvm2ed"; //keystore的解析密码
String friendPassword = "friend4life";//条目的解析密码
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(new FileInputStream(keystoreFile), password.toCharArray());
String alias = "friend";//条目别名
String exportCertFile = "D:\\project\\workspace\\HelloWorld\\out\\production\\HelloWorld\\kunpu\\cert.txt";
String exportPrivateFile = "D:\\project\\workspace\\HelloWorld\\out\\production\\HelloWorld\\kunpu\\privateKey.txt";
String exportPublicFile = "D:\\project\\workspace\\HelloWorld\\out\\production\\HelloWorld\\kunpu\\publicKey.txt";
ExportCert.exportCert(keyStore, alias, exportCertFile);
KeyPair keyPair = ExportCert.getKeyPair(keyStore, alias, friendPassword.toCharArray()); //注意这里的密码是你的别名对应的密码,不指定的话就是你的keystore的解析密码
ExportCert.exportPrivateKey(keyPair.getPrivate(), exportPrivateFile);
ExportCert.exportPublicKey(keyPair.getPublic(), exportPublicFile);
System.out.println("OK");
}
}
将公钥字符串转化为PublicKey对象等方法
/**
* RSA加解密工具类
*/
public class RSAUtils {
//公钥加密
public static String encrypt(String content, PublicKey publicKey) {
try{
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");//java默认"RSA"="RSA/ECB/PKCS1Padding"
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] output = cipher.doFinal(content.getBytes());
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(output);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
//公钥加密
public static byte[] encrypt(byte[] content, PublicKey publicKey) {
try{
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");//java默认"RSA"="RSA/ECB/PKCS1Padding"
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(content);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
//私钥解密
public static byte[] decrypt(byte[] content, PrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(content);
} catch (Exception e){
e.printStackTrace();
return null;
}
}
//私钥解密
public static String decrypt(String content, PrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte [] b = cipher.doFinal(content.getBytes());
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(b);
} catch (Exception e){
e.printStackTrace();
return null;
}
}
/**
* String转公钥PublicKey
* @param key
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* String转私钥PrivateKey
* @param key
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
}
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="REFRESH" content="0;url=dfshealth.html" />
<title>Hadoop Administration</title>
</head>
</html>