I'm using Golang to send messages to Azure IoT Hub and as we may or may not know, Azure does not have an SDK for Golang.
I've found answers on how to do it throughout the REST API using the SAS token
I Found REST API for Azure IoT Hub using the SAS token in SO
code from SO:
func main() {
sasToken :="SharedAccessSignature sr=<your IoT Hub name>.azure-devices.net/devices/<your device ID>&sig=<your signature>&se=<expiry time>&skn=<policy name>"
deviceID := "sampath671"
iotHubName := "certificate122ravi"
url := fmt.Sprintf("https://%s.azure-devices.net/devices/%s?api-version=2020-05-31-preview", iotHubName, deviceID)
requestBody := map[string]interface{}{
"deviceId": deviceID,
"status": "disabled",
"statusReason": "Device disabled for maintenance",
"connectionState": "Disconnected",
"lastActivityTime": "2024-03-12T12:00:00Z",
"cloudToDeviceMessageCount": 10,
}
requestBodyBytes, err := json.Marshal(requestBody)
if err != nil {
log.Fatal(err)
}
req, err := http.NewRequest("PUT", url, bytes.NewBuffer(requestBodyBytes))
if err != nil {
log.Fatal(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", sasToken)
currentETag, err := getCurrentETag(deviceID, sasToken, iotHubName)
if err != nil {
log.Fatal(err)
}
but I can't find anything on using certification for Azure IoT Hub, my Azure IoT Hub device has an x509 authentication need So can someone help me out with Azure IoT Hub device having an x509 authentication?
Thanks in advance.
Even for creating an X.509 Self-Signed device in Azure IoT Hub the Authorization used is SAS token. The REST APIs for IoT Hub services used for device messaging, device management, and job scheduling. They use the Authorization
header as a Shared Access Signature (SAS) token from this document. Thus, the Send Device Event / Send a device-to-cloud message REST API uses a SAS token. We can send messages to an X.509 Self-Signed device using a SAS token only.
The code below in go is for creating an IoT device in Azure IoT Hub with authentication type X.509 Self-Signed:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type DeviceAuthentication struct {
Type string `json:"type"`
X509Thumbprint X509Thumbprint `json:"x509Thumbprint"`
}
type X509Thumbprint struct {
PrimaryThumbprint string `json:"primaryThumbprint"`
SecondaryThumbprint string `json:"secondaryThumbprint"`
}
type DeviceCapabilities struct {
IotEdge bool `json:"iotEdge"`
}
type Device struct {
Authentication DeviceAuthentication `json:"authentication"`
Capabilities DeviceCapabilities `json:"capabilities"`
CloudToDeviceMessageCount int `json:"cloudToDeviceMessageCount"`
ConnectionState string `json:"connectionState"`
ConnectionStateUpdated string `json:"connectionStateUpdatedTime"`
DeviceId string `json:"deviceId"`
DeviceScope string `json:"deviceScope"`
Etag string `json:"etag"`
GenerationId string `json:"generationId"`
LastActivityTime string `json:"lastActivityTime"`
Status string `json:"status"`
StatusReason string `json:"statusReason"`
StatusUpdatedTime string `json:"statusUpdatedTime"`
}
func main() {
sasToken := "SharedAccessSignature sr=<your IoT Hub name>.azure-devices.net/devices/<your device ID>&sig=<your signature>&se=<expiry time>&skn=<policy name>"
deviceID := "sampleDevice"
iotHubName := "your-iot-hub-name"
url := fmt.Sprintf("https://%s.azure-devices.net/devices/%s?api-version=2020-05-31-preview", iotHubName, deviceID)
requestBody := Device{
Authentication: DeviceAuthentication{
Type: "selfSigned",
X509Thumbprint: X509Thumbprint{
PrimaryThumbprint: "YOUR_PRIMARY_THUMBPRINT",
SecondaryThumbprint: "YOUR_SECONDARY_THUMBPRINT",
},
},
Capabilities: DeviceCapabilities{IotEdge: false},
CloudToDeviceMessageCount: 0,
ConnectionState: "Disconnected",
ConnectionStateUpdated: "2024-04-04T00:00:00Z",
DeviceId: deviceID,
DeviceScope: "",
Etag: "",
GenerationId: "",
LastActivityTime: "2024-04-04T00:00:00Z",
Status: "enabled",
StatusReason: "",
StatusUpdatedTime: "2024-04-04T00:00:00Z",
}
requestBodyBytes, err := json.Marshal(requestBody)
if err != nil {
log.Fatal(err)
}
req, err := http.NewRequest("PUT", url, bytes.NewBuffer(requestBodyBytes))
if err != nil {
log.Fatal(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", sasToken)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
responseBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
if resp.StatusCode != http.StatusOK {
log.Fatalf("Failed to create/update device: %s", responseBody)
}
fmt.Println("Device created/updated successfully!")
fmt.Println("Response Body:", string(responseBody))
}
The code below sends a device-to-cloud message to a device using X.509/SAS authentication through the REST API:
package main
import (
"bytes"
"fmt"
"log"
"net/http"
)
func main() {
// Replace these variables with your actual values
iotHubName := "your-iot-hub-name"
deviceID := "your-device-id"
sasToken := "SharedAccessSignature sr=<your IoT Hub name>.azure-devices.net&sig=<your signature>&se=<expiry time>&skn=<policy name>"
// Message payload
message := []byte(`{"data":"Hello from your device!"}`)
// Construct the URL
url := fmt.Sprintf("https://%s.azure-devices.net/devices/%s/messages/events?api-version=2020-03-13", iotHubName, deviceID)
// Create a POST request with the message payload
req, err := http.NewRequest("POST", url, bytes.NewBuffer(message))
if err != nil {
log.Fatal(err)
}
// Set the required headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", sasToken)
// Send the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// Check the response status
if resp.StatusCode == http.StatusNoContent {
fmt.Println("Message sent successfully!")
} else {
fmt.Printf("Failed to send message. Status code: %d\n", resp.StatusCode)
}
}
To check message is sent use the Azure CLI to monitor events from an Azure IoT Hub for a specific device
az iot hub monitor-events --hub-name HubName --device-id deviceidname