Skip to content

Commit e447b5c

Browse files
guntripjc-clarklecoursensabrowning1
authored
Storing your secrets safely (#54997)
Co-authored-by: Joe Clark <[email protected]> Co-authored-by: Laura Coursen <[email protected]> Co-authored-by: Sam Browning <[email protected]>
1 parent 0befe97 commit e447b5c

File tree

4 files changed

+173
-0
lines changed

4 files changed

+173
-0
lines changed
177 KB
Loading

Diff for: content/get-started/learning-to-code/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ children:
88
- /finding-and-understanding-example-code
99
- /reusing-other-peoples-code-in-your-projects
1010
- /learning-to-debug-with-github-copilot
11+
- /storing-your-secrets-safely
1112
shortTitle: Learn to code
1213
---
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
---
2+
title: Storing your secrets safely
3+
shortTitle: Storing secrets safely
4+
intro: "Learn about secrets in software development and how you can manage them safely."
5+
versions:
6+
fpt: '*'
7+
topics:
8+
- GitHub
9+
---
10+
11+
## What is a secret?
12+
13+
In software development, a secret is a piece of sensitive information that is used to authenticate or authorize access to systems, services, data, and APIs. Examples include:
14+
15+
* **API keys** and **access tokens** that allow you to interact with external services such as {% data variables.product.github %}'s REST API. Access tokens also allow services, such as {% data variables.product.prodname_actions %}, to perform tasks that need authentication, as we will experiment with later.
16+
* **Database credentials** that grant access to local and external databases and storage.
17+
* **Private keys**, such as private SSH and PGP keys, that can be used to access other servers and encrypt data.
18+
19+
Since secrets provide so much access, including to critical systems, we can understand why it's so important to keep your **secrets secure**.
20+
21+
### What can happen when a secret is exposed?
22+
23+
* Attackers can gain **unauthorized access** to everything the secret allows access to.
24+
* Hackers can **steal data**, including sensitive user data. This may have privacy and legal ramifications and harm trust in you and your application.
25+
* Exposed secrets can **cost you money** if hackers run unauthorized workloads on your cloud provider accounts.
26+
* Hackers can use an exposed secret to delete, modify, and disrupt servers which can cause **downtime and data loss**.
27+
28+
Consider all the access and abilities a secret grants you and what a hacker could do with it. For example, if a {% data variables.product.pat_generic %} for your {% data variables.product.github %} account was exposed, a hacker could post and make changes on {% data variables.product.github %} as you.
29+
30+
## Best practices for managing your secrets
31+
32+
To avoid these types of issues, follow best practices to prevent leaks and limit damage if a secret is ever exposed.
33+
34+
### Follow the **Principle of Least Privilege (PoLP)**
35+
36+
Whenever possible, restrict what a secret can do and can access to only what is necessary. For example:
37+
38+
* If a secret will only be used to read data and not make changes to data, opt to make it **read only**.
39+
* If the API you're using allows you to limit a secret to only particular scopes or permissions, only select **the ones that you need**. For example, if you only need to create issues with a {% data variables.product.github %} secret, there's no reason for the secret to have access to repository contents or anything else.
40+
* If a secret will give an attacker full access to the user account that owns it, **consider creating service accounts** that can take ownership of the secret.
41+
42+
### Protect secrets in your application
43+
44+
* **Never hardcode a secret**. Always use **environment variables** or your platform's secret management tools (such as {% data variables.product.github %}'s repository secrets).
45+
* If you have to share a secret with someone, use a dedicated tool like a **password manager**. Never send secrets via email or instant message.
46+
* If possible, set **expiration dates** and **rotate your secrets** regularly; this reduces the risk of old secrets being exploited.
47+
* If your application produces a log, ensure that **secrets are redacted before being logged**. Otherwise, active secrets could be saved to plaintext files.
48+
49+
### Limit damage if a secret is exposed
50+
51+
* Consider the secret compromised, even if only exposed for a second, and **revoke the secret immediately**. Then, generate a new secret and store it safely.
52+
* Check any **activity logs** that might show any suspicious activity performed with the compromised secret.
53+
* Consider how the secret was exposed and make changes to your processes so this can't happen again.
54+
55+
## How {% data variables.product.github %} helps keep your secrets secure
56+
57+
There's a lot that you can do to keep your secrets safe, but there's also a lot that {% data variables.product.github %} does to help keep your secrets secret. Everyone makes mistakes, and we're here to help with features that will catch any secrets you accidentally expose:
58+
59+
* **Push protection**, which we'll experiment with later, blocks pushing secrets to your repositories on {% data variables.product.github %}.
60+
* **Secret scanning** scans repositories and creates alerts when it discovers a secret. For some secrets, we also notify the provider so they can take action, such as revoking the secret automatically.
61+
62+
## Practicing safely storing a secret
63+
64+
In this exercise, we'll create a {% data variables.product.pat_generic %} and store it safely so we can use it with {% data variables.product.prodname_actions %}. The action we'll create is a straightforward workflow that responds to an issue.
65+
66+
### 1. Creating a practice repository
67+
68+
We'll start by creating a repository to work from. The `new2code` account has a template repository we can use to quickly get started.
69+
70+
1. Navigate to the [new repository page](https://github.com/new?template_owner=new2code&template_name=secret-action). Following this link will pre-select the template on the `new2code` account.
71+
1. Under "Owner", make sure your user account is selected.
72+
1. In the "Repository name" field, type `secret-action`.
73+
1. Beneath the description field, select **Public** to set the repository visibility.
74+
1. Click **Create repository**.
75+
76+
### 2. Committing a dummy token
77+
78+
Everyone makes mistakes, and it's possible that you'll accidentally commit a secret at some point in your coding journey. In this exercise, we'll intentionally commit a **fake token** so that we can become familiar and comfortable with the alert that gets triggered.
79+
80+
1. Navigate to the repository you just created.
81+
1. Navigate to the YAML workflow file by clicking `.github/workflows` in the list of files.
82+
1. Open the workflow file by clicking `comment.yml` in the list of files.
83+
1. To edit the workflow file, at the top-right, click {% octicon "pencil" aria-label="Edit this file" %}.
84+
1. On line 13, `GH_TOKEN: ""`, insert this dummy token between the quotes:
85+
86+
```text
87+
{% data variables.secret-scanning.learner-example-secret-a %}{% data variables.secret-scanning.learner-example-secret-b %}
88+
```
89+
90+
The end result should look like this:
91+
92+
```yaml
93+
GH_TOKEN: "{% data variables.secret-scanning.learner-example-secret-a %}{% data variables.secret-scanning.learner-example-secret-b %}"
94+
```
95+
96+
1. To attempt to commit the change, at the top right, click **Commit changes...** and then click **Commit changes** again in the dialog.
97+
1. You should now see the push protection alert, telling you that "Secret scanning found a GitHub Secret Scanning secret on line 13".
98+
99+
![Screenshot of a push protection alert for Line 13 of the file we attempted to commit. The "Cancel" button is highlighted in an orange outline.](/assets/images/help/security/push-protection-example.png)
100+
101+
If we weren't experimenting with a dummy token, this would alert us that we were one step away from exposing a token. Review the options you can select on the alert.
102+
1. To stop your commit and avoid exposing the secret, click **Cancel**. In the top right, click **Cancel changes**, then discard your unsaved changes if prompted.
103+
104+
### 3. Creating a real token
105+
106+
Now, let's try following our best practices. First, we'll create a {% data variables.product.pat_generic %} which will allow the action to act on your behalf (the comment it creates will appear to come from your user account).
107+
108+
>[!NOTE] Notice how we follow the Principle of Least Privilege for each configuration step. Your token will have the shortest expiration necessary, only have access to the repository it needs, and have the minimum permissions needed to work.
109+
110+
1. Navigate to the [new {% data variables.product.pat_generic %} page](https://github.com/settings/personal-access-tokens/new).
111+
1. Under "Token name", give your new token a name. You can use something like "Action token".
112+
1. Under "Expiration", select "7 days".
113+
1. Under "Repository access", select **Only select repositories**.
114+
1. In the "Select repositories" dropdown, select **just** the practice repository you created earlier.
115+
1. To the right of "Repository permissions" in the "Permissions" section, click {% octicon "unfold" aria-label="Expand" %} to view all the possible permissions.
116+
1. Scroll down to "Issues" and, in the dropdown on the right, select "Read and write".
117+
1. At the bottom of the page, click **Generate token**. If prompted, confirm by clicking **Generate token** again.
118+
119+
It's crucial to handle the resulting token securely from this moment forward. As we'll be using the token shortly, you can copy it to your clipboard briefly.
120+
121+
### 4. Storing the token safely
122+
123+
We can now store our new token safely in our repository.
124+
125+
1. Navigate to the repository you created at the beginning of the exercise.
126+
{% data reusables.repositories.sidebar-settings %}
127+
{% data reusables.actions.sidebar-secrets-and-variables %}
128+
1. Under "Repository secrets," click **New repository secret**.
129+
1. In the **Name** field, type the name for your secret. For this exercise, we'll use `MY_TOKEN`.
130+
1. In the **Secret** field, paste the {% data variables.product.pat_generic %} you generated previously.
131+
1. Click **Add secret**.
132+
133+
Your secret is now safely encrypted and ready to use!
134+
135+
### 5. Referencing the token in our action
136+
137+
Now we can update the YAML workflow file to use the token and test it works.
138+
139+
1. Navigate back to your repository. If you're in your repository's settings, you can click **{% octicon "code" aria-hidden="true" %} Code** under the repository name.
140+
1. Navigate to the YAML workflow file by clicking `.github/workflows` in the list of files.
141+
1. Open the workflow file by clicking `comment.yml` in the list of files.
142+
1. To start editing the workflow file, at the top-right, click {% octicon "pencil" aria-label="Edit this file" %}.
143+
1. On line 13, `GH_TOKEN: ""`, replace the empty quotes with `{% raw %}${{ secrets.MY_TOKEN }}{% endraw %}`. This will reference the repository secret we added previously.
144+
145+
```yaml
146+
GH_TOKEN: {% raw %}${{ secrets.MY_TOKEN }}{% endraw %}
147+
```
148+
149+
1. To commit the change, at the top-right, click **Commit changes...**
150+
1. In the "Commit changes" dialog, edit "Commit message" to reflect the change we're making. For example, you could enter "Updating workflow to use repository secret".
151+
1. Make sure "Commit directly to the `main` branch" is selected.
152+
1. Click **Commit changes**.
153+
154+
### 6. Testing out the token and workflow
155+
156+
We should be all set now! Let's go ahead and test the workflow.
157+
158+
{% data reusables.repositories.sidebar-issues %}
159+
{% data reusables.repositories.new_issue %}
160+
1. Under "Add a title", you can type any title you like.
161+
1. Under "Add a description", in the text area, type `Hello`.
162+
1. Beneath the text area, click **Create**.
163+
164+
Once the workflow has had time to complete, you should see a new comment appear. The comment will be authored by yourself, as we're using your token, and contain a greeting in return.
165+
166+
## Next steps
167+
168+
For a more in-depth dive into secret scanning and push protection, you can complete the [Introduction to secret scanning](https://github.com/skills/introduction-to-secret-scanning/tree/main) course in {% data variables.product.prodname_learning %}.

Diff for: data/variables/secret-scanning.yml

+4
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ custom-pattern-regular-expression-generator-caps: 'Regular expression generator'
1313
copilot-secret-scanning: 'Copilot secret scanning'
1414
generic-secret-detection: 'generic secret detection'
1515
generic-secret-detection-caps: 'Generic secret detection'
16+
17+
# Combined to provide a secret to demonstrate push protection. Dummy secret, no access.
18+
learner-example-secret-a: 'secret_scanning_ab85fc6f8d76'
19+
learner-example-secret-b: '38cf1c11da812da308d43_abcde'

0 commit comments

Comments
 (0)