이 빠른 시작에서는 Azure Resource Manager(ARM) 템플릿과 API 버전 2025-03-01을 사용해 Azure Application Gateway에 상호 TLS(mTLS) 패스스루 를 배포하는 방법을 보여줍니다. 통과 모드에서 게이트웨이는 클라이언트 인증서를 요청하지만 유효성을 검사하지는 않습니다. 인증서 유효성 검사 및 정책 적용은 백 엔드에서 발생합니다.
주요 기능
- mTLS 통과에 대한 수신기와 SSL 프로필을 연결합니다.
- 게이트웨이에는 클라이언트 CA 인증서가 필요하지 않습니다.
-
verifyClientAuthMode속성은Strict및Passthrough값을 지원합니다. - 포털 지원: Azure 포털에서 직접 mTLS 패스스루를 구성할 수 있습니다.
비고
통과 구성에 대한 PowerShell 및 CLI 지원은 현재 사용할 수 없습니다. Azure 포털 또는 ARM 템플릿을 사용하여 mTLS 통과를 구성할 수 있습니다.
Azure 포털을 사용하여 mTLS 패스스루 구성
Azure 포털에서 Passthrough 클라이언트 인증 방법으로 SSL 프로필을 만들어 mTLS 통과를 직접 구성할 수 있습니다.
Azure 포털에서 Application Gateway 리소스로 이동합니다.
설정에서 SSL 프로필을 선택합니다.
+ 추가를 선택하여 새 SSL 프로필을 만듭니다.
SSL 프로필의 이름을 입력합니다.
클라이언트 인증 탭에서 통과를 선택합니다.
통과 모드에서 클라이언트 인증서는 선택 사항이며 백 엔드 서버는 클라이언트 인증을 담당합니다.
- 필요에 따라 SSL 정책 설정을 구성합니다.
- 추가를 선택하여 SSL 프로필을 만듭니다.
- SSL 프로필을 HTTPS 수신기와 연결합니다.
필수 조건
- Azure 구독 및 리소스 그룹입니다.
- Azure CLI 로컬로 설치됩니다.
- SSL 인증서(Base64로 인코딩된 PFX) 및 암호입니다.
- Linux VM 관리자용 SSH 키입니다(해당하는 경우).
- 패스스루 속성에 대한 API 버전
2025-03-01이상 사용.
mTLS 통과 수신기를 사용하여 Application Gateway 배포
이 템플릿은 다음과 같은 리소스를 만듭니다.
- 두 개의 서브넷이 있는 가상 네트워크(하나는 Application Gateway에 위임됨)입니다.
- 게이트웨이 프런트 엔드의 공용 IP 주소입니다.
- 다음과 같은 Application Gateway(Standard_v2):
- 클라이언트 인증서 통과에 대한 SSL 인증서 및 SSL 프로필입니다.
- HTTPS 수신기 및 라우팅 규칙입니다.
- 앱 서비스를 가리키는 백 엔드 풀입니다.
구성 세부 정보로 템플릿을 업데이트하고 유효한 SSL 인증서를 포함합니다.
매개 변수 파일: deploymentParameters.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"addressPrefix": {
"value": "10.0.0.0/16"
},
"subnetPrefix": {
"value": "10.0.0.0/24"
},
"skuName": {
"value": "Standard_v2"
},
"capacity": {
"value": 2
},
"adminUsername": {
"value": "ubuntu"
},
"adminSSHKey": {
"value": "<your-ssh-public-key>"
},
"certData": {
"value": "<Base64-encoded-PFX-data>"
},
"certPassword": {
"value": "<certificate-password>"
}
}
}
템플릿 파일: deploymentTemplate.json
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"addressPrefix": {
"defaultValue": "10.0.0.0/16",
"type": "String",
"metadata": {
"description": "Address prefix for the Virtual Network"
}
},
"subnetPrefix": {
"defaultValue": "10.0.0.0/24",
"type": "String",
"metadata": {
"description": "Subnet prefix"
}
},
"skuName": {
"defaultValue": "Standard_Medium",
"type": "String",
"metadata": {
"description": "Sku Name"
}
},
"capacity": {
"defaultValue": 2,
"type": "Int",
"metadata": {
"description": "Number of instances"
}
},
"adminUsername": {
"type": "String"
},
"adminSSHKey": {
"type": "securestring"
},
"certData": {
"type": "String",
"metadata": {
"description": "ssl cert data"
}
},
"certPassword": {
"type": "SecureString",
"metadata": {
"description": "ssl cert password"
}
}
},
"variables": {
"applicationGatewayName": "mtlsAppGw",
"idName": "identity",
"publicIPAddressName": "mtlsPip",
"virtualNetworkName": "mtlsVnet",
"subnetName": "appgwsubnet",
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]",
"subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
"publicIPRef": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]",
"applicationGatewayID": "[resourceId('Microsoft.Network/applicationGateways',variables('applicationGatewayName'))]",
"apiVersion": "2025-03-01",
"identityID": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities',variables('idName'))]",
"backendSubnetId": "[concat(variables('vnetID'),'/subnets/backendsubnet')]"
},
"resources": [
{
"type": "Microsoft.Network/virtualNetworks",
"name": "[variables('virtualNetworkName')]",
"apiVersion": "2024-07-01",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('addressPrefix')]"
]
},
"subnets": [
{
"name": "[variables('subnetName')]",
"properties": {
"addressPrefix": "[parameters('subnetPrefix')]",
"delegations": [
{
"name": "Microsoft.Network/applicationGateways",
"properties": {
"serviceName": "Microsoft.Network/applicationGateways"
}
}
]
}
},
{
"name": "backendSubnet",
"properties": {
"addressPrefix": "10.0.2.0/24"
}
}
]
}
},
{
"type": "Microsoft.Network/publicIPAddresses",
"sku": {
"name": "Standard"
},
"name": "[variables('publicIPAddressName')]",
"apiVersion": "2024-07-01",
"location": "[resourceGroup().location]",
"properties": {
"publicIPAllocationMethod": "Static"
}
},
{
"type": "Microsoft.Network/applicationGateways",
"name": "[variables('applicationGatewayName')]",
"apiVersion": "[variables('apiVersion')]",
"location": "[resourceGroup().location]",
"properties": {
"sku": {
"name": "Standard_v2",
"tier": "Standard_v2",
"capacity": 3
},
"sslCertificates": [
{
"name": "sslCert",
"properties": {
"data": "[parameters('certData')]",
"password": "[parameters('certPassword')]"
}
}
],
"sslPolicy": {
"policyType": "Predefined",
"policyName": "AppGwSslPolicy20220101"
},
"sslProfiles": [
{
"name": "sslnotrustedcert",
"id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('applicationGatewayName')), '/sslProfiles/sslnotrustedcert')]",
"properties": {
"clientAuthConfiguration": {
"VerifyClientCertIssuerDN": false,
"VerifyClientRevocation": "None",
"VerifyClientAuthMode": "Passthrough"
}
}
}
],
"gatewayIPConfigurations": [
{
"name": "appGatewayIpConfig",
"properties": {
"subnet": {
"id": "[variables('subnetRef')]"
}
}
}
],
"frontendIPConfigurations": [
{
"name": "appGatewayFrontendIP",
"properties": {
"PublicIPAddress": {
"id": "[variables('publicIPRef')]"
}
}
}
],
"frontendPorts": [
{
"name": "port2",
"properties": {
"Port": 444
}
}
],
"backendAddressPools": [
{
"name": "pool2",
"properties": {
"BackendAddresses": [
{
"fqdn": "headerappgw-hsa5gjh8fpfebcfd.westus-01.azurewebsites.net"
}
]
}
}
],
"backendHttpSettingsCollection": [
{
"name": "settings2",
"properties": {
"Port": 80,
"Protocol": "Http"
}
}
],
"httpListeners": [
{
"name": "listener2",
"properties": {
"FrontendIPConfiguration": {
"Id": "[concat(variables('applicationGatewayID'), '/frontendIPConfigurations/appGatewayFrontendIP')]"
},
"FrontendPort": {
"Id": "[concat(variables('applicationGatewayID'), '/frontendPorts/port2')]"
},
"Protocol": "Https",
"SslCertificate": {
"Id": "[concat(variables('applicationGatewayID'), '/sslCertificates/sslCert')]"
},
"sslProfile": {
"id": "[concat(variables('applicationGatewayID'), '/sslProfiles/sslnotrustedcert')]"
}
}
}
],
"requestRoutingRules": [
{
"Name": "rule2",
"properties": {
"RuleType": "Basic",
"priority": 2000,
"httpListener": {
"id": "[concat(variables('applicationGatewayID'), '/httpListeners/listener2')]"
},
"backendAddressPool": {
"id": "[concat(variables('applicationGatewayID'), '/backendAddressPools/pool2')]"
},
"backendHttpSettings": {
"id": "[concat(variables('applicationGatewayID'), '/backendHttpSettingsCollection/settings2')]"
}
}
}
]
},
"dependsOn": [
"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]"
]
}
]
}
템플릿 배포
다음 Azure CLI 명령을 실행하여 템플릿을 배포합니다.
az deployment group create \
--resource-group <your-resource-group> \
--template-file deploymentTemplate.json \
--parameters @deploymentParameters.json
유효성 검사 및 테스트
배포 유효성 검사
Azure Portal에서 Application Gateway 리소스로 이동합니다.
JSON 보기를 선택하고 API 버전을
2025-03-01선택합니다.SSL 프로필에서
verifyClientAuthMode가Passthrough로 설정되어 있는지 확인합니다."sslProfiles": [ { "name": "sslnotrustedcert", "id": "<sample-subscription-id>", "etag": "W/\"851e4e20-d2b1-4338-9135-e0beac11aa0e\"", "properties": { "provisioningState": "Succeeded", "clientAuthConfiguration": { "verifyClientCertIssuerDN": false, "verifyClientRevocation": "None", "verifyClientAuthMode": "Passthrough" }, "httpListeners": [ { "id": "<sample-subscription-id>" } ] } } ]
백 엔드에 클라이언트 인증서 보내기
클라이언트 인증서를 백 엔드로 전달해야 하는 경우 다시 쓰기 규칙을 구성합니다. 자세한 내용은 Application Gateway를 사용하여 HTTP 헤더 및 URL 다시 쓰기를 참조하세요.
클라이언트가 인증서를 보내면 이 다시 쓰기를 통해 백 엔드 처리를 위해 클라이언트 인증서가 요청 헤더에 포함됩니다.
연결 테스트
클라이언트 인증서가 제공되지 않은 경우에도 연결이 설정되는지 확인합니다.
mTLS 통과 매개 변수
다음 표에서는 mTLS 통과 구성에 대한 매개 변수를 설명합니다.
| 이름 | 유형 | Description |
|---|---|---|
verifyClientCertIssuerDN |
Boolean | 게이트웨이에서 클라이언트 인증서 발급자 이름을 확인할지 여부를 지정합니다. |
verifyClientRevocation |
String | 클라이언트 인증서 해지 확인 모드를 지정합니다. |
verifyClientAuthMode |
String | 클라이언트 인증서 모드를 지정합니다. 유효한 값은 Strict 및 Passthrough입니다. |
통과 모드: 게이트웨이는 클라이언트 인증서를 요청하지만 적용하지는 않습니다. 백 엔드는 인증서의 유효성을 검사하고 정책을 적용합니다.
보안 고려 사항
이 솔루션을 배포하고 관리할 때 조직의 보안 및 데이터 처리 모범 사례를 따릅니다.