5555import java .util .Collection ;
5656import java .util .Collections ;
5757import java .util .List ;
58+ import java .util .concurrent .atomic .AtomicInteger ;
5859import java .util .concurrent .atomic .AtomicLong ;
5960import org .junit .jupiter .api .AfterEach ;
6061import org .junit .jupiter .api .BeforeEach ;
@@ -150,22 +151,47 @@ private X509Certificate mockCertWithSanUri(String uri) throws CertificateExcepti
150151
151152 @ Test
152153 public void getAgentIdentityCertificate_optedOut_returnsNullImmediately () throws IOException {
153- envProvider .setEnv ("GOOGLE_API_PREVENT_TOKEN_SHARING_FOR_GCP_SERVICES" , "true " );
154+ envProvider .setEnv ("GOOGLE_API_PREVENT_TOKEN_SHARING_FOR_GCP_SERVICES" , "false " );
154155 envProvider .setEnv ("GOOGLE_API_CERTIFICATE_CONFIG" , "/non/existent/path" );
155156 assertNull (AgentIdentityUtils .getAgentIdentityCertInfo ());
156157 }
157158
159+ @ Test
160+ public void getAgentIdentityCertificate_preventTokenSharingTrue_doesNotOptOut ()
161+ throws Exception {
162+ envProvider .setEnv ("GOOGLE_API_PREVENT_TOKEN_SHARING_FOR_GCP_SERVICES" , "true" );
163+ AgentIdentityUtils .setWellKnownDir (tempDir .toAbsolutePath ().toString () + "/" );
164+
165+ URL certUrl = getClass ().getClassLoader ().getResource ("agent/agent_spiffe_cert.pem" );
166+ assertNotNull (certUrl , "Test resource agent/agent_spiffe_cert.pem not found" );
167+ String certPath = Paths .get (certUrl .toURI ()).toAbsolutePath ().toString ();
168+ Files .copy (Paths .get (certPath ), tempDir .resolve ("certificates.pem" ));
169+
170+ URL keyUrl = getClass ().getClassLoader ().getResource ("agent/agent_spiffe_key.pem" );
171+ assertNotNull (keyUrl , "Test resource agent/agent_spiffe_key.pem not found" );
172+ String keyPath = Paths .get (keyUrl .toURI ()).toAbsolutePath ().toString ();
173+ Files .copy (Paths .get (keyPath ), tempDir .resolve ("private_key.pem" ));
174+
175+ envProvider .setEnv ("GOOGLE_API_CERTIFICATE_CONFIG" , null );
176+
177+ AgentIdentityUtils .CertInfo info = AgentIdentityUtils .getAgentIdentityCertInfo ();
178+ assertNotNull (info );
179+ assertEquals (
180+ new String (Files .readAllBytes (tempDir .resolve ("certificates.pem" )), StandardCharsets .UTF_8 ),
181+ info .getCertContent ());
182+ }
183+
158184 @ Test
159185 public void getAgentIdentityCertificate_noConfigEnvVar_returnsNull () throws IOException {
160186 AgentIdentityUtils .setTimeService (new FakeTimeService ());
161187 assertNull (AgentIdentityUtils .getAgentIdentityCertInfo ());
162188 }
163189
164190 @ Test
165- public void getAgentIdentityCertificate_happyPath_loadsCertificate () throws IOException {
191+ public void getAgentIdentityCertificate_happyPath_loadsCertificate () throws Exception {
166192 URL certUrl = getClass ().getClassLoader ().getResource ("x509_leaf_certificate.pem" );
167193 assertNotNull (certUrl , "Test resource x509_leaf_certificate.pem not found" );
168- String certPath = new File (certUrl .getFile ()).getAbsolutePath ();
194+ String certPath = Paths . get (certUrl .toURI ()).toAbsolutePath (). toString ();
169195 File configFile = tempDir .resolve ("config.json" ).toFile ();
170196 String configJson =
171197 "{"
@@ -209,6 +235,26 @@ public void getAgentIdentityCertInfo_malformedJson_throwsIOException() throws IO
209235 }
210236 envProvider .setEnv ("GOOGLE_API_CERTIFICATE_CONFIG" , configFile .getAbsolutePath ());
211237 AgentIdentityUtils .setWellKnownDir (tempDir .toAbsolutePath ().toString () + "/" );
238+ FakeTimeService fakeTime = new FakeTimeService ();
239+ AgentIdentityUtils .setTimeService (fakeTime );
240+
241+ IOException e = assertThrows (IOException .class , AgentIdentityUtils ::getAgentIdentityCertInfo );
242+ assertTrue (e .getMessage ().contains ("Failed to parse Agent Identity config JSON" ));
243+ assertEquals (0 , fakeTime .getSleepCount ());
244+ }
245+
246+ @ Test
247+ public void getAgentIdentityCertInfo_configExists_certMissing_throwsIOExceptionAfterRetries ()
248+ throws IOException {
249+ File configFile = tempDir .resolve ("config.json" ).toFile ();
250+ try (FileOutputStream fos = new FileOutputStream (configFile )) {
251+ String json =
252+ "{ \" cert_configs\" : { \" workload\" : { \" cert_path\" : \" /non/existent/cert.pem\" ,"
253+ + " \" key_path\" : \" /non/existent/key.pem\" } } }" ;
254+ fos .write (json .getBytes (StandardCharsets .UTF_8 ));
255+ }
256+ envProvider .setEnv ("GOOGLE_API_CERTIFICATE_CONFIG" , configFile .getAbsolutePath ());
257+ AgentIdentityUtils .setWellKnownDir (tempDir .toAbsolutePath ().toString () + "/" );
212258 AgentIdentityUtils .setTimeService (new FakeTimeService ());
213259
214260 IOException e = assertThrows (IOException .class , AgentIdentityUtils ::getAgentIdentityCertInfo );
@@ -244,15 +290,43 @@ public void shouldEnableMtls_unset_certsPresent_returnsTrue() throws IOException
244290 }
245291
246292 @ Test
247- public void getAgentIdentityCertInfo_fallbackPath_loadsCertificate () throws IOException {
248- AgentIdentityUtils .setWellKnownDir (tempDir .toAbsolutePath ().toString () + "/" );
293+ public void shouldEnableMtls_true_noCertsNoConfig_returnsFalse () throws IOException {
294+ envProvider .setEnv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "true" );
295+ assertFalse (AgentIdentityUtils .shouldEnableMtls (false , false ));
296+ }
249297
250- URL certUrl = getClass ().getClassLoader ().getResource ("x509_leaf_certificate.pem" );
251- assertNotNull (certUrl , "Test resource x509_leaf_certificate.pem not found" );
252- String certPath = new File (certUrl .getFile ()).getAbsolutePath ();
298+ @ Test
299+ public void shouldEnableMtls_false_noCertsNoConfig_returnsFalse () throws IOException {
300+ envProvider .setEnv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "false" );
301+ assertFalse (AgentIdentityUtils .shouldEnableMtls (false , false ));
302+ }
253303
304+ @ Test
305+ public void shouldEnableMtls_unset_noCertsNoConfig_returnsFalse () throws IOException {
306+ envProvider .setEnv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , null );
307+ assertFalse (AgentIdentityUtils .shouldEnableMtls (false , false ));
308+ }
309+
310+ @ Test
311+ public void shouldEnableMtls_unset_certsMissing_configExists_throwsIOException () {
312+ envProvider .setEnv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , null );
313+ assertThrows (IOException .class , () -> AgentIdentityUtils .shouldEnableMtls (false , true ));
314+ }
315+
316+ @ Test
317+ public void getAgentIdentityCertInfo_fallbackPath_loadsCertificate () throws Exception {
318+ AgentIdentityUtils .setWellKnownDir (tempDir .toAbsolutePath ().toString () + "/" );
319+
320+ URL certUrl = getClass ().getClassLoader ().getResource ("agent/agent_spiffe_cert.pem" );
321+ assertNotNull (certUrl , "Test resource agent/agent_spiffe_cert.pem not found" );
322+ String certPath = Paths .get (certUrl .toURI ()).toAbsolutePath ().toString ();
254323 Files .copy (Paths .get (certPath ), tempDir .resolve ("certificates.pem" ));
255324
325+ URL keyUrl = getClass ().getClassLoader ().getResource ("agent/agent_spiffe_key.pem" );
326+ assertNotNull (keyUrl , "Test resource agent/agent_spiffe_key.pem not found" );
327+ String keyPath = Paths .get (keyUrl .toURI ()).toAbsolutePath ().toString ();
328+ Files .copy (Paths .get (keyPath ), tempDir .resolve ("private_key.pem" ));
329+
256330 envProvider .setEnv ("GOOGLE_API_CERTIFICATE_CONFIG" , null );
257331
258332 AgentIdentityUtils .CertInfo info = AgentIdentityUtils .getAgentIdentityCertInfo ();
@@ -289,9 +363,9 @@ public void verifyKeyPair_mismatch_returnsFalse() throws Exception {
289363
290364 @ Test
291365 public void getAgentIdentityCertInfo_mismatch_throwsIOExceptionAfterRetries () throws Exception {
292- URL certUrl = getClass ().getClassLoader ().getResource ("x509_leaf_certificate .pem" );
293- assertNotNull (certUrl , "Test resource x509_leaf_certificate .pem not found" );
294- String certPath = new File (certUrl .getFile ()).getAbsolutePath ();
366+ URL certUrl = getClass ().getClassLoader ().getResource ("agent/agent_spiffe_cert .pem" );
367+ assertNotNull (certUrl , "Test resource agent/agent_spiffe_cert .pem not found" );
368+ String certPath = Paths . get (certUrl .toURI ()).toAbsolutePath (). toString ();
295369
296370 // Generate a random key that won't match the cert
297371 KeyPairGenerator kpg = KeyPairGenerator .getInstance ("RSA" );
@@ -339,8 +413,35 @@ public void getAgentIdentityCertInfo_mismatch_throwsIOExceptionAfterRetries() th
339413 assertEquals (200 , fakeTime .currentTimeMillis ()); // 2 retries * 100ms
340414 }
341415
416+ @ Test
417+ public void getAgentIdentityCertInfo_wellKnownDirExistsNoFiles_notExplicitlyEnabled_returnsNullImmediately ()
418+ throws IOException {
419+ AgentIdentityUtils .setWellKnownDir (tempDir .toAbsolutePath ().toString () + "/" );
420+ FakeTimeService fakeTime = new FakeTimeService ();
421+ AgentIdentityUtils .setTimeService (fakeTime );
422+ envProvider .setEnv ("GOOGLE_API_CERTIFICATE_CONFIG" , null );
423+ envProvider .setEnv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , null );
424+
425+ assertNull (AgentIdentityUtils .getAgentIdentityCertInfo ());
426+ assertEquals (0 , fakeTime .getSleepCount ());
427+ }
428+
429+ @ Test
430+ public void getAgentIdentityCertInfo_wellKnownDirExistsNoFiles_explicitlyEnabled_retriesAndReturnsNull ()
431+ throws IOException {
432+ AgentIdentityUtils .setWellKnownDir (tempDir .toAbsolutePath ().toString () + "/" );
433+ FakeTimeService fakeTime = new FakeTimeService ();
434+ AgentIdentityUtils .setTimeService (fakeTime );
435+ envProvider .setEnv ("GOOGLE_API_CERTIFICATE_CONFIG" , null );
436+ envProvider .setEnv ("GOOGLE_API_USE_CLIENT_CERTIFICATE" , "true" );
437+
438+ assertNull (AgentIdentityUtils .getAgentIdentityCertInfo ());
439+ assertTrue (fakeTime .getSleepCount () > 0 );
440+ }
441+
342442 private static class FakeTimeService implements AgentIdentityUtils .TimeService {
343443 private final AtomicLong currentTime = new AtomicLong (0 );
444+ private final AtomicInteger sleepCount = new AtomicInteger (0 );
344445
345446 @ Override
346447 public long currentTimeMillis () {
@@ -349,8 +450,13 @@ public long currentTimeMillis() {
349450
350451 @ Override
351452 public void sleep (long millis ) throws InterruptedException {
453+ sleepCount .incrementAndGet ();
352454 currentTime .addAndGet (millis );
353455 }
456+
457+ int getSleepCount () {
458+ return sleepCount .get ();
459+ }
354460 }
355461
356462 private static class TestEnvironmentProvider {
0 commit comments