Skip to content

Commit

Permalink
Adds IAM get/set for binding members and roles (#996)
Browse files Browse the repository at this point in the history
  • Loading branch information
gguuss authored Feb 6, 2018
1 parent 9d4d636 commit 76bcb8b
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@
import com.google.api.services.cloudiot.v1.model.DeviceRegistry;
import com.google.api.services.cloudiot.v1.model.DeviceState;
import com.google.api.services.cloudiot.v1.model.EventNotificationConfig;
import com.google.api.services.cloudiot.v1.model.GetIamPolicyRequest;
import com.google.api.services.cloudiot.v1.model.ListDeviceStatesResponse;
import com.google.api.services.cloudiot.v1.model.ModifyCloudToDeviceConfigRequest;
import com.google.api.services.cloudiot.v1.model.PublicKeyCredential;
import com.google.api.services.cloudiot.v1.model.SetIamPolicyRequest;
import com.google.cloud.Role;
import com.google.cloud.pubsub.v1.TopicAdminClient;
import com.google.common.io.Files;
import com.google.iam.v1.Binding;
import com.google.iam.v1.Policy;
import com.google.pubsub.v1.Topic;
import com.google.pubsub.v1.TopicName;

Expand All @@ -48,7 +49,6 @@
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.cli.HelpFormatter;

/**
Expand Down Expand Up @@ -93,15 +93,16 @@ public static Topic createIotTopic(String projectId, String topicId) throws Exce

try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
final Topic topic = topicAdminClient.createTopic(topicName);
Policy policy = topicAdminClient.getIamPolicy(topicName.toString());
com.google.iam.v1.Policy policy = topicAdminClient.getIamPolicy(topicName.toString());
// add role -> members binding
Binding binding =
Binding.newBuilder()
.addMembers("serviceAccount:[email protected]")
.setRole(Role.owner().toString())
.build();
// create updated policy
Policy updatedPolicy = Policy.newBuilder(policy).addBindings(binding).build();
com.google.iam.v1.Policy updatedPolicy =
com.google.iam.v1.Policy.newBuilder(policy).addBindings(binding).build();
topicAdminClient.setIamPolicy(topicName.toString(), updatedPolicy);

System.out.println("Setup topic / policy for: " + topic.getName());
Expand Down Expand Up @@ -578,6 +579,114 @@ public static void setDeviceConfiguration(
System.out.println("Updated: " + config.getVersion());
}

/** Retrieves IAM permissions for the given registry. */
public static void getIamPermissions(
String projectId, String cloudRegion, String registryName)
throws GeneralSecurityException, IOException {
GoogleCredential credential =
GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential);
final CloudIot service = new CloudIot.Builder(
GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init)
.setApplicationName(APP_NAME).build();

final String registryPath = String.format("projects/%s/locations/%s/registries/%s",
projectId, cloudRegion, registryName);

com.google.api.services.cloudiot.v1.model.Policy policy =
service
.projects()
.locations()
.registries()
.getIamPolicy(registryPath, new GetIamPolicyRequest()).execute();

System.out.println("Policy ETAG: " + policy.getEtag());

if (policy.getBindings() != null) {
for (com.google.api.services.cloudiot.v1.model.Binding binding : policy.getBindings()) {
System.out.println(String.format("Role: %s", binding.getRole()));
System.out.println("Binding members: ");
for (String member : binding.getMembers()) {
System.out.println(String.format("\t%s", member));
}
}
} else {
System.out.println(String.format("No policy bindings for %s", registryName));
}
}

/** Sets IAM permissions for the given registry. */
public static void setIamPermissions(
String projectId, String cloudRegion, String registryName,
String member, String role)
throws GeneralSecurityException, IOException {
GoogleCredential credential =
GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all());
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential);
final CloudIot service = new CloudIot.Builder(
GoogleNetHttpTransport.newTrustedTransport(),jsonFactory, init)
.setApplicationName(APP_NAME).build();

final String registryPath = String.format("projects/%s/locations/%s/registries/%s",
projectId, cloudRegion, registryName);

com.google.api.services.cloudiot.v1.model.Policy policy =
service
.projects()
.locations()
.registries()
.getIamPolicy(registryPath, new GetIamPolicyRequest()).execute();

List<com.google.api.services.cloudiot.v1.model.Binding> bindings =
policy.getBindings();

boolean addNewRole = true;
if (bindings != null) {
for (com.google.api.services.cloudiot.v1.model.Binding binding : bindings) {
if (binding.getRole().equals(role)) {
List<String> members = binding.getMembers();
members.add(member);
binding.setMembers(members);
addNewRole = false;
}
}
} else {
bindings = new ArrayList<>();
}

if (addNewRole) {
com.google.api.services.cloudiot.v1.model.Binding bind =
new com.google.api.services.cloudiot.v1.model.Binding();
bind.setRole(role);
List<String> members = new ArrayList<>();
members.add(member);
bind.setMembers(members);

bindings.add(bind);
}

policy.setBindings(bindings);
SetIamPolicyRequest req = new SetIamPolicyRequest().setPolicy(policy);

policy =
service
.projects()
.locations()
.registries()
.setIamPolicy(registryPath, req).execute();

