Configure Azure Hybrid Network Artifact Stores

The azure-native:hybridnetwork:ArtifactStore resource, part of the Pulumi Azure Native provider, defines artifact stores that hold container images, Helm charts, or VHD images for network function publishers. This guide focuses on three capabilities: container registry and storage account backends, network access control, and managed resource group placement.

Artifact stores belong to publisher resources and create backing storage infrastructure in managed resource groups. The examples are intentionally small. Combine them with your own publisher configuration and network policies.

Create a container registry artifact store

Network function publishers need a place to store container images and Helm charts. Artifact stores provide managed storage with replication and access control.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const artifactStore = new azure_native.hybridnetwork.ArtifactStore("artifactStore", {
    artifactStoreName: "TestArtifactStore",
    location: "eastus",
    properties: {
        managedResourceGroupConfiguration: {
            location: "eastus",
            name: "testRg",
        },
        replicationStrategy: azure_native.hybridnetwork.ArtifactReplicationStrategy.SingleReplication,
        storeType: azure_native.hybridnetwork.ArtifactStoreType.AzureContainerRegistry,
    },
    publisherName: "TestPublisher",
    resourceGroupName: "rg",
});
import pulumi
import pulumi_azure_native as azure_native

artifact_store = azure_native.hybridnetwork.ArtifactStore("artifactStore",
    artifact_store_name="TestArtifactStore",
    location="eastus",
    properties={
        "managed_resource_group_configuration": {
            "location": "eastus",
            "name": "testRg",
        },
        "replication_strategy": azure_native.hybridnetwork.ArtifactReplicationStrategy.SINGLE_REPLICATION,
        "store_type": azure_native.hybridnetwork.ArtifactStoreType.AZURE_CONTAINER_REGISTRY,
    },
    publisher_name="TestPublisher",
    resource_group_name="rg")
package main

import (
	hybridnetwork "github.com/pulumi/pulumi-azure-native-sdk/hybridnetwork/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := hybridnetwork.NewArtifactStore(ctx, "artifactStore", &hybridnetwork.ArtifactStoreArgs{
			ArtifactStoreName: pulumi.String("TestArtifactStore"),
			Location:          pulumi.String("eastus"),
			Properties: &hybridnetwork.ArtifactStorePropertiesFormatArgs{
				ManagedResourceGroupConfiguration: &hybridnetwork.ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs{
					Location: pulumi.String("eastus"),
					Name:     pulumi.String("testRg"),
				},
				ReplicationStrategy: pulumi.String(hybridnetwork.ArtifactReplicationStrategySingleReplication),
				StoreType:           pulumi.String(hybridnetwork.ArtifactStoreTypeAzureContainerRegistry),
			},
			PublisherName:     pulumi.String("TestPublisher"),
			ResourceGroupName: pulumi.String("rg"),
		})
		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 artifactStore = new AzureNative.HybridNetwork.ArtifactStore("artifactStore", new()
    {
        ArtifactStoreName = "TestArtifactStore",
        Location = "eastus",
        Properties = new AzureNative.HybridNetwork.Inputs.ArtifactStorePropertiesFormatArgs
        {
            ManagedResourceGroupConfiguration = new AzureNative.HybridNetwork.Inputs.ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs
            {
                Location = "eastus",
                Name = "testRg",
            },
            ReplicationStrategy = AzureNative.HybridNetwork.ArtifactReplicationStrategy.SingleReplication,
            StoreType = AzureNative.HybridNetwork.ArtifactStoreType.AzureContainerRegistry,
        },
        PublisherName = "TestPublisher",
        ResourceGroupName = "rg",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.hybridnetwork.ArtifactStore;
import com.pulumi.azurenative.hybridnetwork.ArtifactStoreArgs;
import com.pulumi.azurenative.hybridnetwork.inputs.ArtifactStorePropertiesFormatArgs;
import com.pulumi.azurenative.hybridnetwork.inputs.ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs;
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 artifactStore = new ArtifactStore("artifactStore", ArtifactStoreArgs.builder()
            .artifactStoreName("TestArtifactStore")
            .location("eastus")
            .properties(ArtifactStorePropertiesFormatArgs.builder()
                .managedResourceGroupConfiguration(ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs.builder()
                    .location("eastus")
                    .name("testRg")
                    .build())
                .replicationStrategy("SingleReplication")
                .storeType("AzureContainerRegistry")
                .build())
            .publisherName("TestPublisher")
            .resourceGroupName("rg")
            .build());

    }
}
resources:
  artifactStore:
    type: azure-native:hybridnetwork:ArtifactStore
    properties:
      artifactStoreName: TestArtifactStore
      location: eastus
      properties:
        managedResourceGroupConfiguration:
          location: eastus
          name: testRg
        replicationStrategy: SingleReplication
        storeType: AzureContainerRegistry
      publisherName: TestPublisher
      resourceGroupName: rg

