Skip to content

Commit 3a5f83c

Browse files
authored
iam: add conformance tests for IAM Identity Management APIs for GCP (#186)
1 parent 347d593 commit 3a5f83c

26 files changed

+1031
-140
lines changed

iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/AbstractIamIT.java

Lines changed: 264 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import com.salesforce.multicloudj.iam.driver.AbstractIam;
55
import com.salesforce.multicloudj.iam.model.PolicyDocument;
66
import com.salesforce.multicloudj.iam.model.Statement;
7+
import com.salesforce.multicloudj.iam.model.CreateOptions;
8+
import com.salesforce.multicloudj.iam.model.TrustConfiguration;
79
import org.junit.jupiter.api.AfterAll;
810
import org.junit.jupiter.api.AfterEach;
911
import org.junit.jupiter.api.Assertions;
@@ -13,11 +15,12 @@
1315
import org.junit.jupiter.api.TestInstance;
1416

1517
import java.util.List;
18+
import java.util.Optional;
1619

1720
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
1821
public abstract class AbstractIamIT {
1922
public interface Harness extends AutoCloseable {
20-
AbstractIam createIamDriver(boolean useValidCredentials);
23+
AbstractIam createIamDriver();
2124

2225
String getIdentityName();
2326

@@ -33,6 +36,10 @@ public interface Harness extends AutoCloseable {
3336

3437
String getIamEndpoint();
3538

39+
String getTrustedPrincipal();
40+
41+
String getTestIdentityName();
42+
3643
default String getPolicyVersion() {
3744
return "";
3845
}
@@ -41,12 +48,14 @@ default String getPolicyVersion() {
4148

4249
List<String> getTestPolicyActions();
4350

44-
String getTestPolicyName();
45-
}
51+
String getTestPolicyName();
52+
}
4653

4754
protected abstract Harness createHarness();
4855

4956
private Harness harness;
57+
private AbstractIam iam;
58+
private IamClient iamClient;
5059

5160
/**
5261
* Initializes the WireMock server before all tests.
@@ -73,27 +82,29 @@ public void shutdownWireMockServer() throws Exception {
7382
@BeforeEach
7483
public void setupTestEnvironment() {
7584
TestsUtil.startWireMockRecording(harness.getIamEndpoint());
85+
iam = harness.createIamDriver();
86+
iamClient = new IamClient(iam);
7687
}
7788

7889
/**
7990
* Cleans up the test environment after each test.
8091
*/
8192
@AfterEach
82-
public void cleanupTestEnvironment() {
93+
public void cleanupTestEnvironment() throws Exception {
8394
TestsUtil.stopWireMockRecording();
95+
if (iamClient != null) {
96+
iamClient.close(); // closes underlying AbstractIam
97+
}
8498
}
8599

86100
@Test
87101
public void testAttachInlinePolicy() {
88-
AbstractIam iam = harness.createIamDriver(true);
89-
IamClient iamClient = new IamClient(iam);
90-
91-
Statement.StatementBuilder statementBuilder = Statement.builder()
102+
Statement.StatementBuilder statementBuilder = Statement.builder()
92103
.effect(harness.getTestPolicyEffect());
93104
for (String action : harness.getTestPolicyActions()) {
94105
statementBuilder.action(action);
95106
}
96-
107+
97108
PolicyDocument policyDocument = PolicyDocument.builder()
98109
.version(harness.getPolicyVersion())
99110
.statement(statementBuilder.build())
@@ -109,10 +120,7 @@ public void testAttachInlinePolicy() {
109120

110121
@Test
111122
public void testGetInlinePolicyDetails() {
112-
AbstractIam iam = harness.createIamDriver(true);
113-
IamClient iamClient = new IamClient(iam);
114-
115-
PolicyDocument policyDocument = PolicyDocument.builder()
123+
PolicyDocument policyDocument = PolicyDocument.builder()
116124
.version(harness.getPolicyVersion())
117125
.statement(Statement.builder()
118126
.effect(harness.getTestPolicyEffect())
@@ -140,15 +148,12 @@ public void testGetInlinePolicyDetails() {
140148

141149
@Test
142150
public void testGetAttachedPolicies() {
143-
AbstractIam iam = harness.createIamDriver(true);
144-
IamClient iamClient = new IamClient(iam);
145-
146-
Statement.StatementBuilder statementBuilder = Statement.builder()
151+
Statement.StatementBuilder statementBuilder = Statement.builder()
147152
.effect(harness.getTestPolicyEffect());
148153
for (String action : harness.getTestPolicyActions()) {
149154
statementBuilder.action(action);
150155
}
151-
156+
152157
PolicyDocument policyDocument = PolicyDocument.builder()
153158
.version(harness.getPolicyVersion())
154159
.statement(statementBuilder.build())
@@ -172,10 +177,7 @@ public void testGetAttachedPolicies() {
172177

173178
@Test
174179
public void testRemovePolicy() {
175-
AbstractIam iam = harness.createIamDriver(true);
176-
IamClient iamClient = new IamClient(iam);
177-
178-
PolicyDocument policyDocument = PolicyDocument.builder()
180+
PolicyDocument policyDocument = PolicyDocument.builder()
179181
.version(harness.getPolicyVersion())
180182
.statement(Statement.builder()
181183
.effect(harness.getTestPolicyEffect())
@@ -190,11 +192,244 @@ public void testRemovePolicy() {
190192
harness.getIdentityName()
191193
);
192194

193-
iamClient.removePolicy(
194-
harness.getIdentityName(),
195-
harness.getTestPolicyName(),
196-
harness.getTenantId(),
197-
harness.getRegion()
198-
);
199-
}
195+
iamClient.removePolicy(
196+
harness.getIdentityName(),
197+
harness.getTestPolicyName(),
198+
harness.getTenantId(),
199+
harness.getRegion()
200+
);
201+
}
202+
203+
private void cleanUpIdentity(String identity) {
204+
try {
205+
iamClient.deleteIdentity(
206+
identity,
207+
harness.getTenantId(),
208+
harness.getRegion()
209+
);
210+
} catch (Exception e) {
211+
// Ignore
212+
}
213+
}
214+
215+
/**
216+
* Tests creating an identity without trust configuration.
217+
*/
218+
@Test
219+
public void testCreateIdentityWithoutTrustConfig() {
220+
String identityName = harness.getTestIdentityName();
221+
String identityId = iamClient.createIdentity(
222+
identityName,
223+
"Test identity for MultiCloudJ integration tests",
224+
harness.getTenantId(),
225+
harness.getRegion(),
226+
Optional.empty(),
227+
Optional.empty()
228+
);
229+
230+
Assertions.assertNotNull(identityId, "Identity ID should not be null");
231+
Assertions.assertFalse(identityId.isEmpty(), "Identity ID should not be empty");
232+
233+
cleanUpIdentity(identityName);
234+
}
235+
236+
/**
237+
* Tests creating an identity with trust configuration.
238+
*/
239+
@Test
240+
public void testCreateIdentityWithTrustConfig() {
241+
String identityName = harness.getTestIdentityName() + "Trusted";
242+
TrustConfiguration trustConfig = TrustConfiguration.builder()
243+
.addTrustedPrincipal(harness.getTrustedPrincipal())
244+
.build();
245+
246+
String identityId = iamClient.createIdentity(
247+
identityName,
248+
"Test identity with trust configuration",
249+
harness.getTenantId(),
250+
harness.getRegion(),
251+
Optional.of(trustConfig),
252+
Optional.empty()
253+
);
254+
255+
Assertions.assertNotNull(identityId, "Identity ID should not be null");
256+
Assertions.assertFalse(identityId.isEmpty(), "Identity ID should not be empty");
257+
258+
cleanUpIdentity(identityName);
259+
}
260+
261+
/**
262+
* Tests creating an identity with CreateOptions.
263+
*/
264+
@Test
265+
public void testCreateIdentityWithOptions() {
266+
String identityName = harness.getTestIdentityName() + "Options";
267+
CreateOptions options = CreateOptions.builder().build();
268+
269+
String identityId = iamClient.createIdentity(
270+
identityName,
271+
"Test identity with options",
272+
harness.getTenantId(),
273+
harness.getRegion(),
274+
Optional.empty(),
275+
Optional.of(options)
276+
);
277+
278+
Assertions.assertNotNull(identityId, "Identity ID should not be null");
279+
Assertions.assertFalse(identityId.isEmpty(), "Identity ID should not be empty");
280+
281+
cleanUpIdentity(identityName);
282+
}
283+
284+
/**
285+
* Tests creating an identity with null description.
286+
*/
287+
@Test
288+
public void testCreateIdentityWithNullDescription() {
289+
String identityName = harness.getTestIdentityName() + "NoDesc";
290+
291+
String identityId = iamClient.createIdentity(
292+
identityName,
293+
null,
294+
harness.getTenantId(),
295+
harness.getRegion(),
296+
Optional.empty(),
297+
Optional.empty()
298+
);
299+
300+
Assertions.assertNotNull(identityId, "Identity ID should not be null");
301+
Assertions.assertFalse(identityId.isEmpty(), "Identity ID should not be empty");
302+
303+
cleanUpIdentity(identityName);
304+
}
305+
306+
/**
307+
* Tests getting an identity by name.
308+
*/
309+
@Test
310+
public void testGetIdentity() throws InterruptedException {
311+
String identityName = harness.getTestIdentityName() + "Get";
312+
// First create an identity
313+
String identityId = iamClient.createIdentity(
314+
identityName,
315+
"Test identity for get operation",
316+
harness.getTenantId(),
317+
harness.getRegion(),
318+
Optional.empty(),
319+
Optional.empty()
320+
);
321+
322+
// sleep for 500ms
323+
Thread.sleep(1000);
324+
325+
// Then retrieve it
326+
String retrievedIdentity = iamClient.getIdentity(
327+
harness.getTestIdentityName() + "Get",
328+
harness.getTenantId(),
329+
harness.getRegion()
330+
);
331+
332+
Assertions.assertNotNull(retrievedIdentity, "Retrieved identity should not be null");
333+
Assertions.assertFalse(retrievedIdentity.isEmpty(), "Retrieved identity should not be empty");
334+
335+
cleanUpIdentity(identityName);
336+
}
337+
338+
/**
339+
* Tests that the provider ID is correctly set.
340+
*/
341+
@Test
342+
public void testProviderId() {
343+
Assertions.assertNotNull(iam.getProviderId(), "Provider ID should not be null");
344+
Assertions.assertEquals(harness.getProviderId(), iam.getProviderId(),
345+
"Provider ID should match the expected value");
346+
}
347+
348+
/**
349+
* Tests exception mapping for provider-specific exceptions.
350+
*/
351+
@Test
352+
public void testExceptionMapping() {
353+
// Test with a generic exception
354+
Throwable genericException = new RuntimeException("Generic error");
355+
Class<? extends com.salesforce.multicloudj.common.exceptions.SubstrateSdkException> exceptionClass =
356+
iam.getException(genericException);
357+
358+
Assertions.assertNotNull(exceptionClass, "Exception class should not be null");
359+
Assertions.assertEquals(
360+
com.salesforce.multicloudj.common.exceptions.UnknownException.class,
361+
exceptionClass,
362+
"Generic exceptions should map to UnknownException"
363+
);
364+
}
365+
366+
/**
367+
* Tests deleting an identity.
368+
*/
369+
@Test
370+
public void testDeleteIdentity() {
371+
// First create an identity
372+
String identityId = iamClient.createIdentity(
373+
harness.getTestIdentityName() + "Delete",
374+
"Test identity for delete operation",
375+
harness.getTenantId(),
376+
harness.getRegion(),
377+
Optional.empty(),
378+
Optional.empty()
379+
);
380+
381+
Assertions.assertNotNull(identityId, "Identity ID should not be null");
382+
383+
// Then delete it - should not throw any exception
384+
Assertions.assertDoesNotThrow(() ->
385+
iamClient.deleteIdentity(
386+
harness.getTestIdentityName() + "Delete",
387+
harness.getTenantId(),
388+
harness.getRegion()
389+
)
390+
);
391+
}
392+
393+
/**
394+
* Tests the complete lifecycle: create, get, and delete an identity.
395+
*/
396+
@Test
397+
public void testIdentityLifecycle() throws InterruptedException {
398+
String testIdentityName = harness.getTestIdentityName() + "LifeCycle";
399+
400+
// Step 1: Create an identity
401+
String identityId = iamClient.createIdentity(
402+
testIdentityName,
403+
"Test identity for lifecycle test",
404+
harness.getTenantId(),
405+
harness.getRegion(),
406+
Optional.empty(),
407+
Optional.empty()
408+
);
409+
410+
Assertions.assertNotNull(identityId, "Identity ID should not be null after creation");
411+
Assertions.assertFalse(identityId.isEmpty(), "Identity ID should not be empty after creation");
412+
413+
// Step 2: Get the identity to verify it exists
414+
Thread.sleep(1000);
415+
416+
String retrievedIdentity = iamClient.getIdentity(
417+
testIdentityName,
418+
harness.getTenantId(),
419+
harness.getRegion()
420+
);
421+
422+
Assertions.assertNotNull(retrievedIdentity, "Retrieved identity should not be null");
423+
Assertions.assertFalse(retrievedIdentity.isEmpty(), "Retrieved identity should not be empty");
424+
425+
// Step 3: Delete the identity
426+
Assertions.assertDoesNotThrow(() ->
427+
iamClient.deleteIdentity(
428+
testIdentityName,
429+
harness.getTenantId(),
430+
harness.getRegion()
431+
),
432+
"Deleting identity should not throw an exception"
433+
);
434+
}
200435
}

iam/iam-gcp/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@
5858
<version>3.12.1</version>
5959
<scope>test</scope>
6060
</dependency>
61+
<dependency>
62+
<groupId>org.wiremock</groupId>
63+
<artifactId>wiremock-grpc-extension</artifactId>
64+
<version>0.11.0</version>
65+
<scope>test</scope>
66+
</dependency>
6167
<dependency>
6268
<groupId>com.salesforce.multicloudj</groupId>
6369
<artifactId>iam-client</artifactId>

0 commit comments

Comments
 (0)