|
| 1 | +package org.utplsql.cli; |
| 2 | + |
| 3 | +import oracle.security.pki.OracleSecretStore; |
| 4 | +import oracle.security.pki.OracleWallet; |
| 5 | +import org.junit.jupiter.api.BeforeAll; |
| 6 | +import org.junit.jupiter.api.Test; |
| 7 | +import org.junit.jupiter.api.io.TempDir; |
| 8 | +import org.utplsql.cli.datasource.TestedDataSourceProvider; |
| 9 | + |
| 10 | +import javax.sql.DataSource; |
| 11 | +import java.nio.file.Files; |
| 12 | +import java.nio.file.Path; |
| 13 | +import java.sql.Connection; |
| 14 | +import java.sql.ResultSet; |
| 15 | +import java.sql.Statement; |
| 16 | +import java.util.regex.Matcher; |
| 17 | +import java.util.regex.Pattern; |
| 18 | + |
| 19 | +import static org.junit.jupiter.api.Assertions.assertEquals; |
| 20 | +import static org.junit.jupiter.api.Assertions.assertTrue; |
| 21 | +import static org.junit.jupiter.api.Assumptions.assumeTrue; |
| 22 | + |
| 23 | +/** |
| 24 | + * Connecting with {@code /@<TNS alias>} using credentials stored in an Oracle Wallet |
| 25 | + * (Secure External Password Store), see issue #225. |
| 26 | + * <p> |
| 27 | + * The wallet, tnsnames.ora and ojdbc.properties are created on the fly from DB_URL / DB_USER / DB_PASS, |
| 28 | + * so no Oracle client tooling (mkstore/orapki) is needed. |
| 29 | + */ |
| 30 | +class WalletConnectionIT { |
| 31 | + |
| 32 | + private static final String TNS_ALIAS = "UTPLSQL_CLI_WALLET"; |
| 33 | + private static final Pattern EZ_CONNECT = Pattern.compile("^//([^:/]+)(?::(\\d+))?/(.+)$"); |
| 34 | + |
| 35 | + @TempDir |
| 36 | + static Path tnsAdmin; |
| 37 | + |
| 38 | + private static String walletConnectString; |
| 39 | + |
| 40 | + @BeforeAll |
| 41 | + static void createWallet() throws Exception { |
| 42 | + Matcher m = EZ_CONNECT.matcher(TestHelper.getUrl()); |
| 43 | + assumeTrue(m.matches(), "DB_URL must be in //host[:port]/service format to generate tnsnames.ora"); |
| 44 | + String host = m.group(1); |
| 45 | + String port = m.group(2) == null ? "1521" : m.group(2); |
| 46 | + String service = m.group(3); |
| 47 | + |
| 48 | + Path walletDir = Files.createDirectories(tnsAdmin.resolve("wallet")); |
| 49 | + char[] walletPassword = "Wallet_Pwd_123".toCharArray(); |
| 50 | + |
| 51 | + OracleWallet wallet = new OracleWallet(); |
| 52 | + wallet.create(walletPassword); |
| 53 | + OracleSecretStore secretStore = wallet.getSecretStore(); |
| 54 | + secretStore.createCredential(TNS_ALIAS.toCharArray(), |
| 55 | + TestHelper.getUser().toCharArray(), |
| 56 | + TestHelper.getPass().toCharArray()); |
| 57 | + wallet.setSecretStore(secretStore); |
| 58 | + wallet.saveAs(walletDir.toString()); |
| 59 | + wallet.createSSO(); |
| 60 | + wallet.saveSSO(); |
| 61 | + |
| 62 | + assertTrue(Files.exists(walletDir.resolve("cwallet.sso")), "auto-login wallet was not created"); |
| 63 | + |
| 64 | + Files.writeString(tnsAdmin.resolve("tnsnames.ora"), |
| 65 | + TNS_ALIAS + " = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = " + host + ")(PORT = " + port + "))" |
| 66 | + + "(CONNECT_DATA = (SERVICE_NAME = " + service + ")))\n"); |
| 67 | + Files.writeString(tnsAdmin.resolve("ojdbc.properties"), |
| 68 | + "oracle.net.wallet_location=(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=" |
| 69 | + + forwardSlashes(walletDir) + ")))\n"); |
| 70 | + |
| 71 | + walletConnectString = "/@" + TNS_ALIAS + "?TNS_ADMIN=" + forwardSlashes(tnsAdmin); |
| 72 | + } |
| 73 | + |
| 74 | + private static String forwardSlashes(Path path) { |
| 75 | + return path.toAbsolutePath().toString().replace('\\', '/'); |
| 76 | + } |
| 77 | + |
| 78 | + @Test |
| 79 | + void connectsAsWalletUser() throws Exception { |
| 80 | + ConnectionConfig config = new ConnectionConfig(walletConnectString); |
| 81 | + DataSource dataSource = new TestedDataSourceProvider(config, 1).getDataSource(); |
| 82 | + |
| 83 | + try (Connection con = dataSource.getConnection(); |
| 84 | + Statement stmt = con.createStatement(); |
| 85 | + ResultSet rs = stmt.executeQuery("select user from dual")) { |
| 86 | + assertTrue(rs.next()); |
| 87 | + assertEquals(TestHelper.getUser().toUpperCase(), rs.getString(1)); |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + @Test |
| 92 | + void runCommandWithWallet() { |
| 93 | + int result = TestHelper.runApp("run", |
| 94 | + walletConnectString, |
| 95 | + "-f=ut_documentation_reporter", |
| 96 | + "-s", |
| 97 | + "--failure-exit-code=0"); |
| 98 | + |
| 99 | + assertEquals(0, result); |
| 100 | + } |
| 101 | +} |
0 commit comments