ошибка secretkeyfactory недоступна в snowflake jdbc

#jdbc #snowflake-cloud-data-platform

#jdbc #snowflake-cloud-data-platform

Вопрос:

Я использую snowflake-jdbc для подключения к базе данных snowflake

ниже приведена библиотека

 <!-- https://mvnrepository.com/artifact/net.snowflake/snowflake-jdbc -->
<dependency>
    <groupId>net.snowflake</groupId>
    <artifactId>snowflake-jdbc</artifactId>
    <version>3.13.11</version>
</dependency>
 

Свойства драйвера заданы ниже.

  String url = "jdbc:snowflake://<account_identifier>.snowflakecomputing.com";
    Properties prop = new Properties();
    prop.put("user", "<user>");
    props.put("private_key_file", "/tmp/rsa_key.p8");
    props.put("private_key_file_pwd", "dummyPassword");
    prop.put("db", "<database_name>");
    prop.put("schema", "<schema_name>");
    prop.put("warehouse", "<warehouse_name>");
    prop.put("role", "<role_name>");

    Connection conn = DriverManager.getConnection(url, prop);
    Statement stat = conn.createStatement();
    ResultSet res = stat.executeQuery("select 1");
    res.next();
    System.out.println(res.getString(1));
    conn.close();
 

Когда я тестирую на своем локальном компьютере, я могу установить соединение, но при развертывании на AWS ECS (docker) Я получаю приведенную ниже ошибку, когда я пытался установить соединение

предоставленный закрытый ключ недействителен или не поддерживает 1.2.840.113549.1.5.13 недоступна secretkeyfactory Я проверил все пути и убедился, что в указанном пути есть файл private_key.

чего-нибудь не хватает в конфигурации?

Ответ №1:

При аутентификации с использованием аутентификации по паре ключей с использованием закрытого ключа, который генерируется с использованием OpenSSL 1.1.1g, и при подключении к Snowflake через драйвер JDBC отображается ошибка типа -Предоставленный закрытый ключ недействителен или не поддерживается -rsa-key-p8. Целью этой статьи является предоставление обходных путей для решения этой проблемы

https://community.snowflake.com/s/article/Private-key-provided-is-invalid-or-not-supported-rsa-key-p8—data-isn-t-an-object-ID

Ответ №2:

Существуют некоторые несовместимости между версией OpenSSL, используемой для шифрования закрытого ключа, и криптографическими библиотеками Java.
Вам нужно изменить подход и не использовать свойства:

   props.put("private_key_file", "/tmp/rsa_key.p8");
  props.put("private_key_file_pwd", "dummyPassword");
 

Но замените их решением с одним свойством ‘PrivateKey‘:

  props.put("privateKey", PrivateKeyReader.get(PRIVATE_KEY_FILE));
 

Вот пример кода, взятый из официальной документации Snowflake:

Цитата из блока: https://docs.snowflake.com/en/user-guide/jdbc-configure.html#privatekey-property-in-connection-properties

 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;

import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Paths;
import java.security.PrivateKey;
import java.security.Security;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.DriverManager;
import java.util.Properties;

public class TestJdbc
{
  // Path to the private key file that you generated earlier.
  private static final String PRIVATE_KEY_FILE = "/<path>/rsa_key.p8";

  public static class PrivateKeyReader
  {

    // If you generated an encrypted private key, implement this method to return
    // the passphrase for decrypting your private key.
    private static String getPrivateKeyPassphrase() {
      return "<private_key_passphrase>";
    }

    public static PrivateKey get(String filename)
            throws Exception
    {
      PrivateKeyInfo privateKeyInfo = null;
      Security.addProvider(new BouncyCastleProvider());
      // Read an object from the private key file.
      PEMParser pemParser = new PEMParser(new FileReader(Paths.get(filename).toFile()));
      Object pemObject = pemParser.readObject();
      if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
        // Handle the case where the private key is encrypted.
        PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
        String passphrase = getPrivateKeyPassphrase();
        InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray());
        privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov);
      } else if (pemObject instanceof PrivateKeyInfo) {
        // Handle the case where the private key is unencrypted.
        privateKeyInfo = (PrivateKeyInfo) pemObject;
      }
      pemParser.close();
      JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);
      return converter.getPrivateKey(privateKeyInfo);
    }
  }

  public static void main(String[] args)
      throws Exception
  {
    String url = "jdbc:snowflake://<account_identifier>.snowflakecomputing.com";
    Properties prop = new Properties();
    prop.put("user", "<user>");
    prop.put("privateKey", PrivateKeyReader.get(PRIVATE_KEY_FILE));
    prop.put("db", "<database_name>");
    prop.put("schema", "<schema_name>");
    prop.put("warehouse", "<warehouse_name>");
    prop.put("role", "<role_name>");

    Connection conn = DriverManager.getConnection(url, prop);
    Statement stat = conn.createStatement();
    ResultSet res = stat.executeQuery("select 1");
    res.next();
    System.out.println(res.getString(1));
    conn.close();
  }
}