The azure-native:deviceregistry:NamespaceDevice resource, part of the Pulumi Azure Native provider, defines a device within a Device Registry namespace: its endpoints, authentication methods, and edge location placement. This guide focuses on three capabilities: OPC UA endpoint authentication methods, inbound connectivity from edge devices, and outbound messaging to Azure services.
Devices belong to a Device Registry namespace and run on Azure Arc-enabled edge locations. They reference secrets for credentials and may connect to Event Grid or other Azure services. The examples are intentionally small. Combine them with your own namespace, CustomLocation, and secret management.
Connect to OPC UA servers with username and password
Industrial deployments often start by connecting to OPC UA servers using username and password authentication.
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 inbound endpoints map defines named connections to OPC UA servers. Each endpoint specifies an address (the OPC UA server URL), an authentication method, and credential references. The usernamePasswordCredentials property points to secret names that store the username and password. The extendedLocation property places the device on a specific Azure Arc CustomLocation, which determines where the device agent runs.
Connect to OPC UA servers without authentication
Development environments sometimes expose OPC UA servers without authentication for quick prototyping.
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 the authentication method to Anonymous removes the need for credentials. The device connects directly to the OPC UA server without presenting username, password, or certificates. This simplifies testing but should not be used in production.
Authenticate with X.509 certificates and trust lists
Production deployments require certificate-based authentication to meet security standards.
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 secret containing the client certificate. The optional trustSettings property specifies a trust list that validates the server’s certificate chain. This example shows two endpoints: one with basic certificate authentication, another that also validates the server certificate against a trust list.
Send device data to Event Grid topics
Devices can publish telemetry to Azure Event Grid for cloud processing.
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 outbound endpoints configuration routes device messages to Azure services. The assigned map defines named destinations; here, an Event Grid topic receives device events. The endpointType identifies the target service, and the address specifies the Event Grid topic URL.
Beyond these examples
These snippets focus on specific device-level features: OPC UA endpoint authentication, inbound and outbound messaging configuration, and edge location placement and device metadata. They’re intentionally minimal rather than full IoT solutions.
The examples reference pre-existing infrastructure such as Azure Arc CustomLocation for edge deployment, Device Registry namespace, secrets for credentials and certificates, and Event Grid topics for outbound examples. They focus on configuring the device rather than provisioning the surrounding infrastructure.
To keep things focused, common device patterns are omitted, including:
- Device discovery and automatic registration (discoveredDeviceRef)
- Device status monitoring and health checks
- Multiple endpoint configurations per device
- Device attributes and custom metadata beyond basic examples
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
usernamePasswordCredentialswithpasswordSecretNameandusernameSecretName - Certificate - Requires
x509CredentialswithcertificateSecretName, optionally withtrustSettings.trustListfor certificate validation
passwordSecretName and usernameSecretName. For certificate authentication, specify certificateSecretName. These reference secrets stored in your secret management system.Edge Device Configuration
extendedLocation property with type set to CustomLocation and a name referencing your custom location resource. This connects the device to your edge infrastructure.address pointing to your OPC UA server (e.g., opc.tcp://192.168.86.23:51211/UA/SampleServer), set endpointType to microsoft.opcua/v1, specify the version, and configure your chosen authentication method.Endpoints & Connectivity
endpoints.inbound or endpoints.outbound respectively.inbound or outbound properties. Each endpoint can have different addresses, authentication methods, and configurations.Device Properties & Immutability
location, deviceName, extendedLocation, externalDeviceId, discoveredDeviceRef, manufacturer, model, and operatingSystem.enabled property controls whether the device is active. It defaults to true and can be toggled to disable a device without deleting it.attributes property to set custom key-value pairs like deviceCategory, deviceOwner, or deviceType. These help organize and categorize your devices.Using a different cloud?
Explore integration guides for other cloud providers: