99import org .junit .jupiter .api .Disabled ;
1010import org .junit .jupiter .api .Test ;
1111
12- import java .lang .reflect .InvocationTargetException ;
1312import java .sql .Connection ;
1413import java .sql .PreparedStatement ;
1514import java .sql .ResultSet ;
16- import java .sql .ResultSetMetaData ;
1715import java .sql .SQLException ;
1816import java .sql .Statement ;
1917import java .util .List ;
2321import static org .assertj .core .api .Assertions .assertThatThrownBy ;
2422
2523/**
26- * This test class shows a competitition between ONE connection pool that uses a DB2
27- * trusted context and two connection pools with and without thread affinity
24+ * Test the basic usage of DB2 trusted context.
2825 */
2926@ Disabled ("DB2 container start is slow - run manually" )
3027class Db2TrustedContextContainerTest {
3128
3229 private static Db2Container container ;
3330
3431 private static ThreadLocal <Db2Tenant > currentTenant = new ThreadLocal <>();
35-
36- private static final Db2Tenant [] TENANTS = {
37- new Db2Tenant (1 , "mandant1" , null , "S1" ),
38- new Db2Tenant (2 , "mandant2" , null , "S2" )
39- };
32+ private static String NO_PASSWORD = null ;
33+ private static final Db2Tenant TENANT1 = new Db2Tenant (1 , "tenant1" , NO_PASSWORD , "S1" ); // schema must be uppercase!
34+ private static final Db2Tenant TENANT2 = new Db2Tenant (2 , "tenant2" , NO_PASSWORD , "S2" );
4035
4136 /**
4237 * Unfortunately, container.dockerSu is protected. So we use some reflection in the meantime
@@ -52,17 +47,12 @@ static void dockerSu(String user, String cmd) {
5247 * Setup the DB2 docker with trusted context support
5348 */
5449 @ BeforeAll
55- static void before () throws InvocationTargetException , IllegalAccessException , SQLException {
56-
57-
50+ static void before () throws SQLException {
5851
59- /* Db2Container.Builder builder = Db2Container.builder("11.5.9.0")
60- .port(55505)
61- .containerName("trusted_context_good");*/
6252
6353 Db2Container .Builder builder = Db2Container .builder ("12.1.1.0" )
6454 .port (55506 )
65- .containerName ("trusted_context_bad " );
55+ .containerName ("trusted_context_12 " );
6656
6757 container = builder
6858 .dbName ("unit" )
@@ -95,56 +85,47 @@ private static void tryExec(Connection conn, String sql) throws SQLException {
9585 }
9686
9787 private static void setupTrustedContext (String localDockerIp ) throws SQLException {
98- // Step 0: reset trustedContext and drop tables from previous r
88+ // Step 0: reset trustedContext and drop tables from previous run
9989 try (Connection conn = container .config ().createAdminConnection ()) {
10090 tryExec (conn , "drop trusted context webapptrust" );
101- tryExec (conn , "drop table WEBUSER .test" );
102- tryExec (conn , "drop table WEBUSER .test2" );
103- tryExec (conn , "drop table S1 .test" );
104- tryExec (conn , "drop table S1 .test2" );
105- tryExec (conn , "drop table S2 .test" );
106- tryExec (conn , "drop table S2 .test2" );
91+ tryExec (conn , "drop table webuser .test" );
92+ tryExec (conn , "drop table webuser .test2" );
93+ tryExec (conn , "drop table s1 .test" );
94+ tryExec (conn , "drop table s1 .test2" );
95+ tryExec (conn , "drop table s2 .test" );
96+ tryExec (conn , "drop table s2 .test2" );
10797 }
10898
10999
110100 // Step 1 create the users (may fail, if user already exists, but does not matter here)
111101 try {
112102 container .dockerSu ("root" , "useradd webuser" );
113103 container .dockerSu ("root" , "echo \" webuser:webpass\" | chpasswd" );
114- container .dockerSu ("root" , "useradd mandant1 " );
115- container .dockerSu ("root" , "useradd mandant2 " );
104+ container .dockerSu ("root" , "useradd tenant1 " ); // no passwd
105+ container .dockerSu ("root" , "useradd tenant2 " ); // no passwd
116106 } catch (CommandException e ) {
117107 // user already exists
118108 }
109+
119110 try (Connection conn = container .config ().createAdminConnection ()) {
120111 Statement stmt = conn .createStatement ();
121112 stmt .execute ("create trusted context webapptrust based upon connection using system authid webuser attributes (address '" + localDockerIp + "') " +
122- "WITH USE FOR " +
123- "mandant1 WITHOUT AUTHENTICATION, " +
124- "mandant2 WITHOUT AUTHENTICATION " +
125- "ENABLE" );
113+ "with use for tenant1 without authentication, tenant2 without authentication enable" );
114+
126115 //stmt.execute("grant connect, createtab on database to user webuser");
127- stmt .execute ("create table WEBUSER.test (id int)" );
128- stmt .execute ("create table S1.test (id int)" );
129- stmt .execute ("create table S2.test (id int)" );
130- stmt .execute ("insert into S1.test values (1)" );
131- stmt .execute ("insert into S2.test values (2)" );
132- stmt .execute ("grant all on schema WEBUSER to user webuser" );
133- stmt .execute ("grant all on schema S1 to user mandant1" );
134- stmt .execute ("grant all on schema S2 to user mandant2" );
135- stmt .execute ("grant connect on database to user mandant1" );
136- stmt .execute ("grant connect on database to user mandant2" );
137-
138- stmt .execute ("GRANT USE OF TABLESPACE USERSPACE1 TO user WEBUSER, user MANDANT1, user MANDANT2" );
139- stmt .execute ("GRANT CONNECT, CREATETAB on database TO user WEBUSER, user MANDANT1, user MANDANT2" );
140-
141- //stmt.execute("GRANT USE OF TABLESPACE USERSPACE1 TO user MANDANT1 WITH GRANT OPTION");
142- //stmt.execute("GRANT USE OF TABLESPACE USERSPACE1 TO user MANDANT2 WITH GRANT OPTION");
143- /* tryExec(conn, "CREATE TABLESPACE DATATS");
144- tryExec(conn, "CREATE TEMPORARY TABLESPACE TEMPDATA");
145- stmt.execute(" GRANT USE OF TABLESPACE DATATS TO user MANDANT1 WITH GRANT OPTION");
146- stmt.execute(" GRANT USE OF TABLESPACE DATATS TO user MANDANT2 WITH GRANT OPTION");
147- */
116+ stmt .execute ("create table webuser.test (id int)" );
117+ stmt .execute ("create table s1.test (id int)" );
118+ stmt .execute ("create table s2.test (id int)" );
119+ stmt .execute ("insert into s1.test values (1)" );
120+ stmt .execute ("insert into s2.test values (2)" );
121+ stmt .execute ("grant all on schema webuser to user webuser" );
122+ stmt .execute ("grant all on schema s1 to user tenant1" );
123+ stmt .execute ("grant all on schema s2 to user tenant2" );
124+
125+ // For DB2-12 we must explicitly grant access to tablespace and allow createtab
126+ stmt .execute ("grant use of tablespace userspace1 to user webuser, user tenant1, user tenant2" );
127+ stmt .execute ("grant connect, createtab on database to user webuser, user tenant1, user tenant2" );
128+
148129 }
149130 }
150131
@@ -165,125 +146,62 @@ Object executeQuery(DataSourcePool pool, String query) throws Exception {
165146 void testTrustedContext () throws Exception {
166147 DataSourcePool pool = getPool (10 );
167148 try {
168- // try (Connection conn = pool.getConnection("webuser", "webpass")) {
169- // conn.createStatement().execute("select * from test");
170- // conn.createStatement().execute("create table test4 (id int) in DATATS");
171- // conn.commit();
172- // }
173- try (Connection conn = pool .getConnection ()) {
174- conn .createStatement ().execute ("create table test2 (id int)" );
175- }
176-
177- // set tenant of this thread to mandant1
149+ // here we are connected as WEBUSER
178150 assertThat (executeQuery (pool , "select current user from sysibm.sysdummy1" )).isEqualTo ("WEBUSER " );
179151 assertThat (executeQuery (pool , "select current sqlid from sysibm.sysdummy1" )).isEqualTo ("WEBUSER " );
180- currentTenant .set (TENANTS [0 ]);
181152
182- // TestDDL
183- pool .status (true );
153+ // switch to tenant 1
154+ currentTenant .set (TENANT1 );
155+ pool .status (true ); // reset hitcount
184156 assertThat (executeQuery (pool , "select * from test" )).isEqualTo (1 ); // each tenant must read its own data!
185157 assertThat (executeQuery (pool , "select * from test" )).isEqualTo (1 ); // check cache hit
186158 assertThat (pool .status (false ).hitCount ()).isEqualTo (2 );
187159
188- assertThatThrownBy (() -> executeQuery (pool , "select * from S2.test" ))
160+ // test if tenant1 can access data from tenant2
161+ assertThatThrownBy (() -> executeQuery (pool , "select * from s2.test" ))
189162 .isInstanceOf (SQLException .class )
190- .hasMessageContaining ("SQLCODE=-551, SQLSTATE=42501, SQLERRMC=MANDANT1;SELECT;S2.TEST" );
191-
192- currentTenant .set (TENANTS [1 ]);
193- assertThat (executeQuery (pool , "select * from S2.test" )).isEqualTo (2 );
163+ .hasMessageContaining ("SQLCODE=-551, SQLSTATE=42501, SQLERRMC=TENANT1;SELECT;S2.TEST" );
194164
165+ currentTenant .set (TENANT2 ); // test with tenant2
166+ assertThat (executeQuery (pool , "select * from s2.test" )).isEqualTo (2 );
195167
196- assertThat (executeQuery (pool , "select current user from sysibm.sysdummy1" )).isEqualTo ("MANDANT2 " );
168+ assertThat (executeQuery (pool , "select current user from sysibm.sysdummy1" )).isEqualTo ("TENANT2 " );
197169 assertThat (executeQuery (pool , "select current sqlid from sysibm.sysdummy1" )).isEqualTo ("S2 " );
198- currentTenant .set (TENANTS [ 0 ] );
199- assertThat (executeQuery (pool , "select current user from sysibm.sysdummy1" )).isEqualTo ("MANDANT1 " );
170+ currentTenant .set (TENANT1 );
171+ assertThat (executeQuery (pool , "select current user from sysibm.sysdummy1" )).isEqualTo ("TENANT1 " );
200172 assertThat (executeQuery (pool , "select current sqlid from sysibm.sysdummy1" )).isEqualTo ("S1 " );
201- currentTenant .set (TENANTS [ 1 ] );
202- assertThat (executeQuery (pool , "select current user from sysibm.sysdummy1" )).isEqualTo ("MANDANT2 " );
173+ currentTenant .set (TENANT2 );
174+ assertThat (executeQuery (pool , "select current user from sysibm.sysdummy1" )).isEqualTo ("TENANT2 " );
203175 assertThat (executeQuery (pool , "select current sqlid from sysibm.sysdummy1" )).isEqualTo ("S2 " );
204176 currentTenant .set (null );
205177 assertThat (executeQuery (pool , "select current user from sysibm.sysdummy1" )).isEqualTo ("WEBUSER " );
206178 assertThat (executeQuery (pool , "select current sqlid from sysibm.sysdummy1" )).isEqualTo ("WEBUSER " );
207179
208180
209- if (false ) {
210- try (Connection conn = pool .getConnection ()) {
211- try (Statement stmt = conn .createStatement ()) {
212- exec (stmt , "SELECT current user FROM SYSIBM.SYSDUMMY1" );
213- exec (stmt , "SELECT current sqlid FROM SYSIBM.SYSDUMMY1" );
214- exec (stmt , "SELECT * FROM SYSIBMADM.PRIVILEGES ORDER BY AUTHID,AUTHIDTYPE, PRIVILEGE" );
215- exec (stmt , "SELECT * FROM SYSCAT.ROLES ORDER BY ROLENAME,ROLEID" );
216- exec (stmt , "SELECT * FROM SYSCAT.SCHEMAAUTH" );
217- exec (stmt , "SELECT * FROM SYSCAT.TABLES ORDER BY TABSCHEMA, TABNAME, OWNER" );
218- exec (stmt , "SELECT * FROM SYSCAT.SCHEMATA ORDER BY SCHEMANAME, OWNER" );
219- }
220- }
221- } else {
222- testDdl (pool , 999 );
223- assertThat (executeQuery (pool , "select * from test2" )).isEqualTo (999 );
224-
181+ // now check, if we can create a table
182+ currentTenant .set (null );
183+ testDdl (pool , 999 );
184+ assertThat (executeQuery (pool , "select * from test2" )).isEqualTo (999 );
225185
226- currentTenant .set (TENANTS [0 ]);
227- try (Connection conn = pool .getConnection ()) {
228- try (Statement stmt = conn .createStatement ()) {
229- stmt .execute ("create table S1.test2 (id int) in USERSPACE1" );
230- }
231- }
232- testDdl (pool , 1 );
233- assertThat (executeQuery (pool , "select * from test2" )).isEqualTo (1 );
186+ currentTenant .set (TENANT1 );
187+ testDdl (pool , 1 );
188+ assertThat (executeQuery (pool , "select * from test2" )).isEqualTo (1 );
234189
235- currentTenant .set (TENANTS [1 ]);
236- testDdl (pool , 2 );
237- assertThat (executeQuery (pool , "select * from test2" )).isEqualTo (2 );
238- }
239- //assertThat(executeQuery(pool, "select * from test")).isEqualTo(2);
190+ currentTenant .set (TENANT2 );
191+ testDdl (pool , 2 );
192+ assertThat (executeQuery (pool , "select * from test2" )).isEqualTo (2 );
240193
241194 } finally {
242195 pool .shutdown ();
243196 }
244197 }
245198
246- private static void exec (Statement stmt , String sql ) throws SQLException {
247- System .out .println ("=============================================================" );
248- System .out .println (sql );
249- ResultSet resultSet = stmt .executeQuery (sql );
250- ResultSetMetaData metaData = resultSet .getMetaData ();
251- int columns = metaData .getColumnCount ();
252- for (int i = 1 ; i <= columns ; i ++) {
253- System .out .print (metaData .getColumnName (i ) + "\t " );
254- }
255- System .out .println ();
256-
257- // Print table body
258- while (resultSet .next ()) {
259- for (int i = 1 ; i <= columns ; i ++) {
260- System .out .print (resultSet .getString (i ) + "\t " );
261- }
262- System .out .println ();
263- }
264- }
265-
266199
267200 private static void testDdl (DataSourcePool pool , int value ) throws SQLException {
268201 try (Connection conn = pool .getConnection ()) {
269- /*try (Statement stmt = conn.createStatement()) {
270- exec(stmt, "SELECT current user FROM SYSIBM.SYSDUMMY1");
271- exec(stmt, "SELECT current sqlid FROM SYSIBM.SYSDUMMY1");
272- exec(stmt, "SELECT * FROM SYSIBMADM.PRIVILEGES WHERE AUTHID = current user");
273- exec(stmt, "SELECT * FROM SYSIBMADM.PRIVILEGES WHERE AUTHID = current sqlid");
274- exec(stmt, "SELECT * FROM SYSCAT.ROLES");
275- exec(stmt, "SELECT * FROM SYSCAT.SCHEMAAUTH");
276- exec(stmt, "SELECT * FROM SYSCAT.TABLES");
277- }*/
278202 try (Statement stmt = conn .createStatement ()) {
279- stmt .execute ("drop table test" );
280- try {
281- stmt .execute ("drop table test2" );
282- conn .commit ();
283- } catch (SQLException e ) {
284- // Table did not exist
285- }
286- stmt .execute ("create table test2 (id int) in USERSPACE1" );
203+ stmt .execute ("drop table test" ); // drop old table
204+ stmt .execute ("create table test2 (id int)" );
287205 try (PreparedStatement pstmt = conn .prepareStatement ("insert into test2 values (?)" )) {
288206 pstmt .setInt (1 , value );
289207 pstmt .executeUpdate ();
@@ -297,7 +215,6 @@ private static void testDdl(DataSourcePool pool, int value) throws SQLException
297215
298216 private static DataSourcePool getPool (int size ) throws SQLException {
299217 return DataSourceBuilder .create ()
300-
301218 .username ("webuser" )
302219 .password ("webpass" )
303220 .maxConnections (size )
0 commit comments