diff --git a/iot/api-client/manager/README.md b/iot/api-client/manager/README.md index c2036a5277c..1c80a53f695 100644 --- a/iot/api-client/manager/README.md +++ b/iot/api-client/manager/README.md @@ -10,7 +10,7 @@ PubSub topic for Cloud IoT as described in [the parent README](../README.md). Manually install [the provided client library](https://cloud.google.com/iot/resources/java/cloud-iot-core-library.jar) for Cloud IoT Core to Maven: - mvn install:install-file -Dfile=cloud-iot-core-library.jar -DgroupId=com.google.apis \ + mvn install:install-file -Dfile=cloud-iot-core-library.jar -DgroupId=com.example.apis \ -DartifactId=google-api-services-cloudiot -Dversion=v1beta1-rev20170418-1.22.0-SNAPSHOT \ -Dpackaging=jar @@ -21,23 +21,116 @@ mvn clean compile assembly:single ## Running the sample -The following command summarizes the sample usage: +The following description summarizes the sample usage: - mvn exec:java \ - -Dexec.mainClass="com.google.cloud.iot.examples.DeviceRegistryExample" \ - -Dexec.args="-project_id=my-project-id \ - -pubsub_topic=projects/my-project-id/topics/my-topic-id \ - -ec_public_key_file=/path/to/ec_public.pem \ - -rsa_certificate_file=/path/to/rsa_cert.pem" + usage: DeviceRegistryExample [--cloud_region ] --command + [--ec_public_key_file ] --project_id --pubsub_topic + --registry_name [--rsa_certificate_file ] + + Cloud IoT Core Commandline Example (Device / Registry management): + + --cloud_region GCP cloud region. + --command Command to run: + create-iot-topic + create-rsa + create-es + create-unauth + create-registry + delete-device + delete-registry + get-device + get-registry + list-devices + list-registries + patch-device-es + patch-device-rsa + --ec_public_key_file Path to ES256 public key file. + --project_id GCP cloud project name. + --pubsub_topic Pub/Sub topic to create registry in. + --registry_name Name for your Device Registry. + --rsa_certificate_file Path to RS256 certificate file. + +https://cloud.google.com/iot-core For example, if your project ID is `blue-jet-123`, your service account credentials are stored in your home folder in creds.json and you have generated your credentials using the shell script provided in the parent folder, you can run the sample as: - mvn exec:java \ - -Dexec.mainClass="com.google.cloud.iot.examples.DeviceRegistryExample" \ - -Dexec.args="-project_id=blue-jet-123 \ - -pubsub_topic=projects/blue-jet-123/topics/device-events \ - -ec_public_key_file=../ec_public.pem \ - -rsa_certificate_file=../rsa_cert.pem" + +## Usage Examples + +Create a PubSub topic, `hello-java`, for the project, `blue-jet-123`: + + java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ + com.example.cloud.iot.examples.DeviceRegistryExample \ + -project_id=blue-jet-123 -pubsub_topic=hello-java + -command=create-iot-topic + +Create an ES device: + + java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ + com.example.cloud.iot.examples.DeviceRegistryExample \ + -project_id=blue-jet-123 -pubsub_topic=hello-java \ + -registry_name=hello-java -ec_public_key_file ../ec_public.pem \ + -device_id="java-device-0" -command=create-es + +Create an RSA device: + + java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ + com.example.cloud.iot.examples.DeviceRegistryExample \ + -project_id=blue-jet-123 -pubsub_topic=hello-java \ + -registry_name=hello-java -rsa_certificate_file ../rsa_cert.pem \ + -device_id="java-device-1" -command=create-rsa + +Create a device without authorization: + + java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ + com.example.cloud.iot.examples.DeviceRegistryExample \ + -project_id=blue-jet-123 -pubsub_topic=hello-java \ + -registry_name=hello-java -device_id="java-device-3" \ + -command=create-unauth + +Create a device registry: + + java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ + com.example.cloud.iot.examples.DeviceRegistryExample \ + -project_id=blue-jet-123 -pubsub_topic=hello-java \ + -registry_name=hello-java -command=create-registry \ + +Get a device registry: + + java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ + com.example.cloud.iot.examples.DeviceRegistryExample \ + -project_id=blue-jet-123 -pubsub_topic=hello-java \ + -registry_name=hello-java -command=get-registry + +List devices: + + java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ + com.example.cloud.iot.examples.DeviceRegistryExample \ + -project_id=blue-jet-123 -pubsub_topic=hello-java \ + -registry_name=hello-java -command=list-devices + +List device registries: + + java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ + com.example.cloud.iot.examples.DeviceRegistryExample \ + -project_id=blue-jet-123 -pubsub_topic=hello-java \ + -registry_name=hello-java -command=list-registries + +Patch a device with ES: + + java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ + com.example.cloud.iot.examples.DeviceRegistryExample \ + -project_id=blue-jet-123 -pubsub_topic=hello-java \ + -registry_name=hello-java -ec_public_key_file ../ec_public.pem \ + -device_id="java-device-1" -command=patch-device-es + +Patch a device with RSA: + + java -cp target/cloudiot-manager-demo-1.0-jar-with-dependencies.jar \ + com.example.cloud.iot.examples.DeviceRegistryExample \ + -project_id=blue-jet-123 -pubsub_topic=hello-java \ + -registry_name=hello-java -rsa_certificate_file ../rsa_cert.pem \ + -device_id="java-device-0" -command=patch-device-rsa diff --git a/iot/api-client/manager/pom.xml b/iot/api-client/manager/pom.xml index 100af9a82e2..7769b851300 100644 --- a/iot/api-client/manager/pom.xml +++ b/iot/api-client/manager/pom.xml @@ -42,6 +42,11 @@ google-api-services-cloudiot v1beta1-rev20170418-1.22.0-SNAPSHOT + + com.google.cloud + google-cloud-pubsub + 0.21.1-beta + com.google.oauth-client google-oauth-client @@ -57,6 +62,20 @@ commons-cli 1.3 + + + + junit + junit + 4.12 + test + + + com.google.truth + truth + 0.34 + test + diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java new file mode 100644 index 00000000000..2415db8aa74 --- /dev/null +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java @@ -0,0 +1,670 @@ +/** + * Copyright 2017, Google, Inc. + * + *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.cloud.iot.examples; + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.client.util.Charsets; +import com.google.api.services.cloudiot.v1beta1.CloudIot; +import com.google.api.services.cloudiot.v1beta1.CloudIotScopes; +import com.google.api.services.cloudiot.v1beta1.model.Device; +import com.google.api.services.cloudiot.v1beta1.model.DeviceConfig; +import com.google.api.services.cloudiot.v1beta1.model.DeviceConfigData; +import com.google.api.services.cloudiot.v1beta1.model.DeviceCredential; +import com.google.api.services.cloudiot.v1beta1.model.DeviceRegistry; +import com.google.api.services.cloudiot.v1beta1.model.ModifyCloudToDeviceConfigRequest; +import com.google.api.services.cloudiot.v1beta1.model.NotificationConfig; +import com.google.api.services.cloudiot.v1beta1.model.PublicKeyCredential; +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; + +import java.io.File; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.xml.bind.DatatypeConverter; + +/** + * Example of using Cloud IoT device manager API to administer devices, registries and projects. + * + *

This example uses the Device Manager API to create, retrieve, disable, list and delete Cloud + * IoT devices and registries, using both RSA and eliptic curve keys for authentication. + * + *

To start, follow the instructions on the Developer Guide at cloud.google.com/iot to create a + * service_account.json file and Cloud Pub/Sub topic as discussed in the guide. You will then need + * to point to the service_account.json file as described in + * https://developers.google.com/identity/protocols/application-default-credentials#howtheywork + * + *

Before running the example, we have to create private and public keys, as described in + * cloud.google.com/iot. Since we are interacting with the device manager, we will only use the + * public keys. The private keys are used to sign JWTs to authenticate devices. See the + * MQTT client example + * for more information. + * + *

Finally, compile and run the example with: + * + *

+ * 
+ * $ mvn clean compile assembly:single
+ * $ mvn exec:java \
+ *       -Dexec.mainClass="com.google.cloud.iot.examples.DeviceRegistryExample" \
+ *       -Dexec.args="-project_id=my-project-id \
+ *                    -pubsub_topic=projects/my-project-id/topics/my-topic-id \
+ *                    -ec_public_key_file=/path/to/ec_public.pem \
+ *                    -rsa_certificate_file=/path/to/rsa_cert.pem"
+ * 
+ * 
+ */ +public class DeviceRegistryExample { + + /** Creates a topic and grants the IoT service account access. */ + public static void createIotTopic(String projectId, String topicId) throws Exception { + // Create a new topic + final TopicName topicName = TopicName.create(projectId, topicId); + + try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { + final Topic topic = topicAdminClient.createTopic(topicName); + Policy policy = topicAdminClient.getIamPolicy(topicName.toString()); + // add role -> members binding + Binding binding = + Binding.newBuilder() + .addMembers("serviceAccount:cloud-iot@system.gserviceaccount.com") + .setRole(Role.owner().toString()) + .build(); + // create updated policy + Policy updatedPolicy = Policy.newBuilder(policy).addBindings(binding).build(); + topicAdminClient.setIamPolicy(topicName.toString(), updatedPolicy); + + System.out.println("Setup topic / policy for: " + topic.getName()); + } + } + + /** Create a registry for Cloud IoT. */ + public static void createRegistry(String cloudRegion, String projectId, String registryName, + String pubsubTopicPath) + throws GeneralSecurityException, IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); + JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); + HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); + final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String projectPath = "projects/" + projectId + "/locations/" + cloudRegion; + final String fullPubsubPath = "projects/" + projectId + "/topics/" + pubsubTopicPath; + + DeviceRegistry registry = new DeviceRegistry(); + NotificationConfig notificationConfig = new NotificationConfig(); + notificationConfig.setPubsubTopicName(fullPubsubPath); + registry.setEventNotificationConfig(notificationConfig); + registry.setId(registryName); + + DeviceRegistry reg = service.projects().locations().registries().create(projectPath, + registry).execute(); + System.out.println("Created registry: " + reg.getName()); + } + + /** Delete this registry from Cloud IoT. */ + public static void deleteRegistry(String cloudRegion, String projectId, 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + String projectPath = "projects/" + projectId + "/locations/" + cloudRegion; + String registryPath = projectPath + "/registries/" + registryName; + + System.out.println("Deleting: " + registryPath); + service.projects().locations().registries().delete(registryPath).execute(); + } + + /** Print all of the devices in this registry to standard out. */ + public static void listDevices(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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + + registryName; + + List devices = + service + .projects() + .locations() + .registries() + .devices() + .list(registryPath) + .execute() + .getDevices(); + + if (devices != null) { + System.out.println("Found " + devices.size() + " devices"); + for (Device d : devices) { + System.out.println("Id: " + d.getId()); + if (d.getConfig() != null) { + // Note that this will show the device config in Base64 encoded format. + System.out.println("Config: " + d.getConfig().toPrettyString()); + } + System.out.println(); + } + } else { + System.out.println("Registry has no devices."); + } + } + + /** Create a device that is authenticated using ES256. */ + public static void createDeviceWithEs256(String deviceId, String publicKeyFilePath, + 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + + "/registries/" + registryName; + + PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); + final String key = Files.toString(new File(publicKeyFilePath), Charsets.UTF_8); + publicKeyCredential.setKey(key); + publicKeyCredential.setFormat("ES256_PEM"); + + DeviceCredential devCredential = new DeviceCredential(); + devCredential.setPublicKey(publicKeyCredential); + + System.out.println("Creating device with id: " + deviceId); + Device device = new Device(); + device.setId(deviceId); + device.setCredentials(Arrays.asList(devCredential)); + + Device createdDevice = + service + .projects() + .locations() + .registries() + .devices() + .create(registryPath, device) + .execute(); + + System.out.println("Created device: " + createdDevice.toPrettyString()); + } + + /** Create a device that is authenticated using RS256. */ + public static void createDeviceWithRs256(String deviceId, String certificateFilePath, + 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + + "/registries/" + registryName; + + PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); + String key = Files.toString(new File(certificateFilePath), Charsets.UTF_8); + publicKeyCredential.setKey(key); + publicKeyCredential.setFormat("RSA_X509_PEM"); + + DeviceCredential devCredential = new DeviceCredential(); + devCredential.setPublicKey(publicKeyCredential); + + System.out.println("Creating device with id: " + deviceId); + Device device = new Device(); + device.setId(deviceId); + device.setCredentials(Arrays.asList(devCredential)); + Device createdDevice = + service + .projects() + .locations() + .registries() + .devices() + .create(registryPath, device) + .execute(); + + System.out.println("Created device: " + createdDevice.toPrettyString()); + } + + /** + * Create a device that has no credentials. + * + *

This is a valid way to construct a device, however until it is patched with a credential the + * device will not be able to connect to Cloud IoT. + */ + public static void createDeviceWithNoAuth(String deviceId, 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + + "/registries/" + registryName; + + System.out.println("Creating device with id: " + deviceId); + Device device = new Device(); + device.setId(deviceId); + device.setCredentials(new ArrayList()); + Device createdDevice = + service + .projects() + .locations() + .registries() + .devices() + .create(registryPath, device) + .execute(); + + System.out.println("Created device: " + createdDevice.toPrettyString()); + } + + /** Delete the given device from the registry. */ + public static void deleteDevice(String deviceId, 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + + "/registries/" + registryName; + + final String devicePath = registryPath + "/devices/" + deviceId; + System.out.println("Deleting device " + devicePath); + service.projects().locations().registries().devices().delete(devicePath).execute(); + } + + /** Retrieves device metadata from a registry. **/ + public static Device getDevice(String deviceId, 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); + CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + "/registries/" + + registryName; + + String devicePath = registryPath + "/devices/" + deviceId; + System.out.println("Retrieving device " + devicePath); + return service.projects().locations().registries().devices().get(devicePath).execute(); + } + + /** Retrieves registry metadata from a project. **/ + public static DeviceRegistry getRegistry( + 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + + "/registries/" + registryName; + return service.projects().locations().registries().get(registryPath).execute(); + } + + /** List all of the configs for the given device. */ + public static void listDeviceConfigs( + String deviceId, 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + + "/registries/" + registryName; + + final String devicePath = registryPath + "/devices/" + deviceId; + System.out.println("Listing device configs for " + devicePath); + List deviceConfigs = + service + .projects() + .locations() + .registries() + .devices() + .configVersions() + .list(devicePath) + .execute() + .getDeviceConfigs(); + + for (DeviceConfig config : deviceConfigs) { + System.out.println("Config version: " + config.getVersion()); + System.out.println("Contents: " + config.getData().getBinaryData()); + System.out.println(); + } + } + + /** Lists all of the registries associated with the given project. */ + public static void listRegistries(String projectId, String cloudRegion) + throws GeneralSecurityException, IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); + JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); + HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); + final CloudIot service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String projectPath = "projects/" + projectId + "/locations/" + cloudRegion; + + List registries = + service + .projects() + .locations() + .registries() + .list(projectPath) + .execute() + .getDeviceRegistries(); + + if (registries != null) { + System.out.println("Found " + registries.size() + " registries"); + for (DeviceRegistry r: registries) { + System.out.println("Id: " + r.getId()); + System.out.println("Name: " + r.getName()); + if (r.getMqttConfig() != null) { + System.out.println("Config: " + r.getMqttConfig().toPrettyString()); + } + System.out.println(); + } + } else { + System.out.println("Project has no registries."); + } + } + + /** Modify the latest cloud to device config for the given device, with the config data. */ + public static void modifyCloudToDeviceConfig(String deviceId, String configData, 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + + "/registries/" + registryName; + final String devicePath = registryPath + "/devices/" + deviceId; + ModifyCloudToDeviceConfigRequest request = new ModifyCloudToDeviceConfigRequest(); + DeviceConfigData data = new DeviceConfigData(); + data.setBinaryData(DatatypeConverter.printBase64Binary(configData.getBytes(Charsets.UTF_8))); + request.setVersionToUpdate(0L); // 0L indicates update all versions + request.setData(data); + DeviceConfig config = + service + .projects() + .locations() + .registries() + .devices() + .modifyCloudToDeviceConfig(devicePath, request) + .execute(); + + System.out.println("Created device config: " + config.toPrettyString()); + } + + /** Patch the device to add an ES256 key for authentication. */ + public static void patchEs256ForAuth(String deviceId, String publicKeyFilePath, 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + + "/registries/" + registryName; + + final String devicePath = registryPath + "/devices/" + deviceId; + PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); + String key = Files.toString(new File(publicKeyFilePath), Charsets.UTF_8); + publicKeyCredential.setKey(key); + publicKeyCredential.setFormat("ES256_PEM"); + + DeviceCredential devCredential = new DeviceCredential(); + devCredential.setPublicKey(publicKeyCredential); + + Device device = new Device(); + device.setCredentials(Arrays.asList(devCredential)); + + Device patchedDevice = + service + .projects() + .locations() + .registries() + .devices() + .patch(devicePath, device) + .setFields("credentials") + .execute(); + + System.out.println("Patched device is " + patchedDevice.toPrettyString()); + } + + /** Patch the device to add an RSA256 key for authentication. */ + public static void patchRsa256ForAuth(String deviceId, String publicKeyFilePath, 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(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, + init); + + final String registryPath = "projects/" + projectId + "/locations/" + cloudRegion + + "/registries/" + registryName; + + final String devicePath = registryPath + "/devices/" + deviceId; + PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); + String key = Files.toString(new File(publicKeyFilePath), Charsets.UTF_8); + publicKeyCredential.setKey(key); + publicKeyCredential.setFormat("RSA_X509_PEM"); + + DeviceCredential devCredential = new DeviceCredential(); + devCredential.setPublicKey(publicKeyCredential); + + Device device = new Device(); + device.setCredentials(Arrays.asList(devCredential)); + + Device patchedDevice = + service + .projects() + .locations() + .registries() + .devices() + .patch(devicePath, device) + .setFields("credentials") + .execute(); + + System.out.println("Patched device is " + patchedDevice.toPrettyString()); + } + + /** Entry poit for CLI. */ + public static void main(String[] args) throws Exception { + DeviceRegistryExampleOptions options = DeviceRegistryExampleOptions.fromFlags(args); + if (options == null) { + // Could not parse. + return; + } + + switch (options.command) { + case "create-iot-topic": + System.out.println("Create IoT Topic:"); + createIotTopic(options.projectId, options.pubsubTopic); + break; + case "create-es": + System.out.println("Create ES Device:"); + createDeviceWithEs256(options.deviceId, options.ecPublicKeyFile, options.projectId, + options.cloudRegion, options.registryName); + break; + case "create-rsa": + System.out.println("Create RSA Device:"); + createDeviceWithRs256(options.deviceId, options.rsaCertificateFile, options.projectId, + options.cloudRegion, options.registryName); + break; + case "create-unauth": + System.out.println("Create Unauth Device"); + createDeviceWithNoAuth(options.deviceId, options.projectId, options.cloudRegion, + options.registryName); + break; + case "create-registry": + System.out.println("Create registry"); + createRegistry(options.cloudRegion, options.projectId, options.registryName, + options.pubsubTopic); + break; + case "delete-device": + System.out.println("Delete device"); + deleteDevice(options.deviceId, options.projectId, options.cloudRegion, + options.registryName); + break; + case "delete-registry": + System.out.println("Delete registry"); + deleteRegistry(options.cloudRegion, options.projectId, options.registryName); + break; + case "get-device": + System.out.println("Get device"); + System.out.println(getDevice(options.deviceId, options.projectId, options.cloudRegion, + options.registryName) + .toPrettyString()); + break; + case "get-registry": + System.out.println("Get registry"); + System.out.println(getRegistry(options.projectId, options.cloudRegion, + options.registryName)); + break; + case "list-devices": + System.out.println("List devices"); + listDevices(options.projectId, options.cloudRegion, options.registryName); + break; + case "list-registries": + System.out.println("List registries"); + listRegistries(options.projectId, options.cloudRegion); + break; + case "patch-device-es": + System.out.println("Patch device with ES"); + patchEs256ForAuth(options.deviceId, options.ecPublicKeyFile, options.projectId, + options.cloudRegion, options.registryName); + break; + case "patch-device-rsa": + System.out.println("Patch device with RSA"); + patchRsa256ForAuth(options.deviceId, options.rsaCertificateFile, options.projectId, + options.cloudRegion, options.registryName); + break; + default: + System.out.println("You entered: " + options.command); + System.out.println("Wrong, wrong, wrong. Usage is like this:"); // TODO: + break; + } + + + /* + // Simple example of interacting with the Cloud IoT API. + String registryName = "cloudiot_device_manager_example_registry_" + System.currentTimeMillis(); + + // Create a new registry with the above name. + DeviceRegistryExample registry = + new DeviceRegistryExample( + options.projectId, options.cloudRegion, registryName, options.pubsubTopic); + + // List the devices in the registry. Since we haven't created any yet, this should be empty. + registry.listDevices(); + + // Create a device that is authenticated using RSA. + String rs256deviceId = "rs256-device"; + registry.createDeviceWithRs256(rs256deviceId, options.rsaCertificateFile); + + // Create a device without an authentication credential. We'll patch it to use elliptic curve + // cryptography. + String es256deviceId = "es256-device"; + registry.createDeviceWithNoAuth(es256deviceId); + + // List the devices again. This should show the above two devices. + registry.listDevices(); + + // Give the device without an authentication credential an elliptic curve credential. + registry.patchEs256ForAuth(es256deviceId, options.ecPublicKeyFile); + + // List the devices in the registry again, still showing the two devices. + registry.listDevices(); + + // List the device configs for the RSA authenticated device. Since we haven't pushed any, this + // list will only contain the default empty config. + registry.listDeviceConfigs(rs256deviceId); + + // Push two new configs to the device. + registry.modifyCloudToDeviceConfig(rs256deviceId, "config v1"); + registry.modifyCloudToDeviceConfig(rs256deviceId, "config v2"); + + // List the configs again. This will show the two configs that we just pushed. + registry.listDeviceConfigs(rs256deviceId); + + // Delete the elliptic curve device. + registry.deleteDevice(es256deviceId); + + // Since we deleted the elliptic curve device, this will only show the RSA device. + registry.listDevices(); + + try { + // Try to delete the registry. However, since the registry is not empty, this will fail and + // throw an exception. + registry.deleteRegistry(); + } catch (IOException e) { + System.out.println("Exception: " + e.getMessage()); + } + + // Delete the RSA device. The registry is now empty. + registry.deleteDevice(rs256deviceId); + + // Since the registry has no devices in it, the delete will succeed. + registry.deleteRegistry(); + */ + } +} diff --git a/iot/api-client/manager/src/main/java/com/google/cloud/iot/examples/DeviceRegistryExampleOptions.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java similarity index 54% rename from iot/api-client/manager/src/main/java/com/google/cloud/iot/examples/DeviceRegistryExampleOptions.java rename to iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java index 57e13153881..2ff9e68de7c 100644 --- a/iot/api-client/manager/src/main/java/com/google/cloud/iot/examples/DeviceRegistryExampleOptions.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java @@ -11,11 +11,13 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package com.google.cloud.iot.examples; + +package com.example.cloud.iot.examples; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; @@ -23,10 +25,13 @@ /** Command line options for the Device Manager example. */ public class DeviceRegistryExampleOptions { String projectId; - String pubsubTopic; String ecPublicKeyFile = "ec_public.pem"; String rsaCertificateFile = "rsa_cert.pem"; String cloudRegion = "us-central1"; + String command = "help"; + String deviceId; // Default to UUID? + String pubsubTopic; + String registryName; /** Construct an DeviceRegistryExampleOptions class from command line flags. */ public static DeviceRegistryExampleOptions fromFlags(String[] args) { @@ -35,18 +40,31 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { options.addOption( Option.builder() .type(String.class) - .longOpt("project_id") + .longOpt("pubsub_topic") .hasArg() - .desc("GCP cloud project name.") + .desc("Pub/Sub topic to create registry in.") .required() .build()); options.addOption( Option.builder() .type(String.class) - .longOpt("pubsub_topic") + .longOpt("command") .hasArg() .desc( - "Pub/Sub topic to create registry with, i.e. 'projects/project-id/topics/topic-id'") + "Command to run:" + + "\n\tcreate-iot-topic" // TODO: Descriptions or too verbose? + + "\n\tcreate-rsa" + + "\n\tcreate-es" + + "\n\tcreate-unauth" + + "\n\tcreate-registry" + + "\n\tdelete-device" + + "\n\tdelete-registry" + + "\n\tget-device" + + "\n\tget-registry" + + "\n\tlist-devices" + + "\n\tlist-registries" + + "\n\tpatch-device-es" + + "\n\tpatch-device-rsa") .required() .build()); @@ -72,6 +90,27 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { .hasArg() .desc("GCP cloud region.") .build()); + options.addOption( + Option.builder() + .type(String.class) + .longOpt("project_id") + .hasArg() + .desc("GCP cloud project name.") + .build()); + options.addOption( + Option.builder() + .type(String.class) + .longOpt("registry_name") + .hasArg() + .desc("Name for your Device Registry.") + .build()); + options.addOption( + Option.builder() + .type(String.class) + .longOpt("device_id") + .hasArg() + .desc("Name for your Device.") + .build()); CommandLineParser parser = new DefaultParser(); CommandLine commandLine; @@ -79,8 +118,27 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { commandLine = parser.parse(options, args); DeviceRegistryExampleOptions res = new DeviceRegistryExampleOptions(); - res.projectId = commandLine.getOptionValue("project_id"); - res.pubsubTopic = commandLine.getOptionValue("pubsub_topic"); + res.command = commandLine.getOptionValue("command"); + + if (res.command.equals("help") || res.command.equals("")) { + throw new ParseException("Invalid command, showing help."); + } + + if (commandLine.hasOption("project_id")) { + res.projectId = commandLine.getOptionValue("project_id"); + } else { + try { + res.projectId = System.getenv("GOOGLE_CLOUD_PROJECT"); + } catch (NullPointerException npe) { + res.projectId = System.getenv("GCLOUD_PROJECT"); + } + } + + if (commandLine.hasOption("pubsub_topic")) { + res.pubsubTopic = commandLine.getOptionValue("pubsub_topic"); + } else { + // TODO: Get from environment variable + } if (commandLine.hasOption("ec_public_key_file")) { res.ecPublicKeyFile = commandLine.getOptionValue("ec_public_key_file"); @@ -91,10 +149,23 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { if (commandLine.hasOption("cloud_region")) { res.cloudRegion = commandLine.getOptionValue("cloud_region"); } + if (commandLine.hasOption("registry_name")) { + res.registryName = commandLine.getOptionValue("registry_name"); + } + if (commandLine.hasOption("device_id")) { + res.deviceId = commandLine.getOptionValue("device_id"); + } return res; } catch (ParseException e) { + String header = "Cloud IoT Core Commandline Example (Device / Registry management): \n\n"; + String footer = "\nhttps://cloud.google.com/iot-core"; + + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("DeviceRegistryExample", header, options, footer, + true); + System.err.println(e.getMessage()); return null; } } -} +} \ No newline at end of file diff --git a/iot/api-client/manager/src/main/java/com/google/cloud/iot/examples/RetryHttpInitializerWrapper.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/RetryHttpInitializerWrapper.java similarity index 99% rename from iot/api-client/manager/src/main/java/com/google/cloud/iot/examples/RetryHttpInitializerWrapper.java rename to iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/RetryHttpInitializerWrapper.java index 71aad88ef33..734585be744 100644 --- a/iot/api-client/manager/src/main/java/com/google/cloud/iot/examples/RetryHttpInitializerWrapper.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/RetryHttpInitializerWrapper.java @@ -11,7 +11,8 @@ * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ -package com.google.cloud.iot.examples; + +package com.example.cloud.iot.examples; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.http.HttpBackOffIOExceptionHandler; diff --git a/iot/api-client/manager/src/main/java/com/google/cloud/iot/examples/DeviceRegistryExample.java b/iot/api-client/manager/src/main/java/com/google/cloud/iot/examples/DeviceRegistryExample.java deleted file mode 100644 index e17766ea578..00000000000 --- a/iot/api-client/manager/src/main/java/com/google/cloud/iot/examples/DeviceRegistryExample.java +++ /dev/null @@ -1,334 +0,0 @@ -/** - * Copyright 2017, Google, Inc. - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.cloud.iot.examples; - -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; -import com.google.api.client.http.HttpRequestInitializer; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.google.api.client.util.Charsets; -import com.google.api.services.cloudiot.v1beta1.CloudIot; -import com.google.api.services.cloudiot.v1beta1.CloudIotScopes; -import com.google.api.services.cloudiot.v1beta1.model.Device; -import com.google.api.services.cloudiot.v1beta1.model.DeviceConfig; -import com.google.api.services.cloudiot.v1beta1.model.DeviceConfigData; -import com.google.api.services.cloudiot.v1beta1.model.DeviceCredential; -import com.google.api.services.cloudiot.v1beta1.model.DeviceRegistry; -import com.google.api.services.cloudiot.v1beta1.model.ModifyCloudToDeviceConfigRequest; -import com.google.api.services.cloudiot.v1beta1.model.NotificationConfig; -import com.google.api.services.cloudiot.v1beta1.model.PublicKeyCredential; -import com.google.common.io.Files; - -import java.io.File; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import javax.xml.bind.DatatypeConverter; - -/** - * Example of using Cloud IoT device manager API to administer devices, registries and projects. - * - *

This example uses the Device Manager API to create, retrieve, disable, list and delete Cloud - * IoT devices and registries, using both RSA and eliptic curve keys for authentication. - * - *

To start, follow the instructions on the Developer Guide at cloud.google.com/iot to create a - * service_account.json file and Cloud Pub/Sub topic as discussed in the guide. You will then need - * to point to the service_account.json file as described in - * https://developers.google.com/identity/protocols/application-default-credentials#howtheywork - * - *

Before running the example, we have to create private and public keys, as described in - * cloud.google.com/iot. Since we are interacting with the device manager, we will only use the - * public keys. The private keys are used to sign JWTs to authenticate devices. See the - * MQTT client example - * for more information. - * - *

Finally, compile and run the example with: - * - *

- * 
- * $ mvn clean compile assembly:single
- * $ mvn exec:java \
- *       -Dexec.mainClass="com.google.cloud.iot.examples.DeviceRegistryExample" \
- *       -Dexec.args="-project_id=my-project-id \
- *                    -pubsub_topic=projects/my-project-id/topics/my-topic-id \
- *                    -ec_public_key_file=/path/to/ec_public.pem \
- *                    -rsa_certificate_file=/path/to/rsa_cert.pem"
- * 
- * 
- */ -public class DeviceRegistryExample { - // Service for administering Cloud IoT Core devices, registries and projects. - private CloudIot service; - // Path to the project and location: "projects/my-project-id/locations/us-central1" - private String projectPath; - // Path to the registry: "projects/my-project-id/location/us-central1/registries/my-registry-id" - private String registryPath; - - /** Construct a new registry with the given name and pubsub topic inside the given project. */ - public DeviceRegistryExample( - String projectId, String location, String registryName, String pubsubTopicPath) - throws IOException, GeneralSecurityException { - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - service = new CloudIot(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init); - projectPath = "projects/" + projectId + "/locations/" + location; - registryPath = projectPath + "/registries/" + registryName; - - NotificationConfig notificationConfig = new NotificationConfig(); - notificationConfig.setPubsubTopicName(pubsubTopicPath); - - DeviceRegistry registry = new DeviceRegistry(); - registry.setEventNotificationConfig(notificationConfig); - registry.setId(registryName); - service.projects().locations().registries().create(projectPath, registry).execute(); - } - - /** Delete this registry from Cloud IoT. */ - public void delete() throws IOException { - System.out.println("Deleting: " + registryPath); - service.projects().locations().registries().delete(registryPath).execute(); - } - - /** Print all of the devices in this registry to standard out. */ - public void listDevices() throws IOException { - List devices = - service - .projects() - .locations() - .registries() - .devices() - .list(registryPath) - .execute() - .getDevices(); - - if (devices != null) { - System.out.println("Found " + devices.size() + " devices"); - for (Device d : devices) { - System.out.println("Id: " + d.getId()); - if (d.getConfig() != null) { - // Note that this will show the device config in Base64 encoded format. - System.out.println("Config: " + d.getConfig().toPrettyString()); - } - System.out.println(); - } - } else { - System.out.println("Registry has no devices."); - } - } - - private DeviceCredential createDeviceCredential(String publicKeyFilePath, String keyFormat) - throws IOException { - PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); - String key = Files.toString(new File(publicKeyFilePath), Charsets.UTF_8); - publicKeyCredential.setKey(key); - publicKeyCredential.setFormat(keyFormat); - - DeviceCredential credential = new DeviceCredential(); - credential.setPublicKey(publicKeyCredential); - return credential; - } - - /** - * Create a new device in this registry with the given id. The device will be authenticated with - * the given public key file. - */ - private void createDevice(String deviceId, List credentials) - throws IOException { - System.out.println("Creating device with id: " + deviceId); - Device device = new Device(); - device.setId(deviceId); - device.setCredentials(credentials); - Device createdDevice = - service - .projects() - .locations() - .registries() - .devices() - .create(registryPath, device) - .execute(); - - System.out.println("Created device: " + createdDevice.toPrettyString()); - } - - /** Create a device that is authenticated using RS256. */ - public void createDeviceWithRs256(String deviceId, String certificateFilePath) - throws IOException { - createDevice( - deviceId, Arrays.asList(createDeviceCredential(certificateFilePath, "RSA_X509_PEM"))); - } - - /** Create a device that is authenticated using ES256. */ - public void createDeviceWithEs256(String deviceId, String publicKeyFilePath) throws IOException { - createDevice(deviceId, Arrays.asList(createDeviceCredential(publicKeyFilePath, "ES256_PEM"))); - } - - /** - * Create a device that has no credentials. - * - *

This is a valid way to construct a device, however until it is patched with a credential the - * device will not be able to connect to Cloud IoT. - */ - public void createDeviceWithNoAuth(String deviceId) throws IOException { - createDevice(deviceId, new ArrayList()); - } - - /** Patch the device to add an ES256 key for authentication. */ - public void patchEs256ForAuth(String deviceId, String publicKeyFilePath) throws IOException { - String devicePath = registryPath + "/devices/" + deviceId; - PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); - String key = Files.toString(new File(publicKeyFilePath), Charsets.UTF_8); - publicKeyCredential.setKey(key); - publicKeyCredential.setFormat("ES256_PEM"); - - DeviceCredential credential = new DeviceCredential(); - credential.setPublicKey(publicKeyCredential); - - Device device = new Device(); - device.setCredentials(Arrays.asList(credential)); - - Device patchedDevice = - service - .projects() - .locations() - .registries() - .devices() - .patch(devicePath, device) - .setFields("credentials") - .execute(); - - System.out.println("Patched device is " + patchedDevice.toPrettyString()); - } - - /** Delete the given device from the registry. */ - public void deleteDevice(String deviceId) throws IOException { - String devicePath = registryPath + "/devices/" + deviceId; - System.out.println("Deleting device " + devicePath); - service.projects().locations().registries().devices().delete(devicePath).execute(); - } - - /** List all of the configs for the given device. */ - public void listDeviceConfigs(String deviceId) throws IOException { - String devicePath = registryPath + "/devices/" + deviceId; - System.out.println("Listing device configs for " + devicePath); - List deviceConfigs = - service - .projects() - .locations() - .registries() - .devices() - .configVersions() - .list(devicePath) - .execute() - .getDeviceConfigs(); - - for (DeviceConfig config : deviceConfigs) { - System.out.println("Config version: " + config.getVersion()); - System.out.println("Contents: " + config.getData().getBinaryData()); - System.out.println(); - } - } - - /** Modify the latest cloud to device config for the given device, with the config data. */ - public void modifyCloudToDeviceConfig(String deviceId, String configData) throws IOException { - String devicePath = registryPath + "/devices/" + deviceId; - ModifyCloudToDeviceConfigRequest request = new ModifyCloudToDeviceConfigRequest(); - DeviceConfigData data = new DeviceConfigData(); - data.setBinaryData(DatatypeConverter.printBase64Binary(configData.getBytes(Charsets.UTF_8))); - request.setVersionToUpdate(0L); // 0L indicates update all versions - request.setData(data); - DeviceConfig config = - service - .projects() - .locations() - .registries() - .devices() - .modifyCloudToDeviceConfig(devicePath, request) - .execute(); - - System.out.println("Created device config: " + config.toPrettyString()); - } - - public static void main(String[] args) throws IOException, GeneralSecurityException { - DeviceRegistryExampleOptions options = DeviceRegistryExampleOptions.fromFlags(args); - if (options == null) { - // Could not parse. - return; - } - - // Simple example of interacting with the Cloud IoT API. - String registryName = "cloudiot_device_manager_example_registry_" + System.currentTimeMillis(); - - // Create a new registry with the above name. - DeviceRegistryExample registry = - new DeviceRegistryExample( - options.projectId, options.cloudRegion, registryName, options.pubsubTopic); - - // List the devices in the registry. Since we haven't created any yet, this should be empty. - registry.listDevices(); - - // Create a device that is authenticated using RSA. - String rs256deviceId = "rs256-device"; - registry.createDeviceWithRs256(rs256deviceId, options.rsaCertificateFile); - - // Create a device without an authentication credential. We'll patch it to use elliptic curve - // cryptography. - String es256deviceId = "es256-device"; - registry.createDeviceWithNoAuth(es256deviceId); - - // List the devices again. This should show the above two devices. - registry.listDevices(); - - // Give the device without an authentication credential an elliptic curve credential. - registry.patchEs256ForAuth(es256deviceId, options.ecPublicKeyFile); - - // List the devices in the registry again, still showing the two devices. - registry.listDevices(); - - // List the device configs for the RSA authenticated device. Since we haven't pushed any, this - // list will only contain the default empty config. - registry.listDeviceConfigs(rs256deviceId); - - // Push two new configs to the device. - registry.modifyCloudToDeviceConfig(rs256deviceId, "config v1"); - registry.modifyCloudToDeviceConfig(rs256deviceId, "config v2"); - - // List the configs again. This will show the two configs that we just pushed. - registry.listDeviceConfigs(rs256deviceId); - - // Delete the elliptic curve device. - registry.deleteDevice(es256deviceId); - - // Since we deleted the elliptic curve device, this will only show the RSA device. - registry.listDevices(); - - try { - // Try to delete the registry. However, since the registry is not empty, this will fail and - // throw an exception. - registry.delete(); - } catch (IOException e) { - System.out.println("Exception: " + e.getMessage()); - } - - // Delete the RSA device. The registry is now empty. - registry.deleteDevice(rs256deviceId); - - // Since the registry has no devices in it, the delete will succeed. - registry.delete(); - } -} diff --git a/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java b/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java new file mode 100644 index 00000000000..0f3e8616781 --- /dev/null +++ b/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java @@ -0,0 +1,87 @@ +/* + Copyright 2017, Google, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.cloud.iot.examples; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + + +/** Tests for iot "Management" sample. */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class ManagerIT { + private ByteArrayOutputStream bout; + private PrintStream out; + private DeviceRegistryExample app; + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String BUCKET = PROJECT_ID; + + @Before + public void setUp() throws IOException { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + app = new DeviceRegistryExample(); + // TODO: Create IoT PubSub Topic + // TODO: Create Registry + } + + @After + public void tearDown() { + // TODO: Delete registry + // TODO: Remove PubSub Topic + System.setOut(null); + } + + @Test + public void testCreateDeleteUnauthDevice() throws Exception { + // TODO: Implement when library is live + } + + @Test + public void testCreateDeleteEsDevice() throws Exception { + // TODO: Implement when library is live + } + + @Test + public void testCreateDeleteRsaDevice() throws Exception { + // TODO: Implement when library is live + } + + @Test + public void testCreateGetDevice() throws Exception { + // TODO: Implement when library is live + } + + + @Test + public void testCreateListDevices() throws Exception { + // TODO: Implement when library is live + } + + @Test + public void testCreateGetRegistry() throws Exception { + // TODO: Implement when library is live + } +}