System.out.println("Policy ETAG: " + policy.getEtag());
for (com.google.api.services.cloudiot.v1.model.Binding binding: policy.getBindings()) {
System.out.println(String.format("Role: %s", binding.getRole()));
System.out.println("Binding members: ");
for (String mem : binding.getMembers()) {
System.out.println(String.format("\t%s", mem));
}
}
}

/** Entry poit for CLI. */
public static void main(String[] args) throws Exception {
DeviceRegistryExampleOptions options = DeviceRegistryExampleOptions.fromFlags(args);
Expand Down Expand Up @@ -626,6 +735,10 @@ public static void main(String[] args) throws Exception {
options.registryName)
.toPrettyString());
break;
case "get-iam-permissions":
System.out.println("Get iam permissions");
getIamPermissions(options.projectId, options.cloudRegion, options.registryName);
break;
case "get-device-state":
System.out.println("Get device state");
List<DeviceState> states = getDeviceStates(options.deviceId, options.projectId,
Expand Down Expand Up @@ -666,6 +779,15 @@ public static void main(String[] args) throws Exception {
options.registryName, options.configuration, options.version);
}
break;
case "set-iam-permissions":
if (options.member == null || options.role == null) {
System.out.println("Specify member and role for the policy you are updating.");
} else {
System.out.println("Setting iam permissions");
setIamPermissions(options.projectId, options.cloudRegion, options.registryName,
options.member, options.role);
}
break;
default:
String header = "Cloud IoT Core Commandline Example (Device / Registry management): \n\n";
String footer = "\nhttps://cloud.google.com/iot-core";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class DeviceRegistryExampleOptions {
String deviceId; // Default to UUID?
String pubsubTopic;
String registryName;
String member;
String role;
long version = 0;
static final Options options = new Options();

Expand Down Expand Up @@ -65,12 +67,14 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) {
+ "\n\tdelete-registry"
+ "\n\tget-device"
+ "\n\tget-device-state"
+ "\n\tget-iam-permissions"
+ "\n\tget-registry"
+ "\n\tlist-devices"
+ "\n\tlist-registries"
+ "\n\tpatch-device-es"
+ "\n\tpatch-device-rsa"
+ "\n\tset-config")
+ "\n\tset-config"
+ "\n\tset-iam-permissions")
.required()
.build());

Expand Down Expand Up @@ -131,6 +135,20 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) {
.hasArg()
.desc("The configuration version to send on the device (0 is latest).")
.build());
options.addOption(
Option.builder()
.type(String.class)
.longOpt("member")
.hasArg()
.desc("The member used for setting IAM permissions.")
.build());
options.addOption(
Option.builder()
.type(String.class)
.longOpt("role")
.hasArg()
.desc("The role (e.g. 'roles/viewer') used when setting IAM permissions.")
.build());

CommandLineParser parser = new DefaultParser();
CommandLine commandLine;
Expand Down Expand Up @@ -181,6 +199,12 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) {
if (commandLine.hasOption("version")) {
res.version = new Long(commandLine.getOptionValue("version")).longValue();
}
if (commandLine.hasOption("member")) {
res.member = commandLine.getOptionValue("member");
}
if (commandLine.hasOption("role")) {
res.role = commandLine.getOptionValue("role");
}

return res;
} catch (ParseException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public class ManagerIT {
private static final String RSA_PATH = "resources/rsa_cert.pem";
private static final String PKCS_PATH = "resources/rsa_private_pkcs8";
private static final String TOPIC_ID = "java-pst-" + (System.currentTimeMillis() / 1000L);
private static final String MEMBER = "group:[email protected]";
private static final String ROLE = "roles/viewer";


private static Topic topic;

Expand Down Expand Up @@ -242,7 +245,6 @@ public void testCreateListDevices() throws Exception {

@Test
public void testCreateGetRegistry() throws Exception {

topic = DeviceRegistryExample.createIotTopic(
PROJECT_ID,
TOPIC_ID);
Expand All @@ -258,6 +260,41 @@ public void testCreateGetRegistry() throws Exception {
}
}

@Test
public void testGetIam() throws Exception {
topic = DeviceRegistryExample.createIotTopic(
PROJECT_ID,
TOPIC_ID);
DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID);
DeviceRegistryExample.getIamPermissions(PROJECT_ID, CLOUD_REGION, REGISTRY_ID);

String got = bout.toString();
Assert.assertTrue(got.contains("ETAG"));

DeviceRegistryExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID);
try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
topicAdminClient.deleteTopic(topic.getNameAsTopicName());
}
}

@Test
public void testSetIam() throws Exception {
topic = DeviceRegistryExample.createIotTopic(
PROJECT_ID,
TOPIC_ID);
DeviceRegistryExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID);
DeviceRegistryExample.setIamPermissions(PROJECT_ID, CLOUD_REGION, REGISTRY_ID, MEMBER, ROLE);
DeviceRegistryExample.getIamPermissions(PROJECT_ID, CLOUD_REGION, REGISTRY_ID);

String got = bout.toString();
Assert.assertTrue(got.contains("ETAG"));

DeviceRegistryExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID);
try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
topicAdminClient.deleteTopic(topic.getNameAsTopicName());
}
}

// HTTP device tests

@Test
Expand Down

0 comments on commit 76bcb8b

Please sign in to comment.