private Dictionary <string, ServiceFabricServiceProject> ExtractProjectReferences( string basePath, string buildOutputPathSuffix, XmlNode document, XmlNamespaceManager namespaceManager) { var projectReferences = new Dictionary <string, ServiceFabricServiceProject>(); var projects = document.SelectNodes("//x:ProjectReference/@Include", namespaceManager); foreach (var service in projects) { if (!(service is XmlAttribute)) { continue; } var attr = service as XmlAttribute; var projectFile = new FileInfo(Path.Combine(basePath, attr.Value)); var serviceProject = new ServiceFabricServiceProject { ProjectFolder = projectFile.Directory, ProjectFile = projectFile }; // TODO Ugly Asp.Net hack thing. ServiceFabricServiceProject projectInfo; string buildOutputPath; var projectFileContents = File.ReadAllText(projectFile.FullName, System.Text.Encoding.UTF8); if (projectFileContents.Contains("<Project Sdk=\"Microsoft.NET.Sdk.Web\">")) { var loader = new ManifestLoader <CoreProjectFile>(false); var projectModel = loader.Load(projectFile.FullName); var propertyGroup = projectModel.PropertyGroup[0]; buildOutputPath = Path.Combine(serviceProject.ProjectFolder.FullName, "bin", _baseConfig.BuildConfiguration, propertyGroup.TargetFramework, propertyGroup.RuntimeIdentifiers[0]); projectInfo = _appManifestHandler.ReadXml(serviceProject, buildOutputPath); projectInfo.IsAspNetCore = true; } else { buildOutputPath = Path.Combine(serviceProject.ProjectFolder.FullName, buildOutputPathSuffix); projectInfo = _appManifestHandler.ReadXml(serviceProject, buildOutputPath); projectInfo.IsAspNetCore = false; } projectReferences.Add(projectInfo.ServiceName, projectInfo); } return(projectReferences); }
public void Test() { var loader = new ManifestLoader <CoreProjectFile>(false); var basePath = new DirectoryInfo(System.AppContext.BaseDirectory); var combined = Path.GetFullPath(Path.Combine(basePath.FullName, @"..\..\..\..\..\src\SFPackager\SFPackager.csproj")); var projModel = loader.Load(combined); Assert.NotEmpty(projModel.PropertyGroup); Assert.NotNull(projModel.PropertyGroup.First().TargetFramework); Assert.NotNull(projModel.PropertyGroup.First().RuntimeIdentifierRaw); Assert.NotEmpty(projModel.PropertyGroup.First().RuntimeIdentifiers); }
public async Task <Dictionary <string, GlobalVersion> > Calculate( ServiceFabricApplicationProject project, VersionNumber currentVersion) { var projectHashes = new Dictionary <string, GlobalVersion>(); foreach (var service in project.Services) { foreach (var subPackage in service.Value.SubPackages) { _log.WriteLine($"Computing hash for Service: {service.Key} - Package: {subPackage.Name}"); var hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); var directory = new DirectoryInfo(subPackage.Path); IOrderedEnumerable <string> files; if (subPackage.PackageType == PackageType.Code) { if (!service.Value.IsGuestExecutable) { files = directory .GetFiles("*", SearchOption.AllDirectories) .Where( x => _packageConfig.HashIncludeExtensions.Any( include => x.FullName.EndsWith(include, StringComparison.CurrentCultureIgnoreCase))) .Where( x => _packageConfig.HashSpecificExludes.All( exclude => !x.FullName.ToLowerInvariant() .Contains(exclude.ToLowerInvariant()))) .Select(x => x.FullName) .OrderBy(x => x); } else { files = directory .GetFiles("*", SearchOption.AllDirectories) .Where( x => _packageConfig.HashSpecificExludes.All( exclude => !x.FullName.ToLowerInvariant() .Contains(exclude.ToLowerInvariant()))) .Select(x => x.FullName) .OrderBy(x => x); } } else { files = directory .GetFiles("*", SearchOption.AllDirectories) .Select(x => x.FullName) .OrderBy(x => x); } foreach (var data in files.Select(File.ReadAllBytes)) { hasher.AppendData(data); } var externalIncludes = _packageConfig .ExternalIncludes .Where(x => x .ApplicationTypeName.Equals(project.ApplicationTypeName, StringComparison.CurrentCultureIgnoreCase)) .Where(x => x .ServiceManifestName.Equals(service.Value.ServiceName, StringComparison.CurrentCultureIgnoreCase)) .Where(x => x .PackageName.Equals(subPackage.Name, StringComparison.CurrentCultureIgnoreCase)) .OrderBy(x => x.SourceFileName); foreach (var externalFile in externalIncludes) { var file = await _fileHandler .GetFileAsBytesAsync(externalFile.SourceFileName) .ConfigureAwait(false); if (!file.IsSuccessful) { throw new IOException("Failed to get external file from storage"); } hasher.AppendData(file.ResponseContent); } var finalHash = hasher.GetHashAndReset(); var hash = BitConverter.ToString(finalHash).Replace("-", "").ToLowerInvariant(); var packageVersion = new GlobalVersion { Hash = hash, VersionType = VersionType.ServicePackage, ParentRef = $"{project.ApplicationTypeName}-{service.Key}", PackageType = subPackage.PackageType }; projectHashes.Add($"{project.ApplicationTypeName}-{service.Key}-{subPackage.Name}", packageVersion); } var serviceManifest = _serviceManifestLoader.Load(service.Value.SourceServiceManifestPath); _manifestHandler.SetServiceEndpoints(serviceManifest, project.ApplicationTypeName, service.Value.ServiceName); using (var serviceManifestStream = new MemoryStream()) { _serviceManifestLoader.Save(serviceManifest, serviceManifestStream); var serviceVersion = new GlobalVersion { VersionType = VersionType.Service, ParentRef = project.ApplicationTypeName, Hash = HashStream(serviceManifestStream) }; projectHashes.Add($"{project.ApplicationTypeName}-{service.Key}", serviceVersion); } } var appManifest = _appManifestLoader.Load(project.ApplicationManifestFileFullPath); _manifestHandler.CleanAppManifest(appManifest); _handleEndpointCert.SetEndpointCerts(_packageConfig, appManifest, project.ApplicationTypeName); _handleEnciphermentCert.SetEnciphermentCerts(_packageConfig, appManifest, project.ApplicationTypeName); var guests = _packageConfig.GuestExecutables.Where(x => x.ApplicationTypeName.Equals(project.ApplicationTypeName, StringComparison.CurrentCultureIgnoreCase)); foreach (var guest in guests) { var policies = new Policies(); if (guest.GuestRunAs != null) { var runAs = new RunAsPolicy { UserRef = guest.GuestRunAs.UserName, CodePackageRef = "Code" }; var runAsPolicies = new List <RunAsPolicy> { runAs }; policies.RunAsPolicy = runAsPolicies; if (appManifest.Principals == null) { appManifest.Principals = new Principals(); } if (appManifest.Principals.Users == null) { appManifest.Principals.Users = new Users(); } if (appManifest.Principals.Users.User == null) { appManifest.Principals.Users.User = new List <User>(); } if (!appManifest.Principals.Users.User.Any(x => x.Name.Equals(guest.GuestRunAs.UserName, StringComparison.CurrentCultureIgnoreCase))) { var user = new User { Name = guest.GuestRunAs.UserName, AccountType = guest.GuestRunAs.AccountType }; appManifest.Principals.Users.User.Add(user); } } var serviceManifestRef = new ServiceManifestRef { ServiceManifestName = guest.PackageName, ServiceManifestVersion = "1.0.0" }; var serviceImport = new ServiceManifestImport { ServiceManifestRef = serviceManifestRef, ConfigOverrides = new ConfigOverrides(), Policies = policies }; appManifest.ServiceManifestImports.Add(serviceImport); } using (var appManifestStream = new MemoryStream()) { _appManifestLoader.Save(appManifest, appManifestStream); projectHashes.Add(project.ApplicationTypeName, new GlobalVersion { VersionType = VersionType.Application, Version = currentVersion, Hash = HashStream(appManifestStream) }); } return(projectHashes); }
/// <summary> /// Perform JAR digital signature verification against a JAR filename on disk /// </summary> /// <param name="jar">JAR container. The caller is expected to dispose this type themselves - it will not be disposed /// by this method</param> /// <param name="certificates">certificate to verify / accept against</param> /// <param name="nonStandardCountCheck">whether to perform the additional file count verification check against /// MANIFEST.MF (recommended if the file is actually an arbitrary ZIP)</param> /// <returns>digital signature verification state of the JAR</returns> public static VerificationResult Jar(IJar jar, IVerificationCertificates certificates, bool nonStandardCountCheck = true) { // Unsigned ZIP and probably not even a JAR if (!jar.Contains(@"META-INF\MANIFEST.MF")) { return(new VerificationResult { Status = SigningStatus.NotSigned, Valid = false }); } IManifestLoader manifestLoader = new ManifestLoader(); ManifestData centralManifest = manifestLoader.Load(jar, @"META-INF\MANIFEST.MF"); if (nonStandardCountCheck) { // Non-standard check: Ensure that no unsigned files have been ADDED // to the JAR (file qty. [except signature itself] must match manifest entries) // int nonManifestFiles = jar.NonSignatureFiles().Count(); if (centralManifest.Entries.Count != nonManifestFiles) { Log.Message($"Expected {centralManifest.Entries.Count} file(s) found {nonManifestFiles}"); return(new VerificationResult { Status = SigningStatus.FundamentalHashMismatch, Valid = false }); } } // Verify the hashes of every file in the JAR // using (var h = new Hasher()) { Log.Message($"Central manifest contains {centralManifest.Entries.Count} entries"); foreach (ManifestEntry e in centralManifest.Entries) { Log.Message($"Digest check {e.Path} ({e.Digest})"); // Check each file matches the hash in the manifest if (jar.SHA256(h, e.Path).ToBase64() != e.Digest) { Log.Message($"{e.Path} has an incorrect digest"); return(new VerificationResult { Status = SigningStatus.FundamentalHashMismatch, Valid = false }); } } } // Detect signatures // // ISignatureFinder finder = new SignatureFinder(); List <Signature> signatures = finder.Find(jar); if (!signatures.Any()) { Log.Message("No signatures detected"); return(new VerificationResult { Status = SigningStatus.NotSigned, Valid = false }); } Log.Message($"{signatures.Count} signature(s) detected"); // Verify signatures // // SignatureVerifier ver = new SignatureVerifier(); if (ver.Verify(jar, centralManifest, signatures, certificates)) { return(new VerificationResult { Status = SigningStatus.SignedValid, Valid = true }); } else { return(new VerificationResult { Status = SigningStatus.SignedInvalid, Valid = false }); } }