Skip to content

Commit d1ea833

Browse files
author
Arin Ghazarian
authored
Add --no-ssl-verify to bbs2gh commands (#870)
1 parent 9bbd350 commit d1ea833

12 files changed

+248
-24
lines changed

RELEASENOTES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
- Fix `gh bbs2gh grant-migrator-role` so it doesn't throw `System.InvalidOperationException`
22
- Rename `AWS_ACCESS_KEY` and `AWS_SECRET_KEY` environment variables to `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` respectively to align with the environment variables that the AWS CLI already uses. Old environment variables are still supported but they will be removed in future.
33
- Send a `User-Agent` header with the current CLI version when downloading migration archives from GitHub Enterprise Server
4-
- Add support for migration archives larger than 2GB when using the blob storage flow
4+
- Add support for migration archives larger than 2GB when using the blob storage flow
5+
- Add `--no-ssh-verify` option to `gh bbs2gh generate-script` and `gh bbs2gh migrate-repo` commands to support migrating from a Bitbucket Server or Bitbucket Data Center instance that uses a self-signed SSL certificate

src/OctoshiftCLI.Tests/bbs2gh/BbsApiFactoryTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,39 @@ public void Should_Create_BbsApi_For_Source_Bbs_Api_With_Default()
5555
githubApi.Should().NotBeNull();
5656
httpClient.DefaultRequestHeaders.Accept.First().MediaType.Should().Be("application/json");
5757
}
58+
59+
[Fact]
60+
public void Should_Create_BbsApi_With_No_Ssl_Verify()
61+
{
62+
using var httpClient = new HttpClient();
63+
64+
_mockHttpClientFactory
65+
.Setup(x => x.CreateClient("NoSSL"))
66+
.Returns(httpClient);
67+
68+
// Act
69+
var githubApi = _bbsApiFactory.Create(BBS_SERVER_URL, "user", "pass", true);
70+
71+
// Assert
72+
githubApi.Should().NotBeNull();
73+
httpClient.DefaultRequestHeaders.Accept.First().MediaType.Should().Be("application/json");
74+
}
75+
76+
[Fact]
77+
public void Should_Create_BbsApi_With_Kerberos_And_No_Ssl_Verify()
78+
{
79+
using var httpClient = new HttpClient();
80+
81+
_mockHttpClientFactory
82+
.Setup(x => x.CreateClient("KerberosNoSSL"))
83+
.Returns(httpClient);
84+
85+
// Act
86+
var githubApi = _bbsApiFactory.CreateKerberos(BBS_SERVER_URL, true);
87+
88+
// Assert
89+
githubApi.Should().NotBeNull();
90+
httpClient.DefaultRequestHeaders.Accept.First().MediaType.Should().Be("application/json");
91+
}
5892
}
5993
}

src/OctoshiftCLI.Tests/bbs2gh/Commands/GenerateScriptCommandTests.cs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public void Should_Have_Options()
3535
{
3636
_command.Should().NotBeNull();
3737
_command.Name.Should().Be("generate-script");
38-
_command.Options.Count.Should().Be(17);
38+
_command.Options.Count.Should().Be(18);
3939

4040
TestHelpers.VerifyCommandOption(_command.Options, "bbs-server-url", true);
4141
TestHelpers.VerifyCommandOption(_command.Options, "github-org", true);
@@ -54,6 +54,7 @@ public void Should_Have_Options()
5454
TestHelpers.VerifyCommandOption(_command.Options, "aws-bucket-name", false);
5555
TestHelpers.VerifyCommandOption(_command.Options, "aws-region", false);
5656
TestHelpers.VerifyCommandOption(_command.Options, "keep-archive", false);
57+
TestHelpers.VerifyCommandOption(_command.Options, "no-ssl-verify", false);
5758
}
5859

5960
[Fact]
@@ -67,11 +68,44 @@ public void It_Gets_A_Kerberos_HttpClient_When_Kerberos_Is_True()
6768

6869
_command.BuildHandler(args, _mockServiceProvider.Object);
6970

70-
_mockBbsApiFactory.Verify(m => m.CreateKerberos(BBS_SERVER_URL));
71+
_mockBbsApiFactory.Verify(m => m.CreateKerberos(BBS_SERVER_URL, false));
7172
}
7273

7374
[Fact]
74-
public void It_Gets_A_Default_HttpClient_When_Kerberos_Is_Not_Set()
75+
public void It_Gets_A_Kerberos_With_No_Ssl_Verify_HttpClient_When_Kerberos_And_No_Ssl_Verify_Are_True()
76+
{
77+
var args = new GenerateScriptCommandArgs
78+
{
79+
BbsServerUrl = BBS_SERVER_URL,
80+
Kerberos = true,
81+
NoSslVerify = true
82+
};
83+
84+
_command.BuildHandler(args, _mockServiceProvider.Object);
85+
86+
_mockBbsApiFactory.Verify(m => m.CreateKerberos(BBS_SERVER_URL, true));
87+
}
88+
89+
[Fact]
90+
public void It_Gets_A_Default_HttpClient_When_Kerberos_And_No_Ssl_Verify_Are_Not_Set()
91+
{
92+
var bbsTestUser = "user";
93+
var bbsTestPassword = "password";
94+
95+
var args = new GenerateScriptCommandArgs
96+
{
97+
BbsServerUrl = BBS_SERVER_URL,
98+
BbsUsername = bbsTestUser,
99+
BbsPassword = bbsTestPassword
100+
};
101+
102+
_command.BuildHandler(args, _mockServiceProvider.Object);
103+
104+
_mockBbsApiFactory.Verify(m => m.Create(BBS_SERVER_URL, bbsTestUser, bbsTestPassword, false));
105+
}
106+
107+
[Fact]
108+
public void It_Gets_A_No_Ssl_Verify_HttpClient_When_No_Ssl_Verify_Is_Set()
75109
{
76110
var bbsTestUser = "user";
77111
var bbsTestPassword = "password";
@@ -81,10 +115,11 @@ public void It_Gets_A_Default_HttpClient_When_Kerberos_Is_Not_Set()
81115
BbsServerUrl = BBS_SERVER_URL,
82116
BbsUsername = bbsTestUser,
83117
BbsPassword = bbsTestPassword,
118+
NoSslVerify = true
84119
};
85120

86121
_command.BuildHandler(args, _mockServiceProvider.Object);
87122

88-
_mockBbsApiFactory.Verify(m => m.Create(BBS_SERVER_URL, bbsTestUser, bbsTestPassword));
123+
_mockBbsApiFactory.Verify(m => m.Create(BBS_SERVER_URL, bbsTestUser, bbsTestPassword, true));
89124
}
90125
}

src/OctoshiftCLI.Tests/bbs2gh/Commands/MigrateRepoCommandTests.cs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public void Should_Have_Options()
5252
var command = new MigrateRepoCommand();
5353
command.Should().NotBeNull();
5454
command.Name.Should().Be("migrate-repo");
55-
command.Options.Count.Should().Be(27);
55+
command.Options.Count.Should().Be(28);
5656

5757
TestHelpers.VerifyCommandOption(command.Options, "bbs-server-url", false);
5858
TestHelpers.VerifyCommandOption(command.Options, "bbs-project", false);
@@ -80,6 +80,7 @@ public void Should_Have_Options()
8080
TestHelpers.VerifyCommandOption(command.Options, "kerberos", false, true);
8181
TestHelpers.VerifyCommandOption(command.Options, "verbose", false);
8282
TestHelpers.VerifyCommandOption(command.Options, "keep-archive", false);
83+
TestHelpers.VerifyCommandOption(command.Options, "no-ssl-verify", false);
8384
}
8485

8586
[Fact]
@@ -137,7 +138,7 @@ public void BuildHandler_Creates_The_Handler()
137138
handler.Should().NotBeNull();
138139