The storeType property determines whether Azure creates a container registry or storage account. The replicationStrategy controls how artifacts are copied across regions; SingleReplication keeps everything in one location. The managedResourceGroupConfiguration specifies where Azure provisions the backing storage infrastructure, separate from your main resource group.

Restrict public network access to the registry

Security policies often require that artifact stores remain private, accessible only through private endpoints or VNet integration.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const artifactStore = new azure_native.hybridnetwork.ArtifactStore("artifactStore", {
    artifactStoreName: "TestArtifactStore",
    location: "eastus",
    properties: {
        backingResourcePublicNetworkAccess: azure_native.hybridnetwork.BackingResourcePublicNetworkAccess.Disabled,
        managedResourceGroupConfiguration: {
            location: "eastus",
            name: "testRg",
        },
        replicationStrategy: azure_native.hybridnetwork.ArtifactReplicationStrategy.SingleReplication,
        storeType: azure_native.hybridnetwork.ArtifactStoreType.AzureContainerRegistry,
    },
    publisherName: "TestPublisher",
    resourceGroupName: "rg",
});
import pulumi
import pulumi_azure_native as azure_native

artifact_store = azure_native.hybridnetwork.ArtifactStore("artifactStore",
    artifact_store_name="TestArtifactStore",
    location="eastus",
    properties={
        "backing_resource_public_network_access": azure_native.hybridnetwork.BackingResourcePublicNetworkAccess.DISABLED,
        "managed_resource_group_configuration": {
            "location": "eastus",
            "name": "testRg",
        },
        "replication_strategy": azure_native.hybridnetwork.ArtifactReplicationStrategy.SINGLE_REPLICATION,
        "store_type": azure_native.hybridnetwork.ArtifactStoreType.AZURE_CONTAINER_REGISTRY,
    },
    publisher_name="TestPublisher",
    resource_group_name="rg")
package main

import (
	hybridnetwork "github.com/pulumi/pulumi-azure-native-sdk/hybridnetwork/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := hybridnetwork.NewArtifactStore(ctx, "artifactStore", &hybridnetwork.ArtifactStoreArgs{
			ArtifactStoreName: pulumi.String("TestArtifactStore"),
			Location:          pulumi.String("eastus"),
			Properties: &hybridnetwork.ArtifactStorePropertiesFormatArgs{
				BackingResourcePublicNetworkAccess: pulumi.String(hybridnetwork.BackingResourcePublicNetworkAccessDisabled),
				ManagedResourceGroupConfiguration: &hybridnetwork.ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs{
					Location: pulumi.String("eastus"),
					Name:     pulumi.String("testRg"),
				},
				ReplicationStrategy: pulumi.String(hybridnetwork.ArtifactReplicationStrategySingleReplication),
				StoreType:           pulumi.String(hybridnetwork.ArtifactStoreTypeAzureContainerRegistry),
			},
			PublisherName:     pulumi.String("TestPublisher"),
			ResourceGroupName: pulumi.String("rg"),
		})
		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 artifactStore = new AzureNative.HybridNetwork.ArtifactStore("artifactStore", new()
    {
        ArtifactStoreName = "TestArtifactStore",
        Location = "eastus",
        Properties = new AzureNative.HybridNetwork.Inputs.ArtifactStorePropertiesFormatArgs
        {
            BackingResourcePublicNetworkAccess = AzureNative.HybridNetwork.BackingResourcePublicNetworkAccess.Disabled,
            ManagedResourceGroupConfiguration = new AzureNative.HybridNetwork.Inputs.ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs
            {
                Location = "eastus",
                Name = "testRg",
            },
            ReplicationStrategy = AzureNative.HybridNetwork.ArtifactReplicationStrategy.SingleReplication,
            StoreType = AzureNative.HybridNetwork.ArtifactStoreType.AzureContainerRegistry,
        },
        PublisherName = "TestPublisher",
        ResourceGroupName = "rg",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.hybridnetwork.ArtifactStore;
import com.pulumi.azurenative.hybridnetwork.ArtifactStoreArgs;
import com.pulumi.azurenative.hybridnetwork.inputs.ArtifactStorePropertiesFormatArgs;
import com.pulumi.azurenative.hybridnetwork.inputs.ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs;
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 artifactStore = new ArtifactStore("artifactStore", ArtifactStoreArgs.builder()
            .artifactStoreName("TestArtifactStore")
            .location("eastus")
            .properties(ArtifactStorePropertiesFormatArgs.builder()
                .backingResourcePublicNetworkAccess("Disabled")
                .managedResourceGroupConfiguration(ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs.builder()
                    .location("eastus")
                    .name("testRg")
                    .build())
                .replicationStrategy("SingleReplication")
                .storeType("AzureContainerRegistry")
                .build())
            .publisherName("TestPublisher")
            .resourceGroupName("rg")
            .build());

    }
}
resources:
  artifactStore:
    type: azure-native:hybridnetwork:ArtifactStore
    properties:
      artifactStoreName: TestArtifactStore
      location: eastus
      properties:
        backingResourcePublicNetworkAccess: Disabled
        managedResourceGroupConfiguration:
          location: eastus
          name: testRg
        replicationStrategy: SingleReplication
        storeType: AzureContainerRegistry
      publisherName: TestPublisher
      resourceGroupName: rg

