示例#1
0
        private void GenerateOrchestrationManifest(BatchSignInput batchData, ContentMap contentMap, string outputPath)
        {
            _log.LogMessage(MessageImportance.High, $"Generating orchestration file manifest into {outputPath}");
            OrchestratedFileJson fileJsonWithInfo = new OrchestratedFileJson
            {
                ExcludeList = _batchData.ExternalFileNames.ToArray() ?? Array.Empty <string>()
            };

            var distinctSigningCombos = batchData.FileSignInfoMap.Values.GroupBy(v => new { v.Certificate, v.StrongName });

            List <OrchestratedFileSignData> newList = new List <OrchestratedFileSignData>();

            foreach (var combinationToSign in distinctSigningCombos)
            {
                var filesInThisGroup = combinationToSign.Select(c => new FileSignDataEntry()
                {
                    FilePath         = c.FileName.RelativePath,
                    SHA256Hash       = contentMap.GetChecksum(c.FileName),
                    PublishToFeedUrl = batchData.PublishUri
                });
                newList.Add(new OrchestratedFileSignData()
                {
                    Certificate = combinationToSign.Key.Certificate,
                    StrongName  = combinationToSign.Key.StrongName,
                    FileList    = filesInThisGroup.ToArray()
                });
            }
            fileJsonWithInfo.SignList = newList.ToArray();
            fileJsonWithInfo.Kind     = "orchestration";

            using (StreamWriter file = File.CreateText(outputPath))
            {
                file.Write(JsonConvert.SerializeObject(fileJsonWithInfo, Formatting.Indented));
            }
        }
示例#2
0
        /// <summary>
        /// Build up the <see cref="ZipData"/> instance for a given zip container. This will also report any consistency
        /// errors found when examining the zip archive.
        /// </summary>
        private ZipData BuildZipData(FileName zipFileName, ContentMap contentMap, TaskLoggingHelper log)
        {
            Debug.Assert(zipFileName.IsZipContainer);

            var nestedExternalBinaries = new List <string>();
            var nestedParts            = new List <ZipPart>();

            using (var package = Package.Open(zipFileName.FullPath, FileMode.Open, FileAccess.Read))
            {
                foreach (var part in package.GetParts())
                {
                    var relativeName = GetPartRelativeFileName(part);
                    var name         = Path.GetFileName(relativeName);
                    if (!IsZipContainer(name) && !IsAssembly(name))
                    {
                        continue;
                    }

                    if (_batchData.ExternalFileNames.Contains(name))
                    {
                        nestedExternalBinaries.Add(name);
                        continue;
                    }

                    if (!_batchData.FileNames.Any(x => FilePathComparer.Equals(x.Name, name)))
                    {
                        log.LogError($"Zip Container '{zipFileName}' has part '{relativeName}' which is not listed in the sign or external list");
                        continue;
                    }

                    // This represents a binary that we need to sign.  Ensure the content in the VSIX is the same as the
                    // content in the binaries directory by doing a checksum match.
                    using (var stream = part.GetStream())
                    {
                        string checksum = _contentUtil.GetChecksum(stream);
                        if (!contentMap.TryGetFileName(checksum, out var checksumName))
                        {
                            log.LogError($"{zipFileName} has part {relativeName} which does not match the content in the binaries directory");
                            continue;
                        }

                        if (!FilePathComparer.Equals(checksumName.Name, name))
                        {
                            log.LogError($"{zipFileName} has part {relativeName} with a different name in the binaries directory: {checksumName}");
                            continue;
                        }

                        nestedParts.Add(new ZipPart(relativeName, checksumName, checksum));
                    }
                }
            }

            return(new ZipData(zipFileName, nestedParts.ToImmutableArray(), nestedExternalBinaries.ToImmutableArray()));
        }
示例#3
0
        private Dictionary <FileName, ZipData> BuildAllZipData(ContentMap contentMap, TaskLoggingHelper log)
        {
            var zipDataMap = new Dictionary <FileName, ZipData>();

            foreach (var zipName in _batchData.FileNames.Where(x => x.IsZipContainer))
            {
                var data = BuildZipData(zipName, contentMap, log);
                zipDataMap[zipName] = data;
            }

            return(zipDataMap);
        }