139140
_mockGithubApiFactory.Verify(m => m.Create(It.IsAny<string>(), It.IsAny<string>()), Times.Never);
140-
_mockBbsApiFactory.Verify(m => m.Create(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
141+
_mockBbsApiFactory.Verify(m => m.Create(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()), Times.Never);
141142
_mockBbsArchiveDownloaderFactory.Verify(m => m.CreateSshDownloader(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>()), Times.Never);
142143
_mockBbsArchiveDownloaderFactory.Verify(m => m.CreateSmbDownloader(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
143144
_mockAzureApiFactory.Verify(m => m.Create(It.IsAny<string>()), Times.Never);
@@ -180,7 +181,7 @@ public void BuildHandler_Creates_Bbs_Api_When_Bbs_Server_Url_Is_Provided()
180181
// Assert
181182
handler.Should().NotBeNull();
182183

183-
_mockBbsApiFactory.Verify(m => m.Create(BBS_SERVER_URL, BBS_USERNAME, BBS_PASSWORD));
184+
_mockBbsApiFactory.Verify(m => m.Create(BBS_SERVER_URL, BBS_USERNAME, BBS_PASSWORD, false));
184185
}
185186

186187
[Fact]
@@ -229,21 +230,52 @@ public void It_Gets_A_Kerberos_HttpClient_When_Kerberos_Is_True()
229230

230231
_command.BuildHandler(args, _mockServiceProvider.Object);
231232

232-
_mockBbsApiFactory.Verify(m => m.CreateKerberos(BBS_SERVER_URL));
233+
_mockBbsApiFactory.Verify(m => m.CreateKerberos(BBS_SERVER_URL, false));
233234
}
234235

235236
[Fact]
236-
public void It_Gets_A_Default_HttpClient_When_Kerberos_Is_Not_Set()
237+
public void It_Gets_A_Kerberos_With_No_Ssl_Verify_HttpClient_When_Kerberos_And_No_Ssl_Verify_Are_True()
238+
{
239+
var args = new MigrateRepoCommandArgs
240+
{
241+
BbsServerUrl = BBS_SERVER_URL,
242+
Kerberos = true,
243+
NoSslVerify = true
244+
};
245+
246+
_command.BuildHandler(args, _mockServiceProvider.Object);
247+
248+
_mockBbsApiFactory.Verify(m => m.CreateKerberos(BBS_SERVER_URL, true));
249+
}
250+
251+
[Fact]
252+
public void It_Gets_A_Default_HttpClient_When_Kerberos_And_No_Ssl_Verify_Are_Not_Set()
253+
{
254+
var args = new MigrateRepoCommandArgs
255+
{
256+
BbsServerUrl = BBS_SERVER_URL,
257+
BbsUsername = BBS_USERNAME,
258+
BbsPassword = BBS_PASSWORD
259+
};
260+
261+
_command.BuildHandler(args, _mockServiceProvider.Object);
262+
263+
_mockBbsApiFactory.Verify(m => m.Create(BBS_SERVER_URL, BBS_USERNAME, BBS_PASSWORD, false));
264+
}
265+
266+
[Fact]
267+
public void It_Gets_A_No_Ssl_Verify_HttpClient_When_No_Ssl_Verify_Is_True()
237268
{
238269
var args = new MigrateRepoCommandArgs
239270
{
240271
BbsServerUrl = BBS_SERVER_URL,
241272
BbsUsername = BBS_USERNAME,
242273
BbsPassword = BBS_PASSWORD,
274+
NoSslVerify = true
243275
};
244276

245277
_command.BuildHandler(args, _mockServiceProvider.Object);
246278

247-
_mockBbsApiFactory.Verify(m => m.Create(BBS_SERVER_URL, BBS_USERNAME, BBS_PASSWORD));
279+
_mockBbsApiFactory.Verify(m => m.Create(BBS_SERVER_URL, BBS_USERNAME, BBS_PASSWORD, true));
248280
}
249281
}

src/OctoshiftCLI.Tests/bbs2gh/Handlers/GenerateScriptCommandHandlerTests.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.IO;
33
using System.Linq;
44
using System.Threading.Tasks;
5+
using FluentAssertions;
56
using Moq;
67
using OctoshiftCLI.BbsToGithub.Commands;
78
using OctoshiftCLI.BbsToGithub.Handlers;
@@ -238,6 +239,42 @@ public async Task One_Repo_With_Kerberos()
238239
_mockFileSystemProvider.Verify(m => m.WriteAllTextAsync(It.IsAny<string>(), It.Is<string>(script => script.Contains(migrateRepoCommand))));
239240
}
240241

