Bug 1382415

Summary: Nova encryption alters the key used
Product: Red Hat OpenStack Reporter: Pablo Iranzo Gómez <pablo.iranzo>
Component: openstack-novaAssignee: Lee Yarwood <lyarwood>
Status: CLOSED ERRATA QA Contact: awaugama
Severity: high Docs Contact:
Priority: high    
Version: 6.0 (Juno)CC: berrange, dasmith, ddomingo, eglynn, jschluet, kchamart, lyarwood, sbauza, sferdjao, sgordon, srevivo, vromanso
Target Milestone: z2Keywords: TestOnly, ZStream
Target Release: 10.0 (Newton)   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: openstack-nova-14.0.2-7.el7ost Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2017-02-23 21:14:26 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Script to simulate the key alteration and to get the one that can be used to open with cryptsetup none

Description Pablo Iranzo Gómez 2016-10-06 15:36:35 UTC
Created attachment 1207974 [details]
Script to simulate the key alteration and to get the one that can be used to open with cryptsetup

Description of problem:

Customer wanted to be able to use cryptsetup to prepare volumes pre-encrypted that could be loaded into OSP env (after injecting files)

For using encryption, 'fixed_key' was set on cinder.conf and nova.conf

Looking at the code for nova, the passphrase is given to the command but as the same fixed_key being used was not working, a debugging 'print' was used, yielding:

fixed_key on config file:
752523eb50c3bf2ba3ff639c250405805fd4e779894ef5360e15e081696a

passphrase passed to cryptsetup:
752523eb50c3bf2ba3ff639c2545805fd4e779894ef536e15e081696a

Once we used the passphrase passed to cryptsetup, we were able to open the device and access the contents.


Version-Release number of selected component (if applicable):

python-nova-2014.2.3-67.el7ost.noarch

At: /usr/lib/python2.7/site-packages/nova/volume/encryptors

cryptsetup.py:        return ''.join(hex(x).replace('0x', '') for x in key)
luks.py:        passphrase = ''.join(hex(x).replace('0x', '') for x in key)


How reproducible:


Steps to Reproduce:
1. Define a passphrase by using fixed_key
2. Use that passphrase to open via cryptsetup the file

Actual results:

FAILS

Expected results:
Ability to open the encrypted volume

Additional info:

See attached script (to be executed on a server with nova libraries) and provide different keys like the one poster above


Script output:
[root@osp6 ~]# python cinder-volume-genkey.py 
Enter the fixed_key: 752523eb50c3bf2ba3ff639c250405805fd4e779894ef5360e15e081696a
ORIG:  752523eb50c3bf2ba3ff639c250405805fd4e779894ef5360e15e081696a
NEW :  752523eb50c3bf2ba3ff639c2545805fd4e779894ef536e15e081696a

Comment 1 Pablo Iranzo Gómez 2016-10-06 16:09:25 UTC
Any fix on the key generation could lead to potential volumes no longer being accessible unless a fallback mechanism is provided for old-encrypted ones.

The code has changed from OSP6 to upstream:

git diff 8c0673d3 luks.py


         key = self._get_key(context).get_encoded()
-        # LUKS uses a passphrase rather than a raw key -- convert to string
-        passphrase = ''.join(hex(x).replace('0x', '') for x in key)
+        passphrase = self._get_passphrase(key)



Initial: https://review.openstack.org/#/c/30976
Change: https://review.openstack.org/#/c/223315


If the 'conversion' code for the key has changed, in case any environment using the old schema (even if there's a log line saying that it's not secure) could face lot of issues on upgrade unless we mangle the key on the updated setup to get the same result from the functions.

Comment 2 Lee Yarwood 2016-10-14 13:08:27 UTC
hex(x) is stripping leading 0's in the individual hex number while we encode the passphrase back to a string via the join, leading to the differences between the original fixed_key hex string and the string used as the passphrase.

As outlined in the attached script the following one liner reproducers the decode and encoding operations that we currently do in OSP 6 / Juno :

>>> ''.join(hex(x).replace('0x', '') for x in array.array('B', '752523eb50c3bf2ba3ff639c250405805fd4e779894ef5360e15e081696a'.decode('hex')).tolist())
'752523eb50c3bf2ba3ff639c2545805fd4e779894ef536e15e081696a'

Original string: 752523eb50c3bf2ba3ff639c250405805fd4e779894ef5360e15e081696a
New string     : 752523eb50c3bf2ba3ff639c25 4 5805fd4e779894ef536 e15e081696a

>>> hex(14)
'0xe'

>>> int(0x0e)
14

>>> int(0xe)
14

>>> hex(4)
'0x4'

>>> int(0x04)
4

>>> int(0x4)
4

The change you listed above didn't change the implementation however it has recently changed in Newton via the following change :

Replace key manager with Castellan
https://review.openstack.org/#/c/309614/

This change introduces the use of the Castellan library and changes the way in which we encode the passphrase before use, again it breaks down to the following one liner :

>>> import binascii
>>> binascii.hexlify(bytes(binascii.unhexlify('752523eb50c3bf2ba3ff639c250405805fd4e779894ef5360e15e081696a'))).decode('utf-8')
u'752523eb50c3bf2ba3ff639c250405805fd4e779894ef5360e15e081696a'

Original string: 752523eb50c3bf2ba3ff639c250405805fd4e779894ef5360e15e081696a
New string     : 752523eb50c3bf2ba3ff639c250405805fd4e779894ef5360e15e081696a

So any attempt to attach a volume encrypted prior to Newton with Newton or later is going to fail unless a) the shorter fixed_key is used b) we retry with the shorter key as a horrible workaround.

I'm going to ask colleagues for advice here before pushing this upstream.

Comment 3 Jon Schlueter 2017-01-11 19:26:05 UTC
According to our records, this should be resolved by openstack-nova-14.0.2-7.el7ost.  This build is available now.

Comment 10 errata-xmlrpc 2017-02-23 21:14:26 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://rhn.redhat.com/errata/RHBA-2017-0319.html