diff --git a/.github/workflows/permission-check.yaml b/.github/workflows/permission-check.yaml index bd56dbeaa3..b562b7a65b 100644 --- a/.github/workflows/permission-check.yaml +++ b/.github/workflows/permission-check.yaml @@ -114,3 +114,508 @@ jobs: with: name: dynamo_permission_integration_test_reports path: core/build/reports/tests/integrationTestDynamoPermission + + integration-test-permission-jdbc-mysql-5-7: + name: MySQL 5.7 Permission Integration Test + runs-on: ubuntu-latest + + steps: + - name: Run MySQL 5.7 + run: | + docker run -e MYSQL_ROOT_PASSWORD=mysql -p 3306:3306 -d mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_bin + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:mysql://localhost:3306/ -Dscalardb.jdbc.username=root -Dscalardb.jdbc.password=mysql + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: mysql_5.7_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-mysql-8-0: + name: MySQL 8.0 Permission Integration Test + runs-on: ubuntu-latest + + steps: + - name: Run MySQL 8.0 + run: | + docker run -e MYSQL_ROOT_PASSWORD=mysql -p 3306:3306 -d mysql:8.0 --character-set-server=utf8mb4 --collation-server=utf8mb4_bin + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:mysql://localhost:3306/ -Dscalardb.jdbc.username=root -Dscalardb.jdbc.password=mysql + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: mysql_8.0_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-mysql-8-4: + name: MySQL 8.4 Permission Integration Test + runs-on: ubuntu-latest + + steps: + - name: Run MySQL 8.4 + run: | + docker run -e MYSQL_ROOT_PASSWORD=mysql -p 3306:3306 -d mysql:8.4 --character-set-server=utf8mb4 --collation-server=utf8mb4_bin + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:mysql://localhost:3306/ -Dscalardb.jdbc.username=root -Dscalardb.jdbc.password=mysql + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: mysql_8.4_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-postgresql-13: + name: PostgreSQL 13 Permission Integration Test + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:13-alpine + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:postgresql://localhost:5432/postgres -Dscalardb.jdbc.username=postgres -Dscalardb.jdbc.password=postgres + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: postgresql_13_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-postgresql-14: + name: PostgreSQL 14 Permission Integration Test + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:14-alpine + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:postgresql://localhost:5432/postgres -Dscalardb.jdbc.username=postgres -Dscalardb.jdbc.password=postgres + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: postgresql_14_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-postgresql-15: + name: PostgreSQL 15 Permission Integration Test + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:15-alpine + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:postgresql://localhost:5432/postgres -Dscalardb.jdbc.username=postgres -Dscalardb.jdbc.password=postgres + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: postgresql_15_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-postgresql-16: + name: PostgreSQL 16 Permission Integration Test + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:16-alpine + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:postgresql://localhost:5432/postgres -Dscalardb.jdbc.username=postgres -Dscalardb.jdbc.password=postgres + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: postgresql_16_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-postgresql-17: + name: PostgreSQL 17 Permission Integration Test + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:17-alpine + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:postgresql://localhost:5432/postgres -Dscalardb.jdbc.username=postgres -Dscalardb.jdbc.password=postgres + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: postgresql_17_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-oracle-19: + name: Oracle 19 Permission Integration Test + runs-on: ubuntu-latest + + services: + oracle: + image: ghcr.io/scalar-labs/oracle/db-prebuilt:19 + credentials: + username: ${{ github.repository_owner }} + password: ${{ secrets.CR_PAT }} + ports: + - 1521:1521 + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:oracle:thin:@//localhost:1521/ORCLPDB1 -Dscalardb.jdbc.username=SYSTEM -Dscalardb.jdbc.password=Oracle + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: oracle_19_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-oracle-21: + name: Oracle 21 Permission Integration Test + runs-on: ubuntu-latest + + services: + oracle: + image: ghcr.io/scalar-labs/oracle/db-prebuilt:21 + credentials: + username: ${{ github.repository_owner }} + password: ${{ secrets.CR_PAT }} + env: + ORACLE_PWD: Oracle + ports: + - 1521:1521 + options: >- + --health-cmd "/opt/oracle/checkDBStatus.sh" + --health-interval 10s + --health-timeout 5s + --health-retries 120 + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:oracle:thin:@//localhost:1521/XEPDB1 -Dscalardb.jdbc.username=SYSTEM -Dscalardb.jdbc.password=Oracle + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: oracle_21_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-oracle-23: + name: Oracle 23 Permission Integration Test + runs-on: ubuntu-latest + + steps: + - name: Free up ~14GB of disk space by removing the Android SDK + run: | + echo "Storage available before deletion" + df -h / + echo + sudo rm -r /usr/local/lib/android + echo "Storage available after deletion" + df -h / + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.CR_PAT }} + + - name: Start Oracle 23 container + run: docker run -d --name oracle-23 -p 1521:1521 ghcr.io/scalar-labs/oracle/db-prebuilt:23 + + - name: Wait for the container to be ready + timeout-minutes: 5 + run: | + while [ "`docker inspect -f {{.State.Health.Status}} oracle-23`" != "healthy" ] + do + sleep 10 + echo "Container is not yet ready" + done + echo "Container is ready" + + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission -Dscalardb.jdbc.url=jdbc:oracle:thin:@//localhost:1521/FREEPDB1 -Dscalardb.jdbc.username=SYSTEM -Dscalardb.jdbc.password=Oracle + + - name: Stop Oracle 23 container + if: always() + run: docker stop oracle-23 | xargs docker rm + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: oracle_23_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-sqlserver-2017: + name: SQL Server 2017 Permission Integration Test + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Sql Server 2017 + uses: rails-sqlserver/setup-mssql@v1 + with: + components: sqlcmd,sqlengine + sa-password: "SqlServer17" + version: 2017 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission "-Dscalardb.jdbc.url=jdbc:sqlserver://localhost:1433;encrypt=true;trustServerCertificate=true" "-Dscalardb.jdbc.username=sa" "-Dscalardb.jdbc.password=SqlServer17" "-Dfile.encoding=UTF-8" + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: sqlserver_2017_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-sqlserver-2019: + name: SQL Server 2019 Permission Integration Test + runs-on: ubuntu-latest + + services: + sqlserver: + image: mcr.microsoft.com/mssql/server:2019-latest + env: + MSSQL_PID: "Express" + SA_PASSWORD: "SqlServer19" + ACCEPT_EULA: "Y" + ports: + - 1433:1433 + options: --name sqlserver19 + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission "-Dscalardb.jdbc.url=jdbc:sqlserver://localhost:1433;encrypt=true;trustServerCertificate=true" "-Dscalardb.jdbc.username=sa" "-Dscalardb.jdbc.password=SqlServer19" + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: sqlserver_2019_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission + + integration-test-permission-jdbc-sqlserver-2022: + name: SQL Server 2022 Permission Integration Test + runs-on: ubuntu-latest + + services: + sqlserver: + image: mcr.microsoft.com/mssql/server:2022-latest + env: + MSSQL_PID: "Express" + SA_PASSWORD: "SqlServer22" + ACCEPT_EULA: "Y" + ports: + - 1433:1433 + options: --name sqlserver22 + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK ${{ env.JAVA_VERSION }} (${{ env.JAVA_VENDOR }}) + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: ${{ env.JAVA_VENDOR }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Execute Gradle 'integrationTestJdbcPermission' task + run: ./gradlew integrationTestJdbcPermission "-Dscalardb.jdbc.url=jdbc:sqlserver://localhost:1433;encrypt=true;trustServerCertificate=true" "-Dscalardb.jdbc.username=sa" "-Dscalardb.jdbc.password=SqlServer22" + + - name: Upload Gradle test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: sqlserver_2022_permission_integration_test_reports + path: core/build/reports/tests/integrationTestJdbcPermission diff --git a/core/build.gradle b/core/build.gradle index 4ff9415558..d102daef09 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -58,6 +58,9 @@ sourceSets { include '**/com/scalar/db/common/*.java' include '**/com/scalar/db/storage/jdbc/*.java' include '**/com/scalar/db/transaction/jdbc/*.java' + exclude '**/com/scalar/db/storage/jdbc/JdbcPermissionTestUtils.java' + exclude '**/com/scalar/db/storage/jdbc/JdbcPermissionIntegrationTest.java' + exclude '**/com/scalar/db/storage/jdbc/JdbcAdminPermissionIntegrationTest.java' } resources.srcDir file('src/integration-test/resources') } @@ -100,6 +103,21 @@ sourceSets { } resources.srcDir file('src/integration-test/resources') } + integrationTestJdbcPermission { + java { + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + srcDir file('src/integration-test/java') + include '**/com/scalar/db/common/*.java' + include '**/com/scalar/db/storage/jdbc/JdbcPermissionTestUtils.java' + include '**/com/scalar/db/storage/jdbc/JdbcAdminTestUtils.java' + include '**/com/scalar/db/storage/jdbc/JdbcTestUtils.java' + include '**/com/scalar/db/storage/jdbc/JdbcEnv.java' + include '**/com/scalar/db/storage/jdbc/JdbcPermissionIntegrationTest.java' + include '**/com/scalar/db/storage/jdbc/JdbcAdminPermissionIntegrationTest.java' + } + resources.srcDir file('src/integration-test/resources') + } } configurations { @@ -127,6 +145,9 @@ configurations { integrationTestDynamoPermissionImplementation.extendsFrom testImplementation integrationTestDynamoPermissionRuntimeOnly.extendsFrom testRuntimeOnly integrationTestDynamoPermissionCompileOnly.extendsFrom testCompileOnly + integrationTestJdbcPermissionImplementation.extendsFrom testImplementation + integrationTestJdbcPermissionRuntimeOnly.extendsFrom testRuntimeOnly + integrationTestJdbcPermissionCompileOnly.extendsFrom testCompileOnly } dependencies { @@ -263,6 +284,17 @@ task integrationTestDynamoPermission(type: Test) { } } +task integrationTestJdbcPermission(type: Test) { + description = 'Runs the integration tests for JDBC permissions.' + group = 'verification' + testClassesDirs = sourceSets.integrationTestJdbcPermission.output.classesDirs + classpath = sourceSets.integrationTestJdbcPermission.runtimeClasspath + outputs.upToDateWhen { false } // ensures integration tests are run every time when called + options { + systemProperties(System.getProperties().findAll { it.key.toString().startsWith("scalardb") }) + } +} + spotless { java { target 'src/*/java/**/*.java' diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminPermissionIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminPermissionIntegrationTest.java new file mode 100644 index 0000000000..d3aa5f9392 --- /dev/null +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcAdminPermissionIntegrationTest.java @@ -0,0 +1,29 @@ +package com.scalar.db.storage.jdbc; + +import com.scalar.db.api.DistributedStorageAdminPermissionIntegrationTestBase; +import com.scalar.db.util.AdminTestUtils; +import com.scalar.db.util.PermissionTestUtils; +import java.util.Properties; + +public class JdbcAdminPermissionIntegrationTest + extends DistributedStorageAdminPermissionIntegrationTestBase { + @Override + protected Properties getProperties(String testName) { + return JdbcEnv.getProperties(testName); + } + + @Override + protected Properties getPropertiesForNormalUser(String testName) { + return JdbcEnv.getPropertiesForNormalUser(testName); + } + + @Override + protected AdminTestUtils getAdminTestUtils(String testName) { + return new JdbcAdminTestUtils(getProperties(testName)); + } + + @Override + protected PermissionTestUtils getPermissionTestUtils(String testName) { + return new JdbcPermissionTestUtils(getProperties(testName)); + } +} diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcEnv.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcEnv.java index 8162116d7f..0cb1c54634 100644 --- a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcEnv.java +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcEnv.java @@ -7,10 +7,14 @@ public final class JdbcEnv { private static final String PROP_JDBC_URL = "scalardb.jdbc.url"; private static final String PROP_JDBC_USERNAME = "scalardb.jdbc.username"; private static final String PROP_JDBC_PASSWORD = "scalardb.jdbc.password"; + private static final String PROP_JDBC_NORMAL_USERNAME = "scalardb.jdbc.normal_username"; + private static final String PROP_JDBC_NORMAL_PASSWORD = "scalardb.jdbc.normal_password"; private static final String DEFAULT_JDBC_URL = "jdbc:postgresql://localhost:5432/"; private static final String DEFAULT_JDBC_USERNAME = "postgres"; private static final String DEFAULT_JDBC_PASSWORD = "postgres"; + private static final String DEFAULT_JDBC_NORMAL_USERNAME = "test"; + private static final String DEFAULT_JDBC_NORMAL_PASSWORD = "test"; private JdbcEnv() {} @@ -36,6 +40,17 @@ public static Properties getProperties(String testName) { return properties; } + public static Properties getPropertiesForNormalUser(String testName) { + String username = System.getProperty(PROP_JDBC_NORMAL_USERNAME, DEFAULT_JDBC_NORMAL_USERNAME); + String password = System.getProperty(PROP_JDBC_NORMAL_PASSWORD, DEFAULT_JDBC_NORMAL_PASSWORD); + + Properties properties = getProperties(testName); + properties.setProperty(DatabaseConfig.USERNAME, username); + properties.setProperty(DatabaseConfig.PASSWORD, password); + + return properties; + } + public static boolean isSqlite() { Properties properties = new Properties(); properties.setProperty( diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcPermissionIntegrationTest.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcPermissionIntegrationTest.java new file mode 100644 index 0000000000..84d7646cbe --- /dev/null +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcPermissionIntegrationTest.java @@ -0,0 +1,28 @@ +package com.scalar.db.storage.jdbc; + +import com.scalar.db.api.DistributedStoragePermissionIntegrationTestBase; +import com.scalar.db.util.AdminTestUtils; +import com.scalar.db.util.PermissionTestUtils; +import java.util.Properties; + +public class JdbcPermissionIntegrationTest extends DistributedStoragePermissionIntegrationTestBase { + @Override + protected Properties getProperties(String testName) { + return JdbcEnv.getProperties(testName); + } + + @Override + protected Properties getPropertiesForNormalUser(String testName) { + return JdbcEnv.getPropertiesForNormalUser(testName); + } + + @Override + protected PermissionTestUtils getPermissionTestUtils(String testName) { + return new JdbcPermissionTestUtils(getProperties(testName)); + } + + @Override + protected AdminTestUtils getAdminTestUtils(String testName) { + return new JdbcAdminTestUtils(getProperties(testName)); + } +} diff --git a/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcPermissionTestUtils.java b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcPermissionTestUtils.java new file mode 100644 index 0000000000..c24e1c98f5 --- /dev/null +++ b/core/src/integration-test/java/com/scalar/db/storage/jdbc/JdbcPermissionTestUtils.java @@ -0,0 +1,145 @@ +package com.scalar.db.storage.jdbc; + +import com.scalar.db.config.DatabaseConfig; +import com.scalar.db.util.PermissionTestUtils; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; +import org.apache.commons.dbcp2.BasicDataSource; + +public class JdbcPermissionTestUtils implements PermissionTestUtils { + private final RdbEngineStrategy rdbEngine; + private final BasicDataSource dataSource; + + public JdbcPermissionTestUtils(Properties properties) { + JdbcConfig config = new JdbcConfig(new DatabaseConfig(properties)); + rdbEngine = RdbEngineFactory.create(config); + dataSource = JdbcUtils.initDataSourceForAdmin(config, rdbEngine); + } + + @Override + public void createNormalUser(String userName, String password) { + try (Connection connection = dataSource.getConnection()) { + String createUserSql = getCreateUserSql(userName, password); + try (Statement statement = connection.createStatement()) { + statement.execute(createUserSql); + } + } catch (SQLException e) { + throw new RuntimeException("Failed to create user: " + userName, e); + } + } + + @Override + public void dropNormalUser(String userName) { + try (Connection connection = dataSource.getConnection()) { + String dropUserSql = getDropUserSql(userName); + try (Statement statement = connection.createStatement()) { + statement.execute(dropUserSql); + } + } catch (SQLException e) { + throw new RuntimeException("Failed to drop user: " + userName, e); + } + } + + @Override + public void grantRequiredPermission(String userName) { + try (Connection connection = dataSource.getConnection()) { + String[] grantStatements = getGrantPermissionStatements(userName); + try (Statement statement = connection.createStatement()) { + for (String sql : grantStatements) { + statement.execute(sql); + } + } + } catch (SQLException e) { + throw new RuntimeException("Failed to grant permissions to user: " + userName, e); + } + } + + private String getCreateUserSql(String userName, String password) { + if (JdbcTestUtils.isMysql(rdbEngine)) { + return String.format("CREATE USER '%s'@'%%' IDENTIFIED BY '%s'", userName, password); + } else if (JdbcTestUtils.isOracle(rdbEngine)) { + return String.format("CREATE USER %s IDENTIFIED BY %s", userName, password); + } else if (JdbcTestUtils.isPostgresql(rdbEngine)) { + return String.format("CREATE USER %s WITH PASSWORD '%s'", userName, password); + } else if (JdbcTestUtils.isSqlite(rdbEngine)) { + throw new UnsupportedOperationException("SQLite does not support user management"); + } else if (JdbcTestUtils.isSqlServer(rdbEngine)) { + return String.format( + "CREATE LOGIN %s WITH PASSWORD = '%s', DEFAULT_DATABASE = master , CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF; CREATE USER %s FOR LOGIN %s", + userName, password, userName, userName); + } else { + throw new UnsupportedOperationException("Creating users is not supported for " + rdbEngine); + } + } + + private String getDropUserSql(String userName) { + if (JdbcTestUtils.isMysql(rdbEngine)) { + return String.format("DROP USER '%s'@'%%'", userName); + } else if (JdbcTestUtils.isOracle(rdbEngine)) { + return String.format("DROP USER %s", userName); + } else if (JdbcTestUtils.isPostgresql(rdbEngine)) { + return String.format("DROP USER %s", userName); + } else if (JdbcTestUtils.isSqlite(rdbEngine)) { + throw new UnsupportedOperationException("SQLite does not support user management"); + } else if (JdbcTestUtils.isSqlServer(rdbEngine)) { + return String.format("DROP USER %s; DROP LOGIN %s", userName, userName); + } else { + throw new UnsupportedOperationException("Dropping users is not supported for " + rdbEngine); + } + } + + private String[] getGrantPermissionStatements(String userName) { + if (JdbcTestUtils.isMysql(rdbEngine)) { + return new String[] { + String.format("GRANT CREATE ON *.* TO '%s'@'%%'", userName), + String.format("GRANT DROP ON *.* TO '%s'@'%%'", userName), + String.format("GRANT INDEX ON *.* TO '%s'@'%%'", userName), + String.format("GRANT ALTER ON *.* TO '%s'@'%%'", userName), + String.format("GRANT SELECT ON *.* TO '%s'@'%%'", userName), + String.format("GRANT INSERT ON *.* TO '%s'@'%%'", userName), + String.format("GRANT UPDATE ON *.* TO '%s'@'%%'", userName), + String.format("GRANT DELETE ON *.* TO '%s'@'%%'", userName) + }; + } else if (JdbcTestUtils.isOracle(rdbEngine)) { + return new String[] { + String.format("GRANT CREATE SESSION TO %s", userName), + String.format("GRANT CREATE USER TO %s", userName), + String.format("GRANT DROP USER TO %s", userName), + String.format("GRANT ALTER USER TO %s", userName), + String.format("GRANT CREATE ANY TABLE TO %s", userName), + String.format("GRANT DROP ANY TABLE TO %s", userName), + String.format("GRANT CREATE ANY INDEX TO %s", userName), + String.format("GRANT DROP ANY INDEX TO %s", userName), + String.format("GRANT ALTER ANY TABLE TO %s", userName), + String.format("GRANT SELECT ANY TABLE TO %s", userName), + String.format("GRANT INSERT ANY TABLE TO %s", userName), + String.format("GRANT UPDATE ANY TABLE TO %s", userName), + String.format("GRANT DELETE ANY TABLE TO %s", userName) + }; + } else if (JdbcTestUtils.isPostgresql(rdbEngine)) { + return new String[] {String.format("ALTER ROLE %s SUPERUSER;", userName)}; + } else if (JdbcTestUtils.isSqlite(rdbEngine)) { + throw new UnsupportedOperationException("SQLite does not support authorization mechanism"); + } else if (JdbcTestUtils.isSqlServer(rdbEngine)) { + return new String[] { + String.format("ALTER ROLE [db_ddladmin] ADD MEMBER %s", userName), + String.format("ALTER ROLE [db_datareader] ADD MEMBER %s", userName), + String.format("ALTER ROLE [db_datawriter] ADD MEMBER %s", userName) + }; + } else { + throw new UnsupportedOperationException( + "Granting permissions is not supported for " + rdbEngine); + } + } + + @Override + public void close() { + try { + dataSource.close(); + } catch (Exception e) { + throw new RuntimeException("Failed to close the data source", e); + } + } +}