From 2433fdab989ee34918a5d07fabd3839b63e5c971 Mon Sep 17 00:00:00 2001 From: ilia-kats Date: Sun, 9 Feb 2025 14:24:16 +0100 Subject: [PATCH] luks_device: allow passphrases to contain newlines (#844) * luks_device: allow passphrases to contain newlines This is useful when passing binary keyfiles from an ansible vault, as it removes the restriction that the binary data cannot contain newlines. The only exception is adding a new key to an existing container, as in that case the two passphrases are separated by a new line. * add integration tests and a changelog fragment * attempt to also make luks_add_key work with passphrases containing newlines * use a deterministic method to generate keyfile 3, improve changelog formatting * add licence and copyright to keyfile3.txt to satisfy CI --- .../luks_device_passphrase_newlines.yml | 2 + plugins/modules/luks_device.py | 18 +-- .../targets/luks_device/files/keyfile3 | Bin 0 -> 4096 bytes .../luks_device/files/keyfile3.license | 3 + .../targets/luks_device/files/keyfile3.txt | 7 ++ .../tasks/tests/keyfile_binary_nocopy.yml | 105 ++++++++++++++++++ .../targets/luks_device/vars/main.yml | 6 + 7 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 changelogs/fragments/luks_device_passphrase_newlines.yml create mode 100644 tests/integration/targets/luks_device/files/keyfile3 create mode 100644 tests/integration/targets/luks_device/files/keyfile3.license create mode 100644 tests/integration/targets/luks_device/files/keyfile3.txt create mode 100644 tests/integration/targets/luks_device/tasks/tests/keyfile_binary_nocopy.yml create mode 100644 tests/integration/targets/luks_device/vars/main.yml diff --git a/changelogs/fragments/luks_device_passphrase_newlines.yml b/changelogs/fragments/luks_device_passphrase_newlines.yml new file mode 100644 index 00000000..281cba52 --- /dev/null +++ b/changelogs/fragments/luks_device_passphrase_newlines.yml @@ -0,0 +1,2 @@ +bugfixes: + - luks_device - allow passphrases to contain newlines (https://github.com/ansible-collections/community.crypto/pull/844). diff --git a/plugins/modules/luks_device.py b/plugins/modules/luks_device.py index 156f4b32..ebb48c64 100644 --- a/plugins/modules/luks_device.py +++ b/plugins/modules/luks_device.py @@ -70,9 +70,6 @@ options: passphrase_encoding: description: - Determine how passphrases are provided to parameters such as O(passphrase), O(new_passphrase), and O(remove_passphrase). - - Please note that binary passphrases cannot contain all possible binary octets. For example, a newline (0x0A) - cannot be used since it indicates that the passphrase is over. If you want to use arbitrary binary data, you must - use keyfiles. type: str default: text choices: @@ -488,8 +485,6 @@ class Handler(object): self._module.fail_json("Error while base64-decoding '{parameter_name}': {exc}".format(parameter_name=parameter_name, exc=exc)) def _run_command(self, command, data=None): - if data is not None: - data += b'\n' return self._module.run_command(command, data=data, binary_data=True) def get_device_by_uuid(self, uuid): @@ -635,6 +630,8 @@ class CryptHandler(Handler): args.extend(['-q', device]) if keyfile: args.append(keyfile) + else: + args.append('-') result = self._run_command(args, data=passphrase) if result[RETURN_CODE] != 0: @@ -646,6 +643,8 @@ class CryptHandler(Handler): args = [self._cryptsetup_bin] if keyfile: args.extend(['--key-file', keyfile]) + else: + args.extend(['--key-file', '-']) if perf_same_cpu_crypt: args.extend(['--perf-same_cpu_crypt']) if perf_submit_from_crypt_cpus: @@ -706,14 +705,16 @@ class CryptHandler(Handler): if keyfile: args.extend(['--key-file', keyfile]) else: + args.extend(['--key-file', '-', '--keyfile-size', str(len(passphrase))]) data.append(passphrase) if new_keyfile: args.append(new_keyfile) else: - data.extend([new_passphrase, new_passphrase]) + args.append('-') + data.append(new_passphrase) - result = self._run_command(args, data=b'\n'.join(data) or None) + result = self._run_command(args, data=b''.join(data) or None) if result[RETURN_CODE] != 0: raise ValueError('Error while adding new LUKS keyslot to %s: %s' % (device, result[STDERR])) @@ -759,6 +760,8 @@ class CryptHandler(Handler): args = [self._cryptsetup_bin, 'luksKillSlot', device, '-q', str(keyslot)] if keyfile: args.extend(['--key-file', keyfile]) + else: + args.extend(['--key-file', '-']) result = self._run_command(args, data=passphrase) if result[RETURN_CODE] != 0: raise ValueError('Error while removing LUKS key from %s: %s' @@ -774,6 +777,7 @@ class CryptHandler(Handler): if keyfile: args.extend(['--key-file', keyfile]) else: + args.extend(['--key-file', '-']) data = passphrase if keyslot is not None: diff --git a/tests/integration/targets/luks_device/files/keyfile3 b/tests/integration/targets/luks_device/files/keyfile3 new file mode 100644 index 0000000000000000000000000000000000000000..3d5c5d153b136199fa2fa898badfadde1eb011cc GIT binary patch literal 4096 zcmV+b5dZJxr-_`%OPIkq`9A|CDwce#Gdw4IWgwIu5&qVWT>+l4&X%sp;;jT`77QL4 z;d+WVkE3-iKI!@9L*Uv-ei!oBCKhF`pCpw%Tu2ChPx8*T7s6{lYj3LjXi&4O_K>S7 z?og*X=em86pi;}}=8Mxyfx7MU2pM%EatZ-W6sYYxLwj+ih7^DcgnE;Rn`?l0$0o{o zr@egZB=alx%n|Lfg0Q>p3x1dihE~cXTcz|UY_vcM5W1&B!%!Yodj%XA=`^OrJxd|3tn4S|W|#jU0O-2Ci-7)v(tG2#Uk#kJ9>F7c%k5paOo4vM!5*QpOGpZLNWplQW1 zN491kZ(TL@5{1A?53-jDBZYl<;n=U?A4o)mf?>HZAs0nI_*sFPM17%$4MzA#K6qB{ zak6vL-^hVt#U)rvQ83xQ)i3+>BDQzGx_4G{&^y^vEZkr?%pvXogLH`CQ=|m3-oQSS zeD7V4?3IEuTwhVUyw;gowOe4GV2SuzLF9~ee-XD zW6CbP^=IZ5*1QUnAA$HO&OZK+47qD3$bopGT2k*i@*noss!mTG^$8Fzmu7V)j?`f! zJoW2UGdW;Z#9+=Vt~o9Y`Q=VoUh)Jm)ZPg)YBB=!vfmRYcJ(Tw)`v$UsY~vFq;`ni>YA zfCl*%nk3V2bE&gFx_YcK&ss{-4A3G&BSGR^pf#Q-PD)aP=7BBHKckU?Py-%v`7}L~ z8bn+lh(^g-uUi)^%W3~;G`IN#>!I)mkue?uTOQ%ZwH}GpI3>S*#B8u46l?-utF?l| ziZ@!{#0Y1t#m*lXN;nB-vZ|ujTUnA2lg40Bj@V$b)V((WFgwy=O%$&ANnJ-U%~?Y< ztxN+NtE$hIv0F-sA^4xjjz<466ft!8(!}#tHm&@Qd(c1qzlFtmT*ag)y2j9+neN|$ z7zAC=f^pgtV8-(K@gzzO`wd+x>_X%ea!|snDwE+jxnhKiq)6ks>_{J9gCu*S&JlOZ z&q*ANW=QOc1@!fr*HDe`gmdSQi23LX;<6>pFl*}2rLvriW;UuT@H2Tz$W+XlL4bdv zD+uyQnmo!0+rhl;cg zKJu(tp4Wfprh^S-g>1oNrh-6b^>pO&lK*0MhyqC{7ZWxpolIDFCCyIYY1-v7;)a5- zqIc5ztYf8Jf93!v-ZvoxMZ=a63%$OzVQSIyq9DodHhH#jw%)sSRxSR&TfZ}<4!8hv z8xz(#+-`hBJ0)S*NS+k=%o}0zDA%(_?UJ|RanEe2`tL|79Sj~AE$}U84O1Px$MXp4 zuY$o$VMs5Yc|Mz@sRa-B&4Q{)qH`kLubJj?GB(iiT?mUw z1N})rhdR^aFwjkBdvwD0?xCK}xuPgV>tMndH!Ctr5V`;NbBcrDEgU~t8h|z1tUgFi zLA>zu>5mjX)I6&oG){J8SUhKse?{K={p`^ z_+uVf>VFsf`IzeSLpFv=>fsUR$)Mw4L3Z0}`9*N3k40G1nlQs8;qRi@YA9@_6S_23VixOgKt)I-VX#6%`tmx;882E+9 z%XU=q(E|B_qAhbVGam0btDQ%r3>Dg=Uuv-ZlE{Hg=;n(hAWowbY!`MjTUnyoCH-|R zykY-JCQYIhP<+$Rdu}i0UQe&`iN7^7JEt!?oVTnyRF%{4mmAnlKKLMiaDuYa(WLA(N3^BsbijKQ~UV(l1%uJZExr0Sk}80LcN)D z2SU8I2=|DMZ^?oj`{96uFTM7&8#Mb`*u>SypSAq{7tsM@TeJ3FShuXdoPmS5^R$kN`WwCDJ`x_5Jj)yIk z!Dh;z05i3gPWH(V!=B9itF$WkPbjp%v{;qhyvEm&{*rNRnkps;?_bURUHY{>vkHCP{C^O!gLc@mw z#z6cTl3dp9G*3Q|z>UkhF#>Tq3P#3B(R2=K4=`@l*$v&ID_TMLuN|JTixp`~X#c$= z0Bly%G0TbL(go3lTn>_w7D6mi zPkndd@$Lr3NXkg9j0ChfU6ph65sJ<>_xf#(f@{M3?n)lA9su|M-b=I_ZO7{=ZR?Kv z&jXVFZdppP8M3exr??syr?}J8Z=G;XGM}oNIO~u9l#G{gz>L` zqEuJQx@F^4gpM^keG&HF&~x7lAp0_aHDib^kmIJ!pDN=>1Q!M>48hPwIR}?n*E1UlrQIzk{oRw zQh2C2^sTtzl*WCqtwIx=f{)7c>at0#lr+#y6@wRX{2$-RzONpb%^3IMdrHHBYy-aP zVdk_ehniV}n43gfXb`qauV!U3bN9LIQ|@#_JaN`v{49)vBgka9_m$%ib=_Z(#$OyG z76eUB21*~;`d+ZUX`(d{zO8Q-trJUKR{E4@FMuycJV+qDnfvqeg}H>Cx{z6RBV8+P z+Ihqq;4c^VtOBwck8A)Z##iWp>M22iFVm5vAg;G*`ZQ^O$;5v@-S&ozD660oU~jJB zh6Hn~!+`y=8<2dsjv0)F0!7pO18Y#F)2@wL?W1I!9#w^nH8IjtpulU~2nf;XxU3mi zc%_sfmKYK3swVlRYI`y732cur1%U!a)lIZ)RW$PGK8iQ}qmCa#VHKMWK0{MR-t%5D zw~Wv+8H(4$V&%%@HDI4cO>z*d?>%dm?jYz%DWhwr|JjTZH&QuHKSbaTNT|Zn^4SM; zy;d!~$=KW1UZc{Eg8T)Q9ux>&6niDoZr6poBysYiuJeLxDa&XmXnK=>vp8qN`qYXc zWLa$dStjDU7d$(Jt^jqYC;oNI8mo(aD)IF9%W0!L2l4&xtJo2^`tmnpKv;b6?IY4@ zJ3QWCQ*orao=A09ea+vFUMO->}(C*_}8-1;d3NF~BEuF&9NYD!4+Y?9Z+Z$j^lte$W|>x;a;t z|CIQhiZ-9f3so|jwsu^-xJ=JVn1xm1?z&=byLTyhUEhjdb)kGpUsem%klXaC(!^sl z;OYe7aYT$fEvy^8Tk|W6SH@+pv#T~pVu9BeDrdLRcrUEtgY3G1N@Y(6p0$PkXkV}w zXGXeu@J$rhcs($w~YzXDFbr z*6(%E>qm5q5t`Un-{BMwOE*NpU2)TXQ$bQ8ftMG}Jlz)v!EKfZ#*Jh$2a1C@MvU_x zHf*0!&LGQzYO<#nflg6$zWk88g~1Ozf)?(M4bcs+hut7dKDJs4^Iv_@Vae=QCsg+l z=#+h4-|=FBTj4DbsjsvPWnNug`@2^PzP)DM5u#p=_G6Yc|xo`cE-qCSH0(I%sgVJP|4q;efYZ!oS7!~eg z+HR&m%6zjNP0*4&kd7?tM1BL;2mV!$hl$Ai<9sCV4~ORV;RvomY%(rpas=#&E>#)% zAx}@CLe;b&dxT(@8z4h2@L6S6ND5L#>gk@N+m;YBvJ{Eejcd^45iCIa0biU{jK$nQ z^KlV!!)iBMIFU^se^j~K!{cwX6?$20o35yXtTga=6Zg8m19th*de%oj14HB_MbHxi%F#UXbjAj= yhm-QaJie?PkOLxs`O6FyCf&f