[OmniOS-discuss] Trust and OmniOS installs

Ben Summers ben at fluffy.co.uk
Thu May 16 06:17:12 EDT 2013


On 8 May 2013, at 14:50, Ben Summers <ben at fluffy.co.uk> wrote:

> 
> Hello,
> 
> I'm rebuilding our infrastructure based on OmniOS, migrating away from Solaris 10. It's great to have a modern and minimal Solarish OS for which you can buy a support contract. (And that vendor not be Oracle.)
> 
> We do have one slight problem in our environment, that we have to trust the network to be able to use the OmniTI repos since they're served over plain HTTP.
> 
> Obviously we have to trust our OS vendor, but I suspect the requirement to trust the network would cause problems with audits from our customers. And besides, we're a security focused company offering a "secure" service, so I like to do things properly.
> 
> Unless OmniTI are kind enough enable https on pkg.omniti.com, is there a way to minimise the number of third parties we are trusting?
> 
> Could we create a mirror somehow over our relatively trusted network in the colo? Or would a simple https proxy work?


To reply to my own message, after discussing with the OmniTI chaps on IRC, and doing a bit of research, it looks like the best solution (that _I_ can implement) is to run a mirror and sign the packages, rather than using an https proxy: https will make it go really slowly.

I had a bit of a play with mirroring and package signing. My notes are below.

In summary, it works well, but I had to make a small patch to the IPS tools because there's a version mismatch with the python M2Crypto library.

So a plan to minimise trust on the network would be to:

 * Run our own mirror of the OmniOS repo in our colo.

 * Write a small script to use pkgrecv to fetch new packages, then pkgsign to sign them.

 * Add our CA certificate to our OmniOS install and change the policy and publisher URL.

Note that this is easy because pkgsign works independently of package creation. IPS' enterprisey roots help here, as it's intended for things like QA signing off on packages before they get deployed.

This isn't a full solution, as there's still trust on the network between OmniTI and our colo network and it complicates disaster recovery, but it's a reasonable workaround, and if we're happy with a set of packages, we can be sure they never change.


If OmniTI wanted to sign their packages and eliminate the problem for everyone, they would need to:

 * Add a CA root to their distribution, and set signature-policy=require-signatures for their IPS publisher

 * After building new packages and sending them to the repo, sign them as a separate step

 * Make available over a separate trusted channel the digest of the ISO image containing the CA root, to start the chain of trust.

This would add maybe 850 bytes to each manifest, but otherwise have no impact on performance. Reasons for OmniTI not doing this are practical issues around running a CA and the extra step in the release process.

Ben




# Get a copy of the OmniOS repo

zfs create -o mountpoint=/export/repos rpool/repos
pkgrepo create /export/repos/omnios
pkgrecv -s http://pkg.omniti.com/omnios/release/ -d /export/repos/omnios '*'
zfs snapshot rpool/repos at after-pkgrecv

# (running pkgrecv again will fetch new packages)


# Get list of all package FMRIs in the repo:

pkgrepo list -s /export/repos/omnios -H -F tsv | awk -F $'\t' 'BEGIN {OFS = FS} {print $8}' > all_pkgs


# Remove one package from the list, for testing

vi all_pkgs
  ... delete the rsync line


# Make a CA and a signing certificate with a hacky CA script (copy at end)

python repo_ca_tool.py repo-test-ca ca
python repo_ca_tool.py repo-test-ca signer "Test Signer"


# Sign all the packages

xargs pkgsign -s /export/repos/omnios/ -a rsa-sha384 -k repo-test-ca/test_signer.key -c repo-test-ca/test_signer.crt -i repo-test-ca/ca.crt < all_pkgs


# Output the the CA cert for use later

cat repo-test-ca/ca.crt 


# Make a repo server config file

vi pkg_depotd.cfg 

------------------
[pkg]
port = 80
inst_root = /export/repos/omnios

[omnios]
feed_description = OmniOS mirror
  update log
------------------

# Run a repo server

/usr/lib/pkg.depotd --cfg pkg_depotd.cfg 


# Visit in web browse to check:

   http://192.168.84.147/omnios/

(view a manifest, note it as a signature line at the very bottom. Look at the rsync manifest, note it doesn't.)


# Change a manifest to break a signature

cd /export/repos/omnios/publisher/omnios/pkg/developer%2Fbuild%2Fautoconf
vi   2.69%2C5.11-0.151006%3A20130506T182715Z
(change a single byte somewhere)


-----------------------------------------------------

# Install OmniOS into a virtual machine, create user...

groupadd ben
useradd -g ben -s /bin/bash -d /export/home/ben -c "Ben Summers" -P "Primary Administrator" -m ben
passwd ben
ipadm create-if e1000g0
ipadm create-addr -T dhcp e1000g0/v4dhcp
init 6

# Log into new VM with ssh.

# Replace the URL of the omnios publisher

pfexec pkg set-publisher -g http://192.168.84.147/omnios/ -G http://pkg.omniti.com/omnios/release/ omnios

# Copy and paste the CA certificate from above into a file

vi /tmp/ca.crt
  ... paste cert... 

# Then set it, and delete the file

pfexec pkg set-publisher --approve-ca-cert /tmp/ca.crt omnios
rm /tmp/ca.crt


# Tell pkg we only want signed packages on this system

pfexec pkg set-property signature-policy require-signatures


# And also for the publisher, for good measure (not sure it's required)

pfexec pkg set-publisher --set-property signature-policy=require-signatures omnios


# Do a pkg update

pkg update

   ... which fails, because there appears to be a version mismatch with the python m2 library.

pfexec vi /usr/lib/python2.6/vendor-packages/pkg/actions/signature.py

edit line 319 -> 
                pub_key = cert.get_pubkey()
                pub_key.reset_context(md=self.hash_alg)
(removing argument, adding extra line)

# Now it works

pfexec pkg update
pfexec pkg install pkg:/package/pkg

# And let's install a signed package

pfexec pkg install gnu-tar

# But rsync can't be installed, because we didn't sign it.

pfexec pkg install rsync

Creating Plan \               
pkg install: The policy for omnios requires signatures to be present but no signature was found in pkg://omnios/network/rsync@3.0.9,5.11-0.151006:20130506T190016Z.

# And autoconf can't be installed, because we changed the manifest

pfexec pkg install autoconf

Creating Plan \               
Errors were encountered while attempting to retrieve package or file data for
the requested operation.
Details follow:

Invalid content: manifest hash failure: fmri: pkg://omnios/developer/build/autoconf@2.69,5.11-0.151006:20130506T182715Z 
expected: 1bd3c48103a369222daba31ec3b9a3214273769c computed: 29cc39b07f5c988b2114fec6477299329d86dc35. (happened 4 times)





------------------------------------------------------------------
#!/usr/bin/env python

import os, sys, subprocess, re

def fatal_error(msg):
    sys.stderr.write(msg+"\n")
    exit(1)

if len(sys.argv) < 3:
    print "usage: ca_tools <dir> <action> [<common name>]"
    print "  action = ca or signer"
    print "  cert requires common name for cert"
    fatal_error("Bad command line args")
    exit(1)

ca_dir = sys.argv[1]
action = sys.argv[2]
common_name = None
if action == 'signer':
    if len(sys.argv) < 4:
        fatal_error("No common name")
    common_name = sys.argv[3]

def make_key(filename):
    if 0 != os.system("openssl genrsa -out "+filename+" 2048"):
        fatal_error("Failed to create key "+filename)

def make_cert(filename, key, common_name, signextra = ''):
    cmd = ["openssl", "req", "-new", "-key", key, "-out", filename+'.csr']
    crt = subprocess.Popen(cmd, stdin=subprocess.PIPE)
    crt.stdin.write(".\n.\n.\n.\n.\n"+common_name+"\n.\n\n\n")
    crt.wait()
    sign_cmd = "openssl x509 -req -sha1 "+signextra+" -days 3650 -in "+filename+'.csr -out '+filename+'.crt'
    if not "CAkey" in sign_cmd:
        sign_cmd = sign_cmd + " -signkey "+key
    if 0 != os.system(sign_cmd):
        fatal_error("Failed to sign cert")

if action == 'ca':
    if os.path.isdir(ca_dir):
        fatal_error(ca_dir + " already exists")
    os.makedirs(ca_dir)
    make_key(ca_dir + '/ca.key')
    make_cert(ca_dir + '/ca', ca_dir + '/ca.key', "PKG CA", "-extensions v3_ca")
    with open(ca_dir + '/ca.srl', "w") as f:
        f.write("10\n")

elif action == 'signer':
    basename = ca_dir+'/'+re.sub(r'[^a-z0-9]', '_', common_name.lower())
    if os.path.isfile(basename+'.key'):
        fatal_error("Already made certs for "+common_name)
    make_key(basename+'.key')
    make_cert(basename, basename+'.key', common_name, "-extensions usr_crt -CA "+ca_dir+"/ca.crt -CAkey "+ca_dir+"/ca.key -CAserial "+ca_dir+"/ca.srl")

else:
    fatal_error("Unknown action "+action)

------------------------------------------------------------------










--
http://bens.me.uk



More information about the OmniOS-discuss mailing list