No 7zip Allowed: Extracting Oracle's Gzipped Java Tarball On Windows to Create an Isolated, Zero Footprint Java Install for CIS CAT Pro

Search for a command to run...

No comments yet. Be the first to comment.
Why Least Privilege Security Engineering Is Frequently Skipped or Done Loosely In a previous life, I was on a team that reviewed the IAM policies specified by developers when they created new Cloud applications or required additional permissions for ...

Obscuring sensitive information like AWS account IDs in screenshots and videos is tedious and error-prone. Even with video editing tools that simplify the process, I still have to repeatedly add and remove blurring boxes as the view changes. You know...

AWS CloudShell joins the ranks of hostless shells for operating in your cloud environment. Cloud shells are a huge help to training and enablement scenarios because they remove the pain of fussy configuration of a user-owned endpoint - which can have...

This article is the third and final of a series. Part 1 justified that human-performed DevOps checklists are essentially source code, and according to GitOps principles, belong in Git just like any other code required for successfully managing a soft...

There are always those who feel checklists are an unnecessary waste of time because they think they can always remember the basics of the steps involved to complete a task. Many are also not aware of the huge, cross-discipline benefits that can come ...

I had a project to package the CIS CAT Pro benchmark auditing tool for Windows and Linux. The unique Windows challenges I experienced are applicable anytime you either need to extract Java for Windows or extract any gzipped or tar archive on Windows - without using 7zip. CIS CAT Pro requires Java and I wanted to create a zero footprint Java install that could be cleanly wiped out by deleting a folder. This allows the automation to be more readily used on production systems because it won’t force a Java install, nor compete with an existing version of Java. (I find it ironic that CIS CAT requires Java - and then frequently flags the copy of Java it is using as a problem)
7zip has had a fair share of security vulnerabilities - consequently installing or using it can set off more than a few security bells where I work - so it was required to have a solution that was 7zip-less.
While it is more than a little frustrating that Java is only provided by Oracle as a gzipped tarball for Windows, this method will work fine for anything else that is only provided for Windows as a gzipped tarball.
The term Infrastructure as Code is thrown around a lot and yet without very many specifics on how adopting this approach would inform coding choices. Sometimes people think of it exclusively in terms of desired state configuration management platforms like Chef, Puppet or Ansible. I have heard others reference it purely as setting up things other than actual end nodes - like what Terraform does.
When I think of Infrastructure as Code it is all inclusive - whether imperative or declarative or whether OS oriented or hypervisor oriented. To me a pure definition of Infrastructure as Code means every last scrape of your configuration can be checked into source control and that the hard core disciplines of traditional development are applied (e.g. structured code, lots of testing, etc.)
Put another way, if the bottom of the stack imperative code (that always underlies declarative systems) stays as the quick and dirty admin coding of the past - it would be the achiles heal of the rest of the stack!
If you’re lucky enough to live in a pure PaaS or FaaS (Serverless) world - then this imperative level probably does not exist (but then you would also not have made it to this point in this article ;) )
For a long time I have felt that minimalizing code around the most pragmatic implementation made it more flexible than I originally anticipated in engineering it - it was a repeating theme. Recently I found that exact idea asserted in the book FIRE: How Fast, Inexpensive, Restrained, and Elegant Methods Ignite Innovation. I see it time and again that picking rudamentary implementations frequently increases their scope by reduce the assumptions. This aspect of coding is somewhat unique to developing automation for a broad audience because business applications rely on bringing all dependencies with them (at least the ones with well written installation code do ;) )
In working with operating system provisioning and software deployment automation, I frequently deal with bootstrap automation - a system that does not have extras and may be in a build environment where it cannot easily get to extras. Additionally, I frequently have to go from freshly booted OS to complete working software stack in one set of orchestration. Dealing with these constraints automatically causes me to reduce the external dependencies I take on anything that does not ship on the box. It’s why I code in PowerShell and Bash - usually the shipped version of these languages is sufficient for anything I want to do. Reducing dependencies not only means I can get to the real work of configuration faster, it means you don’t soil the system with a bunch of installations that have nothing to do with the final software stack that will run on it. In addition, in the Windows world we constantly deal with the fact that exe and msi based installers frequently require special handling like reboots - what a painful situation to be in simply because you need a given utility to automate an installation.
The first phase in a minimalistic approach is to ask “Is there anything on the machine that can already do this task?”
.NET (and therefore PowerShell) has a class for standard .zip extracts (system.io.compression.filesystem) and at first blush this class seems to contain some attempt to handle linux archive technology - but it is not complete and definitely does not handle both gzip and tar.
In fact, using system.io.compression.filesystem is another exercise in minimalism - it has the following benefits over using Windows Explorer’s unzip capability which you find in many code samples:
Other Options Investigated:
Another IaC principle I apply is that software and utilities needed only for installation or only for a temporary purpose, should not be fully installed and integrated (even if removed later) if at all possible. This is a slightly higher scoped “minimalism” than what type of code and utilities are used to perform the installation. In this case it affects both the installation automation and the overall idea of putting CIS CAT on a system. The reason for putting CIS CAT on any system does not have to do with the what the software stack on that system is designed to do for customers - so effort should be made to minimize any impact it would have on the target system. In the case of CIS CAT we have a special concern in that it might be the only reason Java needs to be put on a given system - so it should be isolated and easy to clean off. This level of minimalism, then, informs us that the design of making the CIS CAT and Java install self-isolated and easy to clean off applies to both Linux and Windows.
Here is a summary of the benefits of using the tarball rather than installer edition:
I should mention that I tried tartool.exe - which depends on the assembly we will end up using - unfortunately, tartool was insisting that I install .NET 3.5 / 2.0. Not only do I not want this old version of .NET on my system - but for many versions of Windows this particular optional OS feature must be retrieved from Microsoft and it frequently fails to deploy.
Since this is primarily for instances in Amazon, Amazon’s Corretto Java was tried (which does come as a Zip). However, it was incompatible with at least some of the CIS CAT tests.
I finally settled on calling the assembly ICSharpCode.SharpZipLib.dll directly from PowerShell to untar the Oracle edition.
The following code downloads and extracts SharpZipLib and then uses it to extract Java. Look closely because the lines to acquire SharpZipLib include a little, but surprisingly helpful secret - .nupkg files are really just .zip files. This means any .nupkg file you find on nuget.org or chocolatey.org can be minimalized by downloading them, extracting them and using their contents. In fact, the Universal OpenSSH Installer I created takes advantage of exactly this fact to be usable for non-chocolatey installs!
Another point of IaC minimalism - it turns out SharpZipLib is now available with the “Install-Package” command - however, below I have chosen a direct .zip download for these reasons:
#This code should work on PowerShell 2 and later
#Acquire and unzip the nupkg file containing the assembly
Invoke-WebRequest -uri 'https://github.com/icsharpcode/SharpZipLib/releases/download/v1.1.0/SharpZipLib.1.1.0.nupkg' -outfile "$PWD/SharpZipLib.1.1.0.nupkg"
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::ExtractToDirectory("$PWD/SharpZipLib.1.1.0.nupkg","$PWD")
Write-host "Untaring Java..."
#Using the net45 version because that is the most likely to be preinstalled for my case, but check other folders under "lib" for other .NET serializations
Add-Type -Path "$PWD\lib\net45\ICSharpCode.SharpZipLib.dll"
#Automating the download of Java is intense, here are some ideas: https://stackoverflow.com/questions/24430141/downloading-jdk-using-powershell
$gzippedtarball = [IO.File]::OpenRead("$PWD\jre-8u212-windows-x64.tar.gz")
$inStream=New-Object -TypeName ICSharpCode.SharpZipLib.GZip.GZipInputStream $gzippedtarball
$tarIn = New-Object -TypeName ICSharpCode.SharpZipLib.Tar.TarInputStream $inStream
$archive = [ICSharpCode.SharpZipLib.Tar.TarArchive]::CreateInputTarArchive($tarIn)
$archive.ExtractContents($PWD)
#Set JRE Home and add the JRE Bin folder to the path of the current process (the next two lines could also be written to script to allow quick setup of the isolated version from other scripts)
$env:JRE_HOME="$PWD\jre1.8.0_212"
$env:PATH="$env:JRE_HOME\bin;$env:PATH"
After all that, you may wonder “Why not just untar and rezip the Java archive.” The reasons that I would not do that are rooted in hard experience, they are as follows: