Merge branch '8784-dir-listings'
[arvados.git] / doc / api / storage.html.textile.liquid
1 ---
2 layout: default
3 navsection: api
4 title: Storage in Keep
5 ...
6 {% comment %}
7 Copyright (C) The Arvados Authors. All rights reserved.
8
9 SPDX-License-Identifier: CC-BY-SA-3.0
10 {% endcomment %}
11
12 Keep clients are applications such as @arv-get@, @arv-put@ and @arv-mount@ which store and retrieve data from Keep.  In doing so, these programs interact with both the API server (which stores file metadata in form of Collection objects) and individual Keep servers (which store the actual data blocks).
13
14 !{{site.baseurl}}/images/Keep_reading_writing_block.svg!
15
16 h2. Storing a file
17
18 # The client discovers keep servers (or proxies) using the @accessible@ method on "keep_services":{{site.baseurl}}/api/methods/keep_services.html
19 # Data is split into 64 MiB blocks and the MD5 hash is computed for each block.
20 # The client uploads each block to one or more Keep servers, based on the number of desired replicas.  The priority order is determined using rendezvous hashing, described below.
21 # The Keep server returns a block locator (the MD5 sum of the block) and a "signed token" which the client can use as proof of knowledge for the block.
22 # The client constructs a @manifest@ which lists the blocks by MD5 hash and how to reassemble them into the original files.
23 # The client creates a "collection":{{site.baseurl}}/api/methods/collections.html and provides the @manifest_text@
24 # The API server accepts the collection after validating the signed tokens (proof of knowledge) for each block.
25
26 !{{site.baseurl}}/images/Keep_manifests.svg!
27
28 h2. Fetching a file
29
30 # The client requests a @collection@ object including @manifest_text@ from the APIs server
31 # The server adds "token signatures" to the @manifest_text@ and returns it to the client.
32 # The client discovers keep servers (or proxies) using the @accessible@ method on "keep_services":{{site.baseurl}}/api/methods/keep_services.html
33 # For each data block, the client chooses the highest priority server using rendezvous hashing, described below.
34 # The client sends the data block request to the keep server, along with the token signature from the API which proves to Keep servers that the client is permitted to read a given block.
35 # The server provides the block data after validating the token signature for the block (if the server does not have the block, it returns a 404 and the client tries the next highest priority server)
36
37 !{{site.baseurl}}/images/Keep_rendezvous_hashing.svg!
38
39 Each @keep_service@ resource has an assigned uuid.  To determine priority assignments of blocks to servers, for each keep service compute the MD5 sum of the string concatenation of the block locator (hex-coded hash part only) and service uuid, then sort this list in descending order.  Blocks are preferentially placed on servers with the highest weight.
40
41 h2. Keep server API
42
43 The Keep server is accessed via a simple HTTP REST API.
44
45 *GET /blocklocator+size+A@token*
46
47 Fetch the data block.  Response returns block contents.  If permission checking is enabled, requires a valid token hint.
48
49 *PUT /blocklocator*
50
51 Body: the block contents.  Responds the block locator consisting of MD5 sum of the data, block size, and signed token hint.
52
53 *POST /*
54
55 Body: the block contents.  Responds the block locator consisting of MD5 sum of the data, block size, and signed token hint.
56
57 h2(#locator). Keep locator format
58
59 BNF notation for a valid Keep locator string (with hints).  For example @d41d8cd98f00b204e9800998ecf8427e+0+Z+Ada39a3ee5e6b4b0d3255bfef95601890afd80709@53bed294@
60
61 <pre>
62 locator        ::= sized-digest hint*
63 sized-digest   ::= digest size-hint
64 digest         ::= <32 lowercase hexadecimal digits>
65 size-hint      ::= "+" [0-9]+
66 hint           ::= "+" hint-type hint-content
67 hint-type      ::= [A-Z]+
68 hint-content   ::= [A-Za-z0-9@_-]*
69 sign-hint      ::= "+A" <40 lowercase hexadecimal digits> "@" sign-timestamp
70 sign-timestamp ::= <8 lowercase hexadecimal digits>
71 </pre>
72
73 h3. Token signatures
74
75 A token signature (sign-hint) provides proof-of-access for a data block.  It is computed by taking a SHA1 HMAC of the blob signing token (a shared secret between the API server and keep servers), block digest, current API token, expiration timestamp, and blob signature TTL.
76
77 When communicating with the Keep store to fetch a block, or the API server to create or update a collection, the service computes the expected token signature for each block and compares it to the token signature that was presented by the client.  Keep clients receive valid block signatures when uploading a block to a keep store (getting back a signed token as proof of knowledge) or, from the API server, getting the manifest text of a collection on which the user has read permission.
78
79 Security of a token signature is derived from the following characteristics:
80
81 # Valid signatures can only be generated by entities that know the shared secret (the "blob signing token")
82 # A signature can only be used by an entity that also know the API token that was used to generate it.
83 # It expires after a set date (the expiration time, based on the "blob signature time-to-live (TTL)")
84
85 h3. Regular expression to validate locator
86
87 <pre>
88 /^([0-9a-f]{32})\+([0-9]+)(\+[A-Z][-A-Za-z0-9@_]*)*$/
89 </pre>
90
91 h3. Valid locators
92
93 table(table table-bordered table-condensed).
94 |@d41d8cd98f00b204e9800998ecf8427e+0@|
95 |@d41d8cd98f00b204e9800998ecf8427e+0+Z@|
96 |<code>d41d8cd98f00b204e9800998ecf8427e+0+Z+Ada39a3ee5e6b4b0d3255bfef95601890afd80709@53bed294</code>|
97
98 h3. Invalid locators
99
100 table(table table-bordered table-condensed).
101 ||Why|
102 |@d41d8cd98f00b204e9800998ecf8427e@|No size hint|
103 |@d41d8cd98f00b204e9800998ecf8427e+Z+0@|Other hint before size hint|
104 |@d41d8cd98f00b204e9800998ecf8427e+0+0@|Multiple size hints|
105 |@d41d8cd98f00b204e9800998ecf8427e+0+z@|Hint does not start with uppercase letter|
106 |@d41d8cd98f00b204e9800998ecf8427e+0+Zfoo*bar@|Hint contains invalid character @*@|
107
108 h2. Manifest v1
109
110 A manifest is utf-8 encoded text, consisting of zero or more newline-terminated streams.
111
112 <pre>
113 manifest       ::= stream*
114 stream         ::= stream-name (" " locator)+ (" " file-segment)+ "\n"
115 stream-name    ::= "." ("/" path-component)*
116 path-component ::= <printable ASCII - (whitespace, "/")>+
117 file-segment   ::= position ":" size ":" filename
118 position       ::= [0-9]+
119 size           ::= [0-9]+
120 filename       ::= path-component ("/" path-component)*
121 </pre>
122
123 Notes:
124
125 * The first token is the stream name, consisting of one or more path components, delimited by @"/"@.
126 ** The first path component is always @"."@.
127 ** No path component is empty.
128 ** No path component following the first one can be "." or "..".
129 ** The stream name never begins or ends with @"/"@.
130 * The next N tokens are "keep locators":#locator
131 ** These describe the "data stream".  By logically concatenating the blocks in the order that they appear, we can refer to "positions" in the data stream.
132 * File tokens come after the sequence of keep locators.
133 ** A file token has three parts, delimited by @":"@: position, size, filename.
134 ** Position and size are given in decimal
135 ** The position is the position in the data stream
136 ** The size is the count of bytes following the position in the data stream.  A file size may cross multiple blocks in the data stream.
137 ** Filename may contain @"/"@ characters, but must not start or end with @"/"@, and must not contain @"//"@.
138 ** Filename components (delimited by @"/"@) must not be @"."@ or @".."@.
139 ** There may be multiple file tokens.
140
141 It is legal to have multiple file tokens in the manifest (possible across different streams) with the same combined path name @stream name + "/" + filename@.  This must be interpreted as a concatenation of file content, in the order that the file tokens appear in the manifest.
142
143 Spaces are represented by the escape sequence @\040@.  Spaces in stream names and filenames must be translated when reading and writing manifests.  A manifest may not contain TAB characters, nor other ASCII whitespace characters or control codes other than the spaces or newlines used as delimiters specified above.  A manifest always ends with a newline -- except the empty (zero-length) string, which is a valid manifest.
144
145 h3. Normalized manifest v1
146
147 A normalized manifest is a manifest that meets the following additional restrictions:
148
149 * Streams are in alphanumeric order.
150 * Each stream name is unique within the manifest.
151 * Files within a stream are listed in alphanumeric order.
152 * Blocks within a stream are ordered based on order of file tokens of the stream.  A given block is listed at most once in a stream.
153 * Filename must not contain @"/"@ (the stream name represents the path prefix)
154
155 h3. Example manifests
156
157 A manifest with four files in two directories:
158
159 <pre>
160 . 930625b054ce894ac40596c3f5a0d947+33 0:0:a 0:0:b 0:33:output.txt
161 ./c d41d8cd98f00b204e9800998ecf8427e+0 0:0:d
162 </pre>
163
164 The same manifest with permission signatures on each block:
165
166 <pre>
167 . 930625b054ce894ac40596c3f5a0d947+33+A1f27a35dd9af37191d63ad8eb8985624451e7b79@5835c8bc 0:0:a 0:0:b 0:33:output.txt
168 ./c d41d8cd98f00b204e9800998ecf8427e+0+A27117dcd30c013a6e85d6d74c9a50179a1446efa@5835c8bc 0:0:d
169 </pre>
170
171 A manifest containing a file consisting of multiple blocks and a space in the file name:
172
173 <pre>
174 . c449ed86671e4a34a8b8b9430850beba+67108864 09fcfea01c3a141b89dd0dcfa1b7768e+22534144 0:89643008:Docker\040image.tar
175 </pre>