)]}'
{"swift/common/middleware/crypto.py":[{"author":{"_account_id":18820,"name":"Peter Chng","email":"pchng@ca.ibm.com","username":"pchng"},"change_message_id":"f9b0480d85a97d84cada90f7321a1bc2e200b7c3","unresolved":false,"context_lines":[{"line_number":89,"context_line":"    def get_derived_iv(self, base):"},{"line_number":90,"context_line":"        target_length \u003d self.get_required_iv_length()"},{"line_number":91,"context_line":"        if len(base) \u003c target_length:"},{"line_number":92,"context_line":"            return base.zfill(target_length)"},{"line_number":93,"context_line":"        elif len(base) \u003e target_length:"},{"line_number":94,"context_line":"            hash \u003d md5()"},{"line_number":95,"context_line":"            hash.update(base)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba63e191_423bddeb","line":92,"range":{"start_line":92,"start_character":30,"end_line":92,"end_character":43},"updated":"2016-01-19 16:23:56.000000000","message":"Deriving the IV this way may cause IVs for two different bases to produce the same derived IV. For example:\n\n    \u00270test\u0027.zfill(8) \u003d\u003d \u0027test\u0027.zfill(8) // True\n\nI am not sure if this is a concern. However, just using an md5 hash on the `base` value should produce a value of the suitable length, similar to what is done in the `elif` block below. I think that\u0027s a better way.\n\nExample:\n\n    h \u003d md5(); h.update(\u0027test\u0027); h.hexdigest()\n    \u003e \u0027098f6bcd4621d373cade4e832627b4f6\u0027\n\n    h \u003d md5(); h.update(\u00270test\u0027); h.hexdigest()\n    \u003e \u00271c13f2701648e0b0d46d8a2a5a131a53\u0027\n\nAs mentioned in my comments for `encrypter.py`, this does not produce IVs that are secure/suitable for general encryption and should be marked as such. (i.e. only being used for ETag because we need something predictable, I assume)","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"620f5da0924709f23d9bc56ac359cd2618d949cd","unresolved":false,"context_lines":[{"line_number":89,"context_line":"    def get_derived_iv(self, base):"},{"line_number":90,"context_line":"        target_length \u003d self.get_required_iv_length()"},{"line_number":91,"context_line":"        if len(base) \u003c target_length:"},{"line_number":92,"context_line":"            return base.zfill(target_length)"},{"line_number":93,"context_line":"        elif len(base) \u003e target_length:"},{"line_number":94,"context_line":"            hash \u003d md5()"},{"line_number":95,"context_line":"            hash.update(base)"}],"source_content_type":"text/x-python","patch_set":2,"id":"9a68dd71_98f713f5","line":92,"range":{"start_line":92,"start_character":30,"end_line":92,"end_character":43},"in_reply_to":"9a68dd71_b7f1d497","updated":"2016-01-26 22:41:18.000000000","message":"Given that we were going to just use a fixed IV for all the etags in the beginning and would have accepted all those collisions, I think having this small case is acceptible.  There are still collisions when the user PUTs to the same path more than once - and we are accepting those as okay.  Adding the path as a factor for the iv derivation was an after-thought to at least make it a little better than a fixed value.","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":16964,"name":"Jonathan Hinson","email":"jlhinson@us.ibm.com","username":"jlhinson"},"change_message_id":"48a18fc138a45f6e1f6213356a1b77982d9c6b22","unresolved":false,"context_lines":[{"line_number":89,"context_line":"    def get_derived_iv(self, base):"},{"line_number":90,"context_line":"        target_length \u003d self.get_required_iv_length()"},{"line_number":91,"context_line":"        if len(base) \u003c target_length:"},{"line_number":92,"context_line":"            return base.zfill(target_length)"},{"line_number":93,"context_line":"        elif len(base) \u003e target_length:"},{"line_number":94,"context_line":"            hash \u003d md5()"},{"line_number":95,"context_line":"            hash.update(base)"}],"source_content_type":"text/x-python","patch_set":2,"id":"9a68dd71_b7f1d497","line":92,"range":{"start_line":92,"start_character":30,"end_line":92,"end_character":43},"in_reply_to":"ba63e191_423bddeb","updated":"2016-01-26 17:41:29.000000000","message":"The way we use this method, the base is always the path of the object. In order for this to be an issue, the object and container names would have to be exactly the same, and accountName2 would have to equal one or more zeros + accountName1. I don\u0027t see the point in accommodating this (probably rare) case, since, as you mentioned, these IVs aren\u0027t meant for general encryption anyway. Besides, taking the last 16 (or so) characters of a hash would also cause collisions (not sure how often).\n\nThat said, I\u0027m okay with either approach. Anyone else have an opinion either way?","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"d30469a32603f2c682c864d6babff5bb0af16520","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        else:"},{"line_number":98,"context_line":"            return base"},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def get_fixed_iv(self):"},{"line_number":101,"context_line":"        return \u00271\u0027 * (self.get_required_iv_length())"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"    def create_iv(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_84e665ae","line":100,"updated":"2016-01-14 10:08:34.000000000","message":"This is not used anywhere I suppose?","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":16964,"name":"Jonathan Hinson","email":"jlhinson@us.ibm.com","username":"jlhinson"},"change_message_id":"5d20bb1eb0e647d193bead2ec44458d2b69256ca","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        else:"},{"line_number":98,"context_line":"            return base"},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def get_fixed_iv(self):"},{"line_number":101,"context_line":"        return \u00271\u0027 * (self.get_required_iv_length())"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"    def create_iv(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_d7671ae7","line":100,"in_reply_to":"da6ed579_84e665ae","updated":"2016-01-14 16:04:00.000000000","message":"Not anymore. I was using fixed IVs for etag encryption in the past, but now we derive the IV. This can be removed, but I left it here in case it might be useful later. I can take this out if people think it won\u0027t be used.","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"cd64c11db8243cfc94e547232fe7669207e5cee8","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        else:"},{"line_number":98,"context_line":"            return base"},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def get_fixed_iv(self):"},{"line_number":101,"context_line":"        return \u00271\u0027 * (self.get_required_iv_length())"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"    def create_iv(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_d88830c9","line":100,"in_reply_to":"da6ed579_d7671ae7","updated":"2016-01-18 04:32:53.000000000","message":"go ahead and remove it.  I know we considered using this, but I think our new approach is more production worthy.  :-)","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":16964,"name":"Jonathan Hinson","email":"jlhinson@us.ibm.com","username":"jlhinson"},"change_message_id":"48a18fc138a45f6e1f6213356a1b77982d9c6b22","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        else:"},{"line_number":98,"context_line":"            return base"},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def get_fixed_iv(self):"},{"line_number":101,"context_line":"        return \u00271\u0027 * (self.get_required_iv_length())"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"    def create_iv(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"9a68dd71_578738d7","line":100,"in_reply_to":"da6ed579_d88830c9","updated":"2016-01-26 17:41:29.000000000","message":"Done","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"bb811d4e5387d5f912a02a7722b8d4010ccb6549","unresolved":false,"context_lines":[{"line_number":99,"context_line":"            return base"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    def _get_random_iv(self):"},{"line_number":102,"context_line":"        # here for tests to mock"},{"line_number":103,"context_line":"        return os.urandom(16)"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"    def create_iv(self, iv_base\u003dNone):"}],"source_content_type":"text/x-python","patch_set":12,"id":"5a18252c_3fa32251","line":102,"updated":"2016-04-13 08:25:15.000000000","message":"nit: maybe the comment should be more specific to say, it is in a separate function for tests to mock.","commit_id":"42e668cad30c4d78de16530b10acffd83beb911d"}],"swift/common/middleware/decrypter.py":[{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"594e3c2e3f6cafc1df33e863c71c7a4195e4448c","unresolved":false,"context_lines":[{"line_number":286,"context_line":""},{"line_number":287,"context_line":"        body_crypto_ctxt \u003d self.make_decryption_context(keys)"},{"line_number":288,"context_line":"        if body_crypto_ctxt is None:"},{"line_number":289,"context_line":"            # TODO: is this check necessary, can the context be None?"},{"line_number":290,"context_line":"            return app_resp"},{"line_number":291,"context_line":""},{"line_number":292,"context_line":"        def iter_response(iterable, crypto_ctxt):"}],"source_content_type":"text/x-python","patch_set":9,"id":"9a061dce_e23645e6","line":289,"updated":"2016-04-11 03:07:40.000000000","message":"I looked into this.  It boils down to this: if you trust that getting here means that there is a non-None \u0027X-Object-Sysemta-Crypto-Meta\u0027 header value, then no check is necessary.  In the case of our keymaster, we should feel secure (with future changes) that the override flag will be set if this value is not present, and therefore, this line would not be reached.\n\nLater, I could test using a bad keymaster implementation and see how difficult the debugging would be without this check.  For now, we could probably take it out.  Any other opinions?","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0061ab936931719bbd411e3b3cdf101865353502","unresolved":false,"context_lines":[{"line_number":286,"context_line":""},{"line_number":287,"context_line":"        body_crypto_ctxt \u003d self.make_decryption_context(keys)"},{"line_number":288,"context_line":"        if body_crypto_ctxt is None:"},{"line_number":289,"context_line":"            # TODO: is this check necessary, can the context be None?"},{"line_number":290,"context_line":"            return app_resp"},{"line_number":291,"context_line":""},{"line_number":292,"context_line":"        def iter_response(iterable, crypto_ctxt):"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_aae2899d","line":289,"in_reply_to":"9a061dce_e23645e6","updated":"2016-04-11 11:36:32.000000000","message":"How would the keymaster know when to set override - it could be that x-object-sysmeta-crypto-meta is not present (body is plaintext) but other metadata headers are encrypted (e.g. a later POST) and have their crypto meta, so override would not be appropriate??\n\nLet\u0027s consider/debate in a separate patch","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"}],"swift/common/middleware/encrypter.py":[{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"cd64c11db8243cfc94e547232fe7669207e5cee8","unresolved":false,"context_lines":[{"line_number":53,"context_line":"    :param value: value to encrypt"},{"line_number":54,"context_line":"    :param key: crypto key to use"},{"line_number":55,"context_line":"    :param crypto_meta: a crypto-meta dict of form returned by"},{"line_number":56,"context_line":"        :py:func:`~swift.common.middleware.crypto.Crypto.get_crypto_meta`"},{"line_number":57,"context_line":"    :returns: a tuple of (encrypted value, crypto_meta) where crypto_meta is a"},{"line_number":58,"context_line":"        dict of form returned by"},{"line_number":59,"context_line":"        :py:func:`~swift.common.middleware.crypto.Crypto.get_crypto_meta`"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_78c024e1","line":56,"range":{"start_line":56,"start_character":72,"end_line":56,"end_character":73},"updated":"2016-01-18 04:32:53.000000000","message":"fix the param descriptions to match current args","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":16964,"name":"Jonathan Hinson","email":"jlhinson@us.ibm.com","username":"jlhinson"},"change_message_id":"48a18fc138a45f6e1f6213356a1b77982d9c6b22","unresolved":false,"context_lines":[{"line_number":53,"context_line":"    :param value: value to encrypt"},{"line_number":54,"context_line":"    :param key: crypto key to use"},{"line_number":55,"context_line":"    :param crypto_meta: a crypto-meta dict of form returned by"},{"line_number":56,"context_line":"        :py:func:`~swift.common.middleware.crypto.Crypto.get_crypto_meta`"},{"line_number":57,"context_line":"    :returns: a tuple of (encrypted value, crypto_meta) where crypto_meta is a"},{"line_number":58,"context_line":"        dict of form returned by"},{"line_number":59,"context_line":"        :py:func:`~swift.common.middleware.crypto.Crypto.get_crypto_meta`"}],"source_content_type":"text/x-python","patch_set":2,"id":"9a68dd71_9764d049","line":56,"range":{"start_line":56,"start_character":72,"end_line":56,"end_character":73},"in_reply_to":"da6ed579_78c024e1","updated":"2016-01-26 17:41:29.000000000","message":"Done","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":18820,"name":"Peter Chng","email":"pchng@ca.ibm.com","username":"pchng"},"change_message_id":"f9b0480d85a97d84cada90f7321a1bc2e200b7c3","unresolved":false,"context_lines":[{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    crypto_meta \u003d crypto.get_crypto_meta()"},{"line_number":65,"context_line":"    if iv_base:"},{"line_number":66,"context_line":"        crypto_meta[\u0027iv\u0027] \u003d crypto.get_derived_iv(iv_base)"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    crypto_ctxt \u003d crypto.create_encryption_ctxt(key, crypto_meta[\u0027iv\u0027])"},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"ba63e191_e2f9b14e","line":66,"range":{"start_line":66,"start_character":57,"end_line":66,"end_character":58},"updated":"2016-01-19 16:23:56.000000000","message":"I think we should make it very clear that this method is *ONLY* to be used for ETag to enable conditional GETs using the ETag.\n\nIn general, IVs (we\u0027re actually using as a nonce for CTR mode, but that doesn\u0027t matter here) must not be reused nor be predictable. Using it this way violates these two requirements. \n\nI think the method `get_derived_iv()` should be renamed to make it clear that it is not returning an IV that\u0027s suitable for secure encryption, and furthermore, that using the `iv_base` parameter for `encrypt_header_val()` triggers this behaviour.\n\nOtherwise, these methods could be misused in the future, resulting in improper/insecure encryption.","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"620f5da0924709f23d9bc56ac359cd2618d949cd","unresolved":false,"context_lines":[{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    crypto_meta \u003d crypto.get_crypto_meta()"},{"line_number":65,"context_line":"    if iv_base:"},{"line_number":66,"context_line":"        crypto_meta[\u0027iv\u0027] \u003d crypto.get_derived_iv(iv_base)"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    crypto_ctxt \u003d crypto.create_encryption_ctxt(key, crypto_meta[\u0027iv\u0027])"},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"9a68dd71_f89e4f62","line":66,"range":{"start_line":66,"start_character":57,"end_line":66,"end_character":58},"in_reply_to":"ba63e191_e2f9b14e","updated":"2016-01-26 22:41:18.000000000","message":"maybe call the arg iv_base \"derive_iv\"? \"derived_iv_base\"?\n\nas for the method name, I am not sure how we could do that in a good way.  I dont think crypto should be aware of an etag, and the method could be re-used for something else later that might need a derived iv.  we dont want to use a word like insecure.  it does specify exactly what it is.  Maybe we could rely on the docs for the method itself?  I think that should be good enough.","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":16964,"name":"Jonathan Hinson","email":"jlhinson@us.ibm.com","username":"jlhinson"},"change_message_id":"36b533b7f4f70321d68383d86dccae8176d1fc1d","unresolved":false,"context_lines":[{"line_number":284,"context_line":"        # objects. Since we cannot know on the way in whether or not an object"},{"line_number":285,"context_line":"        # is encrypted, we need a way to supply two etags: one encrypted,"},{"line_number":286,"context_line":"        # one not. I think this can be done, but I haven\u0027t gotten it working"},{"line_number":287,"context_line":"        # yet."},{"line_number":288,"context_line":"        etag, condition \u003d self.get_conditional(req)"},{"line_number":289,"context_line":"        if etag:"},{"line_number":290,"context_line":"            keys \u003d self.get_keys(req.environ)"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_96b5a8ce","line":287,"updated":"2016-01-12 16:49:34.000000000","message":"Disregard the above TODO. I\u0027ve gotten multiple etags working, but I won\u0027t be uploading a new patch set until I\u0027ve written more unit tests.","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"d30469a32603f2c682c864d6babff5bb0af16520","unresolved":false,"context_lines":[{"line_number":286,"context_line":"        # one not. I think this can be done, but I haven\u0027t gotten it working"},{"line_number":287,"context_line":"        # yet."},{"line_number":288,"context_line":"        etag, condition \u003d self.get_conditional(req)"},{"line_number":289,"context_line":"        if etag:"},{"line_number":290,"context_line":"            keys \u003d self.get_keys(req.environ)"},{"line_number":291,"context_line":"            crypto_etag, meta \u003d encrypt_header_val("},{"line_number":292,"context_line":"                self.crypto, etag, keys[self.server_type], iv_base\u003dreq.path)"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_64f8117c","line":289,"updated":"2016-01-14 10:08:34.000000000","message":"I think we anyway are going to do a deterministic encryption for etag irrespective of the conditions, correct? Or am I missing something?","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":16964,"name":"Jonathan Hinson","email":"jlhinson@us.ibm.com","username":"jlhinson"},"change_message_id":"5d20bb1eb0e647d193bead2ec44458d2b69256ca","unresolved":false,"context_lines":[{"line_number":286,"context_line":"        # one not. I think this can be done, but I haven\u0027t gotten it working"},{"line_number":287,"context_line":"        # yet."},{"line_number":288,"context_line":"        etag, condition \u003d self.get_conditional(req)"},{"line_number":289,"context_line":"        if etag:"},{"line_number":290,"context_line":"            keys \u003d self.get_keys(req.environ)"},{"line_number":291,"context_line":"            crypto_etag, meta \u003d encrypt_header_val("},{"line_number":292,"context_line":"                self.crypto, etag, keys[self.server_type], iv_base\u003dreq.path)"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_26852a06","line":289,"in_reply_to":"da6ed579_64f8117c","updated":"2016-01-14 16:04:00.000000000","message":"The only way we\u0027ll have an etag (on a GET) is if there\u0027s an if-match or if-none-match header. If there\u0027s either, we encrypt.","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"d30469a32603f2c682c864d6babff5bb0af16520","unresolved":false,"context_lines":[{"line_number":287,"context_line":"        # yet."},{"line_number":288,"context_line":"        etag, condition \u003d self.get_conditional(req)"},{"line_number":289,"context_line":"        if etag:"},{"line_number":290,"context_line":"            keys \u003d self.get_keys(req.environ)"},{"line_number":291,"context_line":"            crypto_etag, meta \u003d encrypt_header_val("},{"line_number":292,"context_line":"                self.crypto, etag, keys[self.server_type], iv_base\u003dreq.path)"},{"line_number":293,"context_line":"            req.environ[condition] \u003d crypto_etag"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_244539b2","line":290,"updated":"2016-01-14 10:08:34.000000000","message":"What if there are no keys? i.e. for an unencrypted object. Is that upcoming in your next patch?","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":16964,"name":"Jonathan Hinson","email":"jlhinson@us.ibm.com","username":"jlhinson"},"change_message_id":"5d20bb1eb0e647d193bead2ec44458d2b69256ca","unresolved":false,"context_lines":[{"line_number":287,"context_line":"        # yet."},{"line_number":288,"context_line":"        etag, condition \u003d self.get_conditional(req)"},{"line_number":289,"context_line":"        if etag:"},{"line_number":290,"context_line":"            keys \u003d self.get_keys(req.environ)"},{"line_number":291,"context_line":"            crypto_etag, meta \u003d encrypt_header_val("},{"line_number":292,"context_line":"                self.crypto, etag, keys[self.server_type], iv_base\u003dreq.path)"},{"line_number":293,"context_line":"            req.environ[condition] \u003d crypto_etag"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_8c6af57f","line":290,"in_reply_to":"da6ed579_244539b2","updated":"2016-01-14 16:04:00.000000000","message":"Since we are deriving the keys (for now), we will always have keys, regardless of whether or not the object is encrypted. We will then provide both the plaintext etag and an encrypted (w/ object key) copy of that etag. That way, this scheme works even if the object is unencrypted. But the multiple etag logic isn\u0027t in this patch set.","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"cd64c11db8243cfc94e547232fe7669207e5cee8","unresolved":false,"context_lines":[{"line_number":287,"context_line":"        # yet."},{"line_number":288,"context_line":"        etag, condition \u003d self.get_conditional(req)"},{"line_number":289,"context_line":"        if etag:"},{"line_number":290,"context_line":"            keys \u003d self.get_keys(req.environ)"},{"line_number":291,"context_line":"            crypto_etag, meta \u003d encrypt_header_val("},{"line_number":292,"context_line":"                self.crypto, etag, keys[self.server_type], iv_base\u003dreq.path)"},{"line_number":293,"context_line":"            req.environ[condition] \u003d crypto_etag"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_b82bfc93","line":290,"in_reply_to":"da6ed579_8c6af57f","updated":"2016-01-18 04:32:53.000000000","message":"but we still need to have the etag value include both the encrypted and unencrypted version so that legacy objects would be returned when approprate, correct?  So the issue is not the key, because that is derived, but the issue is that we want the match to succeed for legacy (unencrypted) objects.","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"d30469a32603f2c682c864d6babff5bb0af16520","unresolved":false,"context_lines":[{"line_number":291,"context_line":"            crypto_etag, meta \u003d encrypt_header_val("},{"line_number":292,"context_line":"                self.crypto, etag, keys[self.server_type], iv_base\u003dreq.path)"},{"line_number":293,"context_line":"            req.environ[condition] \u003d crypto_etag"},{"line_number":294,"context_line":"            req.headers[\u0027X-Backend-Etag-Is-At\u0027] \u003d \\"},{"line_number":295,"context_line":"                \u0027X-Object-Sysmeta-Crypto-Etag\u0027"},{"line_number":296,"context_line":""},{"line_number":297,"context_line":"        resp \u003d self._app_call(req.environ)"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_84ae657f","line":294,"updated":"2016-01-14 10:08:34.000000000","message":"since we\u0027re doing this before the call below, would this header not be overwritten by EC here?: https://github.com/openstack/swift/blob/master/swift/proxy/controllers/obj.py#L1988","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"cd64c11db8243cfc94e547232fe7669207e5cee8","unresolved":false,"context_lines":[{"line_number":291,"context_line":"            crypto_etag, meta \u003d encrypt_header_val("},{"line_number":292,"context_line":"                self.crypto, etag, keys[self.server_type], iv_base\u003dreq.path)"},{"line_number":293,"context_line":"            req.environ[condition] \u003d crypto_etag"},{"line_number":294,"context_line":"            req.headers[\u0027X-Backend-Etag-Is-At\u0027] \u003d \\"},{"line_number":295,"context_line":"                \u0027X-Object-Sysmeta-Crypto-Etag\u0027"},{"line_number":296,"context_line":""},{"line_number":297,"context_line":"        resp \u003d self._app_call(req.environ)"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_5373c3b4","line":294,"in_reply_to":"da6ed579_0cae0581","updated":"2016-01-18 04:32:53.000000000","message":"Thank you, Mahati, for pointing that out.  I had seen that value was changed for EC, but I put it aside and didn\u0027t address it yet.  But thinking of it now, I think this should work out if I change the footers patch to set that value to the crypto value that we want.\n\nJonathan, I will let you know when I have that done, and then you can rebase, and test the functests when running with EC as your default storage policy.","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":16964,"name":"Jonathan Hinson","email":"jlhinson@us.ibm.com","username":"jlhinson"},"change_message_id":"5d20bb1eb0e647d193bead2ec44458d2b69256ca","unresolved":false,"context_lines":[{"line_number":291,"context_line":"            crypto_etag, meta \u003d encrypt_header_val("},{"line_number":292,"context_line":"                self.crypto, etag, keys[self.server_type], iv_base\u003dreq.path)"},{"line_number":293,"context_line":"            req.environ[condition] \u003d crypto_etag"},{"line_number":294,"context_line":"            req.headers[\u0027X-Backend-Etag-Is-At\u0027] \u003d \\"},{"line_number":295,"context_line":"                \u0027X-Object-Sysmeta-Crypto-Etag\u0027"},{"line_number":296,"context_line":""},{"line_number":297,"context_line":"        resp \u003d self._app_call(req.environ)"}],"source_content_type":"text/x-python","patch_set":2,"id":"da6ed579_0cae0581","line":294,"in_reply_to":"da6ed579_84ae657f","updated":"2016-01-14 16:04:00.000000000","message":"Good point. I\u0027ll look into this more later.","commit_id":"130fd8a031b88f51ae24080e4ae58df304776925"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e1f8e38204c57a7afdb0d8f63d17f15094e53ce","unresolved":false,"context_lines":[{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    crypto_meta \u003d crypto.get_crypto_meta()"},{"line_number":64,"context_line":"    if iv_base:"},{"line_number":65,"context_line":"        crypto_meta[\u0027iv\u0027] \u003d crypto.get_derived_iv(iv_base)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    crypto_ctxt \u003d crypto.create_encryption_ctxt(key, crypto_meta[\u0027iv\u0027])"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"9a061dce_01ba77c0","line":65,"updated":"2016-04-08 18:00:14.000000000","message":"we could keep the interface to Crypto cleaner by passing an optional iv_base arg to get_crypto_meta. That may also simplify mocking the class for tests.","commit_id":"aa2616bd07112f102d03026a8d320157da18fd6b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e1f8e38204c57a7afdb0d8f63d17f15094e53ce","unresolved":false,"context_lines":[{"line_number":79,"context_line":"    for condition in conditions:"},{"line_number":80,"context_line":"        etag \u003d req.environ.get(condition, None)"},{"line_number":81,"context_line":"        if etag is not None:"},{"line_number":82,"context_line":"            return etag, condition"},{"line_number":83,"context_line":"    return None, None"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"9a061dce_2fe16fff","line":82,"updated":"2016-04-08 18:00:14.000000000","message":"This returns on finding the first of the conditional headers.\n\nrfc2616 http://www.ietf.org/rfc/rfc2616.txt\nsays that the response when if-match and if-non-match are present is undefined. Elsewhere (probably in swob.Response) there will be some preference between the two, but here I think we should handle the possibility of both being present.","commit_id":"aa2616bd07112f102d03026a8d320157da18fd6b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e1f8e38204c57a7afdb0d8f63d17f15094e53ce","unresolved":false,"context_lines":[{"line_number":83,"context_line":"    return None, None"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"def get_etag_list(etags):"},{"line_number":87,"context_line":"    etag_list \u003d etags.split(\u0027, \u0027)"},{"line_number":88,"context_line":"    if len(etag_list) \u003e 1:"},{"line_number":89,"context_line":"        for i in range(len(etag_list)):"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a061dce_cff0b3cc","line":86,"updated":"2016-04-08 18:00:14.000000000","message":"there is a parser for etag lists in swob.Match, should re-use that","commit_id":"aa2616bd07112f102d03026a8d320157da18fd6b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e1f8e38204c57a7afdb0d8f63d17f15094e53ce","unresolved":false,"context_lines":[{"line_number":263,"context_line":"            keys \u003d self.get_keys(req.environ)"},{"line_number":264,"context_line":"            etags \u003d get_etag_list(old_etags)"},{"line_number":265,"context_line":"            new_etags \u003d []"},{"line_number":266,"context_line":"            for etag in etags:"},{"line_number":267,"context_line":"                crypto_etag, meta \u003d encrypt_header_val(self.crypto, etag,"},{"line_number":268,"context_line":"                                                       keys[self.server_type],"},{"line_number":269,"context_line":"                                                       iv_base\u003dreq.path)"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a061dce_4fc943ac","line":266,"updated":"2016-04-08 18:00:14.000000000","message":"unless its a * wildcard - we don\u0027t want to encrypt that","commit_id":"aa2616bd07112f102d03026a8d320157da18fd6b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e1f8e38204c57a7afdb0d8f63d17f15094e53ce","unresolved":false,"context_lines":[{"line_number":268,"context_line":"                                                       keys[self.server_type],"},{"line_number":269,"context_line":"                                                       iv_base\u003dreq.path)"},{"line_number":270,"context_line":"                new_etags.extend((etag, crypto_etag))"},{"line_number":271,"context_line":"            req.environ[condition] \u003d \u0027\"{0}\"\u0027.format(\u0027\", \"\u0027.join(new_etags))"},{"line_number":272,"context_line":"            req.headers[\u0027X-Backend-Etag-Is-At\u0027] \u003d \\"},{"line_number":273,"context_line":"                \u0027X-Object-Sysmeta-Crypto-Etag\u0027"},{"line_number":274,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"9a061dce_afe3bf32","line":271,"updated":"2016-04-08 18:00:14.000000000","message":"a * wildcard should not be quoted","commit_id":"aa2616bd07112f102d03026a8d320157da18fd6b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9c04b5322f33269d248a815fc3660ddc58419bd8","unresolved":false,"context_lines":[{"line_number":270,"context_line":"                new_etags.extend((etag, crypto_etag))"},{"line_number":271,"context_line":"            req.environ[condition] \u003d \u0027\"{0}\"\u0027.format(\u0027\", \"\u0027.join(new_etags))"},{"line_number":272,"context_line":"            req.headers[\u0027X-Backend-Etag-Is-At\u0027] \u003d \\"},{"line_number":273,"context_line":"                \u0027X-Object-Sysmeta-Crypto-Etag\u0027"},{"line_number":274,"context_line":""},{"line_number":275,"context_line":"        resp \u003d self._app_call(req.environ)"},{"line_number":276,"context_line":"        start_response(self._response_status, self._response_headers,"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a061dce_230bbe2b","line":273,"updated":"2016-04-06 17:32:20.000000000","message":"should use setdefault here so that if some previous middleware knows better then we respect that","commit_id":"aa2616bd07112f102d03026a8d320157da18fd6b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e1f8e38204c57a7afdb0d8f63d17f15094e53ce","unresolved":false,"context_lines":[{"line_number":277,"context_line":"                       self._response_exc_info)"},{"line_number":278,"context_line":""},{"line_number":279,"context_line":"        if old_etags:"},{"line_number":280,"context_line":"            req.environ[condition] \u003d old_etags"},{"line_number":281,"context_line":"        return resp"},{"line_number":282,"context_line":""},{"line_number":283,"context_line":"    def HEAD(self, req, start_response):"}],"source_content_type":"text/x-python","patch_set":7,"id":"9a061dce_14e125ff","line":280,"updated":"2016-04-08 18:00:14.000000000","message":"was there a reason to put the old values back in the environ?","commit_id":"aa2616bd07112f102d03026a8d320157da18fd6b"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"594e3c2e3f6cafc1df33e863c71c7a4195e4448c","unresolved":false,"context_lines":[{"line_number":22,"context_line":"from swift.common.request_helpers import get_object_transient_sysmeta_prefix, \\"},{"line_number":23,"context_line":"    strip_user_meta_prefix, is_user_meta"},{"line_number":24,"context_line":"from swift.common.swob import ("},{"line_number":25,"context_line":"    Request, HTTPException, HTTPUnprocessableEntity, Match)"},{"line_number":26,"context_line":"from swift.common.middleware.crypto import Crypto"},{"line_number":27,"context_line":"from swift.common.constraints import check_metadata"},{"line_number":28,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_f0af6092","line":25,"updated":"2016-04-11 03:07:40.000000000","message":"nit - use either parenthesis in all the imports here or the slash","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0061ab936931719bbd411e3b3cdf101865353502","unresolved":false,"context_lines":[{"line_number":22,"context_line":"from swift.common.request_helpers import get_object_transient_sysmeta_prefix, \\"},{"line_number":23,"context_line":"    strip_user_meta_prefix, is_user_meta"},{"line_number":24,"context_line":"from swift.common.swob import ("},{"line_number":25,"context_line":"    Request, HTTPException, HTTPUnprocessableEntity, Match)"},{"line_number":26,"context_line":"from swift.common.middleware.crypto import Crypto"},{"line_number":27,"context_line":"from swift.common.constraints import check_metadata"},{"line_number":28,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_ca06e51f","line":25,"in_reply_to":"7a1b2928_f0af6092","updated":"2016-04-11 11:36:32.000000000","message":"Done","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"594e3c2e3f6cafc1df33e863c71c7a4195e4448c","unresolved":false,"context_lines":[{"line_number":256,"context_line":""},{"line_number":257,"context_line":"            req.headers[header_name] \u003d \u0027, \u0027.join(new_etags)"},{"line_number":258,"context_line":"            req.headers[\u0027X-Backend-Etag-Is-At\u0027] \u003d \\"},{"line_number":259,"context_line":"                \u0027X-Object-Sysmeta-Crypto-Etag\u0027"},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"        try:"},{"line_number":262,"context_line":"            yield"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_30e4380c","line":259,"updated":"2016-04-11 03:07:40.000000000","message":"did you decide against the setdefault?","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0061ab936931719bbd411e3b3cdf101865353502","unresolved":false,"context_lines":[{"line_number":256,"context_line":""},{"line_number":257,"context_line":"            req.headers[header_name] \u003d \u0027, \u0027.join(new_etags)"},{"line_number":258,"context_line":"            req.headers[\u0027X-Backend-Etag-Is-At\u0027] \u003d \\"},{"line_number":259,"context_line":"                \u0027X-Object-Sysmeta-Crypto-Etag\u0027"},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"        try:"},{"line_number":262,"context_line":"            yield"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_ade4633b","line":259,"in_reply_to":"7a1b2928_30e4380c","updated":"2016-04-11 11:36:32.000000000","message":"no, I forgot :/ good catch!\n\nwill add a test too","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"594e3c2e3f6cafc1df33e863c71c7a4195e4448c","unresolved":false,"context_lines":[{"line_number":262,"context_line":"            yield"},{"line_number":263,"context_line":"        finally:"},{"line_number":264,"context_line":"            if old_etags:"},{"line_number":265,"context_line":"                req.headers[header_name] \u003d old_etags"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"    def handle_get_or_head(self, req, start_response):"},{"line_number":268,"context_line":"        with self._encrypt_conditional_etags(req, \u0027If-Match\u0027):"}],"source_content_type":"text/x-python","patch_set":9,"id":"9a061dce_626235af","line":265,"range":{"start_line":265,"start_character":2,"end_line":265,"end_character":52},"updated":"2016-04-11 03:07:40.000000000","message":"I think whatever made this required before (when no error occurs) is now gone.  But it is good to restore this value in case of errors, and can\u0027t hurt to simply always do it.  Good change running the method in a \"with\".","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0061ab936931719bbd411e3b3cdf101865353502","unresolved":false,"context_lines":[{"line_number":262,"context_line":"            yield"},{"line_number":263,"context_line":"        finally:"},{"line_number":264,"context_line":"            if old_etags:"},{"line_number":265,"context_line":"                req.headers[header_name] \u003d old_etags"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"    def handle_get_or_head(self, req, start_response):"},{"line_number":268,"context_line":"        with self._encrypt_conditional_etags(req, \u0027If-Match\u0027):"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_58c74f45","line":265,"range":{"start_line":265,"start_character":2,"end_line":265,"end_character":52},"in_reply_to":"9a061dce_626235af","updated":"2016-04-11 11:36:32.000000000","message":"OK thanks for looking into it","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"}],"swift/proxy/controllers/obj.py":[{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"594e3c2e3f6cafc1df33e863c71c7a4195e4448c","unresolved":false,"context_lines":[{"line_number":2209,"context_line":"        # correct conditional etag from wherever X-Backend-Etag-Is-At points,"},{"line_number":2210,"context_line":"        # if it exists at all, to avoid a false 412."},{"line_number":2211,"context_line":"        resp._conditional_etag \u003d resp.headers.get("},{"line_number":2212,"context_line":"            req.headers.get(\u0027X-Backend-Etag-Is-At\u0027))"},{"line_number":2213,"context_line":"        if (is_success(resp.status_int) or is_redirection(resp.status_int) or"},{"line_number":2214,"context_line":"                resp.status_int \u003d\u003d HTTP_REQUESTED_RANGE_NOT_SATISFIABLE):"},{"line_number":2215,"context_line":"            resp.accept_ranges \u003d \u0027bytes\u0027"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_906c2c9e","line":2212,"updated":"2016-04-11 03:07:40.000000000","message":"is this fixing an EC bug?  I know that we set this value in the middleware for crypto cases.  So I assume this is taking care of the non-crypto case?  \n\nI see you mention a false 412.  I do remember seeing a false 412 when debugging the if-match behaviors - even for replication.  let\u0027s chat about this.  I would like to understand.  Thanks!","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0061ab936931719bbd411e3b3cdf101865353502","unresolved":false,"context_lines":[{"line_number":2209,"context_line":"        # correct conditional etag from wherever X-Backend-Etag-Is-At points,"},{"line_number":2210,"context_line":"        # if it exists at all, to avoid a false 412."},{"line_number":2211,"context_line":"        resp._conditional_etag \u003d resp.headers.get("},{"line_number":2212,"context_line":"            req.headers.get(\u0027X-Backend-Etag-Is-At\u0027))"},{"line_number":2213,"context_line":"        if (is_success(resp.status_int) or is_redirection(resp.status_int) or"},{"line_number":2214,"context_line":"                resp.status_int \u003d\u003d HTTP_REQUESTED_RANGE_NOT_SATISFIABLE):"},{"line_number":2215,"context_line":"            resp.accept_ranges \u003d \u0027bytes\u0027"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_18403756","line":2212,"in_reply_to":"7a1b2928_906c2c9e","updated":"2016-04-11 11:36:32.000000000","message":"This change fixed the additional 6 functional test Errors seen when using an EC policy with version 8 of the patch vs replication policy.\n\nWithout this change, when doing a conditional GET with EC, the response here is created with etag \u003d x-object-sysmeta-ec-etag which is the etag of the ciphertext. Then when the response iter starts, it immediately evaluates the match conditions by comparing that Etag value against the match header values in the request (see swob.Response), and of course no etag in If-Match will match the etag of the ciphertext, so the If-Match fails (what I call a \"false 412\").\n\nresp._conditional_etag overrides the response etag value for the purposes of comparing if-match values.\n\nRevert this change and you will see Ec functional tests fail in tests.py:TestFileComparison","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"}],"test/unit/common/middleware/test_decrypter.py":[{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"594e3c2e3f6cafc1df33e863c71c7a4195e4448c","unresolved":false,"context_lines":[{"line_number":81,"context_line":"    def _test_412_response(self, method):"},{"line_number":82,"context_line":"        # simulate a 412 response to a conditional GET which has an Etag header"},{"line_number":83,"context_line":"        data \u003d \u0027the object content\u0027"},{"line_number":84,"context_line":"        env \u003d {\u0027REQUEST_METHOD\u0027: \u0027GET\u0027,"},{"line_number":85,"context_line":"               \u0027swift.crypto.fetch_crypto_keys\u0027: fetch_crypto_keys}"},{"line_number":86,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/o\u0027, environ\u003denv, method\u003dmethod)"},{"line_number":87,"context_line":"        resp_body \u003d \u0027I am sorry, you have failed to meet a precondition\u0027"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_85e50caa","line":84,"updated":"2016-04-11 03:07:40.000000000","message":"shouldn\u0027t the \u0027GET\u0027 be method instead?  Or, since it gets set when using the method arg in the next step, you could remove the REQUEST_METHOD specification.","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0061ab936931719bbd411e3b3cdf101865353502","unresolved":false,"context_lines":[{"line_number":81,"context_line":"    def _test_412_response(self, method):"},{"line_number":82,"context_line":"        # simulate a 412 response to a conditional GET which has an Etag header"},{"line_number":83,"context_line":"        data \u003d \u0027the object content\u0027"},{"line_number":84,"context_line":"        env \u003d {\u0027REQUEST_METHOD\u0027: \u0027GET\u0027,"},{"line_number":85,"context_line":"               \u0027swift.crypto.fetch_crypto_keys\u0027: fetch_crypto_keys}"},{"line_number":86,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/o\u0027, environ\u003denv, method\u003dmethod)"},{"line_number":87,"context_line":"        resp_body \u003d \u0027I am sorry, you have failed to meet a precondition\u0027"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_d32a207e","line":84,"in_reply_to":"7a1b2928_85e50caa","updated":"2016-04-11 11:36:32.000000000","message":"yep, its redundant, thanks, will remove.","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"594e3c2e3f6cafc1df33e863c71c7a4195e4448c","unresolved":false,"context_lines":[{"line_number":122,"context_line":""},{"line_number":123,"context_line":"    def _test_404_response(self, method):"},{"line_number":124,"context_line":"        # simulate a 404 response, sanity check response headers"},{"line_number":125,"context_line":"        env \u003d {\u0027REQUEST_METHOD\u0027: \u0027GET\u0027,"},{"line_number":126,"context_line":"               \u0027swift.crypto.fetch_crypto_keys\u0027: fetch_crypto_keys}"},{"line_number":127,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/o\u0027, environ\u003denv, method\u003dmethod)"},{"line_number":128,"context_line":"        resp_body \u003d \u0027You still have not found what you are looking for\u0027"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_65e270a1","line":125,"updated":"2016-04-11 03:07:40.000000000","message":"same story here with the \u0027GET\u0027","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0061ab936931719bbd411e3b3cdf101865353502","unresolved":false,"context_lines":[{"line_number":122,"context_line":""},{"line_number":123,"context_line":"    def _test_404_response(self, method):"},{"line_number":124,"context_line":"        # simulate a 404 response, sanity check response headers"},{"line_number":125,"context_line":"        env \u003d {\u0027REQUEST_METHOD\u0027: \u0027GET\u0027,"},{"line_number":126,"context_line":"               \u0027swift.crypto.fetch_crypto_keys\u0027: fetch_crypto_keys}"},{"line_number":127,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/o\u0027, environ\u003denv, method\u003dmethod)"},{"line_number":128,"context_line":"        resp_body \u003d \u0027You still have not found what you are looking for\u0027"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_135c9824","line":125,"in_reply_to":"7a1b2928_65e270a1","updated":"2016-04-11 11:36:32.000000000","message":"Done","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"}],"test/unit/common/middleware/test_encrypter.py":[{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"594e3c2e3f6cafc1df33e863c71c7a4195e4448c","unresolved":false,"context_lines":[{"line_number":134,"context_line":"            req \u003d Request.blank(\u0027/v1/a/c/o\u0027, environ\u003denv,"},{"line_number":135,"context_line":"                                headers\u003d{header_name: header_value})"},{"line_number":136,"context_line":"            app \u003d FakeSwift()"},{"line_number":137,"context_line":"            app.register(\u0027GET\u0027, \u0027/v1/a/c/o\u0027, HTTPOk, {})"},{"line_number":138,"context_line":"            resp \u003d req.get_response(encrypter.Encrypter(app, {}))"},{"line_number":139,"context_line":"            self.assertEqual(\u0027200 OK\u0027, resp.status)"},{"line_number":140,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_d02504af","line":137,"updated":"2016-04-11 03:07:40.000000000","message":"You could use method here instead of \u0027GET\u0027.  But it is interesting that this works for a HEAD.  I guess a register for HEAD covers both GET and HEAD?","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0061ab936931719bbd411e3b3cdf101865353502","unresolved":false,"context_lines":[{"line_number":134,"context_line":"            req \u003d Request.blank(\u0027/v1/a/c/o\u0027, environ\u003denv,"},{"line_number":135,"context_line":"                                headers\u003d{header_name: header_value})"},{"line_number":136,"context_line":"            app \u003d FakeSwift()"},{"line_number":137,"context_line":"            app.register(\u0027GET\u0027, \u0027/v1/a/c/o\u0027, HTTPOk, {})"},{"line_number":138,"context_line":"            resp \u003d req.get_response(encrypter.Encrypter(app, {}))"},{"line_number":139,"context_line":"            self.assertEqual(\u0027200 OK\u0027, resp.status)"},{"line_number":140,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_335a7484","line":137,"in_reply_to":"7a1b2928_d02504af","updated":"2016-04-11 11:36:32.000000000","message":"yes, looks like FakeSwift will use a GET response to satisfy a HEAD. But I will fix this.","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"},{"author":{"_account_id":12279,"name":"Janie Richling","email":"jrichli@us.ibm.com","username":"jrichli"},"change_message_id":"594e3c2e3f6cafc1df33e863c71c7a4195e4448c","unresolved":false,"context_lines":[{"line_number":164,"context_line":"        # etags should be quoted but check we can cope if they are not"},{"line_number":165,"context_line":"        do_test("},{"line_number":166,"context_line":"            method, [\u0027*\u0027, \u0027an etag\u0027, \u0027another_etag\u0027],"},{"line_number":167,"context_line":"            expected_plain_etags\u003d[\u0027*\u0027, \u0027\"an etag\"\u0027, \u0027\"another_etag\"\u0027])"},{"line_number":168,"context_line":""},{"line_number":169,"context_line":"    def test_GET_if_match(self):"},{"line_number":170,"context_line":"        self._test_if_match(\u0027GET\u0027, \u0027If-Match\u0027)"}],"source_content_type":"text/x-python","patch_set":9,"id":"7a1b2928_50dd746f","line":167,"updated":"2016-04-11 03:07:40.000000000","message":"great test cases!","commit_id":"96d6ab7b889ea1094e63970b5cfca22b82e619da"}]}
