Skip to content

Commit 8025455

Browse files
authored
Merge pull request #464 from mjcheetham/dpapi
Add DPAPI based credential store on Windows
2 parents a5a1be2 + aa0d913 commit 8025455

File tree

16 files changed

+810
-311
lines changed

16 files changed

+810
-311
lines changed

Git-Credential-Manager.sln

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -33,32 +33,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Installer.Windows", "src\wi
3333
EndProject
3434
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Payload.Windows", "src\windows\Payload.Windows\Payload.Windows.csproj", "{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}"
3535
EndProject
36-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{65E53644-7FB7-4EC2-8C41-4356F7A4C0C4}"
37-
ProjectSection(SolutionItems) = preProject
38-
assets\gcm-transparent.png = assets\gcm-transparent.png
39-
assets\gcmicon.ico = assets\gcmicon.ico
40-
assets\gcmicon128.bmp = assets\gcmicon128.bmp
41-
assets\gcmicon16.bmp = assets\gcmicon16.bmp
42-
assets\gcmicon256.bmp = assets\gcmicon256.bmp
43-
assets\gcmicon32.bmp = assets\gcmicon32.bmp
44-
assets\gcmicon64.bmp = assets\gcmicon64.bmp
45-
assets\gcmweb.png = assets\gcmweb.png
46-
EndProjectSection
47-
EndProject
48-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{83BD5957-AC75-4072-A3D1-ABF3A71951F5}"
49-
ProjectSection(SolutionItems) = preProject
50-
docs\configuration.md = docs\configuration.md
51-
docs\development.md = docs\development.md
52-
docs\environment.md = docs\environment.md
53-
docs\faq.md = docs\faq.md
54-
docs\migration.md = docs\migration.md
55-
docs\netconfig.md = docs\netconfig.md
56-
docs\usage.md = docs\usage.md
57-
docs\architecture.md = docs\architecture.md
58-
docs\hostprovider.md = docs\hostprovider.md
59-
docs\linuxcredstores.md = docs\linuxcredstores.md
60-
EndProjectSection
61-
EndProject
6236
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHub.UI.Windows", "src\windows\GitHub.UI.Windows\GitHub.UI.Windows.csproj", "{4C2DBC8A-B3F2-4C64-870A-BA79DA4BD403}"
6337
EndProject
6438
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Atlassian.Bitbucket", "src\shared\Atlassian.Bitbucket\Atlassian.Bitbucket.csproj", "{B49881A6-E734-490E-8EA7-FB0D9E296CFB}"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OS/@EntryIndexedValue">OS</s:String>
23
<s:String x:Key="/Default/Environment/Hierarchy/Build/SolBuilderDuo/UseMsbuildSolutionBuilder/@EntryValue">No</s:String>
34
<s:Boolean x:Key="/Default/UserDictionary/Words/=PKCE/@EntryIndexedValue">True</s:Boolean>
45
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bitbucket/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Git Credential Manager Core is currently available for Windows, macOS, and Linux
2121
Feature|Windows|macOS|Linux
2222
-|:-:|:-:|:-:
2323
Installer/uninstaller|&#10003;|&#10003;|&#10003;\*
24-
Secure platform credential storage|&#10003;<br/>Windows<br/>Credential<br/>Manager|&#10003;<br/>macOS Keychain|&#10003;<br/>1. Secret Service<br/>2. `pass`/GPG<br/>3. `credential-cache`<br/>4. Plaintext files<br/>[(see more)](docs/linuxcredstores.md)
24+
Secure platform credential storage|&#10003;<br/>[(see more)](docs/credstores.md)|&#10003;<br/>[(see more)](docs/credstores.md)|&#10003;<br/>[(see more)](docs/credstores.md)
2525
Multi-factor authentication support for Azure DevOps|&#10003;|&#10003;|&#10003;
2626
Two-factor authentication support for GitHub|&#10003;|&#10003;|&#10003;
2727
Two-factor authentication support for Bitbucket|&#10003;|&#10003;|&#10003;
@@ -128,7 +128,7 @@ tar -xvf <path-to-tarball> -C /usr/local/bin
128128
git-credential-manager-core configure
129129
```
130130

131-
**Note:** all Linux distributions [require additional configuration](https://aka.ms/gcmcore-linuxcredstores) to use GCM Core.
131+
**Note:** all Linux distributions [require additional configuration](https://aka.ms/gcmcore-credstores) to use GCM Core.
132132

133133
---
134134

@@ -191,9 +191,12 @@ See detailed information [here](https://aka.ms/gcmcore-httpproxy).
191191
- [Environment variables](docs/environment.md)
192192
- [Enterprise configuration](docs/enterprise-config.md)
193193
- [Network and HTTP configuration](docs/netconfig.md)
194+
- [Credential stores](docs/credstores.md)
194195
- [Architectural overview](docs/architecture.md)
195196
- [Host provider specification](docs/hostprovider.md)
196-
- [Linux credential stores](docs/linuxcredstores.md)
197+
198+
## Experimental Features
199+
197200
- [Windows broker (experimental)](docs/windows-broker.md)
198201
- [Azure Repos OAuth tokens (experimental)](docs/azrepos-users-and-tokens.md)
199202

docs/configuration.md

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -219,17 +219,20 @@ git config --global credential.namespace "my-namespace"
219219

220220
Select the type of credential store to use on supported platforms.
221221

222-
Default value is unset.
222+
Default value on Windows is `wincredman`, on macOS is `keychain`, and is unset on Linux.
223223

224-
**Note:** This setting is only supported on Linux platforms. Setting this value on Windows and macOS has no effect. See more information about configuring secret stores on Linux [here](linuxcredstores.md).
224+
**Note:** See more information about configuring secret stores [here](credstores.md).
225225

226-
Value|Credential Store
227-
-|-
228-
_(unset)_|(error)
229-
`secretservice`|[freedesktop.org Secret Service API](https://specifications.freedesktop.org/secret-service/) via [libsecret](https://wiki.gnome.org/Projects/Libsecret) (requires a graphical interface to unlock secret collections).
230-
`gpg`|Use GPG to store encrypted files that are compatible with the [`pass` utility](https://www.passwordstore.org/) (requires GPG and `pass` to initialize the store).
231-
`cache`|Git's built-in [credential cache](https://git-scm.com/docs/git-credential-cache).
232-
`plaintext`|Store credentials in plaintext files (**UNSECURE**). Customize the plaintext store location with [`credential.plaintextStorePath`](#credentialplaintextstorepath).
226+
Value|Credential Store|Platforms
227+
-|-|-
228+
_(unset)_|Windows: `wincredman`<br/>macOS: `keychain`<br/>Linux: _(none)_|-
229+
`wincredman`|Windows Credential Manager (not available over SSH).|Windows
230+
`dpapi`|DPAPI protected files. Customize the DPAPI store location with [credential.dpapiStorePath](#credentialdpapistorepath)|Windows
231+
`keychain`|macOS Keychain.|macOS
232+
`secretservice`|[freedesktop.org Secret Service API](https://specifications.freedesktop.org/secret-service/) via [libsecret](https://wiki.gnome.org/Projects/Libsecret) (requires a graphical interface to unlock secret collections).|Linux
233+
`gpg`|Use GPG to store encrypted files that are compatible with the [`pass` utility](https://www.passwordstore.org/) (requires GPG and `pass` to initialize the store).|macOS, Linux
234+
`cache`|Git's built-in [credential cache](https://git-scm.com/docs/git-credential-cache).|Windows, macOS, Linux
235+
`plaintext`|Store credentials in plaintext files (**UNSECURE**). Customize the plaintext store location with [`credential.plaintextStorePath`](#credentialplaintextstorepath).|Windows, macOS, Linux
233236

234237
##### Example
235238

@@ -267,7 +270,7 @@ git config --global credential.cacheOptions "--timeout 300"
267270

268271
Specify a custom directory to store plaintext credential files in when [`credential.credentialStore`](#credentialcredentialstore) is set to `plaintext`.
269272

270-
Defaults to the value `~/.gcm/store`.
273+
Defaults to the value `~/.gcm/store` or `%USERPROFILE%\.gcm\store`.
271274

272275
#### Example
273276

@@ -279,6 +282,22 @@ git config --global credential.plaintextStorePath /mnt/external-drive/credential
279282

280283
---
281284

285+
### credential.dpapiStorePath
286+
287+
Specify a custom directory to store DPAPI protected credential files in when [`credential.credentialStore`](#credentialcredentialstore) is set to `dpapi`.
288+
289+
Defaults to the value `%USERPROFILE%\.gcm\dpapi_store`.
290+
291+
#### Example
292+
293+
```batch
294+
git config --global credential.dpapiStorePath D:\credentials
295+
```
296+
297+
**Also see: [GCM_DPAPI_STORE_PATH](environment.md#GCM_DPAPI_STORE_PATH)**
298+
299+
---
300+
282301
### credential.msauthFlow
283302

284303
Specify which authentication flow should be used when performing Microsoft authentication and an interactive flow is required.

docs/linuxcredstores.md renamed to docs/credstores.md

Lines changed: 116 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,131 @@
1-
# Credential stores on Linux
1+
# Credential stores
22

3-
There are four options for storing credentials that Git Credential
4-
Manager Core (GCM Core) manages on Linux platforms:
3+
There are several options for storing credentials that GCM Core supports:
54

6-
1. [freedesktop.org Secret Service API](https://specifications.freedesktop.org/secret-service/)
7-
2. GPG/[`pass`](https://www.passwordstore.org/) compatible files
8-
3. Git's built-in [credential cache](https://git-scm.com/docs/git-credential-cache)
9-
4. Plaintext files
5+
- Windows Credential Manager
6+
- macOS Keychain
7+
- [freedesktop.org Secret Service API](https://specifications.freedesktop.org/secret-service/)
8+
- GPG/[`pass`](https://www.passwordstore.org/) compatible files
9+
- Git's built-in [credential cache](https://git-scm.com/docs/git-credential-cache)
10+
- Plaintext files
1011

11-
By default, GCM Core comes unconfigured. After running `git-credential-manager-core configure`, you can select which credential store
12-
to use by setting the [`GCM_CREDENTIAL_STORE`](environment.md#GCM_CREDENTIAL_STORE)
12+
The default credential stores on macOS and Windows are the macOS Keychain and
13+
the Windows Credential Manager, respectively.
14+
15+
GCM comes without a default store on Linux distributions.
16+
17+
You can select which credential store to use by setting the [`GCM_CREDENTIAL_STORE`](environment.md#GCM_CREDENTIAL_STORE)
1318
environment variable, or the [`credential.credentialStore`](configuration.md#credentialcredentialstore)
1419
Git configuration setting.
1520

1621
Some credential stores have limitations, or further configuration required
17-
depending on your particular setup.
22+
depending on your particular setup. See more detailed information below for each
23+
credential store.
24+
25+
## Windows Credential Manager
26+
27+
**Available on:** _Windows_
28+
29+
**This is the default store on Windows.**
30+
31+
**:warning: Does not work over a network/SSH session.**
32+
33+
```batch
34+
SET GCM_CREDENTIAL_STORE="wincredman"
35+
```
1836

19-
## 1. [freedesktop.org Secret Service API](https://specifications.freedesktop.org/secret-service/)
37+
or
2038

2139
```shell
22-
export GCM_CREDENTIAL_STORE=secretservice
40+
git config --global credential.credentialStore wincredman
41+
```
42+
43+
This credential store uses the Windows Credential APIs (`wincred.h`) to store
44+
data securely in the Windows Credential Manager (also known as the Windows
45+
Credential Vault in earlier versions of Windows).
46+
47+
You can [access and manage data in the credential manager](https://support.microsoft.com/en-us/windows/accessing-credential-manager-1b5c916a-6a16-889f-8581-fc16e8165ac0)
48+
from the control panel, or via the [`cmdkey` command-line tool](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmdkey).
49+
50+
When connecting to a Windows machine over a network session (such as SSH), GCM
51+
is unable to persist credentials to the Windows Credential Manager due to
52+
limitations in Windows. Connecting by Remote Desktop doesn't suffer from this
53+
limitation.
54+
55+
## DPAPI protected files
56+
57+
**Available on:** _Windows_
58+
59+
```batch
60+
SET GCM_CREDENTIAL_STORE="dpapi"
61+
```
62+
63+
or
64+
65+
```shell
66+
git config --global credential.credentialStore dpapi
67+
```
68+
69+
This credential store uses Windows DPAPI to encrypt credentials which are stored
70+
as files in your file system. The file structure is the same as the
71+
[plaintext files credential store](#plaintext-files) except the first line (the
72+
secret value) is protected by DPAPI.
73+
74+
By default files are stored in `%USERPROFILE%\.gcm\dpapi_store`. This can be
75+
configured using the environment variable `GCM_DPAPI_STORE_PATH` environment
76+
variable.
77+
78+
If the directory doesn't exist it will be created.
79+
80+
## macOS Keychain
81+
82+
**Available on:** _macOS_
83+
84+
**This is the default store on macOS.**
85+
86+
```shell
87+
export GCM_CREDENTIAL_STORE=keychain
2388
# or
24-
git config --global credential.credentialStore secretservice
89+
git config --global credential.credentialStore keychain
2590
```
2691

92+
This credential store uses the default macOS Keychain, which is typically the
93+
`login` keychain.
94+
95+
You can [manage data stored in the keychain](https://support.apple.com/en-gb/guide/mac-help/mchlf375f392/mac)
96+
using the Keychain Access application.
97+
98+
## [freedesktop.org Secret Service API](https://specifications.freedesktop.org/secret-service/)
99+
100+
**Available on:** _Linux_
101+
27102
**:warning: Requires a graphical user interface session.**
28103

104+
```shell
105+
export GCM_CREDENTIAL_STORE=secretservice
106+
# or
107+
git config --global credential.credentialStore secretservice
108+
```
109+
29110
This credential store uses the `libsecret` library to interact with the Secret
30111
Service. It stores credentials securely in 'collections', which can be viewed by
31112
tools such as `secret-tool` and `seahorse`.
32113

33114
A graphical user interface is required in order to show a secure prompt to
34115
request a secret collection be unlocked.
35116

36-
## 2. GPG/[`pass`](https://www.passwordstore.org/) compatible files
117+
## GPG/[`pass`](https://www.passwordstore.org/) compatible files
118+
119+
**Available on:** _macOS, Linux_
120+
121+
**:warning: Requires `gpg`, `pass`, and a GPG key pair.**
37122

38123
```shell
39124
export GCM_CREDENTIAL_STORE=gpg
40125
# or
41126
git config --global credential.credentialStore gpg
42127
```
43128

44-
**:warning: Requires `gpg`, `pass`, and a GPG key pair.**
45-
46129
This credential store uses GPG to encrypt files containing credentials which are
47130
stored in your file system. The file structure is compatible with the popular
48131
[`pass`](https://www.passwordstore.org/) tool. By default files are stored in
@@ -88,7 +171,9 @@ export GPG_TTY=$(tty)
88171
**Note:** Using `/dev/tty` does not appear to work here - you must use the real
89172
TTY device path, as returned by the `tty` utility.
90173

91-
## 3. Git's built-in [credential cache](https://git-scm.com/docs/git-credential-cache)
174+
## Git's built-in [credential cache](https://git-scm.com/docs/git-credential-cache)
175+
176+
**Available on:** _Windows, macOS, Linux_
92177

93178
```shell
94179
export GCM_CREDENTIAL_STORE=cache
@@ -100,9 +185,10 @@ This credential store uses Git's built-in ephemeral
100185
[in-memory credential cache](https://git-scm.com/docs/git-credential-cache).
101186
This helps you reduce the number of times you have to authenticate but
102187
doesn't require storing credentials on persistent storage. It's good for
103-
scenarios like [Azure Cloud Shell](https://docs.microsoft.com/azure/cloud-shell/overview) or [AWS CloudShell](https://aws.amazon.com/cloudshell/), where you
104-
don't want to leave credentials on disk but also don't want to re-authenticate
105-
on every Git operation.
188+
scenarios like [Azure Cloud Shell](https://docs.microsoft.com/azure/cloud-shell/overview)
189+
or [AWS CloudShell](https://aws.amazon.com/cloudshell/), where you don't want to
190+
leave credentials on disk but also don't want to re-authenticate on every Git
191+
operation.
106192

107193
By default, `git credential-cache` stores your credentials for 900 seconds.
108194
That, and any other
@@ -118,37 +204,36 @@ export GCM_CREDENTIAL_CACHE_OPTIONS="--timeout 300"
118204
git config --global credential.cacheOptions "--timeout 300"
119205
```
120206

121-
## 4. Plaintext files
207+
## Plaintext files
208+
209+
**Available on:** _Windows, macOS, Linux_
210+
211+
**:warning: This is not a secure method of credential storage!**
122212

123213
```shell
124214
export GCM_CREDENTIAL_STORE=plaintext
125215
# or
126216
git config --global credential.credentialStore plaintext
127217
```
128218

129-
**:warning: This is not a secure method of credential storage!**
130-
131219
This credential store saves credentials to plaintext files in your file system.
132-
By default files are stored in `~/.gcm/store` but this can be configured using
133-
the environment variable `GCM_PLAINTEXT_STORE_PATH` environment variable.
220+
By default files are stored in `~/.gcm/store` or `%USERPROFILE%\.gcm\store`.
221+
This can be configured using the environment variable `GCM_PLAINTEXT_STORE_PATH`
222+
environment variable.
134223

135-
If the directory does not exist is will be created.
224+
If the directory doesn't exist it will be created.
136225

137226
On POSIX platforms the newly created store directory will have permissions set
138227
such that only the owner can `r`ead/`w`rite/e`x`ecute (`700` or `drwx---`).
139228
Permissions on existing directories will not be modified.
140229

141230
---
142231

143-
<p align="center">
144-
145232
:warning: **WARNING** :warning:
146233

147234
**This storage mechanism is NOT secure!**
148235

149-
**Secrets and credentials are stored in plaintext files _without any security_!<br/>
150-
Git Credential Manager Core takes no liability for the safety of these
151-
credentials.**
236+
**Secrets and credentials are stored in plaintext files _without any security_!**
152237

153238
It is **HIGHLY RECOMMENDED** to always use one of the other credential store
154239
options above. This option is only provided for compatibility and use in
@@ -159,6 +244,4 @@ permissions on this directory such that no other users or applications can
159244
access files within. If possible, use a path that exists on an external volume
160245
that you take with you and use full-disk encryption.
161246

162-
</p>
163-
164247
---

0 commit comments

Comments
 (0)