<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Oct 24, 2013 at 1:18 PM, Edward Shishkin <span dir="ltr">&lt;<a href="mailto:edward@redhat.com" target="_blank">edward@redhat.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi all,<br>
<br>
So, here is the &quot;all-in-one-translator&quot; version represented by the<br>
Patch Set #2 at <a href="http://review.gluster.org/4667" target="_blank">review.gluster.org/4667</a><br>
<br>
Everything has been addressed except encryption in NFS mounts (see<br>
next mail for details). That is:<br>
<br>
. New design of EOF (end-of-file) handling;<br>
. No oplock translator on the server side;<br>
. All locks are acquired/released by the crypt translator;<br>
. Now we can encrypt srtiped and(or) replicated volumes.<br>
<br>
Common comments.<br>
<br>
In the new design all files on the server are &quot;padded&quot;, whereas the<br>
real file size is stored as xattr. So we introduce a special layer<br>
in the crypt translator, which performs file size translations: every<br>
time when any callback returns struct iatt, we update its ia_size<br>
with the real (non-padded) value.<br>
<br>
The most unpleasant thing in this new design is FOP-&gt;readdirp_cbk():<br>
in this case we need N translations, i.e. N calls to the server (N is<br>
number of directory entries).<br>
<br>
To perform translations we spawn N children. We need a valid list of<br>
dirents after returning from FOP-&gt;readdirp_cbk() of previous<br>
translator, but we don&#39;t want to create a copy of this list (which<br>
can be large enough). For this reason we introduce a reference counter<br>
in struct gf_dirent_t and allocate dynamic structures gf_dirent_t<br>
(instead of on-stack ones), see respective changes in<br>
<br>
./libglusterfs/src/gf-dirent.c<br>
./libglusterfs/src/gf-dirent.h<br>
./xlators/cluster/dht/src/dht-common.c<br>
./xlators/protocol/client/src/client-rpc-fops.c<br></blockquote><div><br></div><div><br></div><div>[pasting from internal email reply]</div><div><br></div>I had a look at the way you are handling readdirplus. I think it is 
overly complex. FOP-&gt;readdirplus() already has a parameter @xdata in 
which you can request per-entry xattr replies.
<br>
<br>So in crypt_readdirp() you need to: dict_set(xdata, FSIZE_XATTR_PREFIX, 0);
<br>
<br>Once you do that, in crypt_readdirp_cbk, you can expect each gf_dirent_t 
to have its dirent-&gt;dict set with FSIZE_XATTR_PREFIX.
<br>
<br>So you just need to iterate over replies in crypt_readdirp_cbk, update 
each dirent-&gt;d_stat.ia_size with value from 
dict_get_uint64(dirent-&gt;xdata, FSIZE_XATTR_PREFIX)
<br>
<br>Please look at how posix-acl does something very similar (loading 
per-entry ACLs into respective inodes via xattrs returned in readdirplus)
<br>
<br><div>Avati</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Thanks,<br>
Edward.<br>
<div class="im"><br>
<br>
On Mon, 14 Oct 2013 14:27:01 -0700<br>
Anand Avati &lt;<a href="mailto:avati@redhat.com">avati@redhat.com</a>&gt; wrote:<br>
<br>
</div><div class=""><div class="h5">&gt; Edward,<br>
&gt; It looks like this patch requires a higher version of openssl (I<br>
&gt; recall you have mentioned before that that dependency was on version<br>
&gt; 1.0.1c? I checked yum update on the build server and the latest<br>
&gt; available version is 1.0.0-27. Is there a &quot;clean&quot; way to get the<br>
&gt; right version of openssl to a RHEL/CENTOS-6.x server?<br>
&gt;<br>
&gt; Also note that the previous submission of the patch was at<br>
&gt; <a href="http://review.gluster.org/4667" target="_blank">http://review.gluster.org/4667</a>. The recent on<br>
&gt; (<a href="http://review.gluster.org/6086" target="_blank">http://review.gluster.org/6086</a>) has a different Change-Id: in the<br>
&gt; commit log. It will be good if you can re-submit the patch with the<br>
&gt; old Change-Id (and abandon #6086) so that we can maintain the history<br>
&gt; of resubmission and the old work on records.<br>
&gt;<br>
&gt; Thanks!<br>
&gt; Avati<br>
&gt;<br>
&gt; On 10/14/2013 07:26 AM, Edward Shishkin (Code Review) wrote:<br>
&gt; &gt; Edward Shishkin has uploaded a new change for review.<br>
&gt; &gt;<br>
&gt; &gt;    <a href="http://review.gluster.org/6086" target="_blank">http://review.gluster.org/6086</a><br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; Change subject: Transparent data encryption and metadata<br>
&gt; &gt; authentication in the systems with non-trusted server (take<br>
&gt; &gt; II) ......................................................................<br>
&gt; &gt;<br>
&gt; &gt; Transparent data encryption and metadata authentication<br>
&gt; &gt; in the systems with non-trusted server (take II)<br>
&gt; &gt;<br>
&gt; &gt; This new functionality can be useful in various cloud technologies.<br>
&gt; &gt; It is implemented via a special encryption/crypt translator, which<br>
&gt; &gt; works on the client side and performs encryption and authentication;<br>
&gt; &gt;<br>
&gt; &gt;                1. Class of supported algorithms<br>
&gt; &gt;<br>
&gt; &gt; The crypt translator can support any atomic symmetric block cipher<br>
&gt; &gt; algorithms (which require to pad plain/cipher text before performing<br>
&gt; &gt; encryption/decryption transform (see glossary in atom.c for<br>
&gt; &gt; definitions). In particular, it can support algorithms with the EOF<br>
&gt; &gt; issue (which require to pad the end of file by extra-data).<br>
&gt; &gt;<br>
&gt; &gt; Crypt translator performs translations<br>
&gt; &gt; user -&gt; (offset, size) -&gt; (aligned-offset, padded-size) -&gt;server<br>
&gt; &gt; (and backward), and resolves individual FOPs (write(), truncate(),<br>
&gt; &gt; etc) to read-modify-write sequences.<br>
&gt; &gt;<br>
&gt; &gt; A volume can contain files encrypted by different algorithms of the<br>
&gt; &gt; mentioned class. To change some option value just reconfigure the<br>
&gt; &gt; volume.<br>
&gt; &gt;<br>
&gt; &gt; Currently only one algorithm is supported: AES_XTS.<br>
&gt; &gt;<br>
&gt; &gt; Example of algorithms, which can not be supported by the crypt<br>
&gt; &gt; translator:<br>
&gt; &gt;<br>
&gt; &gt; 1. Asymmetric block cipher algorithms, which inflate data, e.g. RSA;<br>
&gt; &gt; 2. Symmetric block cipher algorithms with inline MACs for data<br>
&gt; &gt;     authentication.<br>
&gt; &gt;<br>
&gt; &gt;                     2. Implementation notes.<br>
&gt; &gt;<br>
&gt; &gt; a) Atomic algorithms<br>
&gt; &gt;<br>
&gt; &gt; Since any process in a stackable file system manipulates with local<br>
&gt; &gt; data (which can be obsoleted by local data of another process), any<br>
&gt; &gt; atomic cipher algorithm without proper support can lead to non-POSIX<br>
&gt; &gt; behavior. To resolve the &quot;collisions&quot; we introduce locks: before<br>
&gt; &gt; performing FOP-&gt;read(), FOP-&gt;write(), etc. the process should first<br>
&gt; &gt; lock the file.<br>
&gt; &gt;<br>
&gt; &gt; b) Algorithms with EOF issue<br>
&gt; &gt;<br>
&gt; &gt; Such algorithms require to pad the end of file with some extra-data.<br>
&gt; &gt; Without proper support this will result in losing information about<br>
&gt; &gt; real file size. Keeping a track of real file size is a<br>
&gt; &gt; responsibility of the crypt translator. A special extended<br>
&gt; &gt; attribute with the name &quot;trusted.glusterfs.crypt.att.size&quot; is used<br>
&gt; &gt; for this purpose. All files contained in bricks of encrypted volume<br>
&gt; &gt; do have &quot;padded&quot; sizes.<br>
&gt; &gt;<br>
&gt; &gt;                    3. Non-trusted servers and<br>
&gt; &gt;                       Metadata authentication<br>
&gt; &gt;<br>
&gt; &gt; We assume that server, where user&#39;s data is stored on is<br>
&gt; &gt; non-trusted. It means that the server can be subjected to various<br>
&gt; &gt; attacks directed to reveal user&#39;s encrypted personal data. We<br>
&gt; &gt; provide protection against such attacks.<br>
&gt; &gt;<br>
&gt; &gt; Every encrypted file has specific private attributes (cipher<br>
&gt; &gt; algorithm id, atom size, etc), which are packed to a string<br>
&gt; &gt; (so-called &quot;format string&quot;) and stored as a special extended<br>
&gt; &gt; attribute with the name &quot;trusted.glusterfs.crypt.att.cfmt&quot;. We<br>
&gt; &gt; protect the string from tampering. This protection is mandatory,<br>
&gt; &gt; hardcoded and is always on. Without such protection various attacks<br>
&gt; &gt; (based on extending the scope of per-file secret keys) are possible.<br>
&gt; &gt;<br>
&gt; &gt; Our authentication method has been developed in tight collaboration<br>
&gt; &gt; with Red Hat security team and is implemented as &quot;metadata loader of<br>
&gt; &gt; version 1&quot; (see file metadata.c). This method is NIST-compliant and<br>
&gt; &gt; is based on checking 8-byte per-hardlink MACs created(updated) by<br>
&gt; &gt; FOP-&gt;create(), FOP-&gt;link(), FOP-&gt;unlink(), FOP-&gt;rename() by the<br>
&gt; &gt; following unique entities:<br>
&gt; &gt;<br>
&gt; &gt; . file (hardlink) name;<br>
&gt; &gt; . verified file&#39;s object id (gfid).<br>
&gt; &gt;<br>
&gt; &gt; Every time, before manipulating with a file, we check it&#39;s MACs at<br>
&gt; &gt; FOP-&gt;open() time. Some FOPs don&#39;t require a file to be opened (e.g.<br>
&gt; &gt; FOP-&gt;truncate()). In such cases the crypt translator opens the file<br>
&gt; &gt; mandatory.<br>
&gt; &gt;<br>
&gt; &gt;                          4. Generating keys<br>
&gt; &gt;<br>
&gt; &gt; Unique per-file keys are derived by NIST-compliant methods from the<br>
&gt; &gt;<br>
&gt; &gt; a) parent key;<br>
&gt; &gt; b) unique verified object-id of the file (gfid);<br>
&gt; &gt; Per-volume master key, provided by user at mount time is in the root<br>
&gt; &gt; of this &quot;tree of keys&quot;.<br>
&gt; &gt;<br>
&gt; &gt; Those keys are used to:<br>
&gt; &gt;<br>
&gt; &gt; 1) encrypt/decrypt file data;<br>
&gt; &gt; 2) encrypt/decrypt file metadata;<br>
&gt; &gt; 3) create per-file and per-link MACs for metadata authentication.<br>
&gt; &gt;<br>
&gt; &gt;                            5. Instructions<br>
&gt; &gt;                   Getting started with crypt translator<br>
&gt; &gt;<br>
&gt; &gt; Example:<br>
&gt; &gt;<br>
&gt; &gt; 1) Create a volume &quot;myvol&quot; by specifying the option &quot;encrypt&quot;:<br>
&gt; &gt;<br>
&gt; &gt;     # gluster volume create myvol encrypt pepelac:/vols/xvol<br>
&gt; &gt;<br>
&gt; &gt; 2) Set location (absolute pathname) of your master key:<br>
&gt; &gt;<br>
&gt; &gt;     # gluster volume set myvol encryption.master-key /home/me/mykey<br>
&gt; &gt;<br>
&gt; &gt; 3) Set other options to override default options, if needed.<br>
&gt; &gt;<br>
&gt; &gt; 4) On the client side make sure that the file /home/me/mykey exists<br>
&gt; &gt;     and contains proper per-volume master key (that is 256-bit AES<br>
&gt; &gt;     key). This key has to be in hex form, i.e. should be represented<br>
&gt; &gt;     by 64 symbols from the set  {&#39;0&#39;, ..., &#39;9&#39;, &#39;a&#39;, ..., &#39;f&#39;}.<br>
&gt; &gt;     The key should start at the beginning of the file. All symbols<br>
&gt; &gt; at offsets &gt;= 64 are ignored.<br>
&gt; &gt;<br>
&gt; &gt; 5) Mount the volume &quot;myvol&quot; on the client side:<br>
&gt; &gt;<br>
&gt; &gt;     # glusterfs --volfile-server=pepelac --volfile-id=myvol /mnt<br>
&gt; &gt;<br>
&gt; &gt;     After successful mount the file which contains master key may be<br>
&gt; &gt;     removed. NOTE: Keeping the master key between mount sessions is<br>
&gt; &gt; in user&#39;s competence.<br>
&gt; &gt;<br>
&gt; &gt; **********************************************************************<br>
&gt; &gt;<br>
&gt; &gt; WARNING! Losing the master key will make content of all regular<br>
&gt; &gt; files inaccessible. Mount with improper master key allows to access<br>
&gt; &gt; content of directories: file names are not encrypted.<br>
&gt; &gt;<br>
&gt; &gt; **********************************************************************<br>
&gt; &gt;<br>
&gt; &gt;                 6. Options of crypt translator<br>
&gt; &gt;<br>
&gt; &gt; 1) &quot;master-key&quot;: specifies location (absolute pathname) of the file<br>
&gt; &gt;     which contains per-volume master key. There is no default<br>
&gt; &gt; location for master key.<br>
&gt; &gt;<br>
&gt; &gt; 2) &quot;data-key-size&quot;: specifies size of per-file key for data<br>
&gt; &gt; encryption Possible values:<br>
&gt; &gt;     . &quot;256&quot; default value<br>
&gt; &gt;     . &quot;512&quot;<br>
&gt; &gt;<br>
&gt; &gt; 3) &quot;block-size&quot;: specifies atom size. Possible values:<br>
&gt; &gt;     . &quot;512&quot;<br>
&gt; &gt;     . &quot;1024&quot;<br>
&gt; &gt;     . &quot;2048&quot;<br>
&gt; &gt;     . &quot;4096&quot; default value;<br>
&gt; &gt;<br>
&gt; &gt;                         7. Test cases<br>
&gt; &gt;<br>
&gt; &gt; Any workload, which involves the following file operations:<br>
&gt; &gt;<br>
&gt; &gt; -&gt;create();<br>
&gt; &gt; -&gt;open();<br>
&gt; &gt; -&gt;readv();<br>
&gt; &gt; -&gt;writev();<br>
&gt; &gt; -&gt;truncate();<br>
&gt; &gt; -&gt;ftruncate();<br>
&gt; &gt; -&gt;link();<br>
&gt; &gt; -&gt;unlink();<br>
&gt; &gt; -&gt;rename();<br>
&gt; &gt; -&gt;readdirp().<br>
&gt; &gt;<br>
&gt; &gt;                          8. TODOs:<br>
&gt; &gt;<br>
&gt; &gt; 1) Currently size of IOs issued by crypt translator is restricted<br>
&gt; &gt;     by block_size (4K by default). We can use larger IOs to improve<br>
&gt; &gt;     performance.<br>
&gt; &gt;<br>
&gt; &gt; Change-Id: Idc3523a8752888d3dd10f4fe71aa38dfc53d9ded<br>
&gt; &gt; Signed-off-by: Edward Shishkin &lt;<a href="mailto:edward@redhat.com">edward@redhat.com</a>&gt;<br>
&gt; &gt; ---<br>
&gt; &gt; M cli/src/cli-cmd-parser.c<br>
&gt; &gt; M <a href="http://configure.ac" target="_blank">configure.ac</a><br>
&gt; &gt; M doc/gluster.8<br>
&gt; &gt; M libglusterfs/src/gf-dirent.c<br>
&gt; &gt; M libglusterfs/src/gf-dirent.h<br>
&gt; &gt; M xlators/cluster/dht/src/dht-common.c<br>
&gt; &gt; M xlators/encryption/Makefile.am<br>
&gt; &gt; A xlators/encryption/crypt/Makefile.am<br>
&gt; &gt; A xlators/encryption/crypt/src/Makefile.am<br>
&gt; &gt; A xlators/encryption/crypt/src/atom.c<br>
&gt; &gt; A xlators/encryption/crypt/src/crypt-common.h<br>
&gt; &gt; A xlators/encryption/crypt/src/crypt-mem-types.h<br>
&gt; &gt; A xlators/encryption/crypt/src/crypt.c<br>
&gt; &gt; A xlators/encryption/crypt/src/crypt.h<br>
&gt; &gt; A xlators/encryption/crypt/src/data.c<br>
&gt; &gt; A xlators/encryption/crypt/src/keys.c<br>
&gt; &gt; A xlators/encryption/crypt/src/metadata.c<br>
&gt; &gt; A xlators/encryption/crypt/src/metadata.h<br>
&gt; &gt; M xlators/mgmt/glusterd/src/glusterd-store.c<br>
&gt; &gt; M xlators/mgmt/glusterd/src/glusterd-store.h<br>
&gt; &gt; M xlators/mgmt/glusterd/src/glusterd-volgen.c<br>
&gt; &gt; M xlators/mgmt/glusterd/src/glusterd-volume-ops.c<br>
&gt; &gt; M xlators/mgmt/glusterd/src/glusterd-volume-set.c<br>
&gt; &gt; M xlators/mgmt/glusterd/src/glusterd.h<br>
&gt; &gt; M xlators/protocol/client/src/client-rpc-fops.c<br>
&gt; &gt; 25 files changed, 8,733 insertions(+), 28 deletions(-)<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;    git pull ssh://<a href="http://git.gluster.org/glusterfs" target="_blank">git.gluster.org/glusterfs</a> refs/changes/86/6086/1<br>
&gt; &gt;<br>
&gt;<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; Gluster-devel mailing list<br>
&gt; <a href="mailto:Gluster-devel@nongnu.org">Gluster-devel@nongnu.org</a><br>
&gt; <a href="https://lists.nongnu.org/mailman/listinfo/gluster-devel" target="_blank">https://lists.nongnu.org/mailman/listinfo/gluster-devel</a><br>
<br>
<br>
_______________________________________________<br>
Gluster-devel mailing list<br>
<a href="mailto:Gluster-devel@nongnu.org">Gluster-devel@nongnu.org</a><br>
<a href="https://lists.nongnu.org/mailman/listinfo/gluster-devel" target="_blank">https://lists.nongnu.org/mailman/listinfo/gluster-devel</a><br>
</div></div></blockquote></div><br></div></div>