Skip to main content

[Obsolete] Azure package unpack and repack

Azure package

There are a lot of possible scenarios of Azure deployment. Most of them are based on package that we can define and create with Visual Studio.
If you need to change package use Visual studio to repack your project. To prepare specific web.config file, use different build configuration with transformation (web.config.release, web.config.debug etc.)
Only when it's not possible to use Visual Studio to repack Azure package, then it's possible to repack it the way described below.

Package repack

Azure package is a zip archive, that can be opened and changed with any zip archive tool. The structure of that archive is static and is followed by some rules (unfortunately it's not so easy to find information about correct structure and rules used to generate that package). 
Main content (web- or workerrole) of package placed in files with extension ".cssx", which is also a zip archived folder. That folder can be opened and changed, but that will make package invalid, because it's secured by hash value that is stored inside of the package. That means, that next action in repack is a recalculation of hash of changed files. To calculate hash used SHA256Managed algorithm, applied to file content stream:

var hashBytes = new SHA256Managed().ComputeHash(contentStream);
hash = BitConverter.ToString(hashBytes).Replace("-", "");
 
Calculated hash should be placed into ".csman" file in the root of the package. That file has a simple XML structure, so it's not a problem to find an appropriate place for calculated before hash.

 
var item = doc.SelectSingleNode($"//Item[@name='{contentEntry.Name}']");
item.Attributes["hash"].Value = hash;
Obviously that hash should be calculated after changes in the content file stream
using (var archiveStream = File.Open(archivePath, FileMode.Open))
using (var mainarchive = 
    new ZipArchive(archiveStream, ZipArchiveMode.Update))
{
    var contentEntry = mainarchive.Entries
        .Single(e => e.FullName.EndsWith(".cssx"));
    string hash;
    using(var contentStream = contentEntry.Open())
    using (var archive = 
        new ZipArchive(contentStream, ZipArchiveMode.Update))
    {
        var appEntry = archive.GetEntry("[Some entry]");
        // Some work here
    }
    using (var contentStream = contentEntry.Open())
    {
        var hashBytes = new SHA256Managed().ComputeHash(contentStream);
        hash = BitConverter.ToString(hashBytes).Replace("-", "");
    }
    var manifest = mainarchive.Entries
        .Single(entry => entry.FullName.EndsWith(".csman"));
    using (var manStream = manifest.Open())
    {
        var doc = new XmlDocument();
        doc.Load(manStream);
        var query = $"//Item[@name='{contentEntry.Name}']";
        var item = doc.SelectSingleNode(query);
        item.Attributes["hash"].Value = hash;
        manStream.SetLength(0);
        doc.Save(manStream);
    }
}
 This way is not trusted and changes in format or hash calculations are possible.

Comments

Popular posts from this blog

MS Dynamics CRM solutions storage model

It's not a secret that there are two types of solutions exists in CRM: managed and unmanaged. Each has it's own properties and capabilities. In general solutions can be differentiated by next points Managed solution Unmanaged solution Completed solution Cannot be exported Deleted with all its changes and components Under development Can be exported as managed Can’t undo changes done by import   Let's see what makes them behaves in a different way.