0
votes

enter image description hereHello want to ask how to add device in google cloud registry using google cloud iot core with C#

i've tried the following code which is given on google console for adding device to registry but getting error of "Google.Apis.Requests.Request Error The caller does not have permission [403]"

public static CloudIotService CreateAuthorizedClient()
{
    

GoogleCredential credential =
            GoogleCredential.GetApplicationDefaultAsync().Result;
        // Inject the Cloud IoT Core Service scope
        if (credential.IsCreateScopedRequired)
        {
            credential = credential.CreateScoped(new[]
            {
                CloudIotService.Scope.CloudPlatform // Used for IoT + PubSub + IAM
                //CloudIotService.Scope.Cloudiot // Can be used if not accessing Pub/Sub
            });
        }
        return new CloudIotService(new BaseClientService.Initializer
        {
            HttpClientInitializer = credential,
            GZipEnabled = false
        });
    }

public static object CreateRsaDevice(string projectId, string cloudRegion, string registryId, string deviceId, string keyPath)
    {
        keyPath = @"E:\Downloads\thermostat-289211-bb93742bc12f.json";
        projectId= "thermostat - 289211";
        cloudRegion = "us-central1";
        registryId = "testregistry";
        deviceId = "C418B9962BC91";
        var cloudIot = CreateAuthorizedClient();
        var parent = $"projects/{projectId}/locations/{cloudRegion}/registries/{registryId}";

        try
        {
            //var credentials = GoogleCredential.FromFile(keyPath);
            //String keyText = File.ReadAllText(keyPath);
            Device body = new Device()
            {
                Id = deviceId
            };
            body.Credentials = new List<DeviceCredential>();
            body.Credentials.Add(new DeviceCredential()
            {
                PublicKey = new PublicKeyCredential()
                {
                    Key = "here i am entering my public key",
                    Format = "RSA_X509_PEM"
                },
            });

            var device = cloudIot.Projects.Locations.Registries.Devices.Create(body, parent).Execute();
            Console.WriteLine("Device created: ");
            Console.WriteLine($"{device.Id}");
            Console.WriteLine($"\tBlocked: {device.Blocked == true}");
            Console.WriteLine($"\tConfig version: {device.Config.Version}");
            Console.WriteLine($"\tName: {device.Name}");
            Console.WriteLine($"\tState:{device.State}");
        }
        catch (Google.GoogleApiException e)
        {
            Console.WriteLine(e.Message);
            if (e.Error != null) return e.Error.Code;
            return -1;
        }
        return 0;
    }

attaching picture of roles on I am admin page highlighted with yellow is the current account i am using

1
Edit your question and show the IAM roles assigned to the service account. - John Hanley
Here is the doc shows you how to create a registry that you can then add devices to. - Mahboob
The current user might not have access to perform the requested action as described in the document, then confirm that the Service Account, has the permissions to perform that action. - Elba Lazo
I've given all the access of device control to my id also to service account but still not allowing me to add device however registries are creating successfully - Hafiz umer
Confirm that the IOT API is enabled on your project, following the instructions here support.google.com/googleapi/answer/6158841?hl=en, then generate applications credentials here:pantheon.corp.google.com/projectselector2/identity/…, and pass them as environment variables - Elba Lazo

1 Answers

1
votes

See: https://cloud.google.com/iot/docs/samples/device-manager-samples#iot-core-create-rs256-csharp

QUESTION="65413853"
PROJECT="dazwilkin-$(date +%y%m%d)-${QUESTION}"
REGION="us-central1"
REGISTRY="test"

BILLING=$(\
  gcloud alpha billing accounts list \
  --format="value(name)")

gcloud projects create ${PROJECT}
gcloud beta billing projects link ${PROJECT} \
--billing-account=${BILLING}

# Enable Cloud IOT
gcloud services enable cloudiot.googleapis.com \
--project=${PROJECT}

# Create Registry
gcloud iot registries create ${REGISTRY} \
--region=${REGION} \
--project=${PROJECT}

# Create Service Account with permissions for IoT
ROBOT="dellian"
EMAIL="${ROBOT}@${PROJECT}.iam.gserviceaccount.com"

gcloud iam service-accounts create ${ROBOT} \
--project=${PROJECT}

gcloud iam service-accounts keys create ./${ROBOT}.json \
--iam-account=${EMAIL}

gcloud projects add-iam-policy-binding ${PROJECT} \
--member=serviceAccount:${EMAIL} \
--role=roles/cloudiot.provisioner

# Create RSA key
openssl req -x509 -nodes \
-newkey rsa:2048 \
-keyout rsa_private.pem \
-out rsa_cert.pem \
-subj /CN=cloudiot

docker run \
--interactive --tty \
--env=PROJECT=${PROJECT} \
--env=REGION=${REGION} \
--env=REGISTRY=${REGISTRY} \
--volume=${PWD}/app:/app \
--volume=${PWD}/${ROBOT}.json:/secrets/${ROBOT}.json \
--env=GOOGLE_APPLICATION_CREDENTIALS=/secrets/${ROBOT}.json \
--workdir=/app mcr.microsoft.com/dotnet/sdk:5.0 bash

Then:

With app.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Google.Apis.Auth" Version="1.49.0" />
    <PackageReference Include="Google.Apis.CloudIot.v1" Version="1.49.0.2161" />
  </ItemGroup>

</Project>

and:

using Google.Apis.Auth.OAuth2;
using Google.Apis.CloudIot.v1;
using Google.Apis.CloudIot.v1.Data;
using Google.Apis.Services;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace IoTSample
{
    public class IoTExample
    {
        public static void Main(string[] args){

            string projectId = Environment.GetEnvironmentVariable("PROJECT");
            string region = Environment.GetEnvironmentVariable("REGION");
            string registryId = Environment.GetEnvironmentVariable("REGISTRY");
            string deviceId = Environment.GetEnvironmentVariable("DEVICE");
            string keyPath = Environment.GetEnvironmentVariable("KEY");

            GoogleCredential credential = GoogleCredential.GetApplicationDefaultAsync().Result;
            if (credential.IsCreateScopedRequired) {
                credential = credential.CreateScoped(new[]{
                    CloudIotService.Scope.CloudPlatform // Used for IoT + PubSub + IAM
                    //CloudIotService.Scope.Cloudiot // Can be used if not accessing Pub/Sub
                });
            }
            CloudIotService service = new CloudIotService(new BaseClientService.Initializer{
                HttpClientInitializer = credential,
                GZipEnabled = false
            });

            var parent = $"projects/{projectId}/locations/{region}/registries/{registryId}";
            var keyText = File.ReadAllText(keyPath);

            try
            {
                Device body = new Device()
                {
                    Id = deviceId
                };
                body.Credentials = new List<DeviceCredential>();
                body.Credentials.Add(new DeviceCredential()
                {
                    PublicKey = new PublicKeyCredential()
                    {
                        Key = keyText,
                        Format = "RSA_X509_PEM"
                    },
                });

                var device = service.Projects.Locations.Registries.Devices.Create(body, parent).Execute();
                Console.WriteLine("Device created: ");
                Console.WriteLine($"{device.Id}");
                Console.WriteLine($"\tBlocked: {device.Blocked == true}");
                Console.WriteLine($"\tConfig version: {device.Config.Version}");
                Console.WriteLine($"\tName: {device.Name}");
                Console.WriteLine($"\tState:{device.State}");
            }
            catch (Google.GoogleApiException e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}

Your Cloud IoT registry (in this case test) must exist in the project.

See: https://cloud.google.com/iot/docs/how-tos/credentials/keys#generating_an_rsa_key_with_a_self-signed_x509_certificate

export DEVICE="device-01"
export KEY="rsa_cert.pem"

dotnet run

Yields:

Device created: 
test
    Blocked: False
    Config version: 1
    Name: projects/.../devices/2553842783141685
    State:

and:

gcloud iot devices list \
--registry=test \
--region=us-central1 \
--project=${PROJECT}

ID     NUM_ID            BLOCKED
test   2553842783141685

Update 2020-12-31

You may also create a device using the command-line. This would be a useful test to ensure that you've configured everything correctly:

DEVICE="test-02"
KEY="${PWD}/app/rsa_cert.pem"

gcloud iot devices create ${DEVICE} \
--registry=${REGISTRY} \
--public-key=path=${KEY},type=RSA-X509-PEM \
--region=${REGION} \
--project=${PROJECT}

Should yield:

Created device [${DEVICE}].