Is there anyway that I can access the SHA1 of a package during my release process

(peter.m.mcevoy) #1

Hi there,
We are trying to tighten up our build-deploy cycle for PCI purposes and part of what we need to address is the question “How can you prove that the code you built is the code you deployed?”.

We need to be concerned about the integrity of the entire git -> jenkins -> octopus -> servers pipeline, but for the purpose of this question, I’d like to focus on how to prove/document that the artifacts that were built by Jenkins and pushed to Octopus are the same that get deployed.

One idea that I have is to use the internal Octopus Repository, as that seems to calculate the SHA1 of packages stored in it. At deploy time, we would like display the calculated SHA1 of the package (“actual”) and compare that with a value that was calculated by Jenkins (“expected”). The “Deploy a package” step should fail if there was deviance between the expected and actual.

Is this possible? Are their alternate ways of proving this integrity?

Pete

(Michael Richardson) #3

Hi Pete,

Although you’re correct, we do calculate the hash of the packages stored in the built-in package repository, we don’t expose that hash to the deployment process.

However, I’m hopeful you can achieve your goal with minimal extra work from that which would be required even if we did expose the hash.

I’ll walk-through a possible implementation, I’ll be interested to hear if you think it’s appropriate for your scenario.

  1. Add a Run a Script step to the beginning of your deployment process.
  2. Add a package reference to the package you wish to verify. Be sure to set the Extract package during deployment option to false.
  3. In the body of the script, you can obtain the package hash using the Get-FileHash PowerShell cmdlet.

The example below demonstrates this, assuming the package reference name is Acme.Web. You can see the various package variables here.

$packageFilePath = $OctopusParameters["Octopus.Action.Package[Acme.Web].PackageFilePath"]
$hash = (Get-FileHash -Path $packageFilePath -Algorithm Sha1).Hash

# Either verify the hash or save as an output variable

The next question is how to get the hash from Jenkins to compare against. You could make an API call to Jenkins to get it? Or supply it as a prompted variable at deploy time (you could configure this to only be required in the production environment)?

If the two don’t match, you could then fail the deployment. Alternatively, you could create an output variable with the hash, to be used in later steps.

As I mentioned, I think you would have to do most of this even if the package hash was available as a built-in variable. The only extra piece of work is calling the Get-FileHash cmdlet.

What do you think?

(peter.m.mcevoy) #4

We actually came to the same solution as you suggested (using a PackageStep) soon after posting our question… Good to know we are not reinventing the wheel.

For future peoples, Jenkins exposes an MD5 of archived artifacts that you can query using the Http API. Requires the “Fingerprint” plugin. An example URL is:

https://jenkins.mydomain.local/job/MyProduct/job/master/job/MyProduct-Full/196/api/xml?depth-2&tree=fingerprint[*]

and that exposes XML like:

<freeStyleBuild _class="hudson.model.FreeStyleBuild">
    <fingerprint>
        <fileName>MyProduct.200107.80.0+master.96bd29d2ea.196.nupkg</fileName>
        <hash>3192199b77c8e4cfc9f695553ee58803</hash>
        <original/>
        <timestamp>1578432295530</timestamp>
        <usage/>
        <usage/>
        <usage/>
    </fingerprint>
    ...

Of course, YMMV and to use in a script you may need to use the “crumbIssuer” trick to authenticate.

Pete

2 Likes