Skip to content

Commit 94194f7

Browse files
committed
Add support for WIF credentials in App Distribution Gradle Plugin
1 parent 4df9f37 commit 94194f7

8 files changed

Lines changed: 62 additions & 36 deletions

File tree

firebase-appdistribution-gradle/src/main/java/com/google/firebase/appdistribution/gradle/AuthenticatedHttpClient.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package com.google.firebase.appdistribution.gradle
1818

19-
import com.google.api.client.auth.oauth2.Credential
19+
import com.google.api.client.http.HttpRequestInitializer
2020
import com.google.api.client.googleapis.GoogleUtils
2121
import com.google.api.client.http.GenericUrl
2222
import com.google.api.client.http.HttpContent
@@ -34,8 +34,8 @@ private constructor(
3434
private val httpRequestFactory: HttpRequestFactory,
3535
) {
3636
constructor(
37-
credential: Credential
38-
) : this(newGoogleHttpTransport().createRequestFactory(credential))
37+
requestInitializer: HttpRequestInitializer
38+
) : this(newGoogleHttpTransport().createRequestFactory(requestInitializer))
3939

4040
constructor(httpTransport: HttpTransport) : this(httpTransport.createRequestFactory())
4141

firebase-appdistribution-gradle/src/main/java/com/google/firebase/appdistribution/gradle/CredentialsRetriever.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package com.google.firebase.appdistribution.gradle
1818

19-
import com.google.api.client.auth.oauth2.Credential
19+
import com.google.api.client.http.HttpRequestInitializer
2020
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
2121
import com.google.api.client.http.HttpTransport
2222
import com.google.firebase.appdistribution.gradle.AppDistributionEnvironment.Companion.ENV_FIREBASE_TOKEN
@@ -40,13 +40,13 @@ class CredentialsRetriever(
4040
) : this(GoogleNetHttpTransport.newTrustedTransport(), appDistributionEnvironment)
4141

