Skip to content

Commit 71b205d

Browse files
authored
Fixes Azure.AppService.PHPVersion when phpVersion is null Azure#2768 (Azure#2770)
1 parent 4653664 commit 71b205d

11 files changed

+648
-99
lines changed

data/policy-ignore.json

+8
Original file line numberDiff line numberDiff line change
@@ -228,5 +228,13 @@
228228
],
229229
"reason": "Duplicate",
230230
"value": "Azure.AppService.WebSecureFtp"
231+
},
232+
{
233+
"policyDefinitionIds": [
234+
"/providers/Microsoft.Authorization/policyDefinitions/7261b898-8a84-4db8-9e04-18527132abb3",
235+
"/providers/Microsoft.Authorization/policyDefinitions/f466b2a6-823d-470d-8ea5-b031e72d79ae"
236+
],
237+
"reason": "Duplicate",
238+
"value": "Azure.AppService.PHPVersion"
231239
}
232240
]

docs/CHANGELOG-v1.md

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ What's changed since pre-release v1.35.0-B0030:
3838
- Updated `Azure.AppService.NETVersion` to detect out of date .NET versions including .NET 5/6/7 by @BernieWhite.
3939
[#2766](https://github.com/Azure/PSRule.Rules.Azure/issues/2766)
4040
- Bumped rule set to `2024_03`.
41+
- Updated `Azure.AppService.PHPVersion` to detect out of date PHP versions before 8.2 by @BernieWhite.
42+
[#2768](https://github.com/Azure/PSRule.Rules.Azure/issues/2768)
43+
- Fixed `Azure.AppService.PHPVersion` check fails when phpVersion is null.
44+
- Bumped rule set to `2024_03`.
4145
- General improvements:
4246
- Quality updates to rule documentation by @BernieWhite.
4347
[#2570](https://github.com/Azure/PSRule.Rules.Azure/issues/2570)
+56-40
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
2-
reviewed: 2022-05-14
2+
reviewed: 2024-03-24
33
severity: Important
44
pillar: Security
5-
category: Deployment
5+
category: SE:02 Secured development lifecycle
66
resource: App Service
77
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.AppService.PHPVersion/
88
---
@@ -16,62 +16,65 @@ Configure applications to use newer PHP runtime versions.
1616
## DESCRIPTION
1717

1818
Within a App Service app, the version of PHP runtime used to run application/ site code is configurable.
19-
Older versions of PHP may not use the latest security features.
19+
20+
Overtime, a specific version of PHP may become outdated and no longer supported by Microsoft in Azure App Service.
21+
This can lead to security vulnerabilities or are simply not able to use the latest security features.
22+
23+
PHP 8.0 and 8.1 are approaching end of support.
2024

2125
## RECOMMENDATION
2226

23-
Consider updating the site to use a newer PHP runtime version such as `7.4`.
27+
Consider updating the site to use a newer PHP runtime version such as `8.2`.
2428

2529
## EXAMPLES
2630

2731
### Configure with Azure template
2832

2933
To deploy App Services that pass this rule:
3034

31-
- Set `properties.siteConfig.phpVersion` to a minimum of `7.0`.
35+
- Set `properties.siteConfig.linuxFxVersion` to a minimum of `PHP|8.2`.
3236

3337
For example:
3438

3539
```json
3640
{
37-
"type": "Microsoft.Web/sites",
38-
"apiVersion": "2021-03-01",
39-
"name": "[parameters('name')]",
40-
"location": "[parameters('location')]",
41-
"identity": {
42-
"type": "SystemAssigned"
43-
},
44-
"kind": "web",
45-
"properties": {
46-
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('planName'))]",
47-
"httpsOnly": true,
48-
"siteConfig": {
49-
"alwaysOn": true,
50-
"minTlsVersion": "1.2",
51-
"ftpsState": "FtpsOnly",
52-
"remoteDebuggingEnabled": false,
53-
"http20Enabled": true,
54-
"netFrameworkVersion": "OFF",
55-
"phpVersion": "7.4"
56-
}
57-
},
58-
"tags": "[parameters('tags')]",
59-
"dependsOn": [
60-
"[resourceId('Microsoft.Web/serverfarms', parameters('planName'))]"
61-
]
41+
"type": "Microsoft.Web/sites",
42+
"apiVersion": "2023-01-01",
43+
"name": "[parameters('name')]",
44+
"location": "[parameters('location')]",
45+
"identity": {
46+
"type": "SystemAssigned"
47+
},
48+
"kind": "web",
49+
"properties": {
50+
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('planName'))]",
51+
"httpsOnly": true,
52+
"clientAffinityEnabled": false,
53+
"siteConfig": {
54+
"alwaysOn": true,
55+
"minTlsVersion": "1.2",
56+
"ftpsState": "Disabled",
57+
"http20Enabled": true,
58+
"healthCheckPath": "/healthz",
59+
"linuxFxVersion": "PHP|8.2"
60+
}
61+
},
62+
"dependsOn": [
63+
"[resourceId('Microsoft.Web/serverfarms', parameters('planName'))]"
64+
]
6265
}
6366
```
6467

6568
### Configure with Bicep
6669

6770
To deploy App Services that pass this rule:
6871

69-
- Set `properties.siteConfig.phpVersion` to a minimum of `7.0`.
72+
- Set `properties.siteConfig.linuxFxVersion` to a minimum of `PHP|8.2`.
7073

7174
For example:
7275

7376
```bicep
74-
resource webAppPHP 'Microsoft.Web/sites@2021-03-01' = {
77+
resource php 'Microsoft.Web/sites@2023-01-01' = {
7578
name: name
7679
location: location
7780
identity: {
@@ -81,22 +84,35 @@ resource webAppPHP 'Microsoft.Web/sites@2021-03-01' = {
8184
properties: {
8285
serverFarmId: plan.id
8386
httpsOnly: true
87+
clientAffinityEnabled: false
8488
siteConfig: {
8589
alwaysOn: true
8690
minTlsVersion: '1.2'
87-
ftpsState: 'FtpsOnly'
88-
remoteDebuggingEnabled: false
91+
ftpsState: 'Disabled'
8992
http20Enabled: true
90-
netFrameworkVersion: 'OFF'
91-
phpVersion: '7.4'
93+
healthCheckPath: '/healthz'
94+
linuxFxVersion: 'PHP|8.2'
9295
}
9396
}
94-
tags: tags
9597
}
9698
```
9799

100+
### Configure with Azure Policy
101+
102+
To address this issue at runtime use the following policies:
103+
104+
- [App Service apps that use PHP should use a specified 'PHP version'](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/App%20Service/Webapp_Audit_PHP_Latest.json)
105+
`/providers/Microsoft.Authorization/policyDefinitions/7261b898-8a84-4db8-9e04-18527132abb3`
106+
- [App Service app slots that use PHP should use a specified 'PHP version'](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/App%20Service/Webapp_Slot_Audit_PHP_Latest.json)
107+
`/providers/Microsoft.Authorization/policyDefinitions/f466b2a6-823d-470d-8ea5-b031e72d79ae`
108+
109+
## NOTES
110+
111+
From November 2022 - PHP is only supported on Linux-based plans.
112+
98113
## LINKS
99114

100-
- [Security design principles](https://learn.microsoft.com/azure/architecture/framework/security/security-principles#protect-against-code-level-vulnerabilities)
101-
- [Set PHP Version](https://docs.microsoft.com/azure/app-service/configure-language-php#set-php-version)
102-
- [Azure deployment reference](https://docs.microsoft.com/azure/templates/microsoft.web/sites#siteconfig)
115+
- [SE:02 Secured development lifecycle](https://learn.microsoft.com/azure/well-architected/security/secure-development-lifecycle)
116+
- [Set PHP Version](https://learn.microsoft.com/azure/app-service/configure-language-php?pivots=platform-linux#set-php-version)
117+
- [PHP on App Service](https://github.com/Azure/app-service-linux-docs/blob/master/Runtime_Support/php_support.md)
118+
- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.web/sites)

docs/examples-appservice.bicep

+24
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ resource web 'Microsoft.Web/sites@2023-01-01' = {
3636
properties: {
3737
serverFarmId: plan.id
3838
httpsOnly: true
39+
clientAffinityEnabled: false
3940
siteConfig: {
4041
alwaysOn: true
4142
minTlsVersion: '1.2'
@@ -54,6 +55,29 @@ resource web 'Microsoft.Web/sites@2023-01-01' = {
5455
}
5556
}
5657

58+
// An example PHP Web App running on a Linux App Services Plan.
59+
resource php 'Microsoft.Web/sites@2023-01-01' = {
60+
name: name
61+
location: location
62+
identity: {
63+
type: 'SystemAssigned'
64+
}
65+
kind: 'web'
66+
properties: {
67+
serverFarmId: plan.id
68+
httpsOnly: true
69+
clientAffinityEnabled: false
70+
siteConfig: {
71+
alwaysOn: true
72+
minTlsVersion: '1.2'
73+
ftpsState: 'Disabled'
74+
http20Enabled: true
75+
healthCheckPath: '/healthz'
76+
linuxFxVersion: 'PHP|8.2'
77+
}
78+
}
79+
}
80+
5781
// Disable basic publishing credentials for FTP.
5882
resource ftp 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2023-01-01' = {
5983
parent: web

docs/examples-appservice.json

+28-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"_generator": {
66
"name": "bicep",
77
"version": "0.26.54.24096",
8-
"templateHash": "210994321631769997"
8+
"templateHash": "10435733640424545318"
99
}
1010
},
1111
"parameters": {
@@ -55,6 +55,7 @@
5555
"properties": {
5656
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('planName'))]",
5757
"httpsOnly": true,
58+
"clientAffinityEnabled": false,
5859
"siteConfig": {
5960
"alwaysOn": true,
6061
"minTlsVersion": "1.2",
@@ -75,6 +76,32 @@
7576
"[resourceId('Microsoft.Web/serverfarms', parameters('planName'))]"
7677
]
7778
},
79+
{
80+
"type": "Microsoft.Web/sites",
81+
"apiVersion": "2023-01-01",
82+
"name": "[parameters('name')]",
83+
"location": "[parameters('location')]",
84+
"identity": {
85+
"type": "SystemAssigned"
86+
},
87+
"kind": "web",
88+
"properties": {
89+
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('planName'))]",
90+
"httpsOnly": true,
91+
"clientAffinityEnabled": false,
92+
"siteConfig": {
93+
"alwaysOn": true,
94+
"minTlsVersion": "1.2",
95+
"ftpsState": "Disabled",
96+
"http20Enabled": true,
97+
"healthCheckPath": "/healthz",
98+
"linuxFxVersion": "PHP|8.2"
99+
}
100+
},
101+
"dependsOn": [
102+
"[resourceId('Microsoft.Web/serverfarms', parameters('planName'))]"
103+
]
104+
},
78105
{
79106
"type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies",
80107
"apiVersion": "2023-01-01",

src/PSRule.Rules.Azure/rules/Azure.AppService.Rule.ps1

+24-11
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,33 @@ Rule 'Azure.AppService.NETVersion' -Ref 'AZR-000075' -Type 'Microsoft.Web/sites'
7171
}
7272

7373
# Synopsis: Configure applications to use newer PHP runtime versions.
74-
Rule 'Azure.AppService.PHPVersion' -Ref 'AZR-000076' -Type 'Microsoft.Web/sites', 'Microsoft.Web/sites/slots' -Tag @{ release = 'GA'; ruleSet = '2020_12'; 'Azure.WAF/pillar' = 'Security'; } {
75-
$siteConfigs = @(GetWebSiteConfig | Where-Object {
76-
![String]::IsNullOrEmpty($_.Properties.phpVersion)
77-
})
74+
Rule 'Azure.AppService.PHPVersion' -Ref 'AZR-000076' -Type 'Microsoft.Web/sites', 'Microsoft.Web/sites/slots' -Tag @{ release = 'GA'; ruleSet = '2024_03'; 'Azure.WAF/pillar' = 'Security'; } {
75+
$siteConfigs = @(GetWebSiteConfig)
7876
if ($siteConfigs.Length -eq 0) {
79-
return AnyOf {
80-
$Assert.HasDefaultValue($TargetObject, 'Properties.siteConfig.phpVersion', 'OFF')
81-
$Assert.Version($TargetObject, 'Properties.siteConfig.phpVersion', '>=7.0')
77+
if ($Assert.HasFieldValue($TargetObject, 'properties.siteConfig.linuxFxVersion').Result -and $TargetObject.properties.siteConfig.linuxFxVersion -like 'PHP|*') {
78+
$linuxVersion = $TargetObject.properties.siteConfig.linuxFxVersion.Split('|')[1];
79+
return $Assert.Version($linuxVersion, '.', '>=8.2').PathPrefix('properties.siteConfig.linuxFxVersion');
80+
}
81+
elseif (!$Assert.HasDefaultValue($TargetObject, 'properties.siteConfig.phpVersion', 'OFF').Result -and
82+
![String]::IsNullOrEmpty($TargetObject.properties.siteConfig.phpVersion)) {
83+
return $Assert.Version($TargetObject, 'properties.siteConfig.phpVersion', '>=8.2');
84+
}
85+
else {
86+
return $Assert.Pass();
8287
}
8388
}
8489
foreach ($siteConfig in $siteConfigs) {
85-
AnyOf {
86-
$Assert.HasFieldValue($siteConfig, 'Properties.phpVersion', 'OFF')
87-
$Assert.Version($siteConfig, 'Properties.phpVersion', '>=7.0')
90+
$path = $siteConfig._PSRule.path;
91+
if ($Assert.HasFieldValue($siteConfig, 'properties.linuxFxVersion').Result -and $siteConfig.properties.linuxFxVersion -like 'PHP|*') {
92+
$linuxVersion = $siteConfig.properties.linuxFxVersion.Split('|')[1];
93+
$Assert.Version($linuxVersion, '.', '>=8.2').PathPrefix("$path.properties.linuxFxVersion");
94+
}
95+
elseif (!$Assert.HasDefaultValue($siteConfig, 'properties.phpVersion', 'OFF').Result -and
96+
![String]::IsNullOrEmpty($siteConfig.properties.phpVersion)) {
97+
$Assert.Version($siteConfig, 'properties.phpVersion', '>=8.2').PathPrefix($path);
98+
}
99+
else {
100+
$Assert.Pass();
88101
}
89102
}
90103
}
@@ -96,7 +109,7 @@ Rule 'Azure.AppService.AlwaysOn' -Ref 'AZR-000077' -Type 'Microsoft.Web/sites',
96109
return $Assert.HasFieldValue($TargetObject, 'Properties.siteConfig.alwaysOn', $True);
97110
}
98111
foreach ($siteConfig in $siteConfigs) {
99-
$Assert.HasFieldValue($siteConfig, 'Properties.alwaysOn', $True);
112+
$Assert.HasFieldValue($siteConfig, 'properties.alwaysOn', $True);
100113
}
101114
}
102115

src/PSRule.Rules.Azure/rules/Azure.AppService.Rule.yaml

+8-6
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,15 @@ spec:
124124
allOf:
125125
- type: '.'
126126
in:
127-
- 'Microsoft.Web/sites'
128-
- 'Microsoft.Web/sites/slots'
127+
- Microsoft.Web/sites
128+
- Microsoft.Web/sites/slots
129129
- anyOf:
130130
- field: kind
131131
exists: false
132132
- field: kind
133-
equals: 'app'
133+
in:
134+
- app
135+
- app,linux
134136

135137
---
136138
# Synopsis: App Service sites that are API apps.
@@ -145,10 +147,10 @@ spec:
145147
allOf:
146148
- type: '.'
147149
in:
148-
- 'Microsoft.Web/sites'
149-
- 'Microsoft.Web/sites/slots'
150+
- Microsoft.Web/sites
151+
- Microsoft.Web/sites/slots
150152
- field: kind
151-
equals: 'api'
153+
equals: api
152154

153155
---
154156
# Synopsis: App Service sites that are Function apps.

0 commit comments

Comments
 (0)