Uploaded image for project: 'Couchbase Gateway'
  1. Couchbase Gateway
  2. CBG-3951

[3.1.7 backport] Users API for database with default metadataID can return other db users in the bucket

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • Major
    • 3.1.7
    • None
    • None
    • Security Level: Public
    • None
    • CBG Sprint 150
    • 0

    Description

      There are two databases:

      /db1/ -> _default._default
      /db2/ -> _default.collection1

      A call to /db1/_user/?name_only=true can see users created inside of db2, because users in db1 are named _sync:user:alice while users in db2 are named _sync:user:db2:alice and the N1QL query for db1 filters on _sync:user while db2 filters on _sync:user:db.

      A fix for this could be to post N1QL filter on looking for more than 2 colons in the document key, since user documents can not have a colon inside them https://github.com/couchbase/sync_gateway/blob/84997a0d39241fafcc926c86771750f2ad60febd/auth/role.go#L147

      The following is a unit test reproduction:

      func TestUserMultipleDBs(t *testing.T) {
      	base.RequireNumTestDataStores(t, 2)
      	rt := NewRestTester(t, &RestTesterConfig{
      		PersistentConfig: true,
      	})
      	defer rt.Close()
       
      	defaultCollectionDB := "defaultcollectiondb"
      	namedCollectionDB := "namedcollectiondb"
      	// create database using _default._default
      	dbConfig := rt.NewDbConfig()
      	dbConfig.Scopes = nil
      	RequireStatus(t, rt.CreateDatabase(defaultCollectionDB, dbConfig), http.StatusCreated)
       
      	username := "alice"
      	userConfig := string(base.MustJSONMarshal(t,
      		auth.PrincipalConfig{
      			Name:     &username,
      			Password: base.StringPtr(RestTesterDefaultUserPassword),
      		}))
       
      	resp := rt.SendAdminRequest(http.MethodPut, "/{{.db}}/_user/"+username, userConfig)
      	RequireStatus(t, resp, http.StatusCreated)
       
      	resp = rt.SendAdminRequest(http.MethodGet, "/{{.db}}/_user/?name_only=false", "")
      	RequireStatus(t, resp, http.StatusOK)
      	var responseUsers []auth.PrincipalConfig
      	require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &responseUsers))
      	require.Len(t, responseUsers, 1)
       
      	// create a database with a named collection
      	dbConfig = rt.NewDbConfig()
      	dbConfig.Scopes = GetCollectionsConfig(t, rt.TestBucket, 1)
      	RequireStatus(t, rt.CreateDatabase(namedCollectionDB, dbConfig), http.StatusCreated)
       
      	resp = rt.SendAdminRequest(http.MethodPut, "/"+namedCollectionDB+"/_user/"+username, userConfig)
      	RequireStatus(t, resp, http.StatusCreated)
       
      	resp = rt.SendAdminRequest(http.MethodGet, "/"+namedCollectionDB+"/_user/?name_only=false", "")
      	RequireStatus(t, resp, http.StatusOK)
      	require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &responseUsers))
      	require.Len(t, responseUsers, 1)
       
      	resp = rt.SendAdminRequest(http.MethodGet, "/"+defaultCollectionDB+"/_user/?name_only=false", "")
      	RequireStatus(t, resp, http.StatusOK)
      	require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &responseUsers))
      	require.Len(t, responseUsers, 1)
      }
      

      There are at least three places this would need to be fixed:

      https://github.com/couchbase/sync_gateway/blob/84997a0d39241fafcc926c86771750f2ad60febd/db/database.go#L1053
      https://github.com/couchbase/sync_gateway/blob/84997a0d39241fafcc926c86771750f2ad60febd/db/database.go#L1226
      https://github.com/couchbase/sync_gateway/blob/84997a0d39241fafcc926c86771750f2ad60febd/db/database.go#L1297

      Attachments

        Issue Links

          Activity

            People

              tor.colvin Tor Colvin
              tor.colvin Tor Colvin
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                PagerDuty