Skip to content

Commit 2eb5de3

Browse files
committed
Refactor: make fields private in IdentityPoolCredentialSource
and move the certificate content to a file instead of local variable.
1 parent c53de82 commit 2eb5de3

File tree

6 files changed

+71
-45
lines changed

6 files changed

+71
-45
lines changed

oauth2_http/java/com/google/auth/oauth2/CertificateIdentityPoolSubjectTokenSupplier.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,14 @@ public class CertificateIdentityPoolSubjectTokenSupplier
6565
// This check ensures that the credential source was intended for certificate usage.
6666
// IdentityPoolCredentials logic should guarantee credentialLocation is set in this case.
6767
checkNotNull(
68-
credentialSource.certificateConfig,
68+
credentialSource.getCertificateConfig(),
6969
"credentialSource.certificateConfig cannot be null when creating"
7070
+ " CertificateIdentityPoolSubjectTokenSupplier");
7171
}
7272

7373
private static X509Certificate loadLeafCertificate(String path)
7474
throws IOException, CertificateException {
75-
byte[] leafCertBytes;
76-
leafCertBytes = Files.readAllBytes(Paths.get(path));
75+
byte[] leafCertBytes = Files.readAllBytes(Paths.get(path));
7776
return parseCertificate(leafCertBytes);
7877
}
7978

@@ -104,19 +103,19 @@ public String getSubjectToken(ExternalAccountSupplierContext context) throws IOE
104103
try {
105104
// credentialSource.credentialLocation is expected to be non-null here,
106105
// set during IdentityPoolCredentials construction for certificate type.
107-
X509Certificate leafCert = loadLeafCertificate(credentialSource.credentialLocation);
108-
String encodedCert = encodeCert(leafCert);
106+
X509Certificate leafCert = loadLeafCertificate(credentialSource.getCredentialLocation());
107+
String encodedLeafCert = encodeCert(leafCert);
109108

110109
JsonArray certChain = new JsonArray();
111-
certChain.add(new JsonPrimitive(encodedCert));
110+
certChain.add(new JsonPrimitive(encodedLeafCert));
112111

113112
return GSON.toJson(certChain);
114113
} catch (CertificateException e) {
115114
// Catch CertificateException to provide a more specific error message including
116115
// the path of the file that failed to parse, and re-throw as IOException
117116
// as expected by the getSubjectToken method signature for I/O related issues.
118117
throw new IOException(
119-
"Failed to parse certificate from: " + credentialSource.credentialLocation, e);
118+
"Failed to parse certificate(s) from: " + credentialSource.getCredentialLocation(), e);
120119
}
121120
}
122121
}

oauth2_http/java/com/google/auth/oauth2/FileIdentityPoolSubjectTokenSupplier.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import com.google.common.io.CharStreams;
3838
import java.io.BufferedReader;
3939
import java.io.File;
40-
import java.io.FileInputStream;
4140
import java.io.IOException;
4241
import java.io.InputStream;
4342
import java.io.InputStreamReader;
@@ -67,14 +66,15 @@ class FileIdentityPoolSubjectTokenSupplier implements IdentityPoolSubjectTokenSu
6766

