【jceks】使用keytool和hadoop credential生成和解析jceks文件(无密码storepass)

build.gradle文件:

gradle 复制代码
plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.9.23'
}

group = 'com.xxx.test'
version = '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.apache.hadoop:hadoop-common:3.0.0")
    testImplementation 'org.jetbrains.kotlin:kotlin-test'
}

test {
    useJUnitPlatform()
}
kotlin {
    jvmToolchain(8)
}

koltin语言编写。

ranger中的org.apache.ranger.credentialapi.CredentialReader工具类:

kotlin 复制代码
import org.apache.commons.lang3.StringUtils
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.security.alias.CredentialProvider.CredentialEntry
import org.apache.hadoop.security.alias.CredentialProviderFactory
import org.apache.hadoop.security.alias.JavaKeyStoreProvider
import java.util.*

object CredentialReader {


    fun getDecryptedString(CrendentialProviderPath: String?, alias: String?, storeType: String?): String? {
        var CrendentialProviderPath = CrendentialProviderPath
        var alias = alias
        var credential: String? = null
        try {
            if (CrendentialProviderPath == null || alias == null) {
                return null
            }
            var pass: CharArray? = null
            val conf = Configuration()
            var crendentialProviderPrefixJceks = JavaKeyStoreProvider.SCHEME_NAME + "://file"
            val crendentialProviderPrefixLocalJceks = "localjceks://file"
            crendentialProviderPrefixJceks = crendentialProviderPrefixJceks.lowercase(Locale.getDefault())

            var crendentialProviderPrefixBcfks = "bcfks" + "://file"
            var crendentialProviderPrefixLocalBcfks = "localbcfks" + "://file"
            crendentialProviderPrefixBcfks = crendentialProviderPrefixBcfks.lowercase(Locale.getDefault())
            crendentialProviderPrefixLocalBcfks = crendentialProviderPrefixLocalBcfks.lowercase(Locale.getDefault())

            CrendentialProviderPath = CrendentialProviderPath.trim { it <= ' ' }
            alias = alias.trim { it <= ' ' }
            if (CrendentialProviderPath.lowercase(Locale.getDefault()).startsWith(crendentialProviderPrefixJceks) ||
                CrendentialProviderPath.lowercase(Locale.getDefault())
                    .startsWith(crendentialProviderPrefixLocalJceks) ||
                CrendentialProviderPath.lowercase(Locale.getDefault()).startsWith(crendentialProviderPrefixBcfks) ||
                CrendentialProviderPath.lowercase(Locale.getDefault()).startsWith(crendentialProviderPrefixLocalBcfks)
            ) {
                conf[CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH] = CrendentialProviderPath
            } else {
                if (CrendentialProviderPath.startsWith("/")) {
                    if (StringUtils.equalsIgnoreCase(storeType, "bcfks")) {
                        conf[CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH] = CrendentialProviderPath
                    } else {
                        conf[CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH] =
                            JavaKeyStoreProvider.SCHEME_NAME + "://file" + CrendentialProviderPath
                    }
                } else {
                    conf[CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH] =
                        JavaKeyStoreProvider.SCHEME_NAME + "://file/" + CrendentialProviderPath
                }
            }
            val providers = CredentialProviderFactory.getProviders(conf)
            var aliasesList: List<String?> = ArrayList()
            var credEntry: CredentialEntry? = null
            for (provider in providers) {
                //System.out.println("Credential Provider :" + provider);
                aliasesList = provider.aliases
                if (aliasesList != null && aliasesList.contains(alias.lowercase(Locale.getDefault()))) {
                    credEntry = null
                    credEntry = provider.getCredentialEntry(alias.lowercase(Locale.getDefault()))
                    pass = credEntry.credential
                    if (pass != null && pass.size > 0) {
                        credential = String(pass)
                        break
                    }
                }
            }
        } catch (ex: Exception) {
            ex.printStackTrace()
            credential = null
        }
        return credential
    }
}

