forked from dotnet/sign
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Oren Novotny
committed
Sep 13, 2016
1 parent
1eee588
commit 889b77f
Showing
7 changed files
with
195 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.IO.Compression; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace SignService | ||
{ | ||
|
||
|
||
class PowerShellCodeSignService : ICodeSignService | ||
{ | ||
readonly string timeStampUrl; | ||
readonly string thumbprint; | ||
readonly ILogger<PowerShellCodeSignService> logger; | ||
|
||
|
||
// Four things at once as we're hitting the sign server | ||
readonly ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 4 }; | ||
|
||
|
||
public PowerShellCodeSignService(string timeStampUrl, string thumbprint,ILogger<PowerShellCodeSignService> logger) | ||
{ | ||
this.timeStampUrl = timeStampUrl; | ||
this.thumbprint = thumbprint; | ||
this.logger = logger; | ||
} | ||
|
||
public Task Submit(string name, string description, string descriptionUrl, IList<string> files) | ||
{ | ||
// Explicitly put this on a thread because Parallel.ForEach blocks | ||
return Task.Run(() => SubmitInternal(name, description, descriptionUrl, files)); | ||
} | ||
|
||
void SubmitInternal(string name, string description, string descriptionUrl, IList<string> files) | ||
{ | ||
logger.LogInformation("Signing PowerShell job {0} with {1} files", name, files.Count()); | ||
|
||
|
||
|
||
Parallel.ForEach(files, options, (file, state) => | ||
{ | ||
// Sign it | ||
var signtool = new Process | ||
{ | ||
StartInfo = | ||
{ | ||
FileName = "powershell.exe", | ||
UseShellExecute = false, | ||
RedirectStandardError = false, | ||
RedirectStandardOutput = false, | ||
Arguments = $@"-Command ""Set-AuthenticodeSignature {file} @(Get-ChildItem -recurse cert: | where {{$_.Thumbprint -eq '{thumbprint}'}})[0] -TimestampServer '{timeStampUrl}'""" | ||
} | ||
}; | ||
logger.LogInformation(@"""{0}"" {1}", signtool.StartInfo.FileName, signtool.StartInfo.Arguments); | ||
signtool.Start(); | ||
if (!signtool.WaitForExit(30 * 1000)) | ||
{ | ||
signtool.Kill(); | ||
logger.LogError("Error: Set-AuthenticodeSignature took too long to respond {0}", signtool.ExitCode); | ||
throw new Exception($"Set-AuthenticodeSignature took too long to respond with {signtool.StartInfo.Arguments}"); | ||
} | ||
if (signtool.ExitCode != 0) | ||
{ | ||
logger.LogError("Error: Set-AuthenticodeSignaturel returned {0}", signtool.ExitCode); | ||
throw new Exception($"Set-AuthenticodeSignature returned error with {signtool.StartInfo.Arguments}"); | ||
} | ||
signtool.Dispose(); | ||
|
||
}); | ||
} | ||
|
||
public IReadOnlyCollection<string> SupportedFileExtensions { get; } = new List<string> | ||
{ | ||
".ps1", | ||
".psm1" | ||
}; | ||
public bool IsDefault => false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace SignService.SigningTools | ||
{ | ||
public interface ISigningToolAggregate | ||
{ | ||
Task Submit(string name, string description, string descriptionUrl, IList<string> files); | ||
} | ||
|
||
public class SigningToolAggregate : ISigningToolAggregate | ||
{ | ||
readonly ICodeSignService defaultCodeSignService; | ||
readonly IDictionary<string, ICodeSignService> codeSignServices; | ||
|
||
|
||
public SigningToolAggregate(IList<ICodeSignService> services) | ||
{ | ||
// pe files | ||
defaultCodeSignService = services.Single(c => c.IsDefault); | ||
|
||
var list = from cs in services | ||
from ext in cs.SupportedFileExtensions | ||
where !cs.IsDefault | ||
select new { cs, ext }; | ||
|
||
this.codeSignServices = list.ToDictionary(k => k.ext.ToLowerInvariant(), v => v.cs); | ||
} | ||
|
||
|
||
|
||
public async Task Submit(string name, string description, string descriptionUrl, IList<string> files) | ||
{ | ||
// split by code sign service and fallback to default | ||
|
||
var grouped = (from kvp in codeSignServices | ||
join file in files on kvp.Key equals Path.GetExtension(file).ToLowerInvariant() | ||
group file by kvp.Value into g | ||
select g).ToList(); | ||
|
||
// get all files and exclude existing; create default group | ||
var defaultFiles = files.Except(grouped.SelectMany(g => g)) | ||
.Where(IsPeFile) | ||
.Select(f => new {defaultCodeSignService,f }) | ||
.GroupBy(a => a.defaultCodeSignService, k => k.f) | ||
.SingleOrDefault(); // one group here | ||
|
||
if(defaultFiles != null) | ||
grouped.Add(defaultFiles); | ||
|
||
|
||
await Task.WhenAll(grouped.Select(g => g.Key.Submit(name, description, descriptionUrl, g.ToList()))); | ||
} | ||
|
||
static bool IsPeFile(string file) | ||
{ | ||
using (var str = File.OpenRead(file)) | ||
{ | ||
var buffer = new byte[2]; | ||
if (str.CanRead) | ||
{ | ||
var read = str.Read(buffer, 0, 2); | ||
if (read == 2) | ||
{ | ||
// Look for the magic MZ header | ||
return (buffer[0] == 0x4d && buffer[1] == 0x5a); | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters