2017-12-18 3 views
0

Ich versuche einen Backend-NodeJS-Server für den Zugriff (und Bearbeitung) der Gerätekonfiguration auf IoT-Core zu verwenden, siehe API-Dokumentation: https://cloud.google.com/iot/docs/reference/rest/v1/projects.locations.registries.devices/get.Authentifizierungsfehler beim Abrufen und Bearbeiten der Gerätekonfiguration auf dem IoT-Core

Aber ich erhalte immer Fehlercode 401 mit der Fehlermeldung "message": "Request ungültig Authentifizierungsinformationen hatte Expected OAuth 2 Zugriffstoken, Login-Cookie oder anderen gültigen Authentifizierungsnachweis https://developers.google.com/identity/sign-in/web/devconsole-project See...", "Status": "UNBEABSICHTIGT".

Ich erstellte ein Dienstkonto und einen Schlüssel von Google IAM und gab ihm Cloud IoT Device Controller-Berechtigungen, die Gerätekonfigurationen aktualisieren, aber nicht erstellen oder löschen können. Anschließend änderte ich es zu Cloud IoT Admin und sogar Project Editor Berechtigungen, sah aber immer noch die gleiche Fehlermeldung. Bekomme ich die Schlüssel falsch oder mache ich nicht etwas anderes, was ich tun sollte?

-Code unten war, wie ich die Anfrage aufgerufen

function createJwt (projectId, privateKeyFile, algorithm) { 
    // Create a JWT to authenticate this device. The device will be disconnected 
    // after the token expires, and will have to reconnect with a new token. The 
    // audience field should always be set to the GCP project ID. 
    const token = { 
     'iat': parseInt(Date.now()/1000), 
     'exp': parseInt(Date.now()/1000) + 20 * 60, // 20 minutes 
     'aud': projectId 
    }; 
    const privateKey = fs.readFileSync(privateKeyFile); 
    return jwt.sign(token, privateKey, { algorithm: algorithm }); 
} 

app.get('/', function(req, res){ 

    let authToken = createJwt('test-project', './keys/device-config.pem', 'RS256'); 

    const options = { 
     url: 'https://cloudiot.googleapis.com/v1/projects/test-project/locations/us-central1/registries/dev-registry/devices/test-device', 
     headers: { 
      'authorization': 'Bearer ' + authToken, 
      'content-type': 'application/json', 
      'cache-control': 'no-cache' 
     }, 
     json: true 
    } 

    request.get(options, function(error, response){ 
     if(error) res.json(error); 
     else res.json(response); 
    }) 

}); 

Antwort

1

Damit Backend-Server mit IoT-Core interagieren können, ist die Authentifizierungsmethode nicht mit der für MQTT- oder HTTP-Verbindungen des Geräts identisch. Referenz: https://cloud.google.com/iot/docs/samples/device-manager-samples#get_a_device

konnte ich den Code unten

function getClient (serviceAccountJson, cb) { 
    const serviceAccount = JSON.parse(fs.readFileSync(serviceAccountJson)); 
    const jwtAccess = new google.auth.JWT(); 
    jwtAccess.fromJSON(serviceAccount); 
    // Note that if you require additional scopes, they should be specified as a 
    // string, separated by spaces. 
    jwtAccess.scopes = 'https://www.googleapis.com/auth/cloud-platform'; 
    // Set the default authentication to the above JWT access. 
    google.options({ auth: jwtAccess }); 

    const DISCOVERY_API = 'https://cloudiot.googleapis.com/$discovery/rest'; 
    const API_VERSION = 'v1'; 
    const discoveryUrl = `${DISCOVERY_API}?version=${API_VERSION}`; 

    google.discoverAPI(discoveryUrl, {}, (err, client) => { 
     if (err) { 
     console.log('Error during API discovery', err); 
     return undefined; 
     } 
     cb(client); 
    }); 
} 

function getDevice (client, deviceId, registryId, projectId, cloudRegion) { 
    const parentName = `projects/${process.env.GCP_PROJECT_ID}/locations/${cloudRegion}`; 
    const registryName = `${parentName}/registries/${registryId}`; 
    const request = { 
     name: `${registryName}/devices/${deviceId}` 
    }; 

    const promise = new Promise(function(resolve, reject){ 
     client.projects.locations.registries.devices.get(request, (err, data) => { 
      if (err) { 
       console.log('Could not find device:', deviceId); 
       console.log(err); 
       reject(err); 
      } else { 
       console.log(data.config.binaryData); 
       resolve(data); 
      } 
     }); 

    }); 
    return promise; 
} 

