Skip to content

Commit ed7b83c

Browse files
feat: use storage account with disabled public access for function app
1 parent bc72399 commit ed7b83c

23 files changed

+749
-336
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,19 @@ private_dns_rg_name = "myResourceGroup"
6565
```
6666
**If you don't pass these params, we will automatically create the network resources for you.**
6767

68+
## Using pre-created storage account with disabled public access
69+
To use secured storage account with function app, user should create private storage account first, and then upload our function code zip file to the container `<deployment_container_name>`.
70+
Zip file is accessible in our public storage acccount by this url:
71+
https://wekaeastus.blob.core.windows.net/weka-tf-functions-deployment-eastus/dev/c52522f254123df61cd906bbf3dce6af.zip
72+
73+
```hcl
74+
allow_sa_public_network_access = false
75+
deployment_function_app_code_blob = "function_app_code.zip"
76+
deployment_storage_account_name = "myprivatestorage"
77+
deployment_container_name = "weka-deployment"
78+
```
79+
User should also create file share in storage account with the name `${var.deployment_container_name}-share`.
80+
6881
## Usage example
6982
```hcl
7083
provider "azurerm" {

Taskfile.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ tasks:
2727

2828
write_function_hash_to_variables:
2929
cmds:
30-
- ./zip_function_app_creation/write_function_hash_to_variables.sh {{OS}} ${FUNCTION_CODE_PATH}
30+
- ./zip_function_app_creation/write_function_hash_to_variables.sh ${DIST} {{OS}} ${FUNCTION_CODE_PATH}
3131

3232
create_and_upload_zip:
3333
preconditions:

blob.tf

Lines changed: 102 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
locals {
2-
clusterization_target = var.clusterization_target != null ? var.clusterization_target : min(var.cluster_size, max(20, ceil(var.cluster_size * 0.8)))
3-
# fields that depend on LB creation
4-
vmss_health_probe_id = var.create_lb ? azurerm_lb_probe.backend_lb_probe[0].id : null
5-
lb_backend_pool_ids = var.create_lb ? [azurerm_lb_backend_address_pool.lb_backend_pool[0].id] : []
2+
deployment_storage_account_id = var.deployment_storage_account_name == "" ? azurerm_storage_account.deployment_sa[0].id : data.azurerm_storage_account.deployment_blob[0].id
3+
deployment_storage_account_name = var.deployment_storage_account_name == "" ? azurerm_storage_account.deployment_sa[0].name : var.deployment_storage_account_name
4+
deployment_sa_connection_string = var.deployment_storage_account_name == "" ? azurerm_storage_account.deployment_sa[0].primary_connection_string : data.azurerm_storage_account.deployment_blob[0].primary_connection_string
5+
deployment_container_name = var.deployment_container_name == "" ? "${local.alphanumeric_prefix_name}${local.alphanumeric_cluster_name}-deployment" : var.deployment_container_name
6+
deployment_sa_access_key = var.deployment_storage_account_name == "" ? azurerm_storage_account.deployment_sa[0].primary_access_key : data.azurerm_storage_account.deployment_blob[0].primary_access_key
67
}
78

8-
99
resource "azurerm_storage_account" "deployment_sa" {
10-
count = var.deployment_storage_account_name == "" ? 1 : 0
10+
count = var.deployment_storage_account_name == "" && var.allow_sa_public_network_access ? 1 : 0
1111
name = substr("${local.alphanumeric_prefix_name}${local.alphanumeric_cluster_name}deployment", 0, 24)
12-
location = data.azurerm_resource_group.rg.location
12+
location = local.location
1313
resource_group_name = var.rg_name
1414
account_kind = "StorageV2"
1515
account_tier = "Standard"
@@ -20,140 +20,119 @@ resource "azurerm_storage_account" "deployment_sa" {
2020
}
2121
}
2222

23-
resource "azurerm_storage_container" "deployment" {
24-
count = var.deployment_container_name == "" ? 1 : 0
25-
name = "${local.alphanumeric_prefix_name}${local.alphanumeric_cluster_name}-deployment"
26-
storage_account_name = local.deployment_storage_account_name
27-
container_access_type = "private"
28-
depends_on = [azurerm_storage_account.deployment_sa]
29-
}
30-
31-
resource "azurerm_storage_blob" "state" {
32-
name = "state"
33-
storage_account_name = local.deployment_storage_account_name
34-
storage_container_name = local.deployment_container_name
35-
type = "Block"
36-
source_content = "{\"initial_size\":${var.cluster_size}, \"desired_size\":${var.cluster_size}, \"instances\":[], \"clusterized\":false, \"clusterization_target\":${local.clusterization_target}}"
37-
depends_on = [azurerm_storage_container.deployment]
38-
39-
lifecycle {
40-
ignore_changes = all
41-
}
23+
resource "azurerm_storage_account" "logicapp" {
24+
count = var.allow_sa_public_network_access ? 1 : 0
25+
name = substr("${local.alphanumeric_prefix_name}${local.alphanumeric_cluster_name}logicappsa", 0, 24)
26+
resource_group_name = var.rg_name
27+
location = local.location
28+
account_tier = "Standard"
29+
account_replication_type = "LRS"
4230
}
4331

4432
data "azurerm_storage_account" "deployment_blob" {
4533
count = var.deployment_storage_account_name != "" ? 1 : 0
4634
name = var.deployment_storage_account_name
47-
resource_group_name = var.rg_name
35+
resource_group_name = local.resource_group_name
4836
}
4937

50-
resource "azurerm_storage_blob" "vmss_config" {
51-
name = "vmss-config"
52-
storage_account_name = local.deployment_storage_account_name
53-
storage_container_name = local.deployment_container_name
54-
type = "Block"
55-
56-
source_content = jsonencode({
57-
name = "${var.prefix}-${var.cluster_name}-vmss"
58-
location = data.azurerm_resource_group.rg.location
59-
zones = var.zone != null ? [var.zone] : []
60-
resource_group_name = var.rg_name
61-
sku = var.instance_type
62-
upgrade_mode = "Manual"
63-
health_probe_id = local.vmss_health_probe_id
64-
admin_username = var.vm_username
65-
ssh_public_key = local.public_ssh_key
66-
computer_name_prefix = "${var.prefix}-${var.cluster_name}-backend"
67-
custom_data = base64encode(local.custom_data_script)
68-
disable_password_authentication = true
69-
proximity_placement_group_id = local.placement_group_id
70-
single_placement_group = var.vmss_single_placement_group
71-
source_image_id = var.source_image_id
72-
overprovision = false
73-
orchestration_mode = "Uniform"
74-
tags = merge(var.tags_map, {
75-
"weka_cluster" : var.cluster_name,
76-
"user_id" : data.azurerm_client_config.current.object_id,
77-
})
38+
resource "azurerm_private_dns_zone" "blob" {
39+
count = !var.allow_sa_public_network_access && var.create_storage_account_private_links ? 1 : 0
40+
name = "privatelink.blob.core.windows.net"
41+
resource_group_name = local.resource_group_name
7842

79-
os_disk = {
80-
caching = "ReadWrite"
81-
storage_account_type = "Premium_LRS"
43+
lifecycle {
44+
precondition {
45+
condition = var.deployment_function_app_code_blob != ""
46+
error_message = "Function app code blob is not provided"
8247
}
83-
84-
data_disk = {
85-
lun = 0
86-
caching = "None"
87-
create_option = "Empty"
88-
disk_size_gb = local.disk_size
89-
storage_account_type = "Premium_LRS"
48+
precondition {
49+
condition = var.deployment_container_name != ""
50+
error_message = "Function app storage account container name is not provided"
9051
}
91-
92-
identity = {
93-
type = "UserAssigned"
94-
identity_ids = [local.vmss_identity_id]
52+
precondition {
53+
condition = var.deployment_storage_account_name != ""
54+
error_message = "Function app storage account name is not provided"
9555
}
56+
}
57+
}
9658

97-
primary_nic = {
98-
name = "${var.prefix}-${var.cluster_name}-backend-nic-0"
99-
network_security_group_id = local.sg_id
100-
enable_accelerated_networking = var.install_cluster_dpdk
59+
resource "azurerm_private_dns_zone" "file" {
60+
count = !var.allow_sa_public_network_access && var.create_storage_account_private_links ? 1 : 0
61+
name = "privatelink.file.core.windows.net"
62+
resource_group_name = local.resource_group_name
10163

102-
ip_configurations = [{
103-
primary = true
104-
subnet_id = data.azurerm_subnet.subnet.id
105-
load_balancer_backend_address_pool_ids = local.lb_backend_pool_ids
106-
public_ip_address = {
107-
assign = local.assign_public_ip
108-
name = "${var.prefix}-${var.cluster_name}-public-ip"
109-
domain_name_label = "${var.prefix}-${var.cluster_name}-backend"
110-
}
111-
}]
112-
}
64+
depends_on = [azurerm_private_dns_zone.blob]
65+
}
11366

114-
secondary_nics = {
115-
number = local.nics_numbers - 1
116-
name_prefix = "${var.prefix}-${var.cluster_name}-backend-nic"
117-
network_security_group_id = local.sg_id
118-
enable_accelerated_networking = var.install_cluster_dpdk
119-
ip_configurations = [{
120-
primary = true
121-
subnet_id = data.azurerm_subnet.subnet.id
122-
load_balancer_backend_address_pool_ids = local.lb_backend_pool_ids
123-
}]
124-
}
125-
})
126-
depends_on = [
127-
azurerm_storage_container.deployment, azurerm_lb_backend_address_pool.lb_backend_pool, azurerm_lb_probe.backend_lb_probe,
128-
azurerm_proximity_placement_group.ppg, azurerm_lb_rule.backend_lb_rule, azurerm_lb_rule.ui_lb_rule
129-
]
67+
resource "azurerm_private_dns_zone_virtual_network_link" "blob_privatelink" {
68+
count = !var.allow_sa_public_network_access && var.create_storage_account_private_links ? 1 : 0
69+
name = "${var.prefix}-${var.cluster_name}-blob-privatelink"
70+
resource_group_name = local.resource_group_name
71+
private_dns_zone_name = azurerm_private_dns_zone.blob[0].name
72+
virtual_network_id = data.azurerm_virtual_network.vnet.id
13073
}
13174

132-
# state for protocols
133-
resource "azurerm_storage_container" "nfs_deployment" {
134-
count = var.nfs_deployment_container_name == "" ? 1 : 0
135-
name = "${local.alphanumeric_prefix_name}${local.alphanumeric_cluster_name}-protocol-deployment"
136-
storage_account_name = local.deployment_storage_account_name
137-
container_access_type = "private"
138-
depends_on = [azurerm_storage_account.deployment_sa]
75+
resource "azurerm_private_dns_zone_virtual_network_link" "file_privatelink" {
76+
count = !var.allow_sa_public_network_access && var.create_storage_account_private_links ? 1 : 0
77+
name = "${var.prefix}-${var.cluster_name}-file-privatelink"
78+
resource_group_name = local.resource_group_name
79+
private_dns_zone_name = azurerm_private_dns_zone.file[0].name
80+
virtual_network_id = data.azurerm_virtual_network.vnet.id
13981
}
14082

141-
resource "azurerm_storage_blob" "nfs_state" {
142-
count = var.nfs_protocol_gateways_number > 0 ? 1 : 0
143-
name = "nfs_state"
144-
storage_account_name = local.deployment_storage_account_name
145-
storage_container_name = local.nfs_deployment_container_name
146-
type = "Block"
147-
source_content = jsonencode({
148-
initial_size = var.nfs_protocol_gateways_number
149-
desired_size = var.nfs_protocol_gateways_number
150-
instances = []
151-
clusterized = false
152-
clusterization_target = var.nfs_protocol_gateways_number
153-
})
154-
depends_on = [azurerm_storage_container.nfs_deployment]
83+
resource "azurerm_private_endpoint" "file_endpoint" {
84+
count = !var.allow_sa_public_network_access && var.create_storage_account_private_links ? 1 : 0
85+
name = "${var.prefix}-${var.cluster_name}-file-endpoint"
86+
location = data.azurerm_resource_group.rg.location
87+
resource_group_name = data.azurerm_resource_group.rg.name
88+
subnet_id = data.azurerm_subnet.subnet.id
89+
tags = merge(var.tags_map, { "weka_cluster" : var.cluster_name })
90+
91+
private_dns_zone_group {
92+
name = "${var.prefix}-${var.cluster_name}-dns-zone-group-file"
93+
private_dns_zone_ids = [azurerm_private_dns_zone.file[0].id]
94+
}
15595

156-
lifecycle {
157-
ignore_changes = all
96+
private_service_connection {
97+
name = "${var.prefix}-${var.cluster_name}-privateFileSvcCon"
98+
is_manual_connection = false
99+
private_connection_resource_id = local.deployment_storage_account_id
100+
subresource_names = ["file"]
101+
}
102+
}
103+
104+
resource "azurerm_private_endpoint" "blob_endpoint" {
105+
count = !var.allow_sa_public_network_access && var.create_storage_account_private_links ? 1 : 0
106+
name = "${var.prefix}-${var.cluster_name}-blob-endpoint"
107+
location = data.azurerm_resource_group.rg.location
108+
resource_group_name = data.azurerm_resource_group.rg.name
109+
subnet_id = data.azurerm_subnet.subnet.id
110+
tags = merge(var.tags_map, { "weka_cluster" : var.cluster_name })
111+
112+
private_dns_zone_group {
113+
name = "${var.prefix}-${var.cluster_name}-dns-zone-group-blob"
114+
private_dns_zone_ids = [azurerm_private_dns_zone.blob[0].id]
115+
}
116+
private_service_connection {
117+
name = "${var.prefix}-${var.cluster_name}-privateBlobSvcCon"
118+
is_manual_connection = false
119+
private_connection_resource_id = local.deployment_storage_account_id
120+
subresource_names = ["blob"]
121+
}
122+
}
123+
124+
data "azurerm_storage_account_blob_container_sas" "function_app_code_sas" {
125+
count = var.allow_sa_public_network_access ? 0 : 1
126+
connection_string = local.deployment_sa_connection_string
127+
container_name = local.deployment_container_name
128+
start = timestamp()
129+
expiry = formatdate("YYYY-MM-DD'T'hh:mm:ssZ", timeadd(timestamp(), "1h"))
130+
permissions {
131+
read = true
132+
add = false
133+
create = false
134+
write = false
135+
delete = false
136+
list = false
158137
}
159138
}

0 commit comments

Comments
 (0)