The azure-native:deviceregistry:NamespaceDevice resource, part of the Pulumi Azure Native provider, defines a device within a Device Registry namespace: its connectivity endpoints, authentication methods, and edge placement. This guide focuses on three capabilities: OPC UA inbound endpoint configuration, authentication methods (username/password, anonymous, X.509), and outbound Event Grid messaging.
Devices depend on an existing namespace, a CustomLocation for edge deployment, and secret storage for credentials. The examples are intentionally small. Combine them with your own namespace, CustomLocation, and secret management infrastructure.
Connect to OPC UA servers with username and password
Industrial IoT deployments often connect to OPC UA servers on factory equipment using username and password authentication when certificate infrastructure isn’t available.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const namespaceDevice = new azure_native.deviceregistry.NamespaceDevice("namespaceDevice", {
attributes: {
deviceCategory: 16,
deviceOwner: "IT",
deviceType: "sensor",
},
deviceName: "namespace-device-on-edge",
enabled: true,
endpoints: {
inbound: {
theOnlyOPCUABroker: {
address: "opc.tcp://192.168.86.23:51211/UA/SampleServer",
authentication: {
method: azure_native.deviceregistry.AuthenticationMethod.UsernamePassword,
usernamePasswordCredentials: {
passwordSecretName: "pwd-ref",
usernameSecretName: "user-ref",
},
},
endpointType: "microsoft.opcua/v1",
version: "2",
},
},
},
extendedLocation: {
name: "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1",
type: "CustomLocation",
},
externalDeviceId: "unique-edge-device-identifier",
location: "West Europe",
namespaceName: "adr-namespace-gbk0925-n01",
resourceGroupName: "myResourceGroup",
});
import pulumi
import pulumi_azure_native as azure_native
namespace_device = azure_native.deviceregistry.NamespaceDevice("namespaceDevice",
attributes={
"deviceCategory": 16,
"deviceOwner": "IT",
"deviceType": "sensor",
},
device_name="namespace-device-on-edge",
enabled=True,
endpoints={
"inbound": {
"theOnlyOPCUABroker": {
"address": "opc.tcp://192.168.86.23:51211/UA/SampleServer",
"authentication": {
"method": azure_native.deviceregistry.AuthenticationMethod.USERNAME_PASSWORD,
"username_password_credentials": {
"password_secret_name": "pwd-ref",
"username_secret_name": "user-ref",
},
},
"endpoint_type": "microsoft.opcua/v1",
"version": "2",
},
},
},
extended_location={
"name": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1",
"type": "CustomLocation",
},
external_device_id="unique-edge-device-identifier",
location="West Europe",
namespace_name="adr-namespace-gbk0925-n01",
resource_group_name="myResourceGroup")
package main
import (
deviceregistry "github.com/pulumi/pulumi-azure-native-sdk/deviceregistry/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := deviceregistry.NewNamespaceDevice(ctx, "namespaceDevice", &deviceregistry.NamespaceDeviceArgs{
Attributes: pulumi.Any(map[string]interface{}{
"deviceCategory": 16,
"deviceOwner": "IT",
"deviceType": "sensor",
}),
DeviceName: pulumi.String("namespace-device-on-edge"),
Enabled: pulumi.Bool(true),
Endpoints: &deviceregistry.MessagingEndpointsArgs{
Inbound: deviceregistry.InboundEndpointsMap{
"theOnlyOPCUABroker": &deviceregistry.InboundEndpointsArgs{
Address: pulumi.String("opc.tcp://192.168.86.23:51211/UA/SampleServer"),
Authentication: &deviceregistry.HostAuthenticationArgs{
Method: pulumi.String(deviceregistry.AuthenticationMethodUsernamePassword),
UsernamePasswordCredentials: &deviceregistry.UsernamePasswordCredentialsArgs{
PasswordSecretName: pulumi.String("pwd-ref"),
UsernameSecretName: pulumi.String("user-ref"),
},
},
EndpointType: pulumi.String("microsoft.opcua/v1"),
Version: pulumi.String("2"),
},
},
},
ExtendedLocation: &deviceregistry.ExtendedLocationArgs{
Name: pulumi.String("/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1"),
Type: pulumi.String("CustomLocation"),
},
ExternalDeviceId: pulumi.String("unique-edge-device-identifier"),
Location: pulumi.String("West Europe"),
NamespaceName: pulumi.String("adr-namespace-gbk0925-n01"),
ResourceGroupName: pulumi.String("myResourceGroup"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var namespaceDevice = new AzureNative.DeviceRegistry.NamespaceDevice("namespaceDevice", new()
{
Attributes = new Dictionary<string, object?>
{
["deviceCategory"] = 16,
["deviceOwner"] = "IT",
["deviceType"] = "sensor",
},
DeviceName = "namespace-device-on-edge",
Enabled = true,
Endpoints = new AzureNative.DeviceRegistry.Inputs.MessagingEndpointsArgs
{
Inbound =
{
{ "theOnlyOPCUABroker", new AzureNative.DeviceRegistry.Inputs.InboundEndpointsArgs
{
Address = "opc.tcp://192.168.86.23:51211/UA/SampleServer",
Authentication = new AzureNative.DeviceRegistry.Inputs.HostAuthenticationArgs
{
Method = AzureNative.DeviceRegistry.AuthenticationMethod.UsernamePassword,
UsernamePasswordCredentials = new AzureNative.DeviceRegistry.Inputs.UsernamePasswordCredentialsArgs
{
PasswordSecretName = "pwd-ref",
UsernameSecretName = "user-ref",
},
},
EndpointType = "microsoft.opcua/v1",
Version = "2",
} },
},
},
ExtendedLocation = new AzureNative.DeviceRegistry.Inputs.ExtendedLocationArgs
{
Name = "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1",
Type = "CustomLocation",
},
ExternalDeviceId = "unique-edge-device-identifier",
Location = "West Europe",
NamespaceName = "adr-namespace-gbk0925-n01",
ResourceGroupName = "myResourceGroup",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.deviceregistry.NamespaceDevice;
import com.pulumi.azurenative.deviceregistry.NamespaceDeviceArgs;
import com.pulumi.azurenative.deviceregistry.inputs.MessagingEndpointsArgs;
import com.pulumi.azurenative.deviceregistry.inputs.ExtendedLocationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var namespaceDevice = new NamespaceDevice("namespaceDevice", NamespaceDeviceArgs.builder()
.attributes(Map.ofEntries(
Map.entry("deviceCategory", 16),
Map.entry("deviceOwner", "IT"),
Map.entry("deviceType", "sensor")
))
.deviceName("namespace-device-on-edge")
.enabled(true)
.endpoints(MessagingEndpointsArgs.builder()
.inbound(Map.of("theOnlyOPCUABroker", InboundEndpointsArgs.builder()
.address("opc.tcp://192.168.86.23:51211/UA/SampleServer")
.authentication(HostAuthenticationArgs.builder()
.method("UsernamePassword")
.usernamePasswordCredentials(UsernamePasswordCredentialsArgs.builder()
.passwordSecretName("pwd-ref")
.usernameSecretName("user-ref")
.build())
.build())
.endpointType("microsoft.opcua/v1")
.version("2")
.build()))
.build())
.extendedLocation(ExtendedLocationArgs.builder()
.name("/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1")
.type("CustomLocation")
.build())
.externalDeviceId("unique-edge-device-identifier")
.location("West Europe")
.namespaceName("adr-namespace-gbk0925-n01")
.resourceGroupName("myResourceGroup")
.build());
}
}
resources:
namespaceDevice:
type: azure-native:deviceregistry:NamespaceDevice
properties:
attributes:
deviceCategory: 16
deviceOwner: IT
deviceType: sensor
deviceName: namespace-device-on-edge
enabled: true
endpoints:
inbound:
theOnlyOPCUABroker:
address: opc.tcp://192.168.86.23:51211/UA/SampleServer
authentication:
method: UsernamePassword
usernamePasswordCredentials:
passwordSecretName: pwd-ref
usernameSecretName: user-ref
endpointType: microsoft.opcua/v1
version: '2'
extendedLocation:
name: /subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1
type: CustomLocation
externalDeviceId: unique-edge-device-identifier
location: West Europe
namespaceName: adr-namespace-gbk0925-n01
resourceGroupName: myResourceGroup
The endpoints.inbound map defines named connections to OPC UA servers. Each endpoint specifies an address (the OPC UA server URL), an endpointType (“microsoft.opcua/v1”), and authentication details. The usernamePasswordCredentials property references secret names stored in the CustomLocation’s secret store. The extendedLocation property places the device on an Azure Arc-enabled edge location where it can reach the OPC UA server.
Connect to OPC UA servers without authentication
Development environments sometimes expose OPC UA servers that allow anonymous connections.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const namespaceDevice = new azure_native.deviceregistry.NamespaceDevice("namespaceDevice", {
attributes: {
deviceCategory: 16,
deviceOwner: "OT",
deviceType: "dough-maker",
},
deviceName: "namespace-device-on-edge",
enabled: true,
endpoints: {
inbound: {
theOnlyOPCUABroker: {
address: "opc.tcp://192.168.86.23:51211/UA/SampleServer",
authentication: {
method: azure_native.deviceregistry.AuthenticationMethod.Anonymous,
},
endpointType: "microsoft.opcua/v1",
version: "2",
},
},
},
extendedLocation: {
name: "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1",
type: "CustomLocation",
},
externalDeviceId: "unique-edge-device-identifier",
location: "West Europe",
namespaceName: "adr-namespace-gbk0925-n01",
resourceGroupName: "myResourceGroup",
});
import pulumi
import pulumi_azure_native as azure_native
namespace_device = azure_native.deviceregistry.NamespaceDevice("namespaceDevice",
attributes={
"deviceCategory": 16,
"deviceOwner": "OT",
"deviceType": "dough-maker",
},
device_name="namespace-device-on-edge",
enabled=True,
endpoints={
"inbound": {
"theOnlyOPCUABroker": {
"address": "opc.tcp://192.168.86.23:51211/UA/SampleServer",
"authentication": {
"method": azure_native.deviceregistry.AuthenticationMethod.ANONYMOUS,
},
"endpoint_type": "microsoft.opcua/v1",
"version": "2",
},
},
},
extended_location={
"name": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1",
"type": "CustomLocation",
},
external_device_id="unique-edge-device-identifier",
location="West Europe",
namespace_name="adr-namespace-gbk0925-n01",
resource_group_name="myResourceGroup")
package main
import (
deviceregistry "github.com/pulumi/pulumi-azure-native-sdk/deviceregistry/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := deviceregistry.NewNamespaceDevice(ctx, "namespaceDevice", &deviceregistry.NamespaceDeviceArgs{
Attributes: pulumi.Any(map[string]interface{}{
"deviceCategory": 16,
"deviceOwner": "OT",
"deviceType": "dough-maker",
}),
DeviceName: pulumi.String("namespace-device-on-edge"),
Enabled: pulumi.Bool(true),
Endpoints: &deviceregistry.MessagingEndpointsArgs{
Inbound: deviceregistry.InboundEndpointsMap{
"theOnlyOPCUABroker": &deviceregistry.InboundEndpointsArgs{
Address: pulumi.String("opc.tcp://192.168.86.23:51211/UA/SampleServer"),
Authentication: &deviceregistry.HostAuthenticationArgs{
Method: pulumi.String(deviceregistry.AuthenticationMethodAnonymous),
},
EndpointType: pulumi.String("microsoft.opcua/v1"),
Version: pulumi.String("2"),
},
},
},
ExtendedLocation: &deviceregistry.ExtendedLocationArgs{
Name: pulumi.String("/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1"),
Type: pulumi.String("CustomLocation"),
},
ExternalDeviceId: pulumi.String("unique-edge-device-identifier"),
Location: pulumi.String("West Europe"),
NamespaceName: pulumi.String("adr-namespace-gbk0925-n01"),
ResourceGroupName: pulumi.String("myResourceGroup"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var namespaceDevice = new AzureNative.DeviceRegistry.NamespaceDevice("namespaceDevice", new()
{
Attributes = new Dictionary<string, object?>
{
["deviceCategory"] = 16,
["deviceOwner"] = "OT",
["deviceType"] = "dough-maker",
},
DeviceName = "namespace-device-on-edge",
Enabled = true,
Endpoints = new AzureNative.DeviceRegistry.Inputs.MessagingEndpointsArgs
{
Inbound =
{
{ "theOnlyOPCUABroker", new AzureNative.DeviceRegistry.Inputs.InboundEndpointsArgs
{
Address = "opc.tcp://192.168.86.23:51211/UA/SampleServer",
Authentication = new AzureNative.DeviceRegistry.Inputs.HostAuthenticationArgs
{
Method = AzureNative.DeviceRegistry.AuthenticationMethod.Anonymous,
},
EndpointType = "microsoft.opcua/v1",
Version = "2",
} },
},
},
ExtendedLocation = new AzureNative.DeviceRegistry.Inputs.ExtendedLocationArgs
{
Name = "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1",
Type = "CustomLocation",
},
ExternalDeviceId = "unique-edge-device-identifier",
Location = "West Europe",
NamespaceName = "adr-namespace-gbk0925-n01",
ResourceGroupName = "myResourceGroup",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.deviceregistry.NamespaceDevice;
import com.pulumi.azurenative.deviceregistry.NamespaceDeviceArgs;
import com.pulumi.azurenative.deviceregistry.inputs.MessagingEndpointsArgs;
import com.pulumi.azurenative.deviceregistry.inputs.ExtendedLocationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var namespaceDevice = new NamespaceDevice("namespaceDevice", NamespaceDeviceArgs.builder()
.attributes(Map.ofEntries(
Map.entry("deviceCategory", 16),
Map.entry("deviceOwner", "OT"),
Map.entry("deviceType", "dough-maker")
))
.deviceName("namespace-device-on-edge")
.enabled(true)
.endpoints(MessagingEndpointsArgs.builder()
.inbound(Map.of("theOnlyOPCUABroker", InboundEndpointsArgs.builder()
.address("opc.tcp://192.168.86.23:51211/UA/SampleServer")
.authentication(HostAuthenticationArgs.builder()
.method("Anonymous")
.build())
.endpointType("microsoft.opcua/v1")
.version("2")
.build()))
.build())
.extendedLocation(ExtendedLocationArgs.builder()
.name("/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1")
.type("CustomLocation")
.build())
.externalDeviceId("unique-edge-device-identifier")
.location("West Europe")
.namespaceName("adr-namespace-gbk0925-n01")
.resourceGroupName("myResourceGroup")
.build());
}
}
resources:
namespaceDevice:
type: azure-native:deviceregistry:NamespaceDevice
properties:
attributes:
deviceCategory: 16
deviceOwner: OT
deviceType: dough-maker
deviceName: namespace-device-on-edge
enabled: true
endpoints:
inbound:
theOnlyOPCUABroker:
address: opc.tcp://192.168.86.23:51211/UA/SampleServer
authentication:
method: Anonymous
endpointType: microsoft.opcua/v1
version: '2'
extendedLocation:
name: /subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1
type: CustomLocation
externalDeviceId: unique-edge-device-identifier
location: West Europe
namespaceName: adr-namespace-gbk0925-n01
resourceGroupName: myResourceGroup
Setting authentication.method to Anonymous removes the credential requirement. The device connects to the OPC UA server without presenting username, password, or certificates. This configuration is useful for testing but should not be used in production environments.
Authenticate with X.509 certificates and trust lists
Production OPC UA deployments require certificate-based authentication for secure communication.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const namespaceDevice = new azure_native.deviceregistry.NamespaceDevice("namespaceDevice", {
attributes: {
deviceCategory: 16,
deviceOwner: "OT",
deviceType: "OPCUAServers",
},
deviceName: "namespace-device-on-edge",
enabled: true,
endpoints: {
inbound: {
theV1OPCUAEndpoint: {
address: "opc.tcp://192.168.86.23:51211/UA/SampleServer",
authentication: {
method: azure_native.deviceregistry.AuthenticationMethod.Certificate,
x509Credentials: {
certificateSecretName: "cert-secret",
},
},
endpointType: "microsoft.opcua/v1",
version: "2",
},
theV2OPCUAEndpoint: {
address: "opc.tcp://192.168.86.23:51211/UA/SampleServer",
authentication: {
method: azure_native.deviceregistry.AuthenticationMethod.Certificate,
x509Credentials: {
certificateSecretName: "cert-secret",
},
},
endpointType: "microsoft.opcua/v1",
trustSettings: {
trustList: "trust-secret-reference",
},
version: "2",
},
},
},
extendedLocation: {
name: "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1",
type: "CustomLocation",
},
externalDeviceId: "unique-edge-device-identifier",
location: "West Europe",
namespaceName: "adr-namespace-gbk0925-n01",
resourceGroupName: "myResourceGroup",
});
import pulumi
import pulumi_azure_native as azure_native
namespace_device = azure_native.deviceregistry.NamespaceDevice("namespaceDevice",
attributes={
"deviceCategory": 16,
"deviceOwner": "OT",
"deviceType": "OPCUAServers",
},
device_name="namespace-device-on-edge",
enabled=True,
endpoints={
"inbound": {
"theV1OPCUAEndpoint": {
"address": "opc.tcp://192.168.86.23:51211/UA/SampleServer",
"authentication": {
"method": azure_native.deviceregistry.AuthenticationMethod.CERTIFICATE,
"x509_credentials": {
"certificate_secret_name": "cert-secret",
},
},
"endpoint_type": "microsoft.opcua/v1",
"version": "2",
},
"theV2OPCUAEndpoint": {
"address": "opc.tcp://192.168.86.23:51211/UA/SampleServer",
"authentication": {
"method": azure_native.deviceregistry.AuthenticationMethod.CERTIFICATE,
"x509_credentials": {
"certificate_secret_name": "cert-secret",
},
},
"endpoint_type": "microsoft.opcua/v1",
"trust_settings": {
"trust_list": "trust-secret-reference",
},
"version": "2",
},
},
},
extended_location={
"name": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1",
"type": "CustomLocation",
},
external_device_id="unique-edge-device-identifier",
location="West Europe",
namespace_name="adr-namespace-gbk0925-n01",
resource_group_name="myResourceGroup")
package main
import (
deviceregistry "github.com/pulumi/pulumi-azure-native-sdk/deviceregistry/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := deviceregistry.NewNamespaceDevice(ctx, "namespaceDevice", &deviceregistry.NamespaceDeviceArgs{
Attributes: pulumi.Any(map[string]interface{}{
"deviceCategory": 16,
"deviceOwner": "OT",
"deviceType": "OPCUAServers",
}),
DeviceName: pulumi.String("namespace-device-on-edge"),
Enabled: pulumi.Bool(true),
Endpoints: &deviceregistry.MessagingEndpointsArgs{
Inbound: deviceregistry.InboundEndpointsMap{
"theV1OPCUAEndpoint": &deviceregistry.InboundEndpointsArgs{
Address: pulumi.String("opc.tcp://192.168.86.23:51211/UA/SampleServer"),
Authentication: &deviceregistry.HostAuthenticationArgs{
Method: pulumi.String(deviceregistry.AuthenticationMethodCertificate),
X509Credentials: &deviceregistry.X509CredentialsArgs{
CertificateSecretName: pulumi.String("cert-secret"),
},
},
EndpointType: pulumi.String("microsoft.opcua/v1"),
Version: pulumi.String("2"),
},
"theV2OPCUAEndpoint": &deviceregistry.InboundEndpointsArgs{
Address: pulumi.String("opc.tcp://192.168.86.23:51211/UA/SampleServer"),
Authentication: &deviceregistry.HostAuthenticationArgs{
Method: pulumi.String(deviceregistry.AuthenticationMethodCertificate),
X509Credentials: &deviceregistry.X509CredentialsArgs{
CertificateSecretName: pulumi.String("cert-secret"),
},
},
EndpointType: pulumi.String("microsoft.opcua/v1"),
TrustSettings: &deviceregistry.TrustSettingsArgs{
TrustList: pulumi.String("trust-secret-reference"),
},
Version: pulumi.String("2"),
},
},
},
ExtendedLocation: &deviceregistry.ExtendedLocationArgs{
Name: pulumi.String("/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1"),
Type: pulumi.String("CustomLocation"),
},
ExternalDeviceId: pulumi.String("unique-edge-device-identifier"),
Location: pulumi.String("West Europe"),
NamespaceName: pulumi.String("adr-namespace-gbk0925-n01"),
ResourceGroupName: pulumi.String("myResourceGroup"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var namespaceDevice = new AzureNative.DeviceRegistry.NamespaceDevice("namespaceDevice", new()
{
Attributes = new Dictionary<string, object?>
{
["deviceCategory"] = 16,
["deviceOwner"] = "OT",
["deviceType"] = "OPCUAServers",
},
DeviceName = "namespace-device-on-edge",
Enabled = true,
Endpoints = new AzureNative.DeviceRegistry.Inputs.MessagingEndpointsArgs
{
Inbound =
{
{ "theV1OPCUAEndpoint", new AzureNative.DeviceRegistry.Inputs.InboundEndpointsArgs
{
Address = "opc.tcp://192.168.86.23:51211/UA/SampleServer",
Authentication = new AzureNative.DeviceRegistry.Inputs.HostAuthenticationArgs
{
Method = AzureNative.DeviceRegistry.AuthenticationMethod.Certificate,
X509Credentials = new AzureNative.DeviceRegistry.Inputs.X509CredentialsArgs
{
CertificateSecretName = "cert-secret",
},
},
EndpointType = "microsoft.opcua/v1",
Version = "2",
} },
{ "theV2OPCUAEndpoint", new AzureNative.DeviceRegistry.Inputs.InboundEndpointsArgs
{
Address = "opc.tcp://192.168.86.23:51211/UA/SampleServer",
Authentication = new AzureNative.DeviceRegistry.Inputs.HostAuthenticationArgs
{
Method = AzureNative.DeviceRegistry.AuthenticationMethod.Certificate,
X509Credentials = new AzureNative.DeviceRegistry.Inputs.X509CredentialsArgs
{
CertificateSecretName = "cert-secret",
},
},
EndpointType = "microsoft.opcua/v1",
TrustSettings = new AzureNative.DeviceRegistry.Inputs.TrustSettingsArgs
{
TrustList = "trust-secret-reference",
},
Version = "2",
} },
},
},
ExtendedLocation = new AzureNative.DeviceRegistry.Inputs.ExtendedLocationArgs
{
Name = "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1",
Type = "CustomLocation",
},
ExternalDeviceId = "unique-edge-device-identifier",
Location = "West Europe",
NamespaceName = "adr-namespace-gbk0925-n01",
ResourceGroupName = "myResourceGroup",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.deviceregistry.NamespaceDevice;
import com.pulumi.azurenative.deviceregistry.NamespaceDeviceArgs;
import com.pulumi.azurenative.deviceregistry.inputs.MessagingEndpointsArgs;
import com.pulumi.azurenative.deviceregistry.inputs.ExtendedLocationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var namespaceDevice = new NamespaceDevice("namespaceDevice", NamespaceDeviceArgs.builder()
.attributes(Map.ofEntries(
Map.entry("deviceCategory", 16),
Map.entry("deviceOwner", "OT"),
Map.entry("deviceType", "OPCUAServers")
))
.deviceName("namespace-device-on-edge")
.enabled(true)
.endpoints(MessagingEndpointsArgs.builder()
.inbound(Map.ofEntries(
Map.entry("theV1OPCUAEndpoint", InboundEndpointsArgs.builder()
.address("opc.tcp://192.168.86.23:51211/UA/SampleServer")
.authentication(HostAuthenticationArgs.builder()
.method("Certificate")
.x509Credentials(X509CredentialsArgs.builder()
.certificateSecretName("cert-secret")
.build())
.build())
.endpointType("microsoft.opcua/v1")
.version("2")
.build()),
Map.entry("theV2OPCUAEndpoint", InboundEndpointsArgs.builder()
.address("opc.tcp://192.168.86.23:51211/UA/SampleServer")
.authentication(HostAuthenticationArgs.builder()
.method("Certificate")
.x509Credentials(X509CredentialsArgs.builder()
.certificateSecretName("cert-secret")
.build())
.build())
.endpointType("microsoft.opcua/v1")
.trustSettings(TrustSettingsArgs.builder()
.trustList("trust-secret-reference")
.build())
.version("2")
.build())
))
.build())
.extendedLocation(ExtendedLocationArgs.builder()
.name("/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1")
.type("CustomLocation")
.build())
.externalDeviceId("unique-edge-device-identifier")
.location("West Europe")
.namespaceName("adr-namespace-gbk0925-n01")
.resourceGroupName("myResourceGroup")
.build());
}
}
resources:
namespaceDevice:
type: azure-native:deviceregistry:NamespaceDevice
properties:
attributes:
deviceCategory: 16
deviceOwner: OT
deviceType: OPCUAServers
deviceName: namespace-device-on-edge
enabled: true
endpoints:
inbound:
theV1OPCUAEndpoint:
address: opc.tcp://192.168.86.23:51211/UA/SampleServer
authentication:
method: Certificate
x509Credentials:
certificateSecretName: cert-secret
endpointType: microsoft.opcua/v1
version: '2'
theV2OPCUAEndpoint:
address: opc.tcp://192.168.86.23:51211/UA/SampleServer
authentication:
method: Certificate
x509Credentials:
certificateSecretName: cert-secret
endpointType: microsoft.opcua/v1
trustSettings:
trustList: trust-secret-reference
version: '2'
extendedLocation:
name: /subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/microsoft.extendedlocation/customlocations/location1
type: CustomLocation
externalDeviceId: unique-edge-device-identifier
location: West Europe
namespaceName: adr-namespace-gbk0925-n01
resourceGroupName: myResourceGroup
The x509Credentials property references a certificate secret for client authentication. The trustSettings.trustList property references a secret containing trusted certificate authorities, enabling the device to validate the OPC UA server’s certificate. This example shows two endpoints: one with basic certificate authentication, another adding trust list validation for enhanced security.
Send device data to Event Grid topics
Devices can publish telemetry to Azure Event Grid for routing to downstream applications.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const namespaceDevice = new azure_native.deviceregistry.NamespaceDevice("namespaceDevice", {
attributes: {
deviceCategory: 16,
deviceOwner: "IT",
deviceType: "sensor",
},
deviceName: "dev-namespace-gbk0925-n01",
enabled: true,
endpoints: {
outbound: {
assigned: {
eventGridEndpoint: {
address: "https://myeventgridtopic.westeurope-1.eventgrid.azure.net/api/events",
endpointType: "Microsoft.EventGrid",
},
},
},
},
externalDeviceId: "adr-smart-device3-7a848b15-af47-40a7-8c06-a3f43314d44f",
location: "West Europe",
namespaceName: "adr-namespace-gbk0925-n01",
resourceGroupName: "myResourceGroup",
});
import pulumi
import pulumi_azure_native as azure_native
namespace_device = azure_native.deviceregistry.NamespaceDevice("namespaceDevice",
attributes={
"deviceCategory": 16,
"deviceOwner": "IT",
"deviceType": "sensor",
},
device_name="dev-namespace-gbk0925-n01",
enabled=True,
endpoints={
"outbound": {
"assigned": {
"eventGridEndpoint": {
"address": "https://myeventgridtopic.westeurope-1.eventgrid.azure.net/api/events",
"endpoint_type": "Microsoft.EventGrid",
},
},
},
},
external_device_id="adr-smart-device3-7a848b15-af47-40a7-8c06-a3f43314d44f",
location="West Europe",
namespace_name="adr-namespace-gbk0925-n01",
resource_group_name="myResourceGroup")
package main
import (
deviceregistry "github.com/pulumi/pulumi-azure-native-sdk/deviceregistry/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := deviceregistry.NewNamespaceDevice(ctx, "namespaceDevice", &deviceregistry.NamespaceDeviceArgs{
Attributes: pulumi.Any(map[string]interface{}{
"deviceCategory": 16,
"deviceOwner": "IT",
"deviceType": "sensor",
}),
DeviceName: pulumi.String("dev-namespace-gbk0925-n01"),
Enabled: pulumi.Bool(true),
Endpoints: &deviceregistry.MessagingEndpointsArgs{
Outbound: &deviceregistry.OutboundEndpointsArgs{
Assigned: deviceregistry.DeviceMessagingEndpointMap{
"eventGridEndpoint": &deviceregistry.DeviceMessagingEndpointArgs{
Address: pulumi.String("https://myeventgridtopic.westeurope-1.eventgrid.azure.net/api/events"),
EndpointType: pulumi.String("Microsoft.EventGrid"),
},
},
},
},
ExternalDeviceId: pulumi.String("adr-smart-device3-7a848b15-af47-40a7-8c06-a3f43314d44f"),
Location: pulumi.String("West Europe"),
NamespaceName: pulumi.String("adr-namespace-gbk0925-n01"),
ResourceGroupName: pulumi.String("myResourceGroup"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var namespaceDevice = new AzureNative.DeviceRegistry.NamespaceDevice("namespaceDevice", new()
{
Attributes = new Dictionary<string, object?>
{
["deviceCategory"] = 16,
["deviceOwner"] = "IT",
["deviceType"] = "sensor",
},
DeviceName = "dev-namespace-gbk0925-n01",
Enabled = true,
Endpoints = new AzureNative.DeviceRegistry.Inputs.MessagingEndpointsArgs
{
Outbound = new AzureNative.DeviceRegistry.Inputs.OutboundEndpointsArgs
{
Assigned =
{
{ "eventGridEndpoint", new AzureNative.DeviceRegistry.Inputs.DeviceMessagingEndpointArgs
{
Address = "https://myeventgridtopic.westeurope-1.eventgrid.azure.net/api/events",
EndpointType = "Microsoft.EventGrid",
} },
},
},
},
ExternalDeviceId = "adr-smart-device3-7a848b15-af47-40a7-8c06-a3f43314d44f",
Location = "West Europe",
NamespaceName = "adr-namespace-gbk0925-n01",
ResourceGroupName = "myResourceGroup",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.deviceregistry.NamespaceDevice;
import com.pulumi.azurenative.deviceregistry.NamespaceDeviceArgs;
import com.pulumi.azurenative.deviceregistry.inputs.MessagingEndpointsArgs;
import com.pulumi.azurenative.deviceregistry.inputs.OutboundEndpointsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var namespaceDevice = new NamespaceDevice("namespaceDevice", NamespaceDeviceArgs.builder()
.attributes(Map.ofEntries(
Map.entry("deviceCategory", 16),
Map.entry("deviceOwner", "IT"),
Map.entry("deviceType", "sensor")
))
.deviceName("dev-namespace-gbk0925-n01")
.enabled(true)
.endpoints(MessagingEndpointsArgs.builder()
.outbound(OutboundEndpointsArgs.builder()
.assigned(Map.of("eventGridEndpoint", DeviceMessagingEndpointArgs.builder()
.address("https://myeventgridtopic.westeurope-1.eventgrid.azure.net/api/events")
.endpointType("Microsoft.EventGrid")
.build()))
.build())
.build())
.externalDeviceId("adr-smart-device3-7a848b15-af47-40a7-8c06-a3f43314d44f")
.location("West Europe")
.namespaceName("adr-namespace-gbk0925-n01")
.resourceGroupName("myResourceGroup")
.build());
}
}
resources:
namespaceDevice:
type: azure-native:deviceregistry:NamespaceDevice
properties:
attributes:
deviceCategory: 16
deviceOwner: IT
deviceType: sensor
deviceName: dev-namespace-gbk0925-n01
enabled: true
endpoints:
outbound:
assigned:
eventGridEndpoint:
address: https://myeventgridtopic.westeurope-1.eventgrid.azure.net/api/events
endpointType: Microsoft.EventGrid
externalDeviceId: adr-smart-device3-7a848b15-af47-40a7-8c06-a3f43314d44f
location: West Europe
namespaceName: adr-namespace-gbk0925-n01
resourceGroupName: myResourceGroup
The endpoints.outbound.assigned map defines named outbound connections. Each endpoint specifies an address (the Event Grid topic URL) and an endpointType (“Microsoft.EventGrid”). The device publishes events to this endpoint, which Event Grid then routes according to topic subscriptions.
Beyond these examples
These snippets focus on specific device-level features: OPC UA inbound connectivity with multiple authentication methods, outbound Event Grid integration, and edge deployment via CustomLocations. They’re intentionally minimal rather than full IoT solutions.
The examples reference pre-existing infrastructure such as Azure Arc CustomLocations for edge placement, Device Registry namespaces, secret stores for credentials and certificates, and Event Grid topics for outbound messaging. They focus on configuring the device rather than provisioning the surrounding infrastructure.
To keep things focused, common device patterns are omitted, including:
- Device attributes and metadata (attributes property)
- Device enablement state (enabled property)
- Discovered device references (discoveredDeviceRef)
- Operating system and manufacturer details
These omissions are intentional: the goal is to illustrate how each device feature is wired, not provide drop-in IoT modules. See the NamespaceDevice resource reference for all available configuration options.
Let's configure Azure Device Registry Namespace Devices
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Authentication & Security
Three authentication methods are supported:
- Anonymous - No credentials required (set
methodtoAnonymous) - UsernamePassword - Requires
usernamePasswordCredentialswithusernameSecretNameandpasswordSecretName - Certificate - Requires
x509CredentialswithcertificateSecretName
authentication.method to Certificate and provide x509Credentials.certificateSecretName. For trust validation, add trustSettings.trustList with a reference to your trust list secret.passwordSecretName: "pwd-ref", usernameSecretName: "user-ref", certificateSecretName: "cert-secret"). These reference secrets stored in your secret management system.Device Configuration
location, extendedLocation, deviceName, externalDeviceId, discoveredDeviceRef, manufacturer, model, operatingSystem, and resourceGroupName. Changing these requires replacing the resource.enabled: true). You can explicitly set enabled: false to create a disabled device.extendedLocation specifies the Azure Arc custom location for edge-enabled devices. It’s required for devices deployed to edge environments and must include a name (custom location resource ID) and type (typically CustomLocation).Endpoints & Connectivity
endpoints.inbound or endpoints.outbound.assigned.microsoft.opcua/v1 for OPC UA inbound endpoints and Microsoft.EventGrid for Event Grid outbound endpoints. Each endpoint requires an address, endpointType, and authentication configuration.endpoints.inbound with an address (e.g., opc.tcp://192.168.86.23:51211/UA/SampleServer), set endpointType to microsoft.opcua/v1, specify version, and configure authentication with your chosen method.Advanced Features
discoveredDeviceRef is an immutable property populated only when a device is created from the discovery flow. It references the discovered device name and cannot be set manually.Using a different cloud?
Explore integration guides for other cloud providers: