Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/Tasks/ResolveKeySource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ namespace Microsoft.Build.Tasks
/// <summary>
/// Determine the strong name key source
/// </summary>
public class ResolveKeySource : TaskExtension
[MSBuildMultiThreadableTask]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the attribute necessary if the class implements IMultiThreadableTask?

public class ResolveKeySource : TaskExtension, IMultiThreadableTask
{
public TaskEnvironment TaskEnvironment { get; set; } = TaskEnvironment.Fallback;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage — MODERATE

ResolveKeySource has zero unit tests in the repo, and this PR adds none. Other tasks enlightened for multithreaded mode (Copy, Delete, Move, Touch) all have test suites that set TaskEnvironment = TaskEnvironmentHelper.CreateForTest(). While this change is a mechanical pattern application and the infrastructure is tested centrally, consider adding at least a basic test that verifies:

  1. KeyFile with a relative path resolves correctly via TaskEnvironment.GetAbsolutePath (e.g., using TaskEnvironment.CreateWithProjectDirectoryAndEnvironment)
  2. ResolvedKeyFile and error messages preserve the original (non-absolutized) path

The pre-existing test gap isn't this PR's fault, but enlightenment is a good opportunity to start covering this task.


private const string pfxFileExtension = ".pfx";
#if !RUNTIME_TYPE_NETCORE
private const string pfxFileContainerPrefix = "VS_KEY_";
Expand Down Expand Up @@ -118,14 +121,15 @@ private bool ResolveAssemblyKey()
FileStream fs = null;
try
{
AbsolutePath keyFilePath = TaskEnvironment.GetAbsolutePath(KeyFile);
string currentUserName = Environment.UserDomainName + "\\" + Environment.UserName;
// we use the curent user name to randomize the associated container name, i.e different user on the same machine will export to different keys
// this is because SNAPI by default will create keys in "per-machine" crypto store (visible for all the user) but will set the permission such only
// creator will be able to use it. This will make imposible for other user both to sign or export the key again (since they also can not delete that key).
// Now different users will use different container name. We use ToLower(invariant) because this is what the native equivalent of this function (Create new key, or VC++ import-er).
// use as well and we want to keep the hash (and key container name the same) otherwise user could be prompt for a password twice.
byte[] userNameBytes = System.Text.Encoding.Unicode.GetBytes(currentUserName.ToLower(CultureInfo.InvariantCulture));
fs = File.OpenRead(KeyFile);
fs = File.OpenRead(keyFilePath);
int fileLength = (int)fs.Length;
var keyBytes = new byte[fileLength];
fs.ReadFromStream(keyBytes, 0, fileLength);
Expand Down Expand Up @@ -205,15 +209,16 @@ private bool ResolveManifestKey()
if (!string.IsNullOrEmpty(CertificateFile) && !certInStore)
{
#if FEATURE_PFX_SIGNING
AbsolutePath certificateFilePath = TaskEnvironment.GetAbsolutePath(CertificateFile);
// if the cert isn't on disk, we can't import it
if (!FileSystems.Default.FileExists(CertificateFile))
if (!FileSystems.Default.FileExists(certificateFilePath))
{
Log.LogErrorWithCodeFromResources("ResolveKeySource.CertificateNotInStore");
}
else
{
// add the cert to the store optionally prompting for the password
if (X509Certificate2.GetCertContentType(CertificateFile) == X509ContentType.Pfx)
if (X509Certificate2.GetCertContentType(certificateFilePath) == X509ContentType.Pfx)
{
bool imported = false;
// first try it with no password
Expand All @@ -222,7 +227,7 @@ private bool ResolveManifestKey()
try
{
personalStore.Open(OpenFlags.ReadWrite);
cert.Import(CertificateFile, (string)null, X509KeyStorageFlags.PersistKeySet);
cert.Import(certificateFilePath, (string)null, X509KeyStorageFlags.PersistKeySet);
personalStore.Add(cert);
ResolvedThumbprint = cert.Thumbprint;
imported = true;
Expand Down Expand Up @@ -250,7 +255,7 @@ private bool ResolveManifestKey()
var personalStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
var cert = new X509Certificate2(CertificateFile);
var cert = new X509Certificate2(certificateFilePath);
personalStore.Open(OpenFlags.ReadWrite);
personalStore.Add(cert);
ResolvedThumbprint = cert.Thumbprint;
Expand Down
Loading