Uploaded image for project: 'Couchbase Documentation'
  1. Couchbase Documentation
  2. DOC-9848

User able to insert document with insufficient RBAC permissions

    XMLWordPrintable

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • Neo
    • Neo
    • security
    • None
    • DOC-2022-S6, DOC-2022-S7
    • 1

    Description

      CB Version:Enterprise Edition 7.1.0 build 2434 

      Steps to Reproduce:

      1. Create user with only read_write permissions on a collection. Try insert and it fails with NO_ACCESS as expected
      2. Create user with read_write along with query_insert or query_update permissions and try insert. It is successful instead of failing with NO_ACCESS.

        package com.couchbase;
         
        import com.couchbase.client.core.error.DocumentNotFoundException;
        import com.couchbase.client.java.Bucket;
        import com.couchbase.client.java.Cluster;
        import com.couchbase.client.java.ClusterOptions;
        import com.couchbase.client.java.Collection;
        import com.couchbase.client.java.json.JsonObject;
        import com.couchbase.client.java.manager.user.*;
        import com.couchbase.constants.Strings;
        import com.couchbase.transactions.Transactions;
        import com.couchbase.transactions.config.TransactionConfigBuilder;
        import com.couchbase.transactions.error.TransactionFailed;
         
        import java.time.Duration;
        import java.util.*;
        import java.util.stream.Collectors;
        import java.util.stream.Stream;
         
         
        public class sample {
            public static JsonObject initial = JsonObject.create().put(Strings.CONTENT_NAME, "initial");
            public static  Cluster cluster;
         
            public static void main(String[] args) {
                String clusterHostname = "172.23.111.139";
                cluster = Cluster.connect(clusterHostname,
                        ClusterOptions.clusterOptions("Administrator", "password"));
         
                // Collection testCollection = cluster.bucket("testBucket").defaultCollection();
                Collection testCollection = cluster.bucket("testBucket").scope("testScope").collection("testCollection");
         
                createUserAndRoles(testCollection);
                cluster.disconnect();
         
                cluster = Cluster.connect(clusterHostname,
                        ClusterOptions.clusterOptions("testuser", "password"));
                //Collection testuserCollection = cluster.bucket("testBucket").defaultCollection();
                Collection testuserCollection = cluster.bucket("testBucket").scope("testScope").collection("testCollection");
         
                String docId = UUID.randomUUID().toString();
                System.out.println("DocId:"+docId);
                testuserCollection.insert(docId,initial);
                System.out.println("DocContent: "+testuserCollection.get(docId));
            }
         
         
            static void createUserAndRoles(Collection collection) {
                User rbacuser  = new User("testuser");
                rbacuser.password("password");
                UserManager userManager = new UserManager(new AsyncUserManager(cluster.core()));
         
         
                List<Role> allRolesForThisUser = new ArrayList<Role>();
         
                allRolesForThisUser.add(new Role("data_reader", collection.bucketName(),collection.scopeName(),collection.name()));
                allRolesForThisUser.add(new Role("query_insert", collection.bucketName(),collection.scopeName(),collection.name()));
                //allRolesForThisUser.add(new Role("query_update", collection.bucketName(),collection.scopeName(),collection.name()));
                
         
                rbacuser.roles(allRolesForThisUser);
                userManager.upsertUser(rbacuser, UpsertUserOptions.upsertUserOptions().timeout(Duration.ofSeconds(10)));
                try {
                    Thread.sleep(10*1000); //sleep for 10s so that the user and its roles are reflected across nodes.
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
         
          

         

      Attachments

        For Gerrit Dashboard: DOC-9848
        # Subject Branch Project Status CR V

        Activity

          This is a KV operation without transactions.

          If there is a transaction involved and a n1ql operation is done, KV operations will succeed with just query_insert permissions.(Look at MB-50451 for more details)

          Since that's not the case here, maybe KV team should take a look first.

          Praneeth Bokka Would you know when was the last time it worked correctly? Would help to narrow down the build numbers.

          kamini.jagtiani Kamini Jagtiani (Inactive) added a comment - - edited This is a KV operation without transactions. If there is a transaction involved and a n1ql operation is done, KV operations will succeed with just query_insert permissions.(Look at MB-50451 for more details) Since that's not the case here, maybe KV team should take a look first. Praneeth Bokka Would you know when was the last time it worked correctly? Would help to narrow down the build numbers.

          Discussed this with Kamini and moving this to memcached as per our discussion

           

          praneeth.bokka Praneeth Bokka added a comment - Discussed this with Kamini and moving this to memcached as per our discussion  
          owend Daniel Owen added a comment - - edited

          Hi Praneeth Bokka,

          Are you seeing a regression? - or is this a new test.
          Also in the steps to reproduce it states:

          read_write permissions

          Looking at the application code, I assume it is supposed to say just read permissions?

          Looking at ns_server/src/menelaus_roles.erl for the role query_insert we see:

               {query_insert, ?RBAC_COLLECTION_PARAMS,
                [{name, <<"Query Insert">>},
                 {folder, 'query'},
                 {desc, <<"Can execute an INSERT statement on a given bucket, scope or "
                          "collection to add data. This user can access the web console "
                          "and insert data, but cannot read it.">>}],
                [{[{collection, ?RBAC_COLLECTION_PARAMS}, n1ql, insert], [execute]},
                 {[{collection, ?RBAC_COLLECTION_PARAMS}, data, docs], [insert]},
                 {[{bucket, bucket_name}, settings], [read]},
                 {[ui], [read]},
                 {[pools], [read]}]},
          

          Therefore the query_insert role allows the inserting of data.
          Looking at kv_engine/include/memcached/rbac/privileges.h we see

          enum class Privilege {
              /**
               * The `Read` privilege allows for reading documents in the selected
               * bucket.
               */
              Read,
              /**
               * The `Insert` privilege allows for inserting data by using the
               * 'add' command.
               */
              Insert,
          ...
          

          Therefore I believe it is behaving as expected.

          Looking at our documentation for query_insert we do not describe an insert (or delete) privilege. However, I assume at a high-level it can be translated to write privilege in our documentation.

          ccing. Dave Finlay [Ian McCloy for any additional comment

          owend Daniel Owen added a comment - - edited Hi Praneeth Bokka , Are you seeing a regression? - or is this a new test. Also in the steps to reproduce it states: read_write permissions Looking at the application code, I assume it is supposed to say just read permissions? Looking at ns_server/src/menelaus_roles.erl for the role query_insert we see: {query_insert, ?RBAC_COLLECTION_PARAMS, [{name, <<"Query Insert">>}, {folder, 'query'}, {desc, <<"Can execute an INSERT statement on a given bucket, scope or " "collection to add data. This user can access the web console " "and insert data, but cannot read it.">>}], [{[{collection, ?RBAC_COLLECTION_PARAMS}, n1ql, insert], [execute]}, {[{collection, ?RBAC_COLLECTION_PARAMS}, data, docs], [insert]}, {[{bucket, bucket_name}, settings], [read]}, {[ui], [read]}, {[pools], [read]}]}, Therefore the query_insert role allows the inserting of data. Looking at kv_engine/include/memcached/rbac/privileges.h we see enum class Privilege { /** * The `Read` privilege allows for reading documents in the selected * bucket. */ Read, /** * The `Insert` privilege allows for inserting data by using the * 'add' command. */ Insert, ... Therefore I believe it is behaving as expected. Looking at our documentation for query_insert we do not describe an insert (or delete) privilege. However, I assume at a high-level it can be translated to write privilege in our documentation. ccing. Dave Finlay [ Ian McCloy for any additional comment

          Hi Daniel, 

          Apologies for the confusion. Yes it is supposed to be "read_only" instead of "read_write".

          This is a new test case we are adding recently.

          Based on your above mentioned description, do we mean that a user with query_insert permissions will automatically have the regular KV insert permissions??.

           

          Since this is a little misleading, we might have to document this fact of query_insert/(other query perms) explicitly. 

          praneeth.bokka Praneeth Bokka added a comment - Hi Daniel,  Apologies for the confusion. Yes it is supposed to be "read_only" instead of "read_write". This is a new test case we are adding recently. Based on your above mentioned description, do we mean that a user with query_insert permissions will automatically have the regular KV insert permissions??.   Since this is a little misleading, we might have to document this fact of query_insert/(other query perms) explicitly. 
          owend Daniel Owen added a comment - - edited

          Hi Praneeth Bokka

          Apologies for the confusion. Yes it is supposed to be "read_only" instead of "read_write".

          No problem

          This is a new test case we are adding recently.

          Thanks for clarifying

          Based on your above mentioned description, do we mean that a user with query_insert permissions will automatically have the regular KV insert permissions?.

          From the ns_server/src/menelaus_roles.erl code this appears to be the case.

          Since this is a little misleading, we might have to document this fact of query_insert/(other query perms) explicitly.

          As Security PM I will let Ian McCloy comment whether we document the additional permissions e.g. insert.

          thanks

          owend Daniel Owen added a comment - - edited Hi Praneeth Bokka Apologies for the confusion. Yes it is supposed to be "read_only" instead of "read_write". No problem This is a new test case we are adding recently. Thanks for clarifying Based on your above mentioned description, do we mean that a user with query_insert permissions will automatically have the regular KV insert permissions?. From the ns_server/src/menelaus_roles.erl code this appears to be the case. Since this is a little misleading, we might have to document this fact of query_insert/(other query perms) explicitly. As Security PM I will let Ian McCloy comment whether we document the additional permissions e.g. insert. thanks

          Hi Ian, 

          From the documentation: https://docs.couchbase.com/server/current/learn/security/roles.html

          I see we are mentioning, query_insert would allow only INSERT Statements. However as we discussed above, we are able to do a KV insert as well. I think we should document this explicitly. Please let us know your thoughts.

           

          Thanks

          Praneeth

          praneeth.bokka Praneeth Bokka added a comment - Hi Ian,  From the documentation: https://docs.couchbase.com/server/current/learn/security/roles.html I see we are mentioning, query_insert would allow only INSERT Statements. However as we discussed above, we are able to do a KV insert as well. I think we should document this explicitly. Please let us know your thoughts.   Thanks Praneeth
          ianmccloy Ian McCloy added a comment -

          Agreed, the documentation should be updated if a query insert is allowing KV writes. 

          ianmccloy Ian McCloy added a comment - Agreed, the documentation should be updated if a query insert is allowing KV writes. 
          tony.hillman Tony Hillman added a comment - PR at https://github.com/couchbase/docs-server/pull/2564

          People

            tony.hillman Tony Hillman
            praneeth.bokka Praneeth Bokka
            Votes:
            0 Vote for this issue
            Watchers:
            9 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes

                PagerDuty