Skip to content

Commit

Permalink
Merge branch 'pr481' into stable
Browse files Browse the repository at this point in the history
* pr481:
  (GH-399) client certificate support
  (specs) compare with to_lower
  • Loading branch information
ferventcoder committed May 29, 2016
2 parents d54485f + 6f79d85 commit 026df76
Show file tree
Hide file tree
Showing 14 changed files with 136 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ private void reset()
[Fact]
public void GetExecutablePath_should_find_existing_executable()
{
FileSystem.get_executable_path("cmd").ShouldEqual(
FileSystem.get_executable_path("cmd").to_lower().ShouldEqual(
Platform.get_platform() == PlatformType.Windows ?
"c:\\windows\\system32\\cmd.exe"
: "cmd",
Expand All @@ -164,9 +164,9 @@ public void GetExecutablePath_should_find_existing_executable()
[Fact]
public void GetExecutablePath_should_find_existing_executable_with_extension()
{
FileSystem.get_executable_path("cmd.exe").ShouldEqual(
FileSystem.get_executable_path("cmd.exe").to_lower().ShouldEqual(
Platform.get_platform() == PlatformType.Windows ?
"C:\\Windows\\system32\\cmd.exe"
"c:\\windows\\system32\\cmd.exe"
: "cmd.exe",
StringComparer.OrdinalIgnoreCase
);
Expand Down
1 change: 1 addition & 0 deletions src/chocolatey/chocolatey.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
<Compile Include="infrastructure.app\domain\SourceCommandType.cs" />
<Compile Include="infrastructure.app\events\PostRunMessage.cs" />
<Compile Include="infrastructure.app\nuget\ChocolateyNugetCredentialProvider.cs" />
<Compile Include="infrastructure.app\nuget\ChocolateyClientCertificateProvider.cs" />
<Compile Include="infrastructure.app\nuget\NugetPush.cs" />
<Compile Include="infrastructure.app\runners\GenericRunner.cs" />
<Compile Include="infrastructure.app\services\AutomaticUninstallerService.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ private static void set_machine_sources(ChocolateyConfiguration config, ConfigFi
Name = source.Id,
Username = source.UserName,
EncryptedPassword = source.Password,
Certificate = source.Certificate,
EncryptedCertificatePassword = source.CertificatePassword,
Priority = source.Priority
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ public override void configure_argument_parser(OptionSet optionSet, ChocolateyCo
"p=|password=",
"Password - the user's password to the source. Defaults to empty.",
option => configuration.SourceCommand.Password = option.remove_surrounding_quotes())
.Add("cert=",
"Client certificate - PFX pathname for an x509 authenticated feeds. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.Certificate = option.remove_surrounding_quotes())
.Add("cp=|certpassword=",
"Certificate Password - the client certificate's password to the source. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.CertificatePassword = option.remove_surrounding_quotes())
;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon
.Add("p=|password=",
"Password - the user's password to the source. Defaults to empty.",
option => configuration.SourceCommand.Password = option.remove_surrounding_quotes())
.Add("cert=",
"Client certificate - PFX pathname for an x509 authenticated feeds. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.Certificate = option.remove_surrounding_quotes())
.Add("cp=|certpassword=",
"Certificate Password - the client certificate's password to the source. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.CertificatePassword = option.remove_surrounding_quotes())
.Add("ignorechecksums|ignore-checksums",
"IgnoreChecksums - Ignore checksums provided by the package",
option =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon
.Add("p=|password=",
"Password - the user's password to the source. Defaults to empty.",
option => configuration.SourceCommand.Password = option.remove_surrounding_quotes())
.Add("cert=",
"Client certificate - PFX pathname for an x509 authenticated feeds. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.Certificate = option.remove_surrounding_quotes())
.Add("cp=|certpassword=",
"Certificate Password - the client certificate's password to the source. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.CertificatePassword = option.remove_surrounding_quotes())
.Add("page=",
"Page - the 'page' of results to return. Defaults to return all results.", option =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon
.Add("p=|password=",
"Password - the user's password to the source. Defaults to empty.",
option => configuration.SourceCommand.Password = option.remove_surrounding_quotes())
.Add("cert=",
"Client certificate - PFX pathname for an x509 authenticated feeds. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.Certificate = option.remove_surrounding_quotes())
.Add("cp=|certpassword=",
"Certificate Password - the client certificate's password to the source. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.CertificatePassword = option.remove_surrounding_quotes())
;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon
option => configuration.SourceCommand.Username = option.remove_surrounding_quotes())
.Add("p=|password=",
"Password - the user's password to the source. Encrypted in chocolatey.config file.",
option => configuration.SourceCommand.Password = option.remove_surrounding_quotes())
option => configuration.SourceCommand.Password = option.remove_surrounding_quotes())
.Add("cert=",
"Client certificate - PFX pathname for an x509 authenticated feeds. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.Certificate = option.remove_surrounding_quotes())
.Add("cp=|certpassword=",
"Certificate Password - the client certificate's password to the source. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.CertificatePassword = option.remove_surrounding_quotes())
.Add("priority=",
"Priority - The priority order of this source as compared to other sources, lower is better. Defaults to 0 (no priority). All priorities above 0 will be evaluated first, then zero-based values will be evaluated in config file order.",
option => configuration.SourceCommand.Priority = int.Parse(option.remove_surrounding_quotes()))
Expand Down Expand Up @@ -107,6 +113,7 @@ choco sources [list]|add|remove|disable|enable [<options/switches>]
choco source
choco source list
choco source add -n=bob -s""https://somewhere/out/there/api/v2/""
choco source add -n=bob -s""https://somewhere/out/there/api/v2/"" -cert=\Users\bob\bob.pfx
choco source add -n=bob -s""https://somewhere/out/there/api/v2/"" -u=bob -p=12345
choco source disable -n=bob
choco source enable -n=bob
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ public virtual void configure_argument_parser(OptionSet optionSet, ChocolateyCon
.Add("p=|password=",
"Password - the user's password to the source. Defaults to empty.",
option => configuration.SourceCommand.Password = option.remove_surrounding_quotes())
.Add("cert=",
"Client certificate - PFX pathname for an x509 authenticated feeds. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.Certificate = option.remove_surrounding_quotes())
.Add("cp=|certpassword=",
"Certificate Password - the client certificate's password to the source. Defaults to empty. Available in 0.9.10+.",
option => configuration.SourceCommand.CertificatePassword = option.remove_surrounding_quotes())
.Add("ignorechecksums|ignore-checksums",
"IgnoreChecksums - Ignore checksums provided by the package",
option =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,8 @@ public sealed class SourcesCommandConfiguration
public string Username { get; set; }
public string Password { get; set; }
public int Priority { get; set; }
public string Certificate { get; set; }
public string CertificatePassword { get; set; }
}

[Serializable]
Expand All @@ -412,6 +414,8 @@ public sealed class MachineSourceConfiguration
public string Username { get; set; }
public string EncryptedPassword { get; set; }
public int Priority { get; set; }
public string Certificate { get; set; }
public string EncryptedCertificatePassword { get; set; }
}

[Serializable]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,11 @@ public sealed class ConfigFileSourceSetting

[XmlAttribute(AttributeName = "priority")]
public int Priority { get; set; }

[XmlAttribute(AttributeName = "certificate")]
public string Certificate { get; set; }

[XmlAttribute(AttributeName = "certificatePassword")]
public string CertificatePassword { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright © 2011 - Present RealDimensions Software, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace chocolatey.infrastructure.app.nuget
{
using configuration;
using NuGet;
using System;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;

class ChocolateyClientCertificateProvider : IClientCertificateProvider
{
ChocolateyConfiguration _configuration;

public ChocolateyClientCertificateProvider(ChocolateyConfiguration configuration)
{
if (configuration == null)
throw new ArgumentNullException("configuration");
_configuration = configuration;
}

public X509Certificate GetCertificate(Uri uri)
{
if (uri.OriginalString.StartsWith(_configuration.Sources.TrimEnd('/').ToLower(),StringComparison.InvariantCultureIgnoreCase))
{
if (!string.IsNullOrWhiteSpace(_configuration.SourceCommand.Certificate))
{
this.Log().Debug("Using passed in certificate");

return new X509Certificate2(_configuration.SourceCommand.Certificate, _configuration.SourceCommand.CertificatePassword);
}
}

return _configuration.MachineSources.Where(s =>
{
var sourceUri = s.Key.TrimEnd('/').ToLower();
return uri.OriginalString.ToLower().StartsWith(sourceUri)
&& !string.IsNullOrWhiteSpace(s.Certificate);
})
.Select(s =>
{
this.Log().Debug("Using machine source certificate");
try {
var decrypted = string.IsNullOrEmpty(s.EncryptedCertificatePassword)
? string.Empty
: NugetEncryptionUtility.DecryptString(s.EncryptedCertificatePassword);
return new X509Certificate2(s.Certificate, decrypted);
} catch(Exception x)
{
this.Log().Error("Unable to load the certificate: {0}", x);
return null;
}
})
.FirstOrDefault();
}
}
}
1 change: 1 addition & 0 deletions src/chocolatey/infrastructure.app/nuget/NugetCommon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public static IPackageRepository GetRemoteRepository(ChocolateyConfiguration con

// ensure credentials can be grabbed from configuration
HttpClient.DefaultCredentialProvider = new ChocolateyNugetCredentialProvider(configuration);
HttpClient.DefaultCertificateProvider = new ChocolateyClientCertificateProvider(configuration);
if (!string.IsNullOrWhiteSpace(configuration.Proxy.Location))
{
"chocolatey".Log().Debug("Using proxy server '{0}'.".format_with(configuration.Proxy.Location));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ public IEnumerable<ChocolateySource> source_list(ChocolateyConfiguration configu
source.Id,
source.Disabled ? " [Disabled]" : string.Empty,
source.Value,
string.IsNullOrWhiteSpace(source.UserName) ? string.Empty : "(Authenticated)",
(string.IsNullOrWhiteSpace(source.UserName) && string.IsNullOrWhiteSpace(source.Certificate)) ? string.Empty : "(Authenticated)",
source.Priority));
}
list.Add(new ChocolateySource {
Id = source.Id,
Value = source.Value,
Disabled = source.Disabled,
Authenticated = string.IsNullOrWhiteSpace(source.Password),
Authenticated = !(string.IsNullOrWhiteSpace(source.UserName) && string.IsNullOrWhiteSpace(source.Certificate)),
Priority = source.Priority
});
}
Expand All @@ -81,6 +81,8 @@ public void source_add(ChocolateyConfiguration configuration)
Value = configuration.Sources,
UserName = configuration.SourceCommand.Username,
Password = NugetEncryptionUtility.EncryptString(configuration.SourceCommand.Password),
Certificate = configuration.SourceCommand.Certificate,
CertificatePassword = NugetEncryptionUtility.EncryptString(configuration.SourceCommand.CertificatePassword),
Priority = configuration.SourceCommand.Priority
};
configFileSettings.Sources.Add(source);
Expand All @@ -91,10 +93,13 @@ public void source_add(ChocolateyConfiguration configuration)
else
{
var currentPassword = string.IsNullOrWhiteSpace(source.Password) ? null : NugetEncryptionUtility.DecryptString(source.Password);
var currentCertificatePassword = string.IsNullOrWhiteSpace(source.CertificatePassword) ? null : NugetEncryptionUtility.DecryptString(source.CertificatePassword);
if (configuration.Sources.is_equal_to(source.Value) &&
configuration.SourceCommand.Priority == source.Priority &&
configuration.SourceCommand.Username.is_equal_to(source.UserName) &&
configuration.SourceCommand.Password.is_equal_to(currentPassword)
configuration.SourceCommand.Password.is_equal_to(currentPassword) &&
configuration.SourceCommand.CertificatePassword.is_equal_to(currentCertificatePassword) &&
configuration.SourceCommand.Certificate.is_equal_to(source.Certificate)
)
{
if (!configuration.QuietOutput) this.Log().Warn(NO_CHANGE_MESSAGE);
Expand All @@ -105,6 +110,8 @@ public void source_add(ChocolateyConfiguration configuration)
source.Priority = configuration.SourceCommand.Priority;
source.UserName = configuration.SourceCommand.Username;
source.Password = NugetEncryptionUtility.EncryptString(configuration.SourceCommand.Password);
source.CertificatePassword = NugetEncryptionUtility.EncryptString(configuration.SourceCommand.CertificatePassword);
source.Certificate = configuration.SourceCommand.Certificate;

_xmlService.serialize(configFileSettings, ApplicationParameters.GlobalConfigFileLocation);
if (!configuration.QuietOutput) this.Log().Warn(() => "Updated {0} - {1} (Priority {2})".format_with(source.Id, source.Value, source.Priority));
Expand Down

0 comments on commit 026df76

Please sign in to comment.