Skip to content

Commit

Permalink
support to config the encrypted password (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicole00 authored Jan 22, 2024
1 parent 8b9a662 commit e57651a
Show file tree
Hide file tree
Showing 5 changed files with 828 additions and 3 deletions.
23 changes: 23 additions & 0 deletions README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,28 @@ java -cp nebula-exchange_spark_2.4-3.0-SNAPSHOT.jar com.vesoft.exchange.common.G
{target-path-to-save-config-file}
```

## 加密 NebulaGraph 密码
```agsl
spark-submit --master local --class com.vesoft.exchange.common.PasswordEncryption nebula-exchange_spark_2.4-3.0-SNAPSHOT.jar -p {password}
```
加密 密码 nebula,输出结果包括RSA 公钥、私钥和加密后的password,示例:
```agsl
=================== public key begin ===================
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLl7LaNSEXlZo2hYiJqzxgyFBQdkxbQXYU/xQthsBJwjOPhkiY37nokzKnjNlp6mv5ZUomqxLsoNQHEJ6BZD4VPiaiElFAkTD+gyul1v8f3A446Fr2rnVLogWHnz8ECPt7X8jwmpiKOXkOPIhqU5E0Cua+Kk0nnVosbos/VShfiQIDAQAB
=================== public key end ===================
=================== private key begin ===================
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAIuXsto1IReVmjaFiImrPGDIUFB2TFtBdhT/FC2GwEnCM4+GSJjfueiTMqeM2Wnqa/llSiarEuyg1AcQnoFkPhU+JqISUUCRMP6DK6XW/x/cDjjoWvaudUuiBYefPwQI+3tfyPCamIo5eQ48iGpTkTQK5r4qTSedWixuiz9VKF+JAgMBAAECgYADWbfEPwQ1UbTq3Bej3kVLuWMcG0rH4fFYnaq5UQOqgYvFRR7W9H+80lOj6+CIB0ViLgkylmaU4WNVbBOx3VsUFFWSqIIIviKubg8m8ey7KAd9X2wMEcUHi4JyS2+/WSacaXYS5LOmMevvuaOwLEV0QmyM+nNGRIjUdzCLR1935QJBAM+IF8YD5GnoAPPjGIDS1Ljhu/u/Gj6/YBCQKSHQ5+HxHEKjQ/YxQZ/otchmMZanYelf1y+byuJX3NZ04/KSGT8CQQCsMaoFO2rF5M84HpAXPi6yH2chbtz0VTKZworwUnpmMVbNUojf4VwzAyOhT1U5o0PpFbpi+NqQhC63VUN5k003AkEArI8vnVGNMlZbvG7e5/bmM9hWs2viSbxdB0inOtv2g1M1OV+B2gp405ru0/PNVcRV0HQFfCuhVfTSxmspQoAihwJBAJW6EZa/FZbB4JVxreUoAr6Lo8dkeOhT9M3SZbGWZivaFxot/Cp/8QXCYwbuzrJxjqlsZUeOD6694Uk08JkURn0CQQC8V6aRa8ylMhLJFkGkMDHLqHcQCmY53Kd73mUu4+mjMJLZh14zQD9ydFtc0lbLXTeBAMWV3uEdeLhRvdAo3OwV
=================== private key end ===================
=================== encrypted password begin ===================
Io+3y3mLOMnZJJNUPHZ8pKb4VfTvg6wUh6jSu5xdmLAoX/59tK1HTwoN40aOOWJwa1a5io7S4JqcX/jEcAorw7pelITr+F4oB0AMCt71d+gJuu3/lw9bjUEl9tF4Raj82y2Dg39wYbagN84fZMgCD63TPiDIevSr6+MFKASpGrY=
=================== encrypted password end ===================
check: the real password decrypted by private key and encrypted password is: nebula
```

## 版本匹配

Exchange 和 NebulaGraph 的版本对应关系如下:
Expand Down Expand Up @@ -131,6 +153,7 @@ $SPARK_HOME/bin/spark-submit --class com.vesoft.nebula.exchange.Exchange \
nebula-exchange_spark_2.4-3.0-SNAPSHOT.jar \
-c application.conf
```
*8. 自 3.7.0 版本,Exchange支持配置RSA加密后的NebulaGraph密码,并支持生成加密的密码。*
关于 Nebula Exchange 的更多说明,请参考 Exchange 2.0
的[使用手册](https://docs.nebula-graph.com.cn/2.6.2/nebula-exchange/about-exchange/ex-ug-what-is-exchange/) 。
Expand Down
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,28 @@ Such as your datasource is csv, and want to save the template config file in /tm
java -cp nebula-exchange_spark_2.4-3.0-SNAPSHOT.jar com.vesoft.exchange.common.GenerateConfigTemplate -s csv -p /tmp
```
## encrypt NebulaGraph's password
```agsl
spark-submit --master local --class com.vesoft.exchange.common.PasswordEncryption nebula-exchange_spark_2.4-3.0-SNAPSHOT.jar -p {password}
```
When encrypt the password `nebula`, the output includes RSA public key, private key, encrypted password:
```agsl
=================== public key begin ===================
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLl7LaNSEXlZo2hYiJqzxgyFBQdkxbQXYU/xQthsBJwjOPhkiY37nokzKnjNlp6mv5ZUomqxLsoNQHEJ6BZD4VPiaiElFAkTD+gyul1v8f3A446Fr2rnVLogWHnz8ECPt7X8jwmpiKOXkOPIhqU5E0Cua+Kk0nnVosbos/VShfiQIDAQAB
=================== public key end ===================
=================== private key begin ===================
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAIuXsto1IReVmjaFiImrPGDIUFB2TFtBdhT/FC2GwEnCM4+GSJjfueiTMqeM2Wnqa/llSiarEuyg1AcQnoFkPhU+JqISUUCRMP6DK6XW/x/cDjjoWvaudUuiBYefPwQI+3tfyPCamIo5eQ48iGpTkTQK5r4qTSedWixuiz9VKF+JAgMBAAECgYADWbfEPwQ1UbTq3Bej3kVLuWMcG0rH4fFYnaq5UQOqgYvFRR7W9H+80lOj6+CIB0ViLgkylmaU4WNVbBOx3VsUFFWSqIIIviKubg8m8ey7KAd9X2wMEcUHi4JyS2+/WSacaXYS5LOmMevvuaOwLEV0QmyM+nNGRIjUdzCLR1935QJBAM+IF8YD5GnoAPPjGIDS1Ljhu/u/Gj6/YBCQKSHQ5+HxHEKjQ/YxQZ/otchmMZanYelf1y+byuJX3NZ04/KSGT8CQQCsMaoFO2rF5M84HpAXPi6yH2chbtz0VTKZworwUnpmMVbNUojf4VwzAyOhT1U5o0PpFbpi+NqQhC63VUN5k003AkEArI8vnVGNMlZbvG7e5/bmM9hWs2viSbxdB0inOtv2g1M1OV+B2gp405ru0/PNVcRV0HQFfCuhVfTSxmspQoAihwJBAJW6EZa/FZbB4JVxreUoAr6Lo8dkeOhT9M3SZbGWZivaFxot/Cp/8QXCYwbuzrJxjqlsZUeOD6694Uk08JkURn0CQQC8V6aRa8ylMhLJFkGkMDHLqHcQCmY53Kd73mUu4+mjMJLZh14zQD9ydFtc0lbLXTeBAMWV3uEdeLhRvdAo3OwV
=================== private key end ===================
=================== encrypted password begin ===================
Io+3y3mLOMnZJJNUPHZ8pKb4VfTvg6wUh6jSu5xdmLAoX/59tK1HTwoN40aOOWJwa1a5io7S4JqcX/jEcAorw7pelITr+F4oB0AMCt71d+gJuu3/lw9bjUEl9tF4Raj82y2Dg39wYbagN84fZMgCD63TPiDIevSr6+MFKASpGrY=
=================== encrypted password end ===================
check: the real password decrypted by private key and encrypted password is: nebula
```

## Version Compatibility Matrix

Here is the version correspondence between Exchange and NebulaGraph:
Expand Down Expand Up @@ -137,7 +159,7 @@ Here is the version correspondence between Exchange and NebulaGraph:
5. *Since 2.5* While SST import is supported by Exchange, property default values are not yet
supported.
6. *Since 3.0* Exchange is compatible with Spark 2.2, Spark 2.4, and Spark 3.0.
7. *Since 3.7* Exchange supports to config the encrypted NebulaGraph password and supports to generate the encryption password.
Refer
to [application.conf](https://github.com/vesoft-inc/nebula-exchange/blob/master/exchange-common/src/test/resources/application.conf)
as an example to edit the configuration file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* Copyright (c) 2023 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License.
*/

package com.vesoft.exchange.common

import com.vesoft.exchange.Argument

import java.security.spec.{PKCS8EncodedKeySpec, X509EncodedKeySpec}
import java.security.{KeyFactory, KeyPairGenerator, SecureRandom}
import java.util.Base64
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec

object PasswordEncryption {
private val algorithm = "RSA"
private val charset = "UTF-8"

def main(args: Array[String]): Unit = {
val passwdOption = new scopt.OptionParser[PasswordConfig]("encrypt password") {
head("encrypt password")

opt[String]('p', "passwd")
.required()
.valueName("passwd")
.action((x, c) => c.copy(password = x))
.text("your real password")
}.parse(args, PasswordConfig())

require(passwdOption.isDefined && passwdOption.get.password != null, "lack of password parameter")

val password:String = passwdOption.get.password

val (encryptedPasswd, privateKey) = encryptPassword(password)
println(s"=================== private key begin ===================")
println(privateKey)
println(s"=================== private key end ===================\n\n")

println(s"=================== encrypted password begin ===================")
println(encryptedPasswd)
println(s"=================== encrypted password end ===================")

println(s"check: the real password decrypted by private key and encrypted password is: ${decryptPassword(encryptedPasswd, privateKey)}")
}

/**
* encrypt the password
*
* @param password real password
* @return (encryptedPasswd, privateKey)
*/
def encryptPassword(password: String): (String, String) = {
val keyPairGenerator = KeyPairGenerator.getInstance(algorithm)
keyPairGenerator.initialize(1024, new SecureRandom())
val keyPair = keyPairGenerator.generateKeyPair()
val privateKey = keyPair.getPrivate
val privateKeyStr = new String(Base64.getEncoder.encode(privateKey.getEncoded), charset)
val publicKey = keyPair.getPublic
val publicKeyStr = new String(Base64.getEncoder.encode(publicKey.getEncoded), charset)
println(s"=================== public key begin ===================")
println(publicKeyStr)
println(s"=================== public key end ===================\n\n")

// encrypt the password
val encoded = Base64.getDecoder.decode(publicKeyStr)
val rsaPublicKey = KeyFactory.getInstance(algorithm).generatePublic(new X509EncodedKeySpec(encoded))
val cipher = Cipher.getInstance(algorithm)
cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey)
val encodePasswd = new String(Base64.getEncoder.encode(cipher.doFinal(password.getBytes(charset))), charset)
(encodePasswd, privateKeyStr)
}

/**
* decrypt the encrypted password with private key
*
* @param encryptedPassword encrypted password
* @param privateKey rsa private key
* @return real password
*/
def decryptPassword(encryptedPassword: String, privateKey: String): String = {
val encryptedPasswdBytes = Base64.getDecoder.decode(encryptedPassword)
val decodedPrivateKey = Base64.getDecoder.decode(privateKey)
val rsaPrivateKey = KeyFactory.getInstance(algorithm).generatePrivate(new PKCS8EncodedKeySpec(decodedPrivateKey))
val cipher = Cipher.getInstance(algorithm)
cipher.init(Cipher.DECRYPT_MODE, rsaPrivateKey)
val password = new String(cipher.doFinal(encryptedPasswdBytes), charset)
password
}


}

final case class PasswordConfig(password: String = null)
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import java.nio.file.Files
import com.google.common.net.HostAndPort
import com.typesafe.config.{Config, ConfigFactory}
import com.vesoft.exchange.Argument
import com.vesoft.exchange.common.KeyPolicy
import com.vesoft.exchange.common.{KeyPolicy, PasswordEncryption}
import com.vesoft.exchange.common.utils.NebulaUtils
import com.vesoft.nebula.client.graph.data.HostAddress
import org.apache.hadoop.conf.Configuration
Expand Down Expand Up @@ -318,7 +318,14 @@ object Configs {

val user = nebulaConfig.getString("user")
val pswd = nebulaConfig.getString("pswd")
val userEntry = UserConfigEntry(user, pswd)
val enableRSA = getOrElse(nebulaConfig, "enableRSA", false)
val privateKey = getStringOrNull(nebulaConfig, "privateKey")
require(!enableRSA || privateKey != null, "enableRSA is true, privateKey cannot be empty.")
var userEntry = UserConfigEntry(user, pswd)
if (enableRSA) {
userEntry = UserConfigEntry(user, PasswordEncryption.decryptPassword(pswd, privateKey))
}

LOG.info(s"User Config ${userEntry}")

val connectionConfig = getConfigOrNone(nebulaConfig, "connection")
Expand Down
Loading

0 comments on commit e57651a

Please sign in to comment.