Skip to content

Commit c821ecc

Browse files
committed
Merge branch 'main' of https://github.com/MicrosoftDocs/azure-docs-pr into fixedMetrics
2 parents 9c87de2 + 84b7ed4 commit c821ecc

File tree

58 files changed

+896
-784
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+896
-784
lines changed

.openpublishing.redirection.virtual-desktop.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,11 @@
434434
"source_path_from_root": "/articles/virtual-desktop/configure-rdp-shortpath-limit-ports-public-networks.md",
435435
"redirect_url": "/azure/virtual-desktop/configure-rdp-shortpath",
436436
"redirect_document_id": true
437+
},
438+
{
439+
"source_path_from_root": "/articles/virtual-desktop/disaster-recovery.md",
440+
"redirect_url": "/azure/virtual-desktop/disaster-recovery-concepts",
441+
"redirect_document_id": true
437442
}
438443
]
439444
}

articles/aks/app-routing.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,14 @@ az aks create \
6363

6464
### Enable on an existing cluster
6565

66-
To enable application routing on an existing cluster, use the [`az aks approuting enable`][az-aks-approuting-enable] command.
66+
To enable application routing on an existing cluster, use the [`az aks approuting enable`][az-aks-approuting-enable] or the [`az aks enable-addons`][az-aks-enable-addons] command with the `--addons` parameter set to `http_application_routing`.
6767

6868
```azurecli-interactive
69+
# az aks approuting enable
6970
az aks approuting enable --resource-group <ResourceGroupName> --name <ClusterName>
71+
72+
# az aks enable-addons
73+
az aks enable-addons --resource-group <ResourceGroupName> --name <ClusterName> --addons http_application_routing
7074
```
7175

7276
# [Open Service Mesh (OSM) (retired)](#tab/with-osm)

articles/aks/gpu-cluster.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,10 @@ To use Azure Linux, you specify the OS SKU by setting `os-sku` to `AzureLinux` d
177177
name: nvidia-device-plugin-ds
178178
spec:
179179
tolerations:
180-
- key: nvidia.com/gpu
181-
operator: Exists
182-
effect: NoSchedule
180+
- key: "sku"
181+
operator: "Equal"
182+
value: "gpu"
183+
effect: "NoSchedule"
183184
# Mark this pod as a critical add-on; when enabled, the critical add-on
184185
# scheduler reserves resources for critical add-on pods so that they can
185186
# be rescheduled after a failure.