示例#4
0
        /// <summary>
        /// Build up a table of checksum to <see cref="FileName"/> instance map. This will report errors if it
        /// is unable to read any of the files off of disk.
        /// </summary>
        private ContentMap BuildContentMap(TaskLoggingHelper log)
        {
            var contentMap = new ContentMap();

            foreach (var fileName in _batchData.FileNames)
            {
                try
                {
                    if (string.IsNullOrEmpty(fileName.SHA256Hash))
                    {
                        var checksum = _contentUtil.GetChecksum(fileName.FullPath);
                        contentMap.Add(fileName, checksum);
                    }
                    else
                    {
                        if (File.Exists(fileName.FullPath))
                        {
                            contentMap.Add(fileName, fileName.SHA256Hash);
                        }
                        else
                        {
                            throw new FileNotFoundException();
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (!File.Exists(fileName.FullPath))
                    {
                        log.LogError($"Did not find {fileName} at {fileName.FullPath}");
                    }
                    else
                    {
                        log.LogError($"Unable to read content of {fileName.FullPath}: {ex.Message}");
                    }
                }
            }

            return(contentMap);
        }
示例#5
0
        /// <summary>
        /// Actually sign all of the described files.
        /// </summary>
        private bool SignFiles(ContentMap contentMap, Dictionary <FileName, ZipData> zipDataMap)
        {
            // Generate the list of signed files in a deterministic order. Makes it easier to track down
            // bugs if repeated runs use the same ordering.
            var toSignList = _batchData.FileNames.ToList();
            var round      = 0;
            var signedSet  = new HashSet <FileName>();

            bool signFiles(IEnumerable <FileName> files)
            {
                var filesToSign = files.Select(fileName => _batchData.FileSignInfoMap[fileName]).Where(info => !info.IsEmpty).ToArray();

                _log.LogMessage(MessageImportance.High, $"Signing Round {round}: {filesToSign.Length} files to sign.");
                foreach (var file in filesToSign)
                {
                    _log.LogMessage(MessageImportance.Low,
                                    $"File '{file.FileName}' Certificate='{file.Certificate}'" +
                                    (file.StrongName != null ? $" StrongName='{file.StrongName}'" : ""));
                }

                return(_signTool.Sign(_buildEngine, round, filesToSign));
            }

            void repackFiles(IEnumerable <FileName> files)
            {
                foreach (var file in files)
                {
                    if (file.IsZipContainer)
                    {
                        _log.LogMessage(MessageImportance.Low, $"Repacking container: '{file}'");
                        Repack(zipDataMap[file]);
                    }
                }
            }

            // Is this file ready to be signed? That is are all of the items that it depends on already
            // signed?
            bool isReadyToSign(FileName fileName)
            {
                if (!fileName.IsZipContainer)
                {
                    return(true);
                }

                var zipData = zipDataMap[fileName];

                return(zipData.NestedParts.All(x => signedSet.Contains(x.FileName)));
            }

            // Extract the next set of files that should be signed. This is the set of files for which all of the
            // dependencies have been signed.
            List <FileName> extractNextGroup()
            {
                var list = new List <FileName>();
                var i    = 0;

                while (i < toSignList.Count)
                {
                    var current = toSignList[i];
                    if (isReadyToSign(current))
                    {
                        list.Add(current);
                        toSignList.RemoveAt(i);
                    }
                    else
                    {
                        i++;
                    }
                }

                return(list);
            }

            while (toSignList.Count > 0)
            {
                var list = extractNextGroup();
                if (list.Count == 0)
                {
                    throw new InvalidOperationException("No progress made on signing which indicates a bug");
                }

                repackFiles(list);
                if (!signFiles(list))
                {
                    return(false);
                }

                round++;
                list.ForEach(x => signedSet.Add(x));
            }

            return(true);
        }