6867
@Override
6968
public String getSubjectToken(ExternalAccountSupplierContext context) throws IOException {
70-
String credentialFilePath = this.credentialSource.credentialLocation;
69+
String credentialFilePath = this.credentialSource.getCredentialLocation();
7170
if (!Files.exists(Paths.get(credentialFilePath), LinkOption.NOFOLLOW_LINKS)) {
7271
throw new IOException(
7372
String.format(
7473
"Invalid credential location. The file at %s does not exist.", credentialFilePath));
7574
}
7675
try {
77-
return parseToken(new FileInputStream(new File(credentialFilePath)), this.credentialSource);
76+
return parseToken(
77+
Files.newInputStream(new File(credentialFilePath).toPath()), this.credentialSource);
7878
} catch (IOException e) {
7979
throw new IOException(
8080
"Error when attempting to read the subject token from the credential file.", e);

oauth2_http/java/com/google/auth/oauth2/IdentityPoolCredentialSource.java

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,41 @@ public class IdentityPoolCredentialSource extends ExternalAccountCredentials.Cre
4747
private static final long serialVersionUID = -745855247050085694L;
4848
IdentityPoolCredentialSourceType credentialSourceType;
4949
CredentialFormatType credentialFormatType;
50-
String credentialLocation;
50+
private String credentialLocation;
5151
@Nullable String subjectTokenFieldName;
5252
@Nullable Map<String, String> headers;
53-
@Nullable CertificateConfig certificateConfig;
53+
@Nullable private CertificateConfig certificateConfig;
54+
55+
/**
56+
* Gets the location of the credential source. This could be a file path or a URL, depending on
57+
* the {@link IdentityPoolCredentialSourceType}.
58+
*
59+
* @return The location of the credential source.
60+
*/
61+
public String getCredentialLocation() {
62+
return credentialLocation;
63+
}
64+
65+
/**
66+
* Sets the location of the credential source. This method should be used to update the credential
67+
* location.
68+
*
69+
* @param credentialLocation The new location of the credential source.
70+
*/
71+
public void setCredentialLocation(String credentialLocation) {
72+
this.credentialLocation = credentialLocation;
73+
}
74+
75+
/**
76+
* Gets the configuration for X.509-based workload credentials (mTLS), if configured.
77+
*
78+
* @return The {@link CertificateConfig} object, or {@code null} if not configured for
79+
* certificate-based credentials.
80+
*/
81+
@Nullable
82+
public CertificateConfig getCertificateConfig() {
83+
return certificateConfig;
84+
}
5485

5586
/**
5687
* Extracts and configures the {@link CertificateConfig} from the provided credential source.
@@ -60,7 +91,8 @@ public class IdentityPoolCredentialSource extends ExternalAccountCredentials.Cre
6091
* @throws IllegalArgumentException if the 'certificate' entry is not a Map or if required fields
6192
* within the certificate configuration have invalid types.
6293
*/
63-
private CertificateConfig getCertificateConfig(Map<String, Object> credentialSourceMap) {
94+
private CertificateConfig certificateConfigFromSourceMap(
95+
Map<String, Object> credentialSourceMap) {
6496
Object certValue = credentialSourceMap.get("certificate");
6597
if (!(certValue instanceof Map)) {
6698
throw new IllegalArgumentException(
@@ -242,7 +274,7 @@ public IdentityPoolCredentialSource(Map<String, Object> credentialSourceMap) {
242274
credentialSourceType = IdentityPoolCredentialSourceType.URL;
243275
} else if (certificatePresent) {
244276
credentialSourceType = IdentityPoolCredentialSourceType.CERTIFICATE;
245-
this.certificateConfig = getCertificateConfig(credentialSourceMap);
277+
this.certificateConfig = certificateConfigFromSourceMap(credentialSourceMap);
246278
} else {
247279
throw new IllegalArgumentException(
248280
"Missing credential source file location, URL, or certificate. At least one must be specified.");

oauth2_http/java/com/google/auth/oauth2/IdentityPoolCredentials.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ private IdentityPoolSubjectTokenSupplier createCertificateSubjectTokenSupplier(
153153
this.transportFactory = new MtlsHttpTransportFactory(mtlsKeyStore);
154154

155155
// Initialize the subject token supplier with the certificate path.
156-
credentialSource.credentialLocation = x509Provider.getCertificatePath();
156+
credentialSource.setCredentialLocation(x509Provider.getCertificatePath());
157157
return new CertificateIdentityPoolSubjectTokenSupplier(credentialSource);
158158

159159
} catch (IOException e) {
@@ -168,7 +168,7 @@ private IdentityPoolSubjectTokenSupplier createCertificateSubjectTokenSupplier(
168168
private X509Provider getX509Provider(
169169
Builder builder, IdentityPoolCredentialSource credentialSource) {
170170
final IdentityPoolCredentialSource.CertificateConfig certConfig =
171-
credentialSource.certificateConfig;
171+
credentialSource.getCertificateConfig();
172172

173173
// Use the provided X509Provider if available, otherwise initialize a default one.
174174
X509Provider x509Provider = builder.x509Provider;

oauth2_http/java/com/google/auth/oauth2/UrlIdentityPoolSubjectTokenSupplier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public String getSubjectToken(ExternalAccountSupplierContext context) throws IOE
7070
transportFactory
7171
.create()
7272
.createRequestFactory()
73-
.buildGetRequest(new GenericUrl(credentialSource.credentialLocation));
73+
.buildGetRequest(new GenericUrl(credentialSource.getCredentialLocation()));
7474
request.setParser(new JsonObjectParser(OAuth2Utils.JSON_FACTORY));
7575

7676
if (credentialSource.hasHeaders()) {

oauth2_http/javatests/com/google/auth/oauth2/CertificateIdentityPoolSubjectTokenSupplierTest.java

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
package com.google.auth.oauth2;
3333

3434
import static org.junit.Assert.*;
35+
import static org.mockito.Mockito.when;
3536

3637
import com.google.auth.oauth2.IdentityPoolCredentialSource.CertificateConfig;
3738
import com.google.gson.Gson;
@@ -40,16 +41,18 @@
4041
import java.io.ByteArrayInputStream;
4142
import java.io.File;
4243
import java.io.IOException;
44+
import java.net.URISyntaxException;
45+
import java.net.URL;
4346
import java.nio.charset.StandardCharsets;
4447
import java.nio.file.Files;
48+
import java.nio.file.Paths;
4549
import java.security.cert.CertificateException;
4650
import java.security.cert.CertificateFactory;
4751
import java.security.cert.X509Certificate;
4852
import java.util.Base64;
4953
import org.junit.Before;
5054
import org.junit.Rule;
5155
import org.junit.Test;
52-
import org.junit.rules.TemporaryFolder;
5356
import org.junit.runner.RunWith;
5457
import org.junit.runners.JUnit4;
5558
import org.mockito.Mock;
@@ -61,7 +64,6 @@
6164
public class CertificateIdentityPoolSubjectTokenSupplierTest {
6265

6366
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
64-
@Rule public TemporaryFolder tempFolder = new TemporaryFolder();
6567

6668
@Mock private IdentityPoolCredentialSource mockCredentialSource;
6769
@Mock private CertificateConfig mockCertificateConfig;
@@ -70,40 +72,33 @@ public class CertificateIdentityPoolSubjectTokenSupplierTest {
7072
private CertificateIdentityPoolSubjectTokenSupplier supplier;
7173
private static final Gson GSON = new Gson();
7274

73-
// Certificate data from X509ProviderTest
74-
private static final String TEST_CERT_PEM =
75-
"-----BEGIN CERTIFICATE-----\n"
76-
+ "MIICGzCCAYSgAwIBAgIIWrt6xtmHPs4wDQYJKoZIhvcNAQEFBQAwMzExMC8GA1UE\n"
77-
+ "AxMoMTAwOTEyMDcyNjg3OC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbTAeFw0x\n"
78-
+ "MjEyMDExNjEwNDRaFw0yMjExMjkxNjEwNDRaMDMxMTAvBgNVBAMTKDEwMDkxMjA3\n"
79-
+ "MjY4NzguYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20wgZ8wDQYJKoZIhvcNAQEB\n"
80-
+ "BQADgY0AMIGJAoGBAL1SdY8jTUVU7O4/XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQ\n"
81-
+ "GLW8Iftx9wfXe1zuaehJSgLcyCxazfyJoN3RiONBihBqWY6d3lQKqkgsRTNZkdFJ\n"
82-
+ "Wdzl/6CxhK9sojh2p0r3tydtv9iwq5fuuWIvtODtT98EgphhncQAqkKoF3zVAgMB\n"
83-
+ "AAGjODA2MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQM\n"
84-
+ "MAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAD8XQEqzGePa9VrvtEGpf+R4\n"
85-
+ "fkxKbcYAzqYq202nKu0kfjhIYkYSBj6gi348YaxE64yu60TVl42l5HThmswUheW4\n"
86-
+ "uQIaq36JvwvsDP5Zoj5BgiNSnDAFQp+jJFBRUA5vooJKgKgMDf/r/DCOsbO6VJF1\n"
87-
+ "kWwa9n19NFiV0z3m6isj\n"
88-
+ "-----END CERTIFICATE-----\n";
89-
90-
private static final byte[] TEST_CERT_BYTES = TEST_CERT_PEM.getBytes(StandardCharsets.UTF_8);
9175
private static final byte[] INVALID_CERT_BYTES =
9276
"invalid certificate data".getBytes(StandardCharsets.UTF_8);
9377

78+
private byte[] testCertBytesFromFile;
79+
9480
@Before
95-
public void setUp() throws IOException {
96-
File testCertFile = tempFolder.newFile("certificate.pem");
97-
Files.write(testCertFile.toPath(), TEST_CERT_BYTES);
98-
mockCredentialSource.certificateConfig = mockCertificateConfig;
99-
mockCredentialSource.credentialLocation = testCertFile.getAbsolutePath();
81+
public void setUp() throws IOException, URISyntaxException {
82+
ClassLoader classLoader = getClass().getClassLoader();
83+
URL leafCertUrl = classLoader.getResource("x509_leaf_certificate.pem");
84+
assertNotNull("Test leaf certificate file not found!", leafCertUrl);
85+
File testCertFile = new File(leafCertUrl.getFile());
86+
87+
when(mockCertificateConfig.useDefaultCertificateConfig()).thenReturn(false);
88+
when(mockCertificateConfig.getCertificateConfigLocation())
89+
.thenReturn(testCertFile.getAbsolutePath());
90+
91+
when(mockCredentialSource.getCertificateConfig()).thenReturn(mockCertificateConfig);
92+
when(mockCredentialSource.getCredentialLocation()).thenReturn(testCertFile.getAbsolutePath());
93+
10094
supplier = new CertificateIdentityPoolSubjectTokenSupplier(mockCredentialSource);
95+
testCertBytesFromFile = Files.readAllBytes(Paths.get(leafCertUrl.toURI()));
10196
}
10297

10398
@Test
10499
public void parseCertificate_validData_returnsCertificate() throws Exception {
105100
X509Certificate cert =
106-
CertificateIdentityPoolSubjectTokenSupplier.parseCertificate(TEST_CERT_BYTES);
101+
CertificateIdentityPoolSubjectTokenSupplier.parseCertificate(testCertBytesFromFile);
107102
assertNotNull(cert);
108103
}
109104

@@ -136,10 +131,10 @@ public void parseCertificate_invalidData_throwsCertificateException() {
136131

137132
@Test
138133
public void getSubjectToken_success() throws Exception {
139-
// Calculate expected result
134+
// Calculate expected result based on the file content.
140135
CertificateFactory cf = CertificateFactory.getInstance("X.509");
141136
X509Certificate expectedCert =
142-
(X509Certificate) cf.generateCertificate(new ByteArrayInputStream(TEST_CERT_BYTES));
137+
(X509Certificate) cf.generateCertificate(new ByteArrayInputStream(testCertBytesFromFile));
143138
String expectedEncodedDer = Base64.getEncoder().encodeToString(expectedCert.getEncoded());
144139
JsonArray expectedJsonArray = new JsonArray();
145140
expectedJsonArray.add(new JsonPrimitive(expectedEncodedDer));

0 commit comments

Comments
 (0)