CouchDB
  1. CouchDB
  2. COUCHDB-34

Enable replicator to use HTTP authentication

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Blocker Blocker
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 0.9
    • Component/s: Database Core
    • Labels:
      None

      Description

      You can currently give the CouchDB replicator HTTP URIs to remote databases. However, if one of those remote instances is behind HTTP authentication, the replication will fail. It should be possible to specify authentication credentials to the replicator, which it would then use in response to 401 responses.

        Activity

        Hide
        Jan Lehnardt added a comment -

        This DB authentication in trunk, we should get that fixed in 0.9.

        Show
        Jan Lehnardt added a comment - This DB authentication in trunk, we should get that fixed in 0.9.
        Hide
        Adam Kocoloski added a comment -

        I can submit a patch for this if we decide on the API for specifying credentials. The JSON object POSTed to _replicate looks like

        {
        "source": "http://example.com:5984/dbname",
        "target": "dbname",
        "source_options": { "headers": [

        {K,V}

        ] },
        "target_options: { }
        }

        Do we want to make clients do the Base64 encoding themselves? In that case, they can stick the authentication header in the JSON object. Do we want some alternative option in the _options Objects? Do we want to support http://user:pass@host:port URLs?

        Show
        Adam Kocoloski added a comment - I can submit a patch for this if we decide on the API for specifying credentials. The JSON object POSTed to _replicate looks like { "source": "http://example.com:5984/dbname", "target": "dbname", "source_options": { "headers": [ {K,V} ] }, "target_options: { } } Do we want to make clients do the Base64 encoding themselves? In that case, they can stick the authentication header in the JSON object. Do we want some alternative option in the _options Objects? Do we want to support http://user:pass@host:port URLs?
        Hide
        Adam Kocoloski added a comment -

        So, the CouchDB replicator works with HTTP authentication already. Since we have no restrictions on reader access, we only have to worry about two cases: local target and remote target.

        Local Target: specify credentials in the POST to replicate. Either of the following works:
        curl -X POST http://admin:mysecretpassword@localhost:5984/_replicate works
        curl -X POST http://localhost:5984/_replicate -H "Authorization:Basic YWRtaW46bXlzZWNyZXRwYXNzd29yZA=="

        Remote Target: specify credentials in the JSON body. This works in trunk:

        { "source":"test_suite_db_a", "target":"http://admin:mysecretpassword@localhost:5984/test_suite_db_b" }

        This works if you the header value in couch_httpd_misc_handlers:handle_replicate_req using ?b2l:
        {
        "source":"test_suite_db_a",
        "target":"http://localhost:5984/test_suite_db_b",
        "target_options":{
        "headers":

        { "Authorization":"Basic YWRtaW46bXlzZWNyZXRwYXNzd29yZA==" }

        }
        }

        One thing we could do is format a nice 401 response if the replicator fails because of missing credentials. Currently the replicator crashes when update_docs fails and no response is sent to the client. In the local target case returning a 401 is a no brainer.

        In the remote target case it's a little weird because the credentials need to be sent in the JSON body. One idea might be to set realm="target" in the response. CouchDB-aware clients would know that means the credentials need to go in the body, not the URL or Headers.

        Show
        Adam Kocoloski added a comment - So, the CouchDB replicator works with HTTP authentication already. Since we have no restrictions on reader access, we only have to worry about two cases: local target and remote target. Local Target: specify credentials in the POST to replicate. Either of the following works: curl -X POST http://admin:mysecretpassword@localhost:5984/_replicate works curl -X POST http://localhost:5984/_replicate -H "Authorization:Basic YWRtaW46bXlzZWNyZXRwYXNzd29yZA==" Remote Target: specify credentials in the JSON body. This works in trunk: { "source":"test_suite_db_a", "target":"http://admin:mysecretpassword@localhost:5984/test_suite_db_b" } This works if you the header value in couch_httpd_misc_handlers:handle_replicate_req using ?b2l: { "source":"test_suite_db_a", "target":"http://localhost:5984/test_suite_db_b", "target_options":{ "headers": { "Authorization":"Basic YWRtaW46bXlzZWNyZXRwYXNzd29yZA==" } } } One thing we could do is format a nice 401 response if the replicator fails because of missing credentials. Currently the replicator crashes when update_docs fails and no response is sent to the client. In the local target case returning a 401 is a no brainer. In the remote target case it's a little weird because the credentials need to be sent in the JSON body. One idea might be to set realm="target" in the response. CouchDB-aware clients would know that means the credentials need to go in the body, not the URL or Headers.
        Hide
        Adam Kocoloski added a comment -

        I posted some code that makes Couch respond with a 401 status code if a user attempts a replication without proper authentication:

        http://github.com/kocolosk/couchdb/tree/jira-34

        Getting that to work was slightly tricky since it required tracking exceptions across processes. I chose to rework a bit of the message passing in the replication module as a result.

        One downside of this fix is that the replication test will get stuck if run in a browser on a server that has admins defined. Previously that test would just fail when it tried to replicate to a "remote" target, but now when the 401 code comes back the browser keeps asking for credentials, not realizing that the credentials belong in the JSON body instead of the Authorization Header.

        The response in the case of a local target is the usual

        {"error":"unauthorized","reason":"You are not a server or database admin."}

        but if you attempt an unauthorized replication to a remote target you'll receive

        {"error":"unauthorized","reason":"Please authenticate to the target server in the JSON body."}
        Show
        Adam Kocoloski added a comment - I posted some code that makes Couch respond with a 401 status code if a user attempts a replication without proper authentication: http://github.com/kocolosk/couchdb/tree/jira-34 Getting that to work was slightly tricky since it required tracking exceptions across processes. I chose to rework a bit of the message passing in the replication module as a result. One downside of this fix is that the replication test will get stuck if run in a browser on a server that has admins defined. Previously that test would just fail when it tried to replicate to a "remote" target, but now when the 401 code comes back the browser keeps asking for credentials, not realizing that the credentials belong in the JSON body instead of the Authorization Header. The response in the case of a local target is the usual {"error":"unauthorized","reason":"You are not a server or database admin."} but if you attempt an unauthorized replication to a remote target you'll receive {"error":"unauthorized","reason":"Please authenticate to the target server in the JSON body."}
        Hide
        Damien Katz added a comment -

        Fixed as part of the replication security worked recently checked in.

        Show
        Damien Katz added a comment - Fixed as part of the replication security worked recently checked in.
        Hide
        Sam Bisbee added a comment -

        Resolved for a while. Closing.

        Show
        Sam Bisbee added a comment - Resolved for a while. Closing.

          People

          • Assignee:
            Damien Katz
            Reporter:
            Christopher Lenz
          • Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development