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);
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }
Example #4
0
        /// <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
                });
            }
        }