242+
[Fact]
243+
public async Task One_Repo_With_No_Ssl_Verify()
244+
{
245+
// Arrange
246+
_mockBbsApi.Setup(m => m.GetProjects()).ReturnsAsync(new[]
247+
{
248+
(Id: 1, Key: BBS_FOO_PROJECT_KEY, Name: BBS_FOO_PROJECT_NAME),
249+
});
250+
_mockBbsApi.Setup(m => m.GetRepos(BBS_FOO_PROJECT_KEY)).ReturnsAsync(new[]
251+
{
252+
(Id: 1, Slug: BBS_FOO_REPO_1_SLUG, Name: BBS_FOO_REPO_1_NAME),
253+
});
254+
255+
var migrateRepoCommand = $"Exec {{ gh bbs2gh migrate-repo --bbs-server-url \"{BBS_SERVER_URL}\" --bbs-username \"{BBS_USERNAME}\" --bbs-shared-home \"{BBS_SHARED_HOME}\" --bbs-project \"{BBS_FOO_PROJECT_KEY}\" --bbs-repo \"{BBS_FOO_REPO_1_SLUG}\" --ssh-user \"{SSH_USER}\" --ssh-private-key \"{SSH_PRIVATE_KEY}\" --ssh-port {SSH_PORT} --github-org \"{GITHUB_ORG}\" --github-repo \"{BBS_FOO_PROJECT_KEY}-{BBS_FOO_REPO_1_SLUG}\" --verbose --wait --no-ssl-verify }}";
256+
257+
// Act
258+
var args = new GenerateScriptCommandArgs
259+
{
260+
BbsServerUrl = BBS_SERVER_URL,
261+
GithubOrg = GITHUB_ORG,
262+
BbsUsername = BBS_USERNAME,
263+
BbsPassword = BBS_PASSWORD,
264+
BbsSharedHome = BBS_SHARED_HOME,
265+
SshUser = SSH_USER,
266+
SshPrivateKey = SSH_PRIVATE_KEY,
267+
SshPort = SSH_PORT,
268+
Output = new FileInfo(OUTPUT),
269+
Verbose = true,
270+
NoSslVerify = true
271+
};
272+
await _handler.Handle(args);
273+
274+
// Assert
275+
_mockFileSystemProvider.Verify(m => m.WriteAllTextAsync(It.IsAny<string>(), It.Is<string>(script => script.Contains(migrateRepoCommand))));
276+
}
277+
241278
[Fact]
242279
public async Task One_Repo_With_Smb()
243280
{
@@ -385,6 +422,22 @@ public async Task One_Repo_With_Aws_Bucket_Name_And_Region()
385422
_mockFileSystemProvider.Verify(m => m.WriteAllTextAsync(It.IsAny<string>(), It.Is<string>(script => script.Contains(migrateRepoCommand))));
386423
}
387424

425+
[Fact]
426+
public async Task It_Throws_If_BbsServer_Url_Is_Not_Provided_But_No_Ssl_Verify_Is_Provided()
427+
{
428+
// Act
429+
var args = new GenerateScriptCommandArgs
430+
{
431+
NoSslVerify = true
432+
};
433+
434+
// Assert
435+
await _handler.Invoking(x => x.Handle(args))
436+
.Should()
437+
.ThrowExactlyAsync<OctoshiftCliException>()
438+
.WithMessage("*--no-ssl-verify*--bbs-server-url*");
439+
}
440+
388441
private string TrimNonExecutableLines(string script, int skipFirst = 9, int skipLast = 0)
389442
{
390443
var lines = script.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries).AsEnumerable();

src/OctoshiftCLI.Tests/bbs2gh/Handlers/MigrateRepoCommandHandlerTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,25 @@ await _handler.Invoking(x => x.Handle(args))
11481148
.WithMessage("*--bbs-username*--bbs-password*--bbs-server-url*");
11491149
}
11501150