测试案例:

kotlin 复制代码
import org.junit.jupiter.api.Test
class CredentialReaderTest {
    val storeType = "jceks"

    @Test
    fun testDecrypted() {
        var path: String = "D:\\projects\\CredientialReader\\src\\test\\resources\\rangeradmin.jceks"
        path=path.replace("\\","/")
        val alias: String = "unixauthtruststorealias"
        val cred = CredentialReader.getDecryptedString(path, alias, storeType)
        println(cred) 
        // success: somepassword
    }

    /**
     * method: 1, using `keytool` command!
     * [root@ranger conf]# keytool -importpass -alias ranger -storetype jceks -keystore tmp.jceks
     * Enter keystore password:
     * Re-enter new password:
     * Enter the password to be stored:
     * Re-enter password:
     * Enter key password for <ranger>
     *         (RETURN if same as keystore password):
     *
     * [root@ranger conf]# keytool -list -v -storetype jceks -keystore tmp.jceks
     * Enter keystore password:
     * Keystore type: JCEKS
     * Keystore provider: SunJCE
     *
     * Your keystore contains 1 entry
     *
     * Alias name: ranger
     * Creation date: Apr 28, 2025
     * Entry type: SecretKeyEntry
     */
    @Test
    fun testDecryptedTmp() {
    // failed : java.io.IOException: Keystore was tampered with, or password was incorrect
        var path: String = "D:\\projects\\CredientialReader\\src\\test\\resources\\tmp.jceks"
        path=path.replace("\\","/")
        val alias: String = "ranger"
        val cred = CredentialReader.getDecryptedString(path, alias, storeType)
        println(cred)
    }

    /**
     * method: 2, using `hadoop credential` command
     * hadoop credential create -help
     * hadoop credential create ranger  -value 999 -provider localjceks:///home/someone/hdp.jceks
     * hdfs hdfs -copyToLocal /home/someone/hdp.jceks .
     * Note: "localjceks://file" is fixed,"/home/someone/hdp.jceks" is real path
     * hadoop credential create ranger  -value 999 -provider localjceks://file/home/someone/hdp.jceks
     * keytool -list -v -storetype jceks -keystore hdp.jceks
     * 999
     */
    @Test
    fun testDecryptedHdp() {
    // success: 999
        var path: String = "D:\\projects\\CredientialReader\\src\\test\\resources\\hdp.jceks"
        path=path.replace("\\","/")
        val alias: String = "ranger"
        val cred = CredentialReader.getDecryptedString(path, alias, storeType)
        println(cred)
    }
}

使用keytool必须指定storepass,即jceks文件的密码。使用hadoop credential create命令生成的jceks的密码是NONE,就是没有密码。

相关推荐
极客1142 分钟前
数字智慧方案6169丨智慧医院后勤管理解决方案(58页PPT)(文末有下载方式)
大数据
码熔burning2 小时前
【MQ篇】RabbitMQ之死信交换机!
java·分布式·rabbitmq·mq
豪越大豪2 小时前
豪越科技消防立库方案:实现应急物资高效管理
大数据·运维
zyxzyx6662 小时前
Redis实现分布式锁
数据库·redis·分布式
IT成长日记2 小时前
【Hive入门】Hive高级特性:事务表与ACID特性详解
数据仓库·hive·hadoop·事务·acid
大•南瓜糊胡5 小时前
《RabbitMQ 全面解析:从原理到实战的高性能消息队列指南》
分布式·rabbitmq
漫步者TZ5 小时前
【kafka系列】消费者组
分布式·kafka
中草药z6 小时前
【Redis分布式】主从复制
数据库·redis·分布式·主从复制·全量复制·部分复制
yyywoaini~8 小时前
如何搭建spark yarn 模式的集群集群
大数据
小咕聊编程9 小时前
【含文档+PPT+源码】基于大数据的交通流量预测系统
大数据·python·django