app.get('/', function(req, res){ 
    const cb = function(client){ 
     getDevice(client, 'test-device', 'dev-registry', process.env.GCP_PROJECT_ID, 'us-central1') 
      .then(function(response){ 
       let decoded = new Buffer(response.config.binaryData, 'base64').toString(); 
       res.json(decoded); 
      }) 
      .catch(function(error){ 
       res.json(error); 
      }) 
    } 
    getClient(serviceAccountJson, cb); 

}); 
+0

Korrigieren. Entschuldigung, aus der Beschreibung Ihrer Frage ging ich davon aus, dass Sie versucht haben, ein Gerät mit dem IoT Core zu verbinden und vom Gerät aus zu kommunizieren. Nicht, dass Sie das Gerät ändern wollten (ich weiß, dass Sie modify config sagten, aber dann kam der Code von den clientseitigen oder Geräteverbindungs-Samples), also habe ich erraten, was Sie meinten. :) Tut mir leid, dass ich dich zum falschen gelenkt habe! – GabeWeiss

0

nur um zu bestätigen, wenn Sie die SSL-Schlüsselpaar erstellt haben, und wenn Sie das Gerät mit der Cloud IoT-Core-Registrierung registriert, ergab die Art des Taste, die mit dem Radioknopf erstellt wurde, mit dem Sie sie registriert haben?

Auch, um zu bestätigen, legen Sie das Google-Stammzertifikat auf dem Gerät in demselben Verzeichnis wie der private Schlüssel: ./keys/device-config.pem? Wenn nicht, können Sie es holen mit: wget https://pki.google.com/roots.pem.

+0

Hmm ..Okay, also habe ich das versucht, als habe ich ein neues Gerät mit den ssl-Schlüsselpaaren erstellt, es in die Geräte-Registrierung hochgeladen (das entsprechende RS256_X509-Optionsfeld ausgewählt) und sowohl den privaten als auch den öffentlichen Schlüssel in meinem/keys-Ordner gespeichert zeigte immer noch eine 401 nicht autorisierte Fehlermeldung. Wie auch immer, ich bin mir nicht sicher, ob ich richtig verstehe, aber ich brauchte einen Hauptschlüssel für den Zugriff auf alle meine Geräte, anstatt einzelne Geräteschlüssel für den Zugriff auf die Gerätekonfiguration auf Geräten in meiner Registrierung zu verwenden. Ich dachte, der richtige Weg wäre, einen Schlüssel in Google IAM einzurichten, nein? – jlyh

+0

Ich habe auch die roots.pem im gleichen/Schlüssel-Ordner, aber es schien nicht zu helfen .. – jlyh

+0

Ich habe auch versucht, ein Dienstkonto nach den Anweisungen in https://cloud.google.com/docs zu erstellen/authentication/getting-started # creating_a_service_account, aber es hat auch nicht geholfen. – jlyh

1

denken abzurufen und zu aktualisieren Gerätekonfigurationen ich mit, was Sie suchen die Client-Bibliothek für NodeJS tun wird am besten erreicht werden.

Rufen Sie zuerst ein API-Clientobjekt als done in the sample ab. Dadurch werden die Anmeldeinformationen für das Dienstkonto übernommen, die Sie verwendet haben, und die Authentifizierung erfolgt für Google API Core-Server.

An der Stelle im referenzierten Code, an der cb(client); aufgerufen wird, haben Sie Ihr Client-Objekt und sind bereit, Ihr Gerät zu aktualisieren. Fügen Sie die Import- und API-Konstanten aus dem Beispiel hinzu und ersetzen Sie den Code, in dem Sie ein Clientobjekt mit dem folgenden Code haben, und Sie sollten festgelegt werden.

verwenden einige Zeichenfolgen für Ihre Gerätekennungen:

const projectId = 'my-project'; 
const cloudRegion = 'us-central1'; 
const registryId = 'my-registry'; 
const deviceId = 'my-device; 
const config = '{fan: 800}'; 

Als nächstes Ihr Gerät String bilden:

const deviceId = `projects/${projectId}/locations/${cloudRegion}/registries/${registryId}/devices/${deviceId}`; 
const binaryData = Buffer.from(config).toString('base64'); 

Sie jetzt Ihre Anfrage Objekt bilden und auszuführen:

const request = { 
    name: `${registryName}`, 
    versionToUpdate: 0, 
    binaryData: binaryData 
}; 
console.log(request); 

client.projects.locations.registries.devices 
    .modifyCloudToDeviceConfig(
    request, 
    (err, data) => { 
     if (err) { 
     console.log('Could not update config:', deviceId); 
     console.log('Message: ', err); 
     } else { 
     console.log('Success :', data); 
     } 
    }); 

Ihre Die Konfiguration wurde aktualisiert. Wenn Ihr Gerät das Konfigurationsthema in MQTT abonniert hat, erhält es die neueste Konfiguration, andernfalls können Sie die Konfiguration mit HTTP von Ihrem Gerät abrufen.

Verwandte Themen