1151+
[Fact]
1152+
public async Task Errors_If_BbsServer_Url_Not_Provided_But_No_Ssl_Verify_Is_Provided()
1153+
{
1154+
// Act
1155+
var args = new MigrateRepoCommandArgs
1156+
{
1157+
ArchivePath = ARCHIVE_PATH,
1158+
GithubOrg = GITHUB_ORG,
1159+
GithubRepo = GITHUB_REPO,
1160+
NoSslVerify = true
1161+
};
1162+
1163+
// Assert
1164+
await _handler.Invoking(x => x.Handle(args))
1165+
.Should()
1166+
.ThrowExactlyAsync<OctoshiftCliException>()
1167+
.WithMessage("*--no-ssl-verify*--bbs-server-url*");
1168+
}
1169+
11511170
[Fact]
11521171
public async Task Errors_If_BbsServer_Url_Not_Provided_But_Ssh_User_Is_Provided()
11531172
{

src/bbs2gh/BbsApiFactory.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,20 @@ public BbsApiFactory(OctoLogger octoLogger, IHttpClientFactory clientFactory, En
2020
_retryPolicy = retryPolicy;
2121
}
2222

23-
public virtual BbsApi Create(string bbsServerUrl, string bbsUsername, string bbsPassword)
23+
public virtual BbsApi Create(string bbsServerUrl, string bbsUsername, string bbsPassword, bool noSsl = false)
2424
{
2525
bbsUsername ??= _environmentVariableProvider.BbsUsername();
2626
bbsPassword ??= _environmentVariableProvider.BbsPassword();
2727

28-
var httpClient = _clientFactory.CreateClient("Default");
28+
var httpClient = noSsl ? _clientFactory.CreateClient("NoSSL") : _clientFactory.CreateClient("Default");
2929

3030
var bbsClient = new BbsClient(_octoLogger, httpClient, _versionProvider, _retryPolicy, bbsUsername, bbsPassword);
3131
return new BbsApi(bbsClient, bbsServerUrl, _octoLogger);
3232
}
3333

34-
public virtual BbsApi CreateKerberos(string bbsServerUrl)
34+
public virtual BbsApi CreateKerberos(string bbsServerUrl, bool noSsl = false)
3535
{
36-
var httpClient = _clientFactory.CreateClient("Kerberos");
36+
var httpClient = noSsl ? _clientFactory.CreateClient("KerberosNoSSL") : _clientFactory.CreateClient("Kerberos");
3737

3838
var bbsClient = new BbsClient(_octoLogger, httpClient, _versionProvider, _retryPolicy);
3939
return new BbsApi(bbsClient, bbsServerUrl, _octoLogger);

src/bbs2gh/Commands/GenerateScriptCommand.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public GenerateScriptCommand() : base(
3131
AddOption(AwsBucketName);
3232
AddOption(AwsRegion);
3333
AddOption(KeepArchive);
34+
AddOption(NoSslVerify);
3435
}
3536

3637
public Option<string> BbsServerUrl { get; } = new(
@@ -108,6 +109,11 @@ public GenerateScriptCommand() : base(
108109
name: "--keep-archive",
109110
description: "Keeps the downloaded export archive after successfully uploading it. By default, it will be automatically deleted.");
110111

112+
public Option<bool> NoSslVerify { get; } = new(
113+
name: "--no-ssl-verify",
114+
description: "Disables SSL verification when communicating with your Bitbucket Server/Data Center instance. All other migration steps will continue to verify SSL. " +
115+
"If your Bitbucket instance has a self-signed SSL certificate then setting this flag will allow the migration archive to be exported.");
116+
111117
public override GenerateScriptCommandHandler BuildHandler(GenerateScriptCommandArgs args, IServiceProvider sp)
112118
{
113119
if (args is null)
@@ -126,7 +132,9 @@ public override GenerateScriptCommandHandler BuildHandler(GenerateScriptCommandA
126132
var environmentVariableProvider = sp.GetRequiredService<EnvironmentVariableProvider>();
127133

128134
var bbsApiFactory = sp.GetRequiredService<BbsApiFactory>();
129-
var bbsApi = args.Kerberos ? bbsApiFactory.CreateKerberos(args.BbsServerUrl) : bbsApiFactory.Create(args.BbsServerUrl, args.BbsUsername, args.BbsPassword);
135+
var bbsApi = args.Kerberos
136+
? bbsApiFactory.CreateKerberos(args.BbsServerUrl, args.NoSslVerify)
137+
: bbsApiFactory.Create(args.BbsServerUrl, args.BbsUsername, args.BbsPassword, args.NoSslVerify);
130138

131139
return new GenerateScriptCommandHandler(log, versionProvider, fileSystemProvider, bbsApi, environmentVariableProvider);
132140
}
@@ -151,4 +159,5 @@ public class GenerateScriptCommandArgs
151159
public string AwsBucketName { get; set; }
152160
public string AwsRegion { get; set; }
153161
public bool KeepArchive { get; set; }
162+
public bool NoSslVerify { get; set; }
154163
}

0 commit comments

Comments
 (0)