The azure-native:storage:FileServiceProperties resource, part of the Pulumi Azure Native provider, configures service-level settings for Azure Files within a storage account: CORS rules, SMB protocol options, and retention policies. This guide focuses on three capabilities: CORS rules for browser-based access, SMB Multichannel for performance, and SMB security restrictions.
File service properties apply to an existing storage account and affect all file shares within that account. The examples are intentionally small. Combine them with your own storage accounts, file shares, and network configuration.
Configure CORS rules for browser-based file access
Web applications that access Azure Files directly from browsers need CORS rules to authorize cross-origin requests.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const fileServiceProperties = new azure_native.storage.FileServiceProperties("fileServiceProperties", {
accountName: "sto8607",
cors: {
corsRules: [
{
allowedHeaders: [
"x-ms-meta-abc",
"x-ms-meta-data*",
"x-ms-meta-target*",
],
allowedMethods: [
azure_native.storage.AllowedMethods.GET,
azure_native.storage.AllowedMethods.HEAD,
azure_native.storage.AllowedMethods.POST,
azure_native.storage.AllowedMethods.OPTIONS,
azure_native.storage.AllowedMethods.MERGE,
azure_native.storage.AllowedMethods.PUT,
],
allowedOrigins: [
"http://www.contoso.com",
"http://www.fabrikam.com",
],
exposedHeaders: ["x-ms-meta-*"],
maxAgeInSeconds: 100,
},
{
allowedHeaders: ["*"],
allowedMethods: [azure_native.storage.AllowedMethods.GET],
allowedOrigins: ["*"],
exposedHeaders: ["*"],
maxAgeInSeconds: 2,
},
{
allowedHeaders: ["x-ms-meta-12345675754564*"],
allowedMethods: [
azure_native.storage.AllowedMethods.GET,
azure_native.storage.AllowedMethods.PUT,
],
allowedOrigins: [
"http://www.abc23.com",
"https://www.fabrikam.com/*",
],
exposedHeaders: [
"x-ms-meta-abc",
"x-ms-meta-data*",
"x-ms-meta-target*",
],
maxAgeInSeconds: 2000,
},
],
},
fileServicesName: "default",
resourceGroupName: "res4410",
});
import pulumi
import pulumi_azure_native as azure_native
file_service_properties = azure_native.storage.FileServiceProperties("fileServiceProperties",
account_name="sto8607",
cors={
"cors_rules": [
{
"allowed_headers": [
"x-ms-meta-abc",
"x-ms-meta-data*",
"x-ms-meta-target*",
],
"allowed_methods": [
azure_native.storage.AllowedMethods.GET,
azure_native.storage.AllowedMethods.HEAD,
azure_native.storage.AllowedMethods.POST,
azure_native.storage.AllowedMethods.OPTIONS,
azure_native.storage.AllowedMethods.MERGE,
azure_native.storage.AllowedMethods.PUT,
],
"allowed_origins": [
"http://www.contoso.com",
"http://www.fabrikam.com",
],
"exposed_headers": ["x-ms-meta-*"],
"max_age_in_seconds": 100,
},
{
"allowed_headers": ["*"],
"allowed_methods": [azure_native.storage.AllowedMethods.GET],
"allowed_origins": ["*"],
"exposed_headers": ["*"],
"max_age_in_seconds": 2,
},
{
"allowed_headers": ["x-ms-meta-12345675754564*"],
"allowed_methods": [
azure_native.storage.AllowedMethods.GET,
azure_native.storage.AllowedMethods.PUT,
],
"allowed_origins": [
"http://www.abc23.com",
"https://www.fabrikam.com/*",
],
"exposed_headers": [
"x-ms-meta-abc",
"x-ms-meta-data*",
"x-ms-meta-target*",
],
"max_age_in_seconds": 2000,
},
],
},
file_services_name="default",
resource_group_name="res4410")
package main
import (
storage "github.com/pulumi/pulumi-azure-native-sdk/storage/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := storage.NewFileServiceProperties(ctx, "fileServiceProperties", &storage.FileServicePropertiesArgs{
AccountName: pulumi.String("sto8607"),
Cors: &storage.CorsRulesArgs{
CorsRules: storage.CorsRuleArray{
&storage.CorsRuleArgs{
AllowedHeaders: pulumi.StringArray{
pulumi.String("x-ms-meta-abc"),
pulumi.String("x-ms-meta-data*"),
pulumi.String("x-ms-meta-target*"),
},
AllowedMethods: pulumi.StringArray{
pulumi.String(storage.AllowedMethodsGET),
pulumi.String(storage.AllowedMethodsHEAD),
pulumi.String(storage.AllowedMethodsPOST),
pulumi.String(storage.AllowedMethodsOPTIONS),
pulumi.String(storage.AllowedMethodsMERGE),
pulumi.String(storage.AllowedMethodsPUT),
},
AllowedOrigins: pulumi.StringArray{
pulumi.String("http://www.contoso.com"),
pulumi.String("http://www.fabrikam.com"),
},
ExposedHeaders: pulumi.StringArray{
pulumi.String("x-ms-meta-*"),
},
MaxAgeInSeconds: pulumi.Int(100),
},
&storage.CorsRuleArgs{
AllowedHeaders: pulumi.StringArray{
pulumi.String("*"),
},
AllowedMethods: pulumi.StringArray{
pulumi.String(storage.AllowedMethodsGET),
},
AllowedOrigins: pulumi.StringArray{
pulumi.String("*"),
},
ExposedHeaders: pulumi.StringArray{
pulumi.String("*"),
},
MaxAgeInSeconds: pulumi.Int(2),
},
&storage.CorsRuleArgs{
AllowedHeaders: pulumi.StringArray{
pulumi.String("x-ms-meta-12345675754564*"),
},
AllowedMethods: pulumi.StringArray{
pulumi.String(storage.AllowedMethodsGET),
pulumi.String(storage.AllowedMethodsPUT),
},
AllowedOrigins: pulumi.StringArray{
pulumi.String("http://www.abc23.com"),
pulumi.String("https://www.fabrikam.com/*"),
},
ExposedHeaders: pulumi.StringArray{
pulumi.String("x-ms-meta-abc"),
pulumi.String("x-ms-meta-data*"),
pulumi.String("x-ms-meta-target*"),
},
MaxAgeInSeconds: pulumi.Int(2000),
},
},
},
FileServicesName: pulumi.String("default"),
ResourceGroupName: pulumi.String("res4410"),
})
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 fileServiceProperties = new AzureNative.Storage.FileServiceProperties("fileServiceProperties", new()
{
AccountName = "sto8607",
Cors = new AzureNative.Storage.Inputs.CorsRulesArgs
{
CorsRules = new[]
{
new AzureNative.Storage.Inputs.CorsRuleArgs
{
AllowedHeaders = new[]
{
"x-ms-meta-abc",
"x-ms-meta-data*",
"x-ms-meta-target*",
},
AllowedMethods = new[]
{
AzureNative.Storage.AllowedMethods.GET,
AzureNative.Storage.AllowedMethods.HEAD,
AzureNative.Storage.AllowedMethods.POST,
AzureNative.Storage.AllowedMethods.OPTIONS,
AzureNative.Storage.AllowedMethods.MERGE,
AzureNative.Storage.AllowedMethods.PUT,
},
AllowedOrigins = new[]
{
"http://www.contoso.com",
"http://www.fabrikam.com",
},
ExposedHeaders = new[]
{
"x-ms-meta-*",
},
MaxAgeInSeconds = 100,
},
new AzureNative.Storage.Inputs.CorsRuleArgs
{
AllowedHeaders = new[]
{
"*",
},
AllowedMethods = new[]
{
AzureNative.Storage.AllowedMethods.GET,
},
AllowedOrigins = new[]
{
"*",
},
ExposedHeaders = new[]
{
"*",
},
MaxAgeInSeconds = 2,
},
new AzureNative.Storage.Inputs.CorsRuleArgs
{
AllowedHeaders = new[]
{
"x-ms-meta-12345675754564*",
},
AllowedMethods = new[]
{
AzureNative.Storage.AllowedMethods.GET,
AzureNative.Storage.AllowedMethods.PUT,
},
AllowedOrigins = new[]
{
"http://www.abc23.com",
"https://www.fabrikam.com/*",
},
ExposedHeaders = new[]
{
"x-ms-meta-abc",
"x-ms-meta-data*",
"x-ms-meta-target*",
},
MaxAgeInSeconds = 2000,
},
},
},
FileServicesName = "default",
ResourceGroupName = "res4410",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storage.FileServiceProperties;
import com.pulumi.azurenative.storage.FileServicePropertiesArgs;
import com.pulumi.azurenative.storage.inputs.CorsRulesArgs;
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 fileServiceProperties = new FileServiceProperties("fileServiceProperties", FileServicePropertiesArgs.builder()
.accountName("sto8607")
.cors(CorsRulesArgs.builder()
.corsRules(
CorsRuleArgs.builder()
.allowedHeaders(
"x-ms-meta-abc",
"x-ms-meta-data*",
"x-ms-meta-target*")
.allowedMethods(
"GET",
"HEAD",
"POST",
"OPTIONS",
"MERGE",
"PUT")
.allowedOrigins(
"http://www.contoso.com",
"http://www.fabrikam.com")
.exposedHeaders("x-ms-meta-*")
.maxAgeInSeconds(100)
.build(),
CorsRuleArgs.builder()
.allowedHeaders("*")
.allowedMethods("GET")
.allowedOrigins("*")
.exposedHeaders("*")
.maxAgeInSeconds(2)
.build(),
CorsRuleArgs.builder()
.allowedHeaders("x-ms-meta-12345675754564*")
.allowedMethods(
"GET",
"PUT")
.allowedOrigins(
"http://www.abc23.com",
"https://www.fabrikam.com/*")
.exposedHeaders(
"x-ms-meta-abc",
"x-ms-meta-data*",
"x-ms-meta-target*")
.maxAgeInSeconds(2000)
.build())
.build())
.fileServicesName("default")
.resourceGroupName("res4410")
.build());
}
}
resources:
fileServiceProperties:
type: azure-native:storage:FileServiceProperties
properties:
accountName: sto8607
cors:
corsRules:
- allowedHeaders:
- x-ms-meta-abc
- x-ms-meta-data*
- x-ms-meta-target*
allowedMethods:
- GET
- HEAD
- POST
- OPTIONS
- MERGE
- PUT
allowedOrigins:
- http://www.contoso.com
- http://www.fabrikam.com
exposedHeaders:
- x-ms-meta-*
maxAgeInSeconds: 100
- allowedHeaders:
- '*'
allowedMethods:
- GET
allowedOrigins:
- '*'
exposedHeaders:
- '*'
maxAgeInSeconds: 2
- allowedHeaders:
- x-ms-meta-12345675754564*
allowedMethods:
- GET
- PUT
allowedOrigins:
- http://www.abc23.com
- https://www.fabrikam.com/*
exposedHeaders:
- x-ms-meta-abc
- x-ms-meta-data*
- x-ms-meta-target*
maxAgeInSeconds: 2000
fileServicesName: default
resourceGroupName: res4410
The cors property defines an array of corsRules, each specifying which origins, HTTP methods, and headers are permitted. The allowedOrigins list controls which domains can make requests; allowedMethods specifies GET, PUT, POST, and other operations; allowedHeaders and exposedHeaders control which request and response headers are permitted. The maxAgeInSeconds value tells browsers how long to cache the preflight response. Multiple rules let you define different policies for different origins or use cases.
Enable SMB Multichannel for parallel connections
SMB Multichannel allows clients to establish multiple network connections simultaneously, improving throughput for high-bandwidth workloads.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const fileServiceProperties = new azure_native.storage.FileServiceProperties("fileServiceProperties", {
accountName: "sto8607",
fileServicesName: "default",
protocolSettings: {
smb: {
multichannel: {
enabled: true,
},
},
},
resourceGroupName: "res4410",
});
import pulumi
import pulumi_azure_native as azure_native
file_service_properties = azure_native.storage.FileServiceProperties("fileServiceProperties",
account_name="sto8607",
file_services_name="default",
protocol_settings={
"smb": {
"multichannel": {
"enabled": True,
},
},
},
resource_group_name="res4410")
package main
import (
storage "github.com/pulumi/pulumi-azure-native-sdk/storage/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := storage.NewFileServiceProperties(ctx, "fileServiceProperties", &storage.FileServicePropertiesArgs{
AccountName: pulumi.String("sto8607"),
FileServicesName: pulumi.String("default"),
ProtocolSettings: &storage.ProtocolSettingsArgs{
Smb: &storage.SmbSettingArgs{
Multichannel: &storage.MultichannelArgs{
Enabled: pulumi.Bool(true),
},
},
},
ResourceGroupName: pulumi.String("res4410"),
})
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 fileServiceProperties = new AzureNative.Storage.FileServiceProperties("fileServiceProperties", new()
{
AccountName = "sto8607",
FileServicesName = "default",
ProtocolSettings = new AzureNative.Storage.Inputs.ProtocolSettingsArgs
{
Smb = new AzureNative.Storage.Inputs.SmbSettingArgs
{
Multichannel = new AzureNative.Storage.Inputs.MultichannelArgs
{
Enabled = true,
},
},
},
ResourceGroupName = "res4410",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storage.FileServiceProperties;
import com.pulumi.azurenative.storage.FileServicePropertiesArgs;
import com.pulumi.azurenative.storage.inputs.ProtocolSettingsArgs;
import com.pulumi.azurenative.storage.inputs.SmbSettingArgs;
import com.pulumi.azurenative.storage.inputs.MultichannelArgs;
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 fileServiceProperties = new FileServiceProperties("fileServiceProperties", FileServicePropertiesArgs.builder()
.accountName("sto8607")
.fileServicesName("default")
.protocolSettings(ProtocolSettingsArgs.builder()
.smb(SmbSettingArgs.builder()
.multichannel(MultichannelArgs.builder()
.enabled(true)
.build())
.build())
.build())
.resourceGroupName("res4410")
.build());
}
}
resources:
fileServiceProperties:
type: azure-native:storage:FileServiceProperties
properties:
accountName: sto8607
fileServicesName: default
protocolSettings:
smb:
multichannel:
enabled: true
resourceGroupName: res4410
The protocolSettings property contains SMB-specific configuration. Setting multichannel.enabled to true allows clients that support SMB 3.x to open multiple TCP connections to the same file share, distributing I/O across network paths. This improves performance for large file transfers and high-throughput scenarios.
Restrict SMB protocol versions and encryption
Organizations with security requirements often need to enforce specific SMB versions, authentication methods, and encryption standards.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const fileServiceProperties = new azure_native.storage.FileServiceProperties("fileServiceProperties", {
accountName: "sto8607",
fileServicesName: "default",
protocolSettings: {
smb: {
authenticationMethods: "NTLMv2;Kerberos",
channelEncryption: "AES-128-CCM;AES-128-GCM;AES-256-GCM",
kerberosTicketEncryption: "RC4-HMAC;AES-256",
versions: "SMB2.1;SMB3.0;SMB3.1.1",
},
},
resourceGroupName: "res4410",
});
import pulumi
import pulumi_azure_native as azure_native
file_service_properties = azure_native.storage.FileServiceProperties("fileServiceProperties",
account_name="sto8607",
file_services_name="default",
protocol_settings={
"smb": {
"authentication_methods": "NTLMv2;Kerberos",
"channel_encryption": "AES-128-CCM;AES-128-GCM;AES-256-GCM",
"kerberos_ticket_encryption": "RC4-HMAC;AES-256",
"versions": "SMB2.1;SMB3.0;SMB3.1.1",
},
},
resource_group_name="res4410")
package main
import (
storage "github.com/pulumi/pulumi-azure-native-sdk/storage/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := storage.NewFileServiceProperties(ctx, "fileServiceProperties", &storage.FileServicePropertiesArgs{
AccountName: pulumi.String("sto8607"),
FileServicesName: pulumi.String("default"),
ProtocolSettings: &storage.ProtocolSettingsArgs{
Smb: &storage.SmbSettingArgs{
AuthenticationMethods: pulumi.String("NTLMv2;Kerberos"),
ChannelEncryption: pulumi.String("AES-128-CCM;AES-128-GCM;AES-256-GCM"),
KerberosTicketEncryption: pulumi.String("RC4-HMAC;AES-256"),
Versions: pulumi.String("SMB2.1;SMB3.0;SMB3.1.1"),
},
},
ResourceGroupName: pulumi.String("res4410"),
})
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 fileServiceProperties = new AzureNative.Storage.FileServiceProperties("fileServiceProperties", new()
{
AccountName = "sto8607",
FileServicesName = "default",
ProtocolSettings = new AzureNative.Storage.Inputs.ProtocolSettingsArgs
{
Smb = new AzureNative.Storage.Inputs.SmbSettingArgs
{
AuthenticationMethods = "NTLMv2;Kerberos",
ChannelEncryption = "AES-128-CCM;AES-128-GCM;AES-256-GCM",
KerberosTicketEncryption = "RC4-HMAC;AES-256",
Versions = "SMB2.1;SMB3.0;SMB3.1.1",
},
},
ResourceGroupName = "res4410",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storage.FileServiceProperties;
import com.pulumi.azurenative.storage.FileServicePropertiesArgs;
import com.pulumi.azurenative.storage.inputs.ProtocolSettingsArgs;
import com.pulumi.azurenative.storage.inputs.SmbSettingArgs;
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 fileServiceProperties = new FileServiceProperties("fileServiceProperties", FileServicePropertiesArgs.builder()
.accountName("sto8607")
.fileServicesName("default")
.protocolSettings(ProtocolSettingsArgs.builder()
.smb(SmbSettingArgs.builder()
.authenticationMethods("NTLMv2;Kerberos")
.channelEncryption("AES-128-CCM;AES-128-GCM;AES-256-GCM")
.kerberosTicketEncryption("RC4-HMAC;AES-256")
.versions("SMB2.1;SMB3.0;SMB3.1.1")
.build())
.build())
.resourceGroupName("res4410")
.build());
}
}
resources:
fileServiceProperties:
type: azure-native:storage:FileServiceProperties
properties:
accountName: sto8607
fileServicesName: default
protocolSettings:
smb:
authenticationMethods: NTLMv2;Kerberos
channelEncryption: AES-128-CCM;AES-128-GCM;AES-256-GCM
kerberosTicketEncryption: RC4-HMAC;AES-256
versions: SMB2.1;SMB3.0;SMB3.1.1
resourceGroupName: res4410
The smb property within protocolSettings controls which protocol features are allowed. The versions property restricts which SMB protocol versions clients can use (semicolon-separated list). The authenticationMethods property specifies allowed authentication mechanisms (NTLMv2, Kerberos). The channelEncryption property defines permitted encryption algorithms for SMB channel security. The kerberosTicketEncryption property controls Kerberos ticket encryption methods. These settings let you disable older, less secure protocols while maintaining compatibility with clients that support modern standards.
Beyond these examples
These snippets focus on specific file service features: CORS configuration for browser access and SMB protocol tuning. They’re intentionally minimal rather than complete file storage solutions.
The examples reference pre-existing infrastructure such as storage accounts and resource groups. They focus on configuring the file service rather than provisioning the storage account itself.
To keep things focused, common file service patterns are omitted, including:
- Share soft delete retention policies (shareDeleteRetentionPolicy)
- File share creation and management
- Identity-based authentication (Active Directory integration)
- Network access controls and private endpoints
These omissions are intentional: the goal is to illustrate how each file service feature is wired, not provide drop-in storage modules. See the FileServiceProperties resource reference for all available configuration options.
Let's configure Azure File Service Properties
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Resource Configuration & Constraints
fileServicesName parameter only accepts the value default. This is a fixed constraint for Azure File service configuration.accountName, fileServicesName, and resourceGroupName properties are immutable and cannot be modified after the resource is created.CORS Configuration
CorsRule elements in your configuration.CorsRule elements disables CORS entirely for the File service.allowedHeaders, allowedOrigins, and exposedHeaders. You can use patterns like x-ms-meta-* or * for all values.SMB Protocol Settings
protocolSettings.smb.multichannel.enabled to true to enable SMB multichannel for improved performance.Use protocolSettings.smb with semicolon-delimited strings for security options:
authenticationMethods: e.g.,NTLMv2;KerberoschannelEncryption: e.g.,AES-128-CCM;AES-128-GCM;AES-256-GCMkerberosTicketEncryption: e.g.,RC4-HMAC;AES-256versions: e.g.,SMB2.1;SMB3.0;SMB3.1.1