4242
/** Returns the auth credential, if found. Otherwise returns null. */
43-
fun getAuthCredential(serviceCredentialsPath: String? = null): Credential? {
43+
fun getAuthCredential(serviceCredentialsPath: String? = null): HttpRequestInitializer? {
4444
// Check the explicitly passed in service credentials first
4545
if (serviceCredentialsPath != null) {
4646
val serviceCredentialsFile =
4747
ensureFileExists(serviceCredentialsPath, SERVICE_CREDENTIALS_NOT_FOUND)
4848
return try {
49-
ServiceAccountCredentials.fromFile(serviceCredentialsFile).googleCredential
49+
ServiceAccountCredentials.fromFile(serviceCredentialsFile).requestInitializer
5050
} catch (e: IOException) {
5151
throw AppDistributionException(
5252
SERVICE_CREDENTIALS_NOT_FOUND,
@@ -95,7 +95,7 @@ class CredentialsRetriever(
9595
return try {
9696
val envServiceAccountCredentials =
9797
ServiceAccountCredentials.fromFile(serviceCredentialsFile)
98-
envServiceAccountCredentials.googleCredential
98+
envServiceAccountCredentials.requestInitializer
9999
} catch (e: IOException) {
100100
throw AppDistributionException(
101101
SERVICE_CREDENTIALS_NOT_FOUND,

firebase-appdistribution-gradle/src/main/java/com/google/firebase/appdistribution/gradle/FirebaseAppDistribution.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package com.google.firebase.appdistribution.gradle
1818

19-
import com.google.api.client.auth.oauth2.Credential
19+
import com.google.api.client.http.HttpRequestInitializer
2020
import com.google.api.client.http.HttpResponseException
2121
import com.google.firebase.appdistribution.gradle.AppDistributionException.Reason.MISSING_CREDENTIALS
2222
import java.io.IOException
@@ -76,9 +76,9 @@ object FirebaseAppDistribution {
7676
private fun getCredential(options: TesterManagementOptions) =
7777
options.credential ?: throw AppDistributionException(MISSING_CREDENTIALS)
7878

79-
private fun getAuthenticatedHttpClient(credential: Credential): AuthenticatedHttpClient {
79+
private fun getAuthenticatedHttpClient(requestInitializer: HttpRequestInitializer): AuthenticatedHttpClient {
8080
return try {
81-
AuthenticatedHttpClient(credential)
81+
AuthenticatedHttpClient(requestInitializer)
8282
} catch (e: Exception) {
8383
when (e) {
8484
is GeneralSecurityException,

firebase-appdistribution-gradle/src/main/java/com/google/firebase/appdistribution/gradle/TesterManagementOptions.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.google.firebase.appdistribution.gradle
1717

18+
import com.google.api.client.http.HttpRequestInitializer
1819
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
1920
import com.google.firebase.appdistribution.gradle.AppDistributionException.Reason.MISSING_PROJECT_NUMBER
2021
import com.google.firebase.appdistribution.gradle.AppDistributionException.Reason.MISSING_TESTER_EMAILS
@@ -34,7 +35,7 @@ class TesterManagementOptions(
3435
)
3536
) {
3637
val emails = splitCommaOrNewlineSeparatedString(getValueFromStringOrFile(emailsValue, emailsFile))
37-
val credential = credentialsRetriever.getAuthCredential(serviceCredentialsFile)
38+
val credential: HttpRequestInitializer? = credentialsRetriever.getAuthCredential(serviceCredentialsFile)
3839

3940
init {
4041
// If project number is set it would be greater than 0, the default primitive value

firebase-appdistribution-gradle/src/main/java/com/google/firebase/appdistribution/gradle/UploadDistributionOptions.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package com.google.firebase.appdistribution.gradle
1818

19-
import com.google.api.client.auth.oauth2.Credential
19+
import com.google.api.client.http.HttpRequestInitializer
2020
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
2121
import com.google.api.client.http.HttpTransport
2222
import com.google.common.base.Splitter
@@ -71,7 +71,7 @@ internal constructor(
7171
val testers = extractValues(testersValue, testersPath)
7272
val groups = extractValues(groupsValue, groupsPath)
7373
val testDevices = extractTestDevices(testDevicesValue, testDevicesPath)
74-
val credential: Credential? =
74+
val credential: HttpRequestInitializer? =
7575
CredentialsRetriever(transport, appDistributionEnvironment)
7676
.getAuthCredential(serviceCredentialsFile)
7777
val testCases = extractValues(testCasesValue, testCasesPath)

firebase-appdistribution-gradle/src/main/java/com/google/firebase/appdistribution/gradle/models/ServiceAccountCredentials.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@
1616

1717
package com.google.firebase.appdistribution.gradle.models
1818

19-
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
19+
import com.google.auth.http.HttpCredentialsAdapter
20+
import com.google.auth.oauth2.GoogleCredentials
2021
import com.google.firebase.appdistribution.gradle.ApiEndpoints
2122
import java.io.File
2223
import java.nio.file.Files
2324

24-
class ServiceAccountCredentials private constructor(val googleCredential: GoogleCredential) {
25+
class ServiceAccountCredentials private constructor(val requestInitializer: HttpCredentialsAdapter) {
2526
companion object {
2627
fun fromFile(credentials: File): ServiceAccountCredentials =
2728
ServiceAccountCredentials(
28-
GoogleCredential.fromStream(Files.newInputStream(credentials.toPath()))
29-
.createScoped(ApiEndpoints.SCOPES)
29+
HttpCredentialsAdapter(
30+
GoogleCredentials.fromStream(Files.newInputStream(credentials.toPath()))
31+
.createScoped(ApiEndpoints.SCOPES)
32+
)
3033
)
3134
}
3235
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "external_account",
3+
"audience": "//iam.googleapis.com/projects/123456/locations/global/workloadIdentityPools/my-pool/providers/my-provider",
4+
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
5+
"token_url": "https://sts.googleapis.com/v1/token",
6+
"credential_source": {
7+
"file": "/var/run/secrets/token"
8+
}
9+
}

firebase-appdistribution-gradle/src/test/java/com/google/firebase/appdistribution/gradle/CredentialsRetrieverTest.kt

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ package com.google.firebase.appdistribution.gradle
1818

1919
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
2020
import com.google.api.client.http.HttpTransport
21+
import com.google.auth.http.HttpCredentialsAdapter
22+
import com.google.auth.oauth2.ExternalAccountCredentials
23+
import com.google.auth.oauth2.ServiceAccountCredentials as GoogleServiceAccountCredentials
2124
import junit.framework.TestCase.assertEquals
2225
import junit.framework.TestCase.assertNull
2326
import kotlin.test.assertContains
@@ -48,13 +51,24 @@ class CredentialsRetrieverTest {
4851
fun testGetAuthCredential_usesServiceCredentialsJsonPassedIn() {
4952
val credentialsRetriever = CredentialsRetriever()
5053

51-
val credential = getAuthCredential(credentialsRetriever, TEST_SERVICE_CREDENTIALS_PATH)
54+
val credential = credentialsRetriever.getAuthCredential(TEST_SERVICE_CREDENTIALS_PATH) as HttpCredentialsAdapter
55+
val googleCreds = credential.credentials as GoogleServiceAccountCredentials
5256

5357
assertEquals(
5458
"firebase-adminsdk@my-project.iam.gserviceaccount.com",
55-
credential.serviceAccountId
59+
googleCreds.clientEmail
5660
)
57-
assertEquals("abcefg123456789", credential.serviceAccountPrivateKeyId)
61+
assertEquals("abcefg123456789", googleCreds.privateKeyId)
62+
}
63+
64+
@Test
65+
fun testGetAuthCredential_usesWifCredentialsJsonPassedIn() {
66+
val credentialsRetriever = CredentialsRetriever()
67+
68+
val credential = credentialsRetriever.getAuthCredential(TEST_WIF_CREDENTIALS_PATH) as HttpCredentialsAdapter
69+
val googleCreds = credential.credentials
70+
71+
assert(googleCreds is ExternalAccountCredentials)
5872
}
5973

6074
@Test
@@ -65,7 +79,7 @@ class CredentialsRetrieverTest {
6579
environmentVariables[AppDistributionEnvironment.ENV_FIREBASE_TOKEN] = expectedRefreshToken
6680
val credentialsRetriever = CredentialsRetriever(transport)
6781

68-
val credential = getAuthCredential(credentialsRetriever)
82+
val credential = credentialsRetriever.getAuthCredential() as GoogleCredential
6983

7084
assertEquals("some-access-token", credential.accessToken)
7185
}
@@ -77,7 +91,7 @@ class CredentialsRetrieverTest {
7791
environmentVariables["XDG_CONFIG_HOME"] = "src/test/fixtures"
7892
val credentialsRetriever = CredentialsRetriever(transport)
7993

80-
val credential = getAuthCredential(credentialsRetriever)
94+
val credential = credentialsRetriever.getAuthCredential() as GoogleCredential
8195

8296
assertContains("some-access-token", credential.accessToken)
8397
}
@@ -93,13 +107,14 @@ class CredentialsRetrieverTest {
93107
TEST_SERVICE_CREDENTIALS_PATH
94108
val credentialsRetriever = CredentialsRetriever(testEnvironment)
95109

96-
val credential = getAuthCredential(credentialsRetriever)
110+
val credential = credentialsRetriever.getAuthCredential() as HttpCredentialsAdapter
111+
val googleCreds = credential.credentials as GoogleServiceAccountCredentials
97112

98113
assertEquals(
99114
"firebase-adminsdk@my-project.iam.gserviceaccount.com",
100-
credential.serviceAccountId
115+
googleCreds.clientEmail
101116
)
102-
assertEquals("abcefg123456789", credential.serviceAccountPrivateKeyId)
117+
assertEquals("abcefg123456789", googleCreds.privateKeyId)
103118
}
104119

105120
@Test
@@ -120,17 +135,18 @@ class CredentialsRetrieverTest {
120135
val credentialsRetriever = CredentialsRetriever(transport)
121136

122137
// Also pass in service credentials json directly
123-
val credential = getAuthCredential(credentialsRetriever, TEST_SERVICE_CREDENTIALS_PATH)
138+
val credential = credentialsRetriever.getAuthCredential(TEST_SERVICE_CREDENTIALS_PATH) as HttpCredentialsAdapter
139+
val googleCreds = credential.credentials as GoogleServiceAccountCredentials
124140

125141
// Verify service credentials auth is configured
126142
assertEquals(
127143
"firebase-adminsdk@my-project.iam.gserviceaccount.com",
128-
credential.serviceAccountId
144+
googleCreds.clientEmail
129145
)
130-
assertEquals("abcefg123456789", credential.serviceAccountPrivateKeyId)
146+
assertEquals("abcefg123456789", googleCreds.privateKeyId)
131147

132148
// Verify the firebase refresh token was not used
133-
assertNull(credential.accessToken)
149+
assertNull(googleCreds.accessToken)
134150
}
135151

136152
@Test
@@ -147,7 +163,7 @@ class CredentialsRetrieverTest {
147163
)
148164
val credentialsRetriever = CredentialsRetriever(transport)
149165

150-
val credential = getAuthCredential(credentialsRetriever)
166+
val credential = credentialsRetriever.getAuthCredential() as GoogleCredential
151167

152168
// Verify access token is the one set as the env firebase token
153169
assertEquals("access-token-for-env-firebase-token", credential.accessToken)
@@ -164,20 +180,17 @@ class CredentialsRetrieverTest {
164180
environmentVariables[AppDistributionEnvironment.ENV_GOOGLE_APPLICATION_CREDENTIALS] =
165181
TEST_SERVICE_CREDENTIALS_PATH
166182

167-
val credential = getAuthCredential(credentialsRetriever)
183+
val credential = credentialsRetriever.getAuthCredential() as GoogleCredential
168184

169185
// Verify Firebase CLI token is used, which also verifies that default credentials aren't used
170186
// since it's not of type ServiceAccountCredentials
171187
assertEquals("some-access-token", credential.accessToken)
172188
}
173189

174-
private fun getAuthCredential(
175-
credentialsRetriever: CredentialsRetriever,
176-
serviceCredentialsPath: String? = null
177-
) = credentialsRetriever.getAuthCredential(serviceCredentialsPath) as GoogleCredential
178-
179190
companion object {
180191
private val TEST_SERVICE_CREDENTIALS_PATH =
181192
FixtureUtils.getFixtureAsFile("test-service-credentials.json").absolutePath
193+
private val TEST_WIF_CREDENTIALS_PATH =
194+
FixtureUtils.getFixtureAsFile("test-wif-credentials.json").absolutePath
182195
}
183196
}

0 commit comments

Comments
 (0)