1 /* 2 * Copyright 2021 Google LLC 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * * Neither the name of Google LLC nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 package com.google.auth.oauth2.functional; 33 34 import static org.junit.Assert.assertEquals; 35 import static org.junit.Assert.assertNotNull; 36 import static org.junit.Assert.assertNull; 37 import static org.junit.Assert.assertTrue; 38 import static org.junit.Assert.fail; 39 40 import com.google.api.client.http.GenericUrl; 41 import com.google.api.client.http.HttpRequest; 42 import com.google.api.client.http.HttpResponse; 43 import com.google.api.client.http.HttpTransport; 44 import com.google.api.client.http.javanet.NetHttpTransport; 45 import com.google.api.client.json.gson.GsonFactory; 46 import com.google.api.client.json.webtoken.JsonWebSignature; 47 import com.google.auth.http.HttpCredentialsAdapter; 48 import com.google.auth.oauth2.GoogleCredentials; 49 import com.google.auth.oauth2.IdToken; 50 import com.google.auth.oauth2.IdTokenCredentials; 51 import com.google.auth.oauth2.IdTokenProvider; 52 import java.io.FileNotFoundException; 53 import java.io.IOException; 54 import org.junit.Test; 55 56 public final class FTServiceAccountCredentialsTest { 57 private final String cloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"; 58 59 private final String cloudTasksUrl = 60 "https://cloudtasks.googleapis.com/v2/projects/gcloud-devel/locations"; 61 private final String storageUrl = 62 "https://storage.googleapis.com/storage/v1/b?project=gcloud-devel"; 63 private final String bigQueryUrl = 64 "https://bigquery.googleapis.com/bigquery/v2/projects/gcloud-devel/datasets"; 65 private final String computeUrl = 66 "https://compute.googleapis.com/compute/v1/projects/gcloud-devel/zones/us-central1-a/instances"; 67 68 @Test NoScopeNoAudienceComputeTest()69 public void NoScopeNoAudienceComputeTest() throws Exception { 70 HttpResponse response = executeRequestWithCredentialsWithoutScope(computeUrl); 71 assertEquals(200, response.getStatusCode()); 72 } 73 74 @Test NoScopeNoAudienceBigQueryTest()75 public void NoScopeNoAudienceBigQueryTest() throws Exception { 76 HttpResponse response = executeRequestWithCredentialsWithoutScope(bigQueryUrl); 77 assertEquals(200, response.getStatusCode()); 78 } 79 80 @Test NoScopeNoAudienceOnePlatformTest()81 public void NoScopeNoAudienceOnePlatformTest() throws Exception { 82 HttpResponse response = executeRequestWithCredentialsWithoutScope(cloudTasksUrl); 83 assertEquals(200, response.getStatusCode()); 84 } 85 86 // TODO: add Storage case 87 88 @Test AudienceSetNoScopeTest()89 public void AudienceSetNoScopeTest() throws Exception { 90 final GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); 91 92 IdTokenCredentials tokenCredential = 93 IdTokenCredentials.newBuilder() 94 .setIdTokenProvider((IdTokenProvider) credentials) 95 .setTargetAudience(cloudTasksUrl) 96 .build(); 97 98 assertNull(tokenCredential.getIdToken()); 99 tokenCredential.refresh(); 100 IdToken idToken = tokenCredential.getIdToken(); 101 assertNotNull(idToken); 102 assertTrue(idToken.getExpirationTime().getTime() > System.currentTimeMillis()); 103 JsonWebSignature jws = 104 JsonWebSignature.parse(GsonFactory.getDefaultInstance(), idToken.getTokenValue()); 105 assertEquals(cloudTasksUrl, jws.getPayload().get("aud")); 106 assertEquals("https://accounts.google.com", jws.getPayload().get("iss")); 107 } 108 109 @Test ScopeSetNoAudienceStorageTest()110 public void ScopeSetNoAudienceStorageTest() throws Exception { 111 HttpResponse response = executeRequestWithCredentialsWithScope(storageUrl, cloudPlatformScope); 112 assertEquals(200, response.getStatusCode()); 113 } 114 115 @Test ScopeSetNoAudienceComputeTest()116 public void ScopeSetNoAudienceComputeTest() throws Exception { 117 118 HttpResponse response = executeRequestWithCredentialsWithScope(computeUrl, cloudPlatformScope); 119 assertEquals(200, response.getStatusCode()); 120 } 121 122 @Test ScopeSetNoAudienceBigQueryTest()123 public void ScopeSetNoAudienceBigQueryTest() throws Exception { 124 HttpResponse response = executeRequestWithCredentialsWithScope(bigQueryUrl, cloudPlatformScope); 125 assertEquals(200, response.getStatusCode()); 126 } 127 128 @Test ScopeSetNoAudienceOnePlatformTest()129 public void ScopeSetNoAudienceOnePlatformTest() throws Exception { 130 HttpResponse response = 131 executeRequestWithCredentialsWithScope(cloudTasksUrl, cloudPlatformScope); 132 assertEquals(200, response.getStatusCode()); 133 } 134 135 @Test WrongScopeComputeTest()136 public void WrongScopeComputeTest() throws Exception { 137 executeRequestWrongScope(computeUrl); 138 } 139 140 @Test WrongScopeStorageTest()141 public void WrongScopeStorageTest() throws Exception { 142 executeRequestWrongScope(storageUrl); 143 } 144 145 @Test WrongScopeBigQueryTest()146 public void WrongScopeBigQueryTest() throws Exception { 147 executeRequestWrongScope(bigQueryUrl); 148 } 149 150 @Test WrongScopeOnePlatformTest()151 public void WrongScopeOnePlatformTest() throws Exception { 152 executeRequestWrongScope(cloudTasksUrl); 153 } 154 executeRequestWrongScope(String serviceUri)155 private void executeRequestWrongScope(String serviceUri) 156 throws FileNotFoundException, IOException { 157 String expectedMessage = "403 Forbidden"; 158 159 try { 160 executeRequestWithCredentialsWithScope( 161 serviceUri, "https://www.googleapis.com/auth/adexchange.buyer"); 162 fail("Should throw exception: " + expectedMessage); 163 } catch (IOException expected) { 164 assertTrue(expected.getMessage().contains(expectedMessage)); 165 } 166 } 167 executeRequestWithCredentialsWithoutScope(String serviceUrl)168 private HttpResponse executeRequestWithCredentialsWithoutScope(String serviceUrl) 169 throws IOException { 170 final GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); 171 GenericUrl genericUrl = new GenericUrl(serviceUrl); 172 HttpCredentialsAdapter adapter = new HttpCredentialsAdapter(credentials); 173 HttpTransport transport = new NetHttpTransport(); 174 HttpRequest request = transport.createRequestFactory(adapter).buildGetRequest(genericUrl); 175 return request.execute(); 176 } 177 executeRequestWithCredentialsWithScope(String serviceUrl, String scope)178 private HttpResponse executeRequestWithCredentialsWithScope(String serviceUrl, String scope) 179 throws IOException { 180 181 final GoogleCredentials credentials = 182 GoogleCredentials.getApplicationDefault().createScoped(scope); 183 GenericUrl genericUrl = new GenericUrl(serviceUrl); 184 HttpCredentialsAdapter adapter = new HttpCredentialsAdapter(credentials); 185 HttpTransport transport = new NetHttpTransport(); 186 HttpRequest request = transport.createRequestFactory(adapter).buildGetRequest(genericUrl); 187 return request.execute(); 188 } 189 } 190