Skip to content
This repository has been archived by the owner on Oct 3, 2023. It is now read-only.

feat: implement testPermission api of organizations #125

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions clirr-ignored-differences.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- see http://mojo.codehaus.org/clirr-maven-plugin/examples/ignored-differences.html -->
<differences>
<difference>
<className>com/google/cloud/resourcemanager/ResourceManager</className>
<method>java.util.Map testOrgPermissions(java.lang.String, java.util.List)</method>
<differenceType>7012</differenceType>
</difference>
<difference>
<className>com/google/cloud/resourcemanager/spi/v1beta1/ResourceManagerRpc</className>
<method>java.util.Map testOrgPermissions(java.lang.String, java.util.List)</method>
<differenceType>7012</differenceType>
</difference>
</differences>
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
<google.core-http.version>1.93.3</google.core-http.version>
<api-client.version>1.30.9</api-client.version>
<easymock.version>3.6</easymock.version>
<mockito.version>1.10.19</mockito.version>
<objenesis.version>2.6</objenesis.version>
<google.auth.version>0.20.0</google.auth.version>
<http-client-bom.version>1.34.2</http-client-bom.version>
Expand Down Expand Up @@ -205,6 +206,12 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.google.cloud.resourcemanager.spi.v1beta1.ResourceManagerRpc;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Map;

/**
* An interface for Google Cloud Resource Manager.
Expand Down Expand Up @@ -337,4 +338,20 @@ public static ProjectListOption fields(ProjectField... fields) {
* Platform Services</a>
*/
List<Boolean> testPermissions(String projectId, List<String> permissions);

/**
* Returns the permissions and their results representing whether the caller has the permissions
* on the specified Organization.
*
* @param resource the organization's resource name, e.g. "organizations/123"
* @param permissions the set of permissions to check for the resource. Permissions with wildcards
* (such as '*' or 'storage.*') are not allowed.
* @return the permissions and their results representing whether the caller has the permissions
* on the specified Organization.
* @throws ResourceManagerException upon failure
* @see <a href=
* "https://cloud.google.com/resource-manager/reference/rest/v1/organizations/testIamPermissions">
* Resource Manager testIamPermissions</a>
*/
Map<String, Boolean> testOrgPermissions(String resource, List<String> permissions);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not new in this PR, and shouldn't be fixed now, but the distinction between ResourceManager and ResourceManagerImpl is likely unnecessary and just makes the code more complicated for no particular reason.

}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public ResourceManagerException(IOException exception) {
* @throws ResourceManagerException when {@code ex} was caused by a {@code
* ResourceManagerException}
*/
static ResourceManagerException translateAndThrow(RetryHelperException ex) {
public static ResourceManagerException translateAndThrow(RetryHelperException ex) {
BaseServiceException.translate(ex);
throw new ResourceManagerException(UNKNOWN_CODE, ex.getMessage(), ex.getCause());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
Expand Down Expand Up @@ -273,6 +274,25 @@ public List<Boolean> call() {
}
}

@Override
public Map<String, Boolean> testOrgPermissions(
final String resource, final List<String> permissions) {
try {
return runWithRetries(
new Callable<Map<String, Boolean>>() {
@Override
public Map<String, Boolean> call() throws IOException {
return resourceManagerRpc.testOrgPermissions(resource, permissions);
}
},
getOptions().getRetrySettings(),
EXCEPTION_HANDLER,
getOptions().getClock());
} catch (RetryHelperException ex) {
throw ResourceManagerException.translateAndThrow(ex);
}
}

private Map<ResourceManagerRpc.Option, ?> optionMap(Option... options) {
Map<ResourceManagerRpc.Option, Object> temp = Maps.newEnumMap(ResourceManagerRpc.Option.class);
for (Option option : options) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.google.api.services.cloudresourcemanager.model.TestIamPermissionsRequest;
import com.google.api.services.cloudresourcemanager.model.TestIamPermissionsResponse;
import com.google.api.services.cloudresourcemanager.model.UndeleteProjectRequest;
import com.google.cloud.RetryHelper;
import com.google.cloud.Tuple;
import com.google.cloud.http.BaseHttpServiceException;
import com.google.cloud.http.HttpTransportOptions;
Expand Down Expand Up @@ -301,4 +302,26 @@ projectId, new TestIamPermissionsRequest().setPermissions(permissions))
throw translate(ex);
}
}