The backingResourcePublicNetworkAccess property controls whether the underlying container registry accepts connections from the public internet. Setting it to Disabled restricts access to private endpoints and VNet-integrated resources. This extends the basic configuration with network isolation.

Store VHD images in Azure Storage

Some network functions use VHD-based virtual machines rather than containers, requiring blob storage instead of a container registry.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const artifactStore = new azure_native.hybridnetwork.ArtifactStore("artifactStore", {
    artifactStoreName: "TestArtifactStore",
    location: "eastus",
    properties: {
        backingResourcePublicNetworkAccess: azure_native.hybridnetwork.BackingResourcePublicNetworkAccess.Enabled,
        managedResourceGroupConfiguration: {
            location: "eastus",
            name: "testRg",
        },
        replicationStrategy: azure_native.hybridnetwork.ArtifactReplicationStrategy.SingleReplication,
        storeType: azure_native.hybridnetwork.ArtifactStoreType.AzureStorageAccount,
    },
    publisherName: "TestPublisher",
    resourceGroupName: "rg",
});
import pulumi
import pulumi_azure_native as azure_native

artifact_store = azure_native.hybridnetwork.ArtifactStore("artifactStore",
    artifact_store_name="TestArtifactStore",
    location="eastus",
    properties={
        "backing_resource_public_network_access": azure_native.hybridnetwork.BackingResourcePublicNetworkAccess.ENABLED,
        "managed_resource_group_configuration": {
            "location": "eastus",
            "name": "testRg",
        },
        "replication_strategy": azure_native.hybridnetwork.ArtifactReplicationStrategy.SINGLE_REPLICATION,
        "store_type": azure_native.hybridnetwork.ArtifactStoreType.AZURE_STORAGE_ACCOUNT,
    },
    publisher_name="TestPublisher",
    resource_group_name="rg")
package main

import (
	hybridnetwork "github.com/pulumi/pulumi-azure-native-sdk/hybridnetwork/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := hybridnetwork.NewArtifactStore(ctx, "artifactStore", &hybridnetwork.ArtifactStoreArgs{
			ArtifactStoreName: pulumi.String("TestArtifactStore"),
			Location:          pulumi.String("eastus"),
			Properties: &hybridnetwork.ArtifactStorePropertiesFormatArgs{
				BackingResourcePublicNetworkAccess: pulumi.String(hybridnetwork.BackingResourcePublicNetworkAccessEnabled),
				ManagedResourceGroupConfiguration: &hybridnetwork.ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs{
					Location: pulumi.String("eastus"),
					Name:     pulumi.String("testRg"),
				},
				ReplicationStrategy: pulumi.String(hybridnetwork.ArtifactReplicationStrategySingleReplication),
				StoreType:           pulumi.String(hybridnetwork.ArtifactStoreTypeAzureStorageAccount),
			},
			PublisherName:     pulumi.String("TestPublisher"),
			ResourceGroupName: pulumi.String("rg"),
		})
		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 artifactStore = new AzureNative.HybridNetwork.ArtifactStore("artifactStore", new()
    {
        ArtifactStoreName = "TestArtifactStore",
        Location = "eastus",
        Properties = new AzureNative.HybridNetwork.Inputs.ArtifactStorePropertiesFormatArgs
        {
            BackingResourcePublicNetworkAccess = AzureNative.HybridNetwork.BackingResourcePublicNetworkAccess.Enabled,
            ManagedResourceGroupConfiguration = new AzureNative.HybridNetwork.Inputs.ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs
            {
                Location = "eastus",
                Name = "testRg",
            },
            ReplicationStrategy = AzureNative.HybridNetwork.ArtifactReplicationStrategy.SingleReplication,
            StoreType = AzureNative.HybridNetwork.ArtifactStoreType.AzureStorageAccount,
        },
        PublisherName = "TestPublisher",
        ResourceGroupName = "rg",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.hybridnetwork.ArtifactStore;
import com.pulumi.azurenative.hybridnetwork.ArtifactStoreArgs;
import com.pulumi.azurenative.hybridnetwork.inputs.ArtifactStorePropertiesFormatArgs;
import com.pulumi.azurenative.hybridnetwork.inputs.ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs;
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 artifactStore = new ArtifactStore("artifactStore", ArtifactStoreArgs.builder()
            .artifactStoreName("TestArtifactStore")
            .location("eastus")
            .properties(ArtifactStorePropertiesFormatArgs.builder()
                .backingResourcePublicNetworkAccess("Enabled")
                .managedResourceGroupConfiguration(ArtifactStorePropertiesFormatManagedResourceGroupConfigurationArgs.builder()
                    .location("eastus")
                    .name("testRg")
                    .build())
                .replicationStrategy("SingleReplication")
                .storeType("AzureStorageAccount")
                .build())
            .publisherName("TestPublisher")
            .resourceGroupName("rg")
            .build());

    }
}
resources:
  artifactStore:
    type: azure-native:hybridnetwork:ArtifactStore
    properties:
      artifactStoreName: TestArtifactStore
      location: eastus
      properties:
        backingResourcePublicNetworkAccess: Enabled
        managedResourceGroupConfiguration:
          location: eastus
          name: testRg
        replicationStrategy: SingleReplication
        storeType: AzureStorageAccount
      publisherName: TestPublisher
      resourceGroupName: rg

When storeType is AzureStorageAccount, Azure provisions a storage account instead of a container registry. This supports VHD images and other blob-based artifacts. The backingResourcePublicNetworkAccess property works the same way, controlling whether the storage account accepts public connections.

Beyond these examples

These snippets focus on specific artifact store features: container registry and storage account backends, network access control, and managed resource group placement. They’re intentionally minimal rather than full publisher deployments.

The examples reference pre-existing infrastructure such as publisher resources and resource groups for artifact store and managed resources. They focus on configuring the artifact store rather than provisioning the surrounding publisher hierarchy.

To keep things focused, common artifact store patterns are omitted, including:

  • Multi-region replication strategies
  • Custom tags for cost tracking
  • Private endpoint configuration
  • Identity and access management (IAM roles)

These omissions are intentional: the goal is to illustrate how each artifact store feature is wired, not provide drop-in publisher modules. See the ArtifactStore resource reference for all available configuration options.

Let's configure Azure Hybrid Network Artifact Stores

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Store Types
What types of artifact stores can I create?
You can create artifact stores backed by Azure Container Registry (AzureContainerRegistry) or Azure Storage Account (AzureStorageAccount).
What's the managed resource group configuration for?
The managedResourceGroupConfiguration specifies the location and name of the managed resource group that will contain the backing storage resources. This configuration is required when creating an artifact store.
Network Access & Security
How do I control public network access to the artifact store?
Use the backingResourcePublicNetworkAccess property with values Enabled or Disabled to control whether the backing resource (Container Registry or Storage Account) is accessible from public networks.
Resource Management
What properties can't I change after creating an artifact store?
The properties location, artifactStoreName, publisherName, and resourceGroupName are immutable and cannot be changed after creation. Modifying these requires replacing the resource.
Can I use different API versions for this resource?
Yes, other API versions like 2023-09-01 are available. You can access them by generating a local SDK package using pulumi package add azure-native hybridnetwork [ApiVersion].

Using a different cloud?

Explore storage guides for other cloud providers: