Skip to content

Commit 74bd35f

Browse files
committed
Add exercise 5 task 3
1 parent 580b7d7 commit 74bd35f

File tree

3 files changed

+175
-113
lines changed

3 files changed

+175
-113
lines changed

Solution/Exercise-03/Task-2/main.bicep

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ resource containerRegistry 'Microsoft.ContainerRegistry/registries@2020-11-01-pr
5050
}
5151
}
5252

53-
resource appServicePlan 'Microsoft.Web/serverFarms@2020-12-01' = {
53+
resource appServicePlan 'Microsoft.Web/serverFarms@2022-09-01' = {
5454
name: appServicePlanName
5555
location: location
5656
kind: 'linux'
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
@description('Environment of the web app')
2+
param environment string = 'dev'
3+
4+
@description('Location of services')
5+
param location string = resourceGroup().location
6+
7+
var webAppName = '${uniqueString(resourceGroup().id)}-${environment}'
8+
var appServicePlanName = '${uniqueString(resourceGroup().id)}-mpnp-asp'
9+
var logAnalyticsName = '${uniqueString(resourceGroup().id)}-mpnp-la'
10+
var appInsightsName = '${uniqueString(resourceGroup().id)}-mpnp-ai'
11+
var sku = 'P0V3'
12+
var registryName = '${uniqueString(resourceGroup().id)}mpnpreg'
13+
var registrySku = 'Standard'
14+
var imageName = 'techexcel/dotnetcoreapp'
15+
var startupCommand = ''
16+
var redisCacheName = '${uniqueString(resourceGroup().id)}-mpnp-redis'
17+
var redisCacheSku = 'Basic'
18+
19+
resource redisCache 'Microsoft.Cache/Redis@2023-08-01' = {
20+
name: redisCacheName
21+
location: location
22+
properties: {
23+
sku: {
24+
name: redisCacheSku
25+
family: 'C'
26+
capacity: 0
27+
}
28+
enableNonSslPort: false
29+
minimumTlsVersion: '1.2'
30+
redisConfiguration: {
31+
'maxmemory-policy': 'volatile-lru'
32+
}
33+
}
34+
}
35+
36+
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = {
37+
name: logAnalyticsName
38+
location: location
39+
properties: {
40+
sku: {
41+
name: 'PerGB2018'
42+
}
43+
retentionInDays: 90
44+
workspaceCapping: {
45+
dailyQuotaGb: 1
46+
}
47+
}
48+
}
49+
50+
resource appInsights 'Microsoft.Insights/components@2020-02-02-preview' = {
51+
name: appInsightsName
52+
location: location
53+
kind: 'web'
54+
properties: {
55+
Application_Type: 'web'
56+
WorkspaceResourceId: logAnalyticsWorkspace.id
57+
}
58+
}
59+
60+
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2020-11-01-preview' = {
61+
name: registryName
62+
location: location
63+
sku: {
64+
name: registrySku
65+
}
66+
properties: {
67+
adminUserEnabled: true
68+
}
69+
}
70+
71+
resource appServicePlan 'Microsoft.Web/serverFarms@2022-09-01' = {
72+
name: appServicePlanName
73+
location: location
74+
kind: 'linux'
75+
properties: {
76+
reserved: true
77+
}
78+
sku: {
79+
name: sku
80+
}
81+
}
82+
83+
resource appServiceApp 'Microsoft.Web/sites@2020-12-01' = {
84+
name: webAppName
85+
location: location
86+
properties: {
87+
serverFarmId: appServicePlan.id
88+
httpsOnly: true
89+
clientAffinityEnabled: false
90+
siteConfig: {
91+
linuxFxVersion: 'DOCKER|${containerRegistry.name}.azurecr.io/${uniqueString(resourceGroup().id)}/${imageName}'
92+
http20Enabled: true
93+
minTlsVersion: '1.2'
94+
appCommandLine: startupCommand
95+
appSettings: [
96+
{
97+
name: 'WEBSITES_ENABLE_APP_SERVICE_STORAGE'
98+
value: 'false'
99+
}
100+
{
101+
name: 'DOCKER_REGISTRY_SERVER_URL'
102+
value: 'https://${containerRegistry.name}.azurecr.io'
103+
}
104+
{
105+
name: 'DOCKER_REGISTRY_SERVER_USERNAME'
106+
value: containerRegistry.name
107+
}
108+
{
109+
name: 'DOCKER_REGISTRY_SERVER_PASSWORD'
110+
value: containerRegistry.listCredentials().passwords[0].value
111+
}
112+
{
113+
name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
114+
value: appInsights.properties.InstrumentationKey
115+
}
116+
]
117+
}
118+
}
119+
}
120+
121+
output application_name string = appServiceApp.name
122+
output application_url string = appServiceApp.properties.hostNames[0]
123+
output container_registry_name string = containerRegistry.name

docs/05_fix_performance_issue/0503.md

Lines changed: 51 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,51 @@
1-
---
2-
title: '3. Implement auto-scaling in template'
3-
layout: default
4-
nav_order: 3
5-
parent: 'Exercise 05: Fix a performance issue using GitHub Copilot'
6-
---
7-
8-
# Task 03 - Implement auto-scaling in the template (20 minutes)
9-
10-
## Introduction
11-
12-
The Munson's Pickles and Preserves Team Messaging System is up and running! They even have a proper Git Flow to protect against unintended changes to the main branch, and are recording application telemetry into App Insights. Before we are truly production-ready, though, there is one topic we have to cover: security.
13-
14-
One good DevOps practice is to enable protections against code-level vulnerabilities, and GitHub provides a number of useful features in this area. First, there are Issues, which allow developers or users to open 'tickets' indicating bugs to be fixed or potential vulnerabilities. If your organization prefers security flaws to be reported in a location other than GitHub, you have the option to provide a custom Security policy which describes the process for reporting.
15-
16-
In addition to these manual processes, GitHub also provides automated tools for scanning code for common errors. In this task, you will utilize the built-in Dependabot, which provides alerts if your repository contains libraries, packages, or external dependencies with known vulnerabilities. You will also set up a workflow with CodeQL, which can scan your source code for common coding errors or basic security flaws. This will help to ensure that the Team Messaging System contains code without any known vulnerabilities.
17-
18-
## Description
19-
20-
In this task, you will improve the security of your repository using some of GitHub's built-in tools.
21-
22-
1. Ask GitHub Copilot, "What do I need in a GitHub repository's security file?"
23-
2. Find the repository's Security policy. If there is an existing policy, make an edit and merge your change back into the main branch. Otherwise, create a policy using the template provided. GitHub Security policies are Markdown documents that indicate the preferred way to report security vulnerabilities for the repository.
24-
3. Ask GitHub Copilot, "How do I enable Dependabot alerts on a GitHub repository?" Then, enable Dependabot alerts for the repository. Dependabot is an automated tool that creates a pull request when any dependencies in the code base has a known vulnerability.
25-
4. Ask GitHub Copilot, "How do I create a code scanning workflow in a GitHub repository?" After that, set up and run a Code scanning workflow for the repository using GitHub's 'CodeQL Analysis.' This workflow can run either on each pull request or on a schedule, and it checks your code for common vulnerabilities or errors.
26-
5. Ask GitHub Copilot, "How can I view the results of a CodeQL analysis in GitHub?" Then, navigate to the results.
27-
6. You should have one security issue from code scanning. Review the security issue and read up on how to correct the issue. Create a new GitHub Issue and feature branch. Then, resolve the issue, using GitHub Copilot to assist you.
28-
29-
## Success Criteria
30-
31-
- In GitHub, you should be able to view the 'closed' pull request which either created or updated the Security policy (SECURITY.md file).
32-
- Additionally, you should be able to view a new 'open' pull request created by Dependabot requesting an update of a dependency.
33-
- Finally, you should be able to view the results of the CodeQL Analysis in the Security tab.
34-
35-
## Learning Resources
36-
37-
- [Learn more about adding a security policy to your repository](https://docs.github.com/en/github/managing-security-vulnerabilities/adding-a-security-policy-to-your-repository).
38-
- [Learn more about Dependabot and vulnerable dependencies](https://docs.github.com/en/github/managing-security-vulnerabilities/managing-vulnerabilities-in-your-projects-dependencies).
39-
- [Learn more about automated code scanning and understanding results](https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code).
40-
41-
## Tips
42-
43-
- If you are stuck, check out the 'Security' tab of your repository on GitHub.
44-
45-
## Solution
46-
47-
<details markdown="block">
48-
<summary>Expand this section to view the solution</summary>
49-
50-
1. Select **Settings** in your repo, then **Code security and analysis**. Select **Enable** on "Dependabot alerts" and "Dependabot security updates."
51-
52-
![Enabled Dependabot alerts and security updates](../../Media/EnableDependabot.png)
53-
54-
**Note** This will also automatically enable "Dependency graph."
55-
2. Navigate to [https://github.com/electron/electron/blob/main/SECURITY.md](https://github.com/electron/electron/blob/main/SECURITY.md) for information about security policies. This is an example of a sample security policy that you could use for this exercise.
56-
3. In your GitHub repo, select **Security**, **Policy**, and **Start setup**
57-
58-
![Start the security policy setup](../../Media/StartSecurityPolicySetup.png)
59-
60-
4. Paste the security policy into the Markdown file (you can overwrite what is there now) and update it for the Munson's Pickles and Preserves Team Messaging System and the GitHub repo your code is in. Then, commit the changes to the main branch.
61-
62-
![Commit the updated security policy](../../Media/CommitSecurityPolicy.png)
63-
64-
5. Next, we need to enable CodeQL. Select **Settings** and then **Code security and analysis**.
65-
6. Scroll down if needed and select **Set up** in "Code scanning" for "CodeQL analysis."
66-
67-
![Setup CodeQL analysis](../../Media/CodeQLAnalysisSetup.png)
68-
69-
7. If you select "Default", the code scan will immediately be run. For this exercise, select **Advanced**.
70-
71-
![Select Default](../../Media/CodeQLAdvanced.png)
72-
73-
8. By choosing the advanced option, you can see the YAML for the pipeline that actually performs the code check. We don't need to make any changes here, but it's something you should be familiar with. An easy change to make in this file would be if you want to adjust the schedule of when the scan runs.
74-
75-
![Commit the CodeQL YAML](../../Media/CodeQLYAMLCommit.png)
76-
77-
After you've reviewed the YAML, commit the change to main.
78-
79-
![Commit the change](../../Media/CodeQLCommitChange.png)
80-
81-
9. After you've committed the change, select **Actions** and you should see your CodeQL Scan workflow running.
82-
83-
![CodeQL scan running](../../Media/CodeQLScanRunning.png)
84-
85-
10. After about 5 minutes, you should see the workflow has completed.
86-
87-
![Workflow complete](../../Media/CodeQLWorkflowComplete.png)
88-
89-
11. After it's complete, go back to **Settings** and **Code security and analysis**. Then, select the ellipsis **...** next to the "Set up" menu. From the ellipsis dropdown, explore each of the first two options: "View last scan log" and "View Code Scanning alerts." You will find one High-risk vulnerability around arbitrary file access during archive extraction.
90-
91-
{: .note }
92-
> This page will still show "Set up" because we chose the Advanced option instead of Basic.
93-
94-
![View code scanning results](../../Media/CodeQLViewResults.png)
95-
96-
12. Select the alert and then choose "Show more" to view details on the security issue. It turns out that an attacker could traverse to an arbitrary directory based on the way the MP&P staff wrote this function. In order to correct the function and prevent a directory traversal attack, replace `WriteToDirectory()` with the following code:
97-
98-
```csharp
99-
public static void WriteToDirectory(ZipArchiveEntry entry, string destDirectory)
100-
{
101-
string destFileName = Path.GetFullPath(Path.Combine(destDirectory, entry.FullName));
102-
string fullDestDirPath = Path.GetFullPath(destDirectory + Path.DirectorySeparatorChar);
103-
if (!destFileName.StartsWith(fullDestDirPath)) {
104-
throw new System.InvalidOperationException("Entry is outside the target dir: " + destFileName);
105-
}
106-
entry.ExtractToFile(destFileName);
107-
}
108-
```
109-
110-
Commit the code and create a pull request to the main branch. You should then see a CodeQL scan for the pull request, and after it succeeds, complete the pull request. Then, return to the code scanning results view and confirm that no issues remain on the list.
111-
112-
</details>
1+
---
2+
title: '3. Add support for Azure Cache for Redis'
3+
layout: default
4+
nav_order: 3
5+
parent: 'Exercise 05: Fix a performance issue using GitHub Copilot'
6+
---
7+
8+
# Task 03 - Add support for Azure Cache for Redis (30 minutes)
9+
10+
## Introduction
11+
12+
The Munson's Pickles and Preserves development team has learned a considerable amount from you. They are running into one more problem they would like your assistance with. At certain points of the day, users overwhelm the Team Messaging System, causing performance issues at critical points in the day. They would like your assistance in deploying a caching tier to reduce some of the load on their databases. They would like to make this deployment in a way that supports their new infrastructure as code mode of operation. Their developers will handle making code changes to support this new caching layer.
13+
14+
{: .note }
15+
> The actual Team Messaging System that we have used in this demo operates on a built-in memory cache on the web server. For that reason, this task is more in line with a standard database-driven web application than the one you have worked with so far.
16+
17+
## Description
18+
19+
In this task, you will update the infrastructure as code Bicep script and create an instance of Azure Cache for Redis for the Team Messaging System web application.
20+
21+
1. Create an Issue and a feature branch associated with your infrastructure as code changes.
22+
2. Use GitHub Copilot to add support for the Basic SKU (C0) of Azure Cache for Redis.
23+
3. Check in your changes and have GitHub Copilot assist on creating the commit message.
24+
4. Create a pull request to the main branch, using GitHub Copilot Enterprise to create a pull request summary. Have another team member review and approve your code before you merge the code into the main branch.
25+
5. Ensure that the deployment completes (including a manual execution of the Azure Bicep workflow) and review your resource group in the Azure Portal to ensure that Azure Cache for Redis exists.
26+
27+
## Success Criteria
28+
29+
- In GitHub, you should see a successful execution of the **Azure Bicep** GitHub Actions workflow.
30+
- In the Azure Portal, you should see your Azure Cache for Redis instance.
31+
32+
## Learning Resources
33+
34+
- [Quickstart: Create an Azure Cache for Redis using Bicep](https://learn.microsoft.com/azure/azure-cache-for-redis/cache-redis-cache-bicep-provision?tabs=CLI).
35+
36+
## Tips
37+
38+
- If you receive an error message like the following:
39+
40+
> The subscription is not registered to use namespace 'Microsoft.Cache'. See https://aka.ms/rps-not-found for how to register subscriptions.
41+
42+
Be sure to enable the **Microsoft.Cache** namespace [in the Azure Portal](https://learn.microsoft.com/azure/azure-resource-manager/troubleshooting/error-register-resource-provider?tabs=azure-portal).
43+
44+
## Solution
45+
46+
<details markdown="block">
47+
<summary>Expand this section to view the solution</summary>
48+
49+
- The final Bicep script is [in the solution folder]((https://github.com/microsoft/TechExcel-Accelerate-developer-productivity-with-GitHub-Copilot-and-Dev-Box/blob/main/Solution/Exercise-05/Task-3/main.bicep)). Before looking at this script, try to use GitHub Copilot to generate the changes to your existing `/src/InfrastructureAsCode/main.bicep` file. You may wish to use a prompt such as "Please add in a Basic C0 instance of Azure Cache for Redis." Then, you may wish to compare what GitHub Copilot generated.
50+
51+
</details>

0 commit comments

Comments
 (0)