Skip to content

Commit 228f7cd

Browse files
authored
Merge pull request #607 from mminns/issue/573-OAuth2-support-for-Bitbucket-DC
Issue/573 OAuth2 support for Bitbucket DC
2 parents 3392430 + 6c28d76 commit 228f7cd

Some content is hidden

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

48 files changed

+1800
-384
lines changed

docs/bitbucket-development.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,76 @@ be accessed using the credentials `admin`/`admin` at
123123
Atlassian has [documentation][atlassian-sdk] on how to download and install
124124
their SDK.
125125

126+
## OAuth2 Configuration
127+
128+
Bitbucket DC [7.20](https://confluence.atlassian.com/bitbucketserver/bitbucket-data-center-and-server-7-20-release-notes-1101934428.html)
129+
added support for OAuth2 Incoming Application Links and this can be used to
130+
support OAuth2 authentication for Git. This is especially useful in environments
131+
where Bitbucket uses SSO as it removes the requirement for users to manage
132+
[SSH keys](https://confluence.atlassian.com/display/BITBUCKETSERVER0717/Using+SSH+keys+to+secure+Git+operations)
133+
or manual [HTTP access tokens](https://confluence.atlassian.com/display/BITBUCKETSERVER0717/Personal+access+tokens).
134+
135+
### Host Configuration
136+
137+
For more details see
138+
[Bitbucket's documentation on Data Center and Server Application Links to other Applications](https://confluence.atlassian.com/bitbucketserver/link-to-other-applications-1018764620.html)
139+
140+
Create Incoming OAuth 2 Application Link:
141+
<!-- markdownlint-disable MD034 -->
142+
1. Navigate to Administration/Application Links
143+
1. Create Link
144+
1. Screen 1
145+
- External Application [check]
146+
- Incoming Application [check]
147+
1. Screen 2
148+
- Name : GCM
149+
- Redirect URL : `http://localhost:34106/`
150+
- Application Permissions : Repositories.Read [check], Repositories.Write [check]
151+
1. Save
152+
<!-- markdownlint-enable MD034 -->
153+
1. Copy the `ClientId` and `ClientSecret` to configure GCM
154+
155+
### Client Configuration
156+
157+
Set the OAuth2 configuration use the `ClientId` and `ClientSecret` copied above,
158+
(for details see [credential.bitbucketDataCenterOAuthClientId](configuration.md#credential.bitbucketDataCenterOAuthClientId)
159+
and [credential.bitbucketDataCenterOAuthClientSecret](configuration.md#credential.bitbucketDataCenterOAuthClientSecret))
160+
161+
❯ git config --global credential.bitbucketDataCenterOAuthClientId {`Copied ClientId`}
162+
163+
❯ git config --global credential.bitbucketDataCenterOAuthClientSecret {`Copied ClientSecret`}
164+
<!-- markdownlint-disable MD034 -->
165+
As described in [Configuration options](configuration.md#Configuration%20options)
166+
the settings can be made more specific to apply only to a specific Bitbucket DC
167+
host by specifying the host url, e.g. https://bitbucket.example.com/
168+
<!-- markdownlint-enable MD034 -->
169+
170+
❯ git config --global credential.https://bitbucket.example.com.bitbucketDataCenterOAuthClientId {`Copied ClientId`}
171+
172+
❯ git config --global credential.https://bitbucket.example.com.bitbucketDataCenterOAuthClientSecret {`Copied ClientSecret`}
173+
<!-- markdownlint-disable MD034 -->
174+
Due to the way GCM resolves hosts and determines REST API urls, if the Bitbucket
175+
DC instance is hosted under a relative url (e.g. https://example.com/bitbucket)
176+
it is necessary to configure Git to send the full path to GCM. This is done
177+
using the [credential.useHttpPath](configuration.md#credential.useHttpPath)
178+
setting.
179+
❯ git config --global credential.https://example.com/bitbucket.usehttppath true
180+
<!-- markdownlint-enable MD034 -->
181+
182+
If a port number is used in the url of the Bitbucket DC instance the Git
183+
configuration needs to reflect this. However, due to [Issue 608](https://github.com/GitCredentialManager/git-credential-manager/issues/608)
184+
the port is ignored when resolving [credential.bitbucketDataCenterOAuthClientId](configuration.md#credential.bitbucketDataCenterOAuthClientId)
185+
and [credential.bitbucketDataCenterOAuthClientSecret](configuration.md#credential.bitbucketDataCenterOAuthClientSecret).
186+
<!-- markdownlint-disable MD034 -->
187+
For example, a Bitbucket DC host at https://example.com:7990/bitbucket would
188+
require configuration in the form:
189+
<!-- markdownlint-enable MD034 -->
190+
❯ git config --global credential.https://example.com/bitbucket.bitbucketDataCenterOAuthClientId {`Copied ClientId`}
191+
192+
❯ git config --global credential.https://example.com/bitbucket.bitbucketDataCenterOAuthClientSecret {`Copied ClientSecret`}
193+
194+
❯ git config --global credential.https://example.com:7990/bitbucket.usehttppath true
195+
126196
[additional-info]:https://confluence.atlassian.com/display/BITBUCKET/App+passwords
127197
[atlas-run-standalone]: https://developer.atlassian.com/server/framework/atlassian-sdk/atlas-run-standalone/
128198
[bitbucket]: https://bitbucket.org

docs/configuration.md

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ Value|Refresh Credentials Before Returning
272272
#### Example
273273

274274
```shell
275-
git config --global credential.bitbucketAlwaysRefreshCredentials 1
275+
git config --global credential.bitbucketAlwaysRefreshCredentials true
276276
```
277277

278278
Defaults to false/disabled.
@@ -281,6 +281,79 @@ Defaults to false/disabled.
281281

282282
---
283283

284+
### credential.bitbucketValidateStoredCredentials
285+
286+
Forces GCM to validate any stored credentials before returning them to Git. It
287+
does this by calling a REST API resource that requires authentication.
288+
289+
Disabling this option reduces the HTTP traffic within GCM when it is retrieving
290+
credentials. This may improve user performance, but will increase the number of
291+
times Git remote calls fail to authenticate with the host and therefore require
292+
the user to re-try the Git remote call.
293+
294+
Enabling this option helps ensure Git is always provided with valid credentials.
295+
296+
Value|Validate credentials
297+
-|-
298+
`true`, `1`, `yes`, `on`_(default)_|Always
299+
`false`, `0`, `no`, `off`|Never
300+
301+
#### Example
302+
303+
```shell
304+
git config --global credential.bitbucketValidateStoredCredentials true
305+
```
306+
307+
Defaults to true/enabled.
308+
309+
**Also see: [GCM_BITBUCKET_VALIDATE_STORED_CREDENTIALS](environment.md#GCM_BITBUCKET_VALIDATE_STORED_CREDENTIALS)**
310+
311+
---
312+
313+
### credential.bitbucketDataCenterOAuthClientId
314+
315+
To use OAuth with Bitbucket DC it is necessary to create an external, incoming
316+
[AppLink](https://confluence.atlassian.com/bitbucketserver/configure-an-incoming-link-1108483657.html).
317+
318+
It is then necessary to configure the local GCM installation with both the OAuth
319+
[ClientId](configuration.md#credential.bitbucketDataCenterOAuthClientId) and
320+
[ClientSecret](configuration.md#credential.bitbucketDataCenterOauthSecret) from
321+
the AppLink.
322+
323+
#### Example
324+
325+
```shell
326+
git config --global credential.bitbucketDataCenterOAuthClientId 1111111111111111111
327+
```
328+
329+
Defaults to undefined.
330+
331+
**Also see: [GCM_BITBUCKET_DATACENTER_CLIENTID](environment.md#GCM_BITBUCKET_DATACENTER_CLIENTID)**
332+
333+
---
334+
335+
### credential.bitbucketDataCenterOAuthClientSecret
336+
337+
To use OAuth with Bitbucket DC it is necessary to create an external, incoming
338+
[AppLink](https://confluence.atlassian.com/bitbucketserver/configure-an-incoming-link-1108483657.html).
339+
340+
It is then necessary to configure the local GCM installation with both the OAuth
341+
[ClientId](configuration.md#credential.bitbucketDataCenterOAuthClientId) and
342+
[ClientSecret](configuration.md#credential.bitbucketDataCenterOauthSecret)
343+
from the AppLink.
344+
345+
#### Example
346+
347+
```shell
348+
git config --global credential.bitbucketDataCenterOAuthClientSecret 222222222222222222222
349+
```
350+
351+
Defaults to undefined.
352+
353+
**Also see: [GCM_BITBUCKET_DATACENTER_CLIENTSECRET](environment.md#GCM_BITBUCKET_DATACENTER_CLIENTSECRET)**
354+
355+
---
356+
284357
### credential.gitHubAuthModes
285358

286359
Override the available authentication modes presented during GitHub
@@ -336,7 +409,8 @@ git config --global credential.gitLabAuthModes "browser"
336409
### credential.namespace
337410

338411
Use a custom namespace prefix for credentials read and written in the OS
339-
credential store. Credentials will be stored in the format `{namespace}:{service}`.
412+
credential store. Credentials will be stored in the format
413+
`{namespace}:{service}`.
340414

341415
Defaults to the value `git`.
342416

docs/environment.md

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,98 @@ export GCM_BITBUCKET_ALWAYS_REFRESH_CREDENTIALS=1
430430

431431
Defaults to false/disabled.
432432

433-
**Also see: [credential.bitbucketAlwaysRefreshCredentials][credential-bitbucketalwaysrefreshcredentials]**
433+
**Also see: [credential.bitbucketAlwaysRefreshCredentials](configuration.md#credentialbitbucketAlwaysRefreshCredentials)**
434+
435+
---
436+
437+
### GCM_BITBUCKET_VALIDATE_STORED_CREDENTIALS
438+
439+
Forces GCM to validate any stored credentials before returning them to Git. It
440+
does this by calling a REST API resource that requires authentication.
441+
442+
Disabling this option reduces the HTTP traffic within GCM when it is retrieving
443+
credentials. This may improve user performance, but will increase the number of
444+
times Git remote calls fail to authenticate with the host and therefore require
445+
the user to re-try the Git remote call.
446+
447+
Enabling this option helps ensure Git is always provided with valid credentials.
448+
449+
Value|Validate credentials
450+
-|-
451+
`true`, `1`, `yes`, `on`_(default)_|Always
452+
`false`, `0`, `no`, `off`|Never
453+
454+
#### Windows
455+
456+
```batch
457+
SET GCM_BITBUCKET_VALIDATE_STORED_CREDENTIALS=1
458+
```
459+
460+
#### macOS/Linux
461+
462+
```bash
463+
export GCM_BITBUCKET_VALIDATE_STORED_CREDENTIALS=1
464+
```
465+
466+
Defaults to true/enabled.
467+
468+
**Also see: [credential.bitbucketValidateStoredCredentials](configuration.md#credentialbitbucketValidateStoredCredentials)**
469+
470+
---
471+
472+
### GCM_BITBUCKET_DATACENTER_CLIENTID
473+
474+
To use OAuth with Bitbucket DC it is necessary to create an external, incoming
475+
[AppLink](https://confluence.atlassian.com/bitbucketserver/configure-an-incoming-link-1108483657.html).
476+
477+
It is then necessary to configure the local GCM installation with the OAuth
478+
[ClientId](environment.md#GCM_BITBUCKET_DATACENTER_CLIENTID) and
479+
[ClientSecret](environment.md#GCM_BITBUCKET_DATACENTER_CLIENTSECRET)
480+
from the AppLink.
481+
482+
#### Windows
483+
484+
```batch
485+
SET GCM_BITBUCKET_DATACENTER_CLIENTID=1111111111111111111
486+
```
487+
488+
#### macOS/Linux
489+
490+
```bash
491+
export GCM_BITBUCKET_DATACENTER_CLIENTID=1111111111111111111
492+
```
493+
494+
Defaults to undefined.
495+
496+
**Also see: [credential.bitbucketDataCenterOAuthClientId](configuration.md#credentialbitbucketDataCenterOAuthClientId)**
497+
498+
---
499+
500+
### GCM_BITBUCKET_DATACENTER_CLIENTSECRET
501+
502+
To use OAuth with Bitbucket DC it is necessary to create an external, incoming
503+
[AppLink](https://confluence.atlassian.com/bitbucketserver/configure-an-incoming-link-1108483657.html).
504+
505+
It is then necessary to configure the local GCM installation with the OAuth
506+
[ClientId](environment.md#GCM_BITBUCKET_DATACENTER_CLIENTID) and
507+
[ClientSecret](environment.md#GCM_BITBUCKET_DATACENTER_CLIENTSECRET)
508+
from the AppLink.
509+
510+
#### Windows
511+
512+
```batch
513+
SET GCM_BITBUCKET_DATACENTER_CLIENTSECRET=222222222222222222222
514+
```
515+
516+
#### macOS/Linux
517+
518+
```bash
519+
export GCM_BITBUCKET_DATACENTER_CLIENTSECRET=222222222222222222222
520+
```
521+
522+
Defaults to undefined.
523+
524+
**Also see: [credential.bitbucketDataCenterOAuthClientSecret](configuration.md#credentialbitbucketDataCenterOAuthClientSecret)**
434525

435526
---
436527

@@ -501,7 +592,8 @@ export GCM_GITLAB_AUTHMODES="browser"
501592
### GCM_NAMESPACE
502593

503594
Use a custom namespace prefix for credentials read and written in the OS
504-
credential store. Credentials will be stored in the format `{namespace}:{service}`.
595+
credential store. Credentials will be stored in the format
596+
`{namespace}:{service}`.
505597

506598
Defaults to the value `git`.
507599

src/shared/Atlassian.Bitbucket.Tests/Atlassian.Bitbucket.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<PrivateAssets>all</PrivateAssets>
1414
</PackageReference>
1515
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
16-
<PackageReference Include="ReportGenerator" Version="4.8.13" />
16+
<PackageReference Include="ReportGenerator" Version="5.1.9" />
1717
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
1818
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
1919
</ItemGroup>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System;
2+
using Xunit;
3+
4+
namespace Atlassian.Bitbucket.Tests
5+
{
6+
public class BitbucketHelperTest
7+
{
8+
[Theory]
9+
[InlineData(null, false)]
10+
[InlineData("", false)]
11+
[InlineData(" ", false)]
12+
[InlineData("bitbucket.org", true)]
13+
[InlineData("BITBUCKET.ORG", true)]
14+
[InlineData("BiTbUcKeT.OrG", true)]
15+
[InlineData("bitbucket.example.com", false)]
16+
[InlineData("bitbucket.example.org", false)]
17+
[InlineData("bitbucket.org.com", false)]
18+
[InlineData("bitbucket.org.org", false)]
19+
public void BitbucketHelper_IsBitbucketOrg_StringHost(string str, bool expected)
20+
{
21+
bool actual = BitbucketHelper.IsBitbucketOrg(str);
22+
Assert.Equal(expected, actual);
23+
}
24+
25+
[Theory]
26+
[InlineData("http://bitbucket.org", true)]
27+
[InlineData("https://bitbucket.org", true)]
28+
[InlineData("http://bitbucket.org/path", true)]
29+
[InlineData("https://bitbucket.org/path", true)]
30+
[InlineData("http://BITBUCKET.ORG", true)]
31+
[InlineData("https://BITBUCKET.ORG", true)]
32+
[InlineData("http://BITBUCKET.ORG/PATH", true)]
33+
[InlineData("https://BITBUCKET.ORG/PATH", true)]
34+
[InlineData("http://BiTbUcKeT.OrG", true)]
35+
[InlineData("https://BiTbUcKeT.OrG", true)]
36+
[InlineData("http://BiTbUcKeT.OrG/pAtH", true)]
37+
[InlineData("https://BiTbUcKeT.OrG/pAtH", true)]
38+
[InlineData("http://bitbucket.example.com", false)]
39+
[InlineData("https://bitbucket.example.com", false)]
40+
[InlineData("http://bitbucket.example.com/path", false)]
41+
[InlineData("https://bitbucket.example.com/path", false)]
42+
[InlineData("http://bitbucket.example.org", false)]
43+
[InlineData("https://bitbucket.example.org", false)]
44+
[InlineData("http://bitbucket.example.org/path", false)]
45+
[InlineData("https://bitbucket.example.org/path", false)]
46+
[InlineData("http://bitbucket.org.com", false)]
47+
[InlineData("https://bitbucket.org.com", false)]
48+
[InlineData("http://bitbucket.org.com/path", false)]
49+
[InlineData("https://bitbucket.org.com/path", false)]
50+
[InlineData("http://bitbucket.org.org", false)]
51+
[InlineData("https://bitbucket.org.org", false)]
52+
[InlineData("http://bitbucket.org.org/path", false)]
53+
[InlineData("https://bitbucket.org.org/path", false)]
54+
public void BitbucketHelper_IsBitbucketOrg_Uri(string str, bool expected)
55+
{
56+
bool actual = BitbucketHelper.IsBitbucketOrg(new Uri(str));
57+
Assert.Equal(expected, actual);
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)