-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds IAM get/set for binding members and roles #996
Changes from all commits
33aa2b9
dc80df9
26192ab
e650b53
b176141
38d4d47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
|
||
|
@@ -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; | ||
|
||
/** | ||
|
@@ -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 = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also, not a fan. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the code that does not appear in documentation, it's necessary for testing the API and is a convenient helper if someone is using this to automate device provisioning. |
||
com.google.iam.v1.Policy.newBuilder(policy).addBindings(binding).build(); | ||
topicAdminClient.setIamPolicy(topicName.toString(), updatedPolicy); | ||
|
||
System.out.println("Setup topic / policy for: " + topic.getName()); | ||
|
@@ -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 = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ugly |
||
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); | ||
|
@@ -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, | ||
|
@@ -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"; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
|
||
|
@@ -242,7 +245,6 @@ public void testCreateListDevices() throws Exception { | |
|
||
@Test | ||
public void testCreateGetRegistry() throws Exception { | ||
|
||
topic = DeviceRegistryExample.createIotTopic( | ||
PROJECT_ID, | ||
TOPIC_ID); | ||
|
@@ -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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a fan of this -- is it required?