diff --git a/iot/manager/manager.js b/iot/manager/manager.js index 9394a68e17..7f597c931b 100644 --- a/iot/manager/manager.js +++ b/iot/manager/manager.js @@ -573,6 +573,34 @@ function getDeviceState (client, deviceId, registryId, projectId, // [END iot_get_device_state] } +// Retrieve the given device's configuration history from the registry. +function getDeviceConfigs (client, deviceId, registryId, projectId, + cloudRegion) { + // [START iot_get_device_configs] + // Client retrieved in callback + // getClient(serviceAccountJson, function(client) {...}); + // const cloudRegion = 'us-central1'; + // const deviceId = 'my-device'; + // const projectId = 'adjective-noun-123'; + // const registryId = 'my-registry'; + const parentName = `projects/${projectId}/locations/${cloudRegion}`; + const registryName = `${parentName}/registries/${registryId}`; + const request = { + name: `${registryName}/devices/${deviceId}` + }; + + client.projects.locations.registries.devices.configVersions.list(request, + (err, data) => { + if (err) { + console.log('Could not find device:', deviceId); + console.log(err); + } else { + console.log('Configs:', data); + } + }); + // [END iot_get_device_configs] +} + // Retrieve the given device's state from the registry. function setDeviceConfig (client, deviceId, registryId, projectId, cloudRegion, data, version) { @@ -656,6 +684,80 @@ function getClient (serviceAccountJson, cb) { }); } +// Retrieves the IAM policy for a given registry. +function getIamPolicy (client, registryId, projectId, cloudRegion) { + // [START iot_get_iam_policy] + // Client retrieved in callback + // getClient(serviceAccountJson, function(client) {...}); + // const cloudRegion = 'us-central1'; + // const projectId = 'adjective-noun-123'; + // const registryId = 'my-registry'; + const parentName = `projects/${projectId}/locations/${cloudRegion}`; + const registryName = `${parentName}/registries/${registryId}`; + const request = { + 'resource_': `${registryName}` + }; + + client.projects.locations.registries.getIamPolicy(request, (err, data) => { + if (err) { + console.log('Could not find policy for: ', registryId); + console.log('Trace: ', err); + } else { + console.log(`ETAG: ${data.etag}`); + data.bindings = data.bindings || []; + data.bindings.forEach((_binding) => { + console.log(`Role: ${_binding.role}`); + _binding.members || (_binding.members = []); + _binding.members.forEach((_member) => { + console.log(`\t${_member}`); + }); + }); + } + }); + // [END iot_get_iam_policy] +} + +// Sets the IAM permissions for a given registry to a single member / role. +function setIamPolicy (client, registryId, projectId, cloudRegion, member, + role) { + // [START iot_set_iam_policy] + // Client retrieved in callback + // setClient(serviceAccountJson, function(client) {...}); + // const cloudRegion = 'us-central1'; + // const projectId = 'adjective-noun-123'; + // const registryId = 'my-registry'; + const parentName = `projects/${projectId}/locations/${cloudRegion}`; + const registryName = `${parentName}/registries/${registryId}`; + const request = { + 'resource_': `${registryName}`, + 'resource': {'policy': { + 'bindings': [{ + 'members': member, + 'role': role + }] + }} + }; + + client.projects.locations.registries.setIamPolicy(request, (err, data) => { + if (err) { + console.log('Could not set policy for: ', registryId); + console.log('Trace: ', err); + } else { + console.log(`ETAG: ${data.etag}`); + console.log(JSON.stringify(data)); + data.bindings = data.bindings || []; + data.bindings.forEach((_binding) => { + console.log(`Role: ${_binding.role}`); + _binding.members || (_binding.members = []); + _binding.members.forEach((_member) => { + console.log(`\t${_member}`); + }); + }); + } + }); + // [END iot_set_iam_policy] +} + require(`yargs`) // eslint-disable-line .demand(1) .options({ @@ -788,6 +890,18 @@ require(`yargs`) // eslint-disable-line getClient(opts.serviceAccount, cb); } ) + .command( + `getDeviceConfigs `, + `Retrieves device configurations given a device ID.`, + {}, + (opts) => { + const cb = function (client) { + getDeviceConfigs(client, opts.deviceId, opts.registryId, opts.projectId, + opts.cloudRegion); + }; + getClient(opts.serviceAccount, cb); + } + ) .command( `getDeviceState `, `Retrieves device state given a device ID.`, @@ -870,6 +984,30 @@ require(`yargs`) // eslint-disable-line getClient(opts.serviceAccount, cb); } ) + .command( + `getIamPolicy `, + `Gets the IAM permissions for a given registry`, + {}, + (opts) => { + const cb = function (client) { + getIamPolicy(client, opts.registryId, opts.projectId, + opts.cloudRegion); + }; + getClient(opts.serviceAccount, cb); + } + ) + .command( + `setIamPolicy `, + `Gets the IAM permissions for a given registry`, + {}, + (opts) => { + const cb = function (client) { + setIamPolicy(client, opts.registryId, opts.projectId, + opts.cloudRegion, opts.member, opts.role); + }; + getClient(opts.serviceAccount, cb); + } + ) .example(`node $0 createEs256Device my-es-device my-registry ../ec_public.pem`) .example(`node $0 createRegistry my-registry my-iot-topic --serviceAccount=$HOME/creds_iot.json --project_id=my-project-id`) .example(`node $0 createRsa256Device my-rsa-device my-registry ../rsa_cert.pem`) @@ -878,12 +1016,14 @@ require(`yargs`) // eslint-disable-line .example(`node $0 deleteRegistry my-device my-registry`) .example(`node $0 getDevice my-device my-registry`) .example(`node $0 getDeviceState my-device my-registry`) + .example(`node $0 getIamPolicy my-registry`) .example(`node $0 getRegistry my-registry`) .example(`node $0 listDevices my-node-registry`) .example(`node $0 listRegistries`) .example(`node $0 patchRsa256 my-device my-registry ../rsa_cert.pem`) .example(`node $0 patchEs256 my-device my-registry ../ec_public.pem`) .example(`node $0 setConfig my-device my-registry "test" 0`) + .example(`node $0 setIamPolicy my-registry user:example@example.com roles/viewer`) .example(`node $0 setupTopic my-iot-topic --serviceAccount=$HOME/creds_iot.json --projectId=my-project-id`) .wrap(120) .recommendCommands() diff --git a/iot/manager/system-test/manager.test.js b/iot/manager/system-test/manager.test.js index e797d24992..78aaa31c70 100644 --- a/iot/manager/system-test/manager.test.js +++ b/iot/manager/system-test/manager.test.js @@ -61,6 +61,24 @@ test(`should create and delete an unauthorized device`, async (t) => { output = await tools.runAsync(`${cmd} deleteRegistry ${localRegName}`, cwd); }); +test(`should list configs for a device`, async (t) => { + const localDevice = `test-device-configs`; + const localRegName = `${registryName}-unauth`; + let output = await tools.runAsync(`${cmd} setupIotTopic ${topicName}`, cwd); + output = await tools.runAsync( + `${cmd} createRegistry ${localRegName} ${topicName}`, cwd); + output = await tools.runAsync( + `${cmd} createUnauthDevice ${localDevice} ${localRegName}`, cwd); + t.regex(output, new RegExp(`Created device`)); + output = await tools.runAsync( + `${cmd} getDeviceConfigs ${localDevice} ${localRegName}`, cwd); + t.regex(output, new RegExp(`Configs`)); + output = await tools.runAsync( + `${cmd} deleteDevice ${localDevice} ${localRegName}`, cwd); + t.regex(output, new RegExp(`Successfully deleted device`)); + output = await tools.runAsync(`${cmd} deleteRegistry ${localRegName}`, cwd); +}); + test(`should create and delete an RSA256 device`, async (t) => { const localDevice = `test-rsa-device`; const localRegName = `${registryName}-rsa256`; @@ -170,6 +188,21 @@ test(`should create and get a device`, async (t) => { output = await tools.runAsync(`${cmd} deleteRegistry ${localRegName}`, cwd); }); +test(`should create and get an iam policy`, async (t) => { + const localMember = `group:dpebot@google.com`; + const localRole = `roles/viewer`; + const localRegName = `${registryName}-get`; + let output = await tools.runAsync(`${cmd} setupIotTopic ${topicName}`, cwd); + output = await tools.runAsync( + `${cmd} createRegistry ${localRegName} ${topicName}`, cwd); + output = await tools.runAsync( + `${cmd} setIamPolicy ${localRegName} ${localMember} ${localRole}`, cwd); + t.regex(output, new RegExp(`ETAG`)); + output = await tools.runAsync(`${cmd} getIamPolicy ${localRegName}`, cwd); + t.regex(output, new RegExp(`dpebot`)); + output = await tools.runAsync(`${cmd} deleteRegistry ${localRegName}`, cwd); +}); + test(`should create and delete a registry`, async (t) => { let output = await tools.runAsync(`${cmd} setupIotTopic ${topicName}`, cwd); output = await tools.runAsync(