articles/aks/private-clusters.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Create a private cluster with default basic networking using the [`az aks create
5858
```azurecli-interactive
5959
az aks create \
6060
--name <private-cluster-name> \
61-
--resource-group-name <private-cluster-resource-group> \
61+
--resource-group <private-cluster-resource-group> \
6262
--load-balancer-sku standard \
6363
--enable-private-cluster \
6464
--generate-ssh-keys

articles/app-service/app-service-web-configure-tls-mutual-auth.md

Lines changed: 147 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ author: msangapu-msft
66
ms.author: msangapu
77
ms.assetid: cd1d15d3-2d9e-4502-9f11-a306dac4453a
88
ms.topic: article
9-
ms.date: 12/11/2020
9+
ms.date: 06/21/2024
1010
ms.devlang: csharp
11-
ms.custom: devx-track-csharp, devx-track-extended-java, devx-track-js
11+
ms.custom: devx-track-csharp, devx-track-extended-java, devx-track-js, devx-track-python
1212
---
1313
# Configure TLS mutual authentication for Azure App Service
1414

@@ -36,7 +36,7 @@ az webapp update --set clientCertEnabled=true --name <app-name> --resource-group
3636
```
3737
### [Bicep](#tab/bicep)
3838

39-
For Bicep, modify the properties `clientCertEnabled`, `clientCertMode`, and `clientCertExclusionPaths`. A sampe Bicep snippet is provided for you:
39+
For Bicep, modify the properties `clientCertEnabled`, `clientCertMode`, and `clientCertExclusionPaths`. A sample Bicep snippet is provided for you:
4040

4141
```bicep
4242
resource appService 'Microsoft.Web/sites@2020-06-01' = {
@@ -57,7 +57,7 @@ resource appService 'Microsoft.Web/sites@2020-06-01' = {
5757

5858
### [ARM](#tab/arm)
5959

60-
For ARM templates, modify the properties `clientCertEnabled`, `clientCertMode`, and `clientCertExclusionPaths`. A sampe ARM template snippet is provided for you:
60+
For ARM templates, modify the properties `clientCertEnabled`, `clientCertMode`, and `clientCertExclusionPaths`. A sample ARM template snippet is provided for you:
6161

6262
```ARM
6363
{
@@ -438,4 +438,147 @@ public class ClientCertValidator {
438438
}
439439
```
440440

441+
## Python sample
442+
443+
The following Flask and Django Python code samples implement a decorator named `authorize_certificate` that can be used on a view function to permit access only to callers that present a valid client certificate. It expects a PEM formatted certificate in the `X-ARR-ClientCert` header and uses the Python [cryptography](https://pypi.org/project/cryptography/) package to validate the certificate based on its fingerprint (thumbprint), subject common name, issuer common name, and beginning and expiration dates. If validation fails, the decorator ensures that an HTTP response with status code 403 (Forbidden) is returned to the client.
444+
445+
### [Flask](#tab/flask)
446+
447+
```python
448+
from functools import wraps
449+
from datetime import datetime, timezone
450+
from flask import abort, request
451+
from cryptography import x509
452+
from cryptography.x509.oid import NameOID
453+
from cryptography.hazmat.primitives import hashes
454+
455+
456+
def validate_cert(request):
457+
458+
try:
459+
cert_value = request.headers.get('X-ARR-ClientCert')
460+
if cert_value is None:
461+
return False
462+
463+
cert_data = ''.join(['-----BEGIN CERTIFICATE-----\n', cert_value, '\n-----END CERTIFICATE-----\n',])
464+
cert = x509.load_pem_x509_certificate(cert_data.encode('utf-8'))
465+
466+
fingerprint = cert.fingerprint(hashes.SHA1())
467+
if fingerprint != b'12345678901234567890':
468+
return False
469+
470+
subject = cert.subject
471+
subject_cn = subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value
472+
if subject_cn != "contoso.com":
473+
return False
474+
475+
issuer = cert.issuer
476+
issuer_cn = issuer.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value
477+
if issuer_cn != "contoso.com":
478+
return False
479+
480+
current_time = datetime.now(timezone.utc)
481+
482+
if current_time < cert.not_valid_before_utc:
483+
return False
484+
485+
if current_time > cert.not_valid_after_utc:
486+
return False
487+
488+
return True
489+
490+
except Exception as e:
491+
# Handle any errors encountered during validation
492+
print(f"Encountered the following error during certificate validation: {e}")
493+
return False
494+
495+
def authorize_certificate(f):
496+
@wraps(f)
497+
def decorated_function(*args, **kwargs):
498+
if not validate_cert(request):
499+
abort(403)
500+
return f(*args, **kwargs)
501+
return decorated_function
502+
```
503+
504+
The following code snippet shows how to use the decorator on a Flask view function.
505+
506+
```python
507+
@app.route('/hellocert')
508+
@authorize_certificate
509+
def hellocert():
510+
print('Request for hellocert page received')
511+
return render_template('index.html')
512+
```
513+
514+
### [Django](#tab/django)
515+
516+
```python
517+
from functools import wraps
518+
from datetime import datetime, timezone
519+
from django.core.exceptions import PermissionDenied
520+
from cryptography import x509
521+
from cryptography.x509.oid import NameOID
522+
from cryptography.hazmat.primitives import hashes
523+
524+
525+
def validate_cert(request):
526+
527+
try:
528+
cert_value = request.headers.get('X-ARR-ClientCert')
529+
if cert_value is None:
530+
return False
531+
532+
cert_data = ''.join(['-----BEGIN CERTIFICATE-----\n', cert_value, '\n-----END CERTIFICATE-----\n',])
533+
cert = x509.load_pem_x509_certificate(cert_data.encode('utf-8'))
534+
535+
fingerprint = cert.fingerprint(hashes.SHA1())
536+
if fingerprint != b'12345678901234567890':
537+
return False
538+
539+
subject = cert.subject
540+
subject_cn = subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value
541+
if subject_cn != "contoso.com":
542+
return False
543+
544+
issuer = cert.issuer
545+
issuer_cn = issuer.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value
546+
if issuer_cn != "contoso.com":
547+
return False
548+
549+
current_time = datetime.now(timezone.utc)
550+
551+
if current_time < cert.not_valid_before_utc:
552+
return False
553+
554+
if current_time > cert.not_valid_after_utc:
555+
return False
556+
557+
return True
558+
559+
except Exception as e:
560+
# Handle any errors encountered during validation
561+
print(f"Encountered the following error during certificate validation: {e}")
562+
return False
563+
564+
def authorize_certificate(view):
565+
@wraps(view)
566+
def _wrapped_view(request, *args, **kwargs):
567+
if not validate_cert(request):
568+
raise PermissionDenied
569+
return view(request, *args, **kwargs)
570+
return _wrapped_view
571+
```
572+
573+
The following code snippet shows how to use the decorator on a Django view function.
574+
575+
```python
576+
@authorize_certificate
577+
def hellocert(request):
578+
print('Request for hellocert page received')
579+
return render(request, 'hello_azure/index.html')
580+
```
581+
582+
---
583+
441584
[exclusion-paths]: ./media/app-service-web-configure-tls-mutual-auth/exclusion-paths.png

articles/app-service/configure-ssl-certificate.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,18 +311,19 @@ After the certificate renews inside your key vault, App Service automatically sy
311311

312312
## Frequently asked questions
313313

314-
- [How can I automate adding a bring-your-owncertificate to an app?](#how-can-i-automate-adding-a-bring-your-owncertificate-to-an-app)
315-
- [Frequently asked questions for App Service certificates](configure-ssl-app-service-certificate.md#frequently-asked-questions)
316-
#### How can I automate adding a bring-your-owncertificate to an app?
314+
### How can I automate adding a bring-your-owncertificate to an app?
317315

318316
- [Azure CLI: Bind a custom TLS/SSL certificate to a web app](scripts/cli-configure-ssl-certificate.md)
319317
- [Azure PowerShell Bind a custom TLS/SSL certificate to a web app using PowerShell](scripts/powershell-configure-ssl-certificate.md)
320318

321-
#### Can I configure a private CA certificate on my app?
322-
323-
App Service has a list of Trusted Root Certificates which you cannot modify in the multi-tenant variant version of App Service, but you can load your own CA certificate in the Trusted Root Store in an App Service Environment (ASE), which is a single-tenant environment in App Service. (The Free, Basic, Standard, and Premium App Service Plans are all multi-tenant, and the Isolated Plans are single-tenant.)
324-
- [Private client certificate](environment/overview-certificates.md)
325-
319+
### Can I use a private CA (certificate authority) certificate for inbound TLS on my app?
320+
You can use a private CA certificate for inbound TLS in an [App Service Environment version 3 (ASEv3)](./environment/overview-certificates.md). This isn't possible in App Service (multi-tenant). For more information on App Service multi-tenant vs. single-tenant, see [App Service Environment v3 and App Service public multitenant comparison](./environment/ase-multi-tenant-comparison.md).
321+
322+
### Can I make outbound calls using a private CA (certificate authority) client certificate from my app?
323+
This is only supported for Windows container apps in multi-tenant App Service. In addition, you can make outbound calls using a private CA client certificate with both code-based and container-based apps in an [App Service Environment version 3 (ASEv3)](./environment/overview-certificates.md). For more information on App Service multi-tenant vs. single-tenant, see [App Service Environment v3 and App Service public multitenant comparison](./environment/ase-multi-tenant-comparison.md).
324+
325+
### Can I load a private CA (certificate authority) certificate in my App Service Trusted Root Store?
326+
You can load your own CA certificate into the Trusted Root Store in an [App Service Environment version 3 (ASEv3)](./environment/overview-certificates.md). You can't modify the list of Trusted Root Certificates in App Service (multi-tenant). For more information on App Service multi-tenant vs. single-tenant, see [App Service Environment v3 and App Service public multitenant comparison](./environment/ase-multi-tenant-comparison.md).
326327

327328
## More resources
328329

articles/azure-cache-for-redis/cache-best-practices-client-libraries.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Although we don't own or support any client libraries, we do recommend some libr
2828
| ioredis | Node.js | [Link](https://github.com/luin/ioredis) | [More information here](https://ioredis.readthedocs.io/en/stable/API/) |
2929

3030
> [!NOTE]
31-
> Your application can to connect and use your Azure Cache for Redis instance with any client library that can also communicate with open-source Redis.
31+
> Your application can use any client library that is compatible with open-source Redis to connect to your Azure Cache for Redis instance.
3232
3333
## Client library-specific guidance
3434

articles/azure-cache-for-redis/cache-troubleshoot-timeouts.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,11 @@ There are several changes you can make to mitigate high server load:
145145

146146
- Investigate what is causing high server load such as [long-running commands](#long-running-commands), noted in this article, because of high memory pressure.
147147
- [Scale](cache-how-to-scale.md) out to more shards to distribute load across multiple Redis processes or scale up to a larger cache size with more CPU cores. For more information, see [Azure Cache for Redis planning FAQs](./cache-planning-faq.yml).
148-
- If your production workload on a _C1_ cache is negatively affected by extra latency from virus scanning, you can reduce the effect by to pay for a higher tier offering with multiple CPU cores, such as _C2_.
148+
- If your production workload on a _C1_ cache is negatively affected by extra latency from some internal defender scan runs, you can reduce the effect by scaling to a higher tier offering with multiple CPU cores, such as _C2_.
149149

150150
#### Spikes in server load
151151

152-
On _C0_ and _C1_ caches, you might see short spikes in server load not caused by an increase in requests a couple times a day while virus scanning is running on the VMs. You see higher latency for requests while virus scanning is happening on these tiers. Caches on the _C0_ and _C1_ tiers only have a single core to multitask, dividing the work of serving virus scanning and Redis requests.
152+
On _C0_ and _C1_ caches, you might see short spikes in server load not caused by an increase in requests a couple times a day while internal defender scanning is running on the VMs. You see higher latency for requests while internal defender scans happen on these tiers. Caches on the _C0_ and _C1_ tiers only have a single core to multitask, dividing the work of serving internal defender scanning and Redis requests.
153153

154154
### High memory usage
155155

articles/azure-monitor/agents/data-collection-text-log.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ The table created in the script has two columns:
4646

4747
- `TimeGenerated` (datetime) [Required]
4848
- `RawData` (string) [Optional if table schema provided]
49-
- 'FilePath' (string) [Optional]
49+
- `FilePath` (string) [Optional]
50+
- `Computer` (string) [Optional]
5051
- `YourOptionalColumn` (string) [Optional]
5152

52-
The default table schema for log data collected from text files is 'TimeGenerated' and 'RawData'. Adding the 'FilePath' to either team is optional. If you know your final schema or your source is a JSON log, you can add the final columns in the script before creating the table. You can always [add columns using the Log Analytics table UI](../logs/create-custom-table.md#add-or-delete-a-custom-column) later.
53+
The default table schema for log data collected from text files is 'TimeGenerated' and 'RawData'. Adding the 'FilePath' or 'Computer' to either stream is optional. If you know your final schema or your source is a JSON log, you can add the final columns in the script before creating the table. You can always [add columns using the Log Analytics table UI](../logs/create-custom-table.md#add-or-delete-a-custom-column) later.
5354

5455
Your column names and JSON attributes must exactly match to automatically parse into the table. Both columns and JSON attributes are case sensitive. For example `Rawdata` will not collect the event data. It must be `RawData`. Ingestion will drop JSON attributes that do not have a corresponding column.
5556

@@ -76,7 +77,11 @@ $tableParams = @'
7677
"name": "FilePath",
7778
"type": "String"
7879
},
79-
{
80+
{
81+
"name": "Computer",
82+
"type": "String"
83+
},
84+
{
8085
"name": "YourOptionalColumn",
8186
"type": "String"
8287
}

0 commit comments

Comments
 (0)