@Override
public Map<String, Boolean> testOrgPermissions(String resource, List<String> permissions)
throws IOException {
try {
TestIamPermissionsResponse response =
resourceManager
.organizations()
.testIamPermissions(
resource, new TestIamPermissionsRequest().setPermissions(permissions))
.execute();
Set<String> permissionsOwned =
ImmutableSet.copyOf(firstNonNull(response.getPermissions(), ImmutableList.<String>of()));
ImmutableMap.Builder<String, Boolean> answer = ImmutableMap.builder();
for (String permission : permissions) {
answer.put(permission, permissionsOwned.contains(permission));
}
return answer.build();
} catch (RetryHelper.RetryHelperException ex) {
throw ResourceManagerException.translateAndThrow(ex);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.cloud.ServiceRpc;
import com.google.cloud.Tuple;
import com.google.cloud.resourcemanager.ResourceManagerException;
import java.io.IOException;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -124,5 +125,13 @@ Integer getInt(Map<Option, ?> options) {
*/
List<Boolean> testPermissions(String projectId, List<String> permissions);

// TODO(ajaykannan): implement "Organization" functionality when available (issue #319)
/**
* Tests whether the caller has the given permissions on the specified Organization. Returns the
* permissions and their results corresponding to whether or not the user has the permission in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no longer need " corresponding to whether or not the user has the permission in

  • the same position of input list."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

* the same position of input list.
*
* @throws ResourceManagerException upon failure
*/
Map<String, Boolean> testOrgPermissions(String resource, List<String> permissions)
throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.google.api.gax.paging.Page;
import com.google.cloud.Identity;
Expand All @@ -38,6 +41,7 @@
import com.google.cloud.resourcemanager.testing.LocalResourceManagerHelper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
Expand All @@ -46,7 +50,11 @@
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ResourceManagerImplTest {

private static final LocalResourceManagerHelper RESOURCE_MANAGER_HELPER =
Expand Down Expand Up @@ -75,6 +83,9 @@ public class ResourceManagerImplTest {
.addIdentity(Role.editor(), Identity.serviceAccount("serviceaccount@gmail.com"))
.build();

private ResourceManagerRpcFactory rpcFactoryMock = Mockito.mock(ResourceManagerRpcFactory.class);
private ResourceManagerRpc resourceManagerRpcMock = Mockito.mock(ResourceManagerRpc.class);

@BeforeClass
public static void beforeClass() {
RESOURCE_MANAGER_HELPER.start();
Expand Down Expand Up @@ -456,4 +467,54 @@ public void testRuntimeException() {
assertEquals(exceptionMessage, exception.getCause().getMessage());
}
}

@Test
public void testTestOrgPermissions() throws IOException {
String organization = "organization/12345";
List<String> permissions =
ImmutableList.of(
"resourcemanager.organizations.get", "resourcemanager.organizations.getIamPolicy");
Map<String, Boolean> expected =
ImmutableMap.of(
"resourcemanager.organizations.get",
true,
"resourcemanager.organizations.getIamPolicy",
false);
when(rpcFactoryMock.create(Mockito.any(ResourceManagerOptions.class)))
.thenReturn(resourceManagerRpcMock);
ResourceManager resourceManager =
ResourceManagerOptions.newBuilder()
.setServiceRpcFactory(rpcFactoryMock)
.build()
.getService();
when(resourceManagerRpcMock.testOrgPermissions(organization, permissions)).thenReturn(expected);
Map<String, Boolean> actual = resourceManager.testOrgPermissions(organization, permissions);
assertEquals(expected, actual);
verify(resourceManagerRpcMock).testOrgPermissions(organization, permissions);
}

@Test
public void testTestOrgPermissionsWithResourceManagerException() throws IOException {
String organization = "organizations/12345";
String exceptionMessage = "Not Found";
List<String> permissions =
ImmutableList.of(
"resourcemanager.organizations.get", "resourcemanager.organizations.getIamPolicy");
when(rpcFactoryMock.create(Mockito.any(ResourceManagerOptions.class)))
.thenReturn(resourceManagerRpcMock);
ResourceManager resourceManager =
ResourceManagerOptions.newBuilder()
.setServiceRpcFactory(rpcFactoryMock)
.build()
.getService();
doThrow(new ResourceManagerException(404, exceptionMessage))
.when(resourceManagerRpcMock)
.testOrgPermissions(organization, permissions);
try {
resourceManager.testOrgPermissions(organization, permissions);
} catch (ResourceManagerException expected) {
assertEquals(404, expected.getCode());
assertEquals(exceptionMessage, expected.getMessage());
}
}
}