diff --git a/client/grpc/Ns.cc b/client/grpc/Ns.cc
index be02d1492d3162431d6f501951b012a788e9f849..7bd4e7549482f1a11fd9b45e69ff8939cf60fde4 100644
--- a/client/grpc/Ns.cc
+++ b/client/grpc/Ns.cc
@@ -10,7 +10,7 @@ int usage(const char* prog)
   fprintf(stderr, "usage: %s [--key <ssl-key-file> "
           "--cert <ssl-cert-file> "
           "--ca <ca-cert-file>] "
-          "[--endpoint <host:port>] [--token <auth-token>] [--xattr <key:val>] [--mode <mode>] [--username <username>] [ [--groupname <groupname>] [--uid <uid>] [--gid <gid>] [--owner-uid <uid>] [--owner-gid <gid>] [--acl <acl>] [--sysacl] [--norecycle] [-r] [--max-version <max-version>] [--target <target>] [--year <year>] [--month <month>] [--day <day>] [--inodes <#>] [--volume <#>] [--quota volume|inode] -p <path> <command>\n", prog);
+          "[--endpoint <host:port>] [--token <auth-token>] [--xattr <key:val>] [--mode <mode>] [--username <username>] [ [--groupname <groupname>] [--uid <uid>] [--gid <gid>] [--owner-uid <uid>] [--owner-gid <gid>] [--acl <acl>] [--sysacl] [--norecycle] [-r] [--max-version <max-version>] [--target <target>] [--year <year>] [--month <month>] [--day <day>] [--inodes <#>] [--volume <#>] [--quota volume|inode] [--position <position>] [--front] -p <path> <command>\n", prog);
 
   fprintf(stderr,
 	  "                                     -p <path> mkdir \n"
@@ -23,7 +23,7 @@ int usage(const char* prog)
 	  "                     --xattr <!key=> -p <path> setxattr # deletes key\n"
 	  " --owner-uid <uid> --owner-gid <gid> -p <path> chown \n"
 	  "                       --mode <mode> -p <path> chmod \n"
-	  "       [--sysacl] [-r] [--acl <acl>] -p <path> acl \n"
+	  " [--sysacl] [-r] [--acl <acl>] [--position <pos>] [--front] -p <path> acl \n"
 	  "     --ztoken <token> | [--acl] [-r] -p <path> token\n"
 	  "                [--max-version <max> -p <path> create-version \n"
 	  "                                     -p <path> list-version \n"
@@ -77,6 +77,7 @@ int main(int argc, const char* argv[])
   bool recursive = false;
   bool norecycle = false;
   bool sysacl = false;
+  uint32_t position = 0;
   std::string eostoken = "";
 
   for (auto i = 1; i < argc; ++i) {
@@ -282,6 +283,34 @@ int main(int argc, const char* argv[])
       }
     }
 
+    if (option == "--position") {
+      if (position) {
+        std::cout << "Please specify only one of --front or --position" << std::endl;
+        return usage(argv[0]);
+      }
+      if (argc > i + 1) {
+        try {
+          position = std::stoi(argv[i+1]);
+          ++i;
+        } catch (std::exception& e) {
+          return usage(argv[0]);
+        }
+        continue;
+      } else {
+        return usage(argv[0]);
+      }
+
+    }
+
+    if (option == "--front") {
+      if (position) {
+        std::cout << "Please specify only one of --front or --position" << std::endl;
+        return usage(argv[0]);
+      }
+      position = 1;
+      continue;
+    }
+
     if (option == "--mode") {
       if (argc > i + 1) {
 	mode = strtol(argv[i+1],0,8);
@@ -483,6 +512,10 @@ int main(int argc, const char* argv[])
     } else {
       request.mutable_acl()->set_type(eos::rpc::NSRequest::AclRequest::USER_ACL);
     }
+
+    if (position) {
+      request.mutable_acl()->set_position(position);
+    }
   } else if (cmd == "token") {
     request.mutable_token()->mutable_token()->mutable_token()->set_expires(time(NULL) + 300);
     if (!path.empty()) {
diff --git a/common/grpc-proto b/common/grpc-proto
index d5b42da35097e8ff5f1e878b9ccc9c1daa292ca5..ae3ce89ff4cee18faed9f4bcd176f3a48d45f2de 160000
--- a/common/grpc-proto
+++ b/common/grpc-proto
@@ -1 +1 @@
-Subproject commit d5b42da35097e8ff5f1e878b9ccc9c1daa292ca5
+Subproject commit ae3ce89ff4cee18faed9f4bcd176f3a48d45f2de
diff --git a/console/commands/com_proto_acl.cc b/console/commands/com_proto_acl.cc
index 3c0a9e87f488a4dbd4ca300708536494c059f5d0..84a4f2c96526f1b5dceba509857b8d266916ba89 100644
--- a/console/commands/com_proto_acl.cc
+++ b/console/commands/com_proto_acl.cc
@@ -60,13 +60,16 @@ void com_acl_help()
 {
   std::ostringstream oss;
   oss
-      << "Usage: eos acl [-l|--list] [-R|--recursive] "
+      << "Usage: eos acl [-l|--list] [-R|--recursive]"
+      << " [-p | --position <pos>] [-f | --front] "
       << "[--sys|--user] [<rule>] <path>" << std::endl
       << "  atomically set and modify ACLs for the given directory path" << std::endl
       << std::endl
       << "  -h, --help      : print help message" << std::endl
       << "  -R, --recursive : apply to directories recursively" << std::endl
       << "  -l, --list      : list ACL rules" << std::endl
+      << "  -p, --position  : add the acl rule at specified position" << std::endl
+      << "  -f, --front     : add the acl rule at the front position" << std::endl
       << "      --user      : handle/list user.acl rules on directory. " << std::endl
       << "                    Regular users can modify these." << std::endl
       << "      --sys       : handle/list sys.acl rules on directory." << std::endl
@@ -81,6 +84,10 @@ void com_acl_help()
       << "    When modifying permissions every ACL flag can be added with" <<
       std::endl
       << "    \"+\" or removed with \"-\"." << std::endl
+      << "    By default rules are appended at the end of acls" << std::endl
+      << "    This ordering can be changed via --position flag" << std::endl
+      << "    which will add the new rule at a given position starting at 1 or" << std::endl
+      << "    the --front flag which adds the rule at the front instead" << std::endl
       << std::endl
       << "Examples:" << std::endl
       << "  acl --user u:1001=rwx /eos/dev/" << std::endl
@@ -90,6 +97,8 @@ void com_acl_help()
       << "  acl --user u:1001:+m /eos/dev" << std::endl
       << "    Add change mode permission flag for user id 1001" << std::endl
       << "  acl --user u:1010= /eos/dev" << std::endl
-      << "    Remove all ACls for user id 1001" << std::endl;
+      << "    Remove all ACls for user id 1001" << std::endl
+      << "  acl --front --user u:1001:rwx /eos/dev" << std::endl
+      << "     Add the user id 1001 rule to the front of ACL rules" << std::endl;
   std::cerr << oss.str() << std::endl;
 }
diff --git a/console/commands/helpers/AclHelper.cc b/console/commands/helpers/AclHelper.cc
index 21e0ab4ed2146700c2ec46908ec67a672e874487..52f899a6e82b93b97a3d843719382d7a8d76f201 100644
--- a/console/commands/helpers/AclHelper.cc
+++ b/console/commands/helpers/AclHelper.cc
@@ -146,7 +146,6 @@ AclHelper::ParseCommand(const char* arg)
   eos::common::StringTokenizer tokenizer(arg);
   tokenizer.GetLine();
   bool type_set = false;
-
   // Get opts
   while ((temp = tokenizer.GetToken(false)) != 0) {
     // Trimming
@@ -167,6 +166,36 @@ AclHelper::ParseCommand(const char* arg)
       acl->set_recursive(true);
       continue;
     }
+    if ((token == "-f") || (token == "--front")) {
+      if (acl->position()) {
+        std::cerr << "error: set only one of position or front argument" << std::endl;
+        return false;
+      }
+      acl->set_position(1);
+      continue;
+    }
+
+    if ((token == "-p") || (token == "--position")) {
+      if (acl->position()) {
+        std::cerr << "error: set only one of position or front argument" << std::endl;
+        return false;
+      }
+
+      std::string spos;
+      if (!tokenizer.NextToken(spos)) {
+        std::cerr << "error: position needs an argument!" << std::endl;
+        return false;
+      }
+      try {
+        int pos = std::stoi(spos);
+        if (pos > 0)
+          acl->set_position(pos);
+      } catch (const std::exception& e) {
+        std::cerr << "error: position needs to be integer" << std::endl;
+        return false;
+      }
+      continue;
+    }
 
     if ((token == "-l") || (token == "--list")) {
       acl->set_op(AclProto::LIST);
diff --git a/doc/clicommands/acl.rst b/doc/clicommands/acl.rst
index e219d1b6e7665d4777d1438b228e696a4fd16ce9..8e0846b2e221a56b646ab70290273f989cd7bf1d 100644
--- a/doc/clicommands/acl.rst
+++ b/doc/clicommands/acl.rst
@@ -3,21 +3,28 @@ acl
 
 .. code-block:: text
 
-  eos acl [-l|--list] [-R|--recursive] [--sys|--user] [<rule>] <path>
+  eos acl [-l|--list] [-R|--recursive] [-p | --position <pos>] [-f | --front] [--sys|--user] [<rule>] <path>
     atomically set and modify ACLs for the given directory path
 .. code-block:: text
 
     -h, --help      : print help message
     -R, --recursive : apply to directories recursively
     -l, --list      : list ACL rules
-    --user      : handle/list user.acl rules on directory
-    --sys       : handle/list sys.acl rules on directory
+    -p, --position  : add the acl rule at specified position
+    -f, --front     : add the acl rule at the front position
+        --user      : handle/list user.acl rules on directory
+        --sys       : handle/list sys.acl rules on directory
     <rule> is created similarly to chmod rules. Every rule begins with
     [u|g|egroup] followed by ":" or "=" and an identifier.
     ":" is used to for modifying permissions while
     "=" is used for setting/overwriting permissions.
     When modifying permissions every ACL flag can be added with
-    "+" or removed with "-".
+    "+" or removed with "-
+    By default rules are appended at the end of acls
+    This ordering can be changed via --position flag
+    which will add the new rule at a given position starting at 1 or
+    the --front flag which adds the rule at the front instead
+
   Examples:
     acl --user u:1001=rwx /eos/dev/
     Set ACLs for user id 1001 to rwx
diff --git a/mgm/grpc/GrpcNsInterface.cc b/mgm/grpc/GrpcNsInterface.cc
index f9b5a8e350c75e0d9ba600c80cc657beedebdc88..ae83401185b8fe7e4cd2ab2cd5ec7c951b6243c0 100644
--- a/mgm/grpc/GrpcNsInterface.cc
+++ b/mgm/grpc/GrpcNsInterface.cc
@@ -2236,6 +2236,11 @@ GrpcNsInterface::Acl(eos::common::VirtualIdentity& vid,
     req.mutable_acl()->set_op(eos::console::AclProto::LIST);
   }
 
+  uint32_t position = request->position();
+  if (position) {
+    req.mutable_acl()->set_position(position);
+  }
+
   req.mutable_acl()->set_rule(request->rule());
   eos::mgm::AclCmd aclcmd(std::move(req), vid);
   eos::console::ReplyProto preply = aclcmd.ProcessRequest();
diff --git a/mgm/proc/user/AclCmd.cc b/mgm/proc/user/AclCmd.cc
index 56cb5fb63441614e0bf563c2da04122cfbf4431f..f14968d8e59c8d623cde225815b6043e95fdc1e0 100644
--- a/mgm/proc/user/AclCmd.cc
+++ b/mgm/proc/user/AclCmd.cc
@@ -146,7 +146,14 @@ AclCmd::ModifyAcls(const eos::console::AclProto& acl)
   for (const auto& elem : paths) {
     GetAcls(elem, dir_acls, acl.sys_acl(), false);
     GenerateRuleMap(dir_acls, rule_map);
-    ApplyRule(rule_map);
+    // ACL position is 1-indexed as 0 is the default numeric protobuf val
+    auto [err, acl_pos] = GetRulePosition(rule_map.size(), acl.position());
+    if (err) {
+      mErr = "error: rule position cannot be met!";
+      return err;
+    }
+
+    ApplyRule(rule_map,acl_pos);
     new_acl_val = GenerateAclString(rule_map);
 
     // Set xattr without taking the namespace lock
@@ -268,8 +275,7 @@ AclCmd::GenerateRuleMap(const std::string& acl_string, RuleMap& rmap)
 
     std::string single_acl = std::string(acl_string.begin() + curr_pos,
                                          acl_string.begin() + pos);
-    Rule elem = GetRuleFromString(single_acl);
-    rmap.insert(elem);
+    insert_or_assign(rmap, GetRuleFromString(single_acl));
     curr_pos = pos + 1;
 
     if (curr_pos > acl_string.length()) {
@@ -515,12 +521,19 @@ AclCmd::CheckCorrectId(const std::string& id) const
 //------------------------------------------------------------------------------
 // Apply client modification rule(s) to the acls of the current entry
 //------------------------------------------------------------------------------
-void AclCmd::ApplyRule(RuleMap& rules)
+void AclCmd::ApplyRule(RuleMap& rules, size_t pos)
 {
   unsigned short temp_rule = 0;
 
-  if (!mSet && rules.find(mId) != rules.end()) {
-    temp_rule = rules[mId];
+  if (!mSet) {
+    auto it = std::find_if(rules.begin(),
+                           rules.end(),
+                           [&](const Rule& rule) -> bool {
+                             return rule.first == mId;
+                           });
+    if (it != rules.end()) {
+      temp_rule = it->second;
+    }
   }
 
   if (mAddRule != 0) {
@@ -531,7 +544,16 @@ void AclCmd::ApplyRule(RuleMap& rules)
     temp_rule = temp_rule & (~mRmRule);
   }
 
-  rules[mId] = temp_rule;
+  if (pos != 0) {
+    auto [it, err] = get_iterator(rules, pos);
+    if (err != 0) {
+      mErr = "Invalid position of rule, errc=" + std::to_string(err);
+    }
+    insert_or_assign(rules, mId, temp_rule, it, true);
+    return;
+  }
+
+  insert_or_assign(rules, mId, temp_rule);
 }
 
 //------------------------------------------------------------------------------
@@ -615,4 +637,34 @@ AclCmd::AclBitmaskToString(const unsigned short int in)
   return ret;
 }
 
+std::pair<int, size_t>
+AclCmd::GetRulePosition(size_t rule_map_sz, size_t rule_pos)
+{
+
+  std::pair<int,size_t> result {0,0};
+
+  // Trivial case, nothing is set
+  if (!rule_map_sz && !rule_pos) {
+    return result;
+  }
+
+  if (!rule_map_sz) {
+    // Only valid case here is that the client asks the first position!
+    if (rule_pos != 1) {
+      result.first = EINVAL;
+    }
+  }
+
+  if (rule_map_sz && rule_pos) {
+    if (rule_pos > rule_map_sz) {
+      result.first = EINVAL;
+    }
+
+    result.second = rule_pos;
+  }
+
+  return result;
+}
+
+
 EOSMGMNAMESPACE_END
diff --git a/mgm/proc/user/AclCmd.hh b/mgm/proc/user/AclCmd.hh
index 0643f24a6bc49a0b2d3226712731da89f5d336b7..24fed5fcabe354117d17377d2ae49fc7f3e8a7b0 100644
--- a/mgm/proc/user/AclCmd.hh
+++ b/mgm/proc/user/AclCmd.hh
@@ -24,12 +24,85 @@
 #include "mgm/Namespace.hh"
 #include "mgm/proc/ProcCommand.hh"
 #include "proto/Acl.pb.h"
-#include <unordered_map>
+#include <list>
 
 EOSMGMNAMESPACE_BEGIN
 
 typedef std::pair<std::string, unsigned short> Rule;
-typedef std::unordered_map<std::string, unsigned short> RuleMap;
+//typedef std::unordered_map<std::string, unsigned short> RuleMap;
+// We use a list as we need to be able to insert at any position
+typedef std::list<Rule> RuleMap;
+
+template <typename C, typename K>
+typename C::iterator key_position(C& c, const K& k)
+{
+  return std::find_if(c.begin(),
+                      c.end(),
+                      [&k](const typename C::value_type& val)->bool {
+                        return k == val.first;
+                      });
+}
+
+template <typename C, typename K, typename V>
+void insert_or_assign(C& c, K&& k, V&& v)
+{
+  auto it = key_position(c,k);
+  if (it != c.end()) {
+    it->second = v;
+    return;
+  }
+  c.emplace_back(std::make_pair(std::forward<K>(k),
+                                std::forward<V>(v)));
+}
+
+template <typename C, typename K, typename V,
+          typename It = typename C::iterator>
+void insert_or_assign(C& c, K&& k, V&& v, It&& pos, bool move_existing=false)
+{
+  auto it = key_position(c,k);
+  if (it != c.end()) {
+    if (!move_existing || it == pos) {
+      it->second = v;
+      return;
+    }
+    // This function currently moves an existing key to a given position too, if
+    // this is not needed, we could skip the following erase! Since Iterator is at a
+    // different position, erase this, we'll readd the key back at the last step
+    auto next_it = c.erase(it);
+    // In case we're demoting an element the erase would've dropped an element
+    // so the index position should be incremented!
+    if (pos != c.end() &&
+        (std::distance(c.begin(), next_it) <= std::distance(c.begin(), pos))) {
+      ++pos;
+    }
+  }
+  c.insert(pos, std::make_pair(std::forward<K>(k),
+                               std::forward<V>(v)));
+}
+
+template <typename C>
+void insert_or_assign(C& c, typename C::value_type&& value)
+{
+  using first_type = typename C::value_type::first_type;
+  using second_type = typename C::value_type::second_type;
+  insert_or_assign(c,
+                   std::forward<first_type>(value.first),
+                   std::forward<second_type>(value.second));
+}
+
+template <typename C>
+std::pair<typename C::iterator, int>
+get_iterator(C& c, size_t pos)
+{
+  if (pos == 0 || pos > c.size()) {
+    return std::make_pair(c.end(),EINVAL);
+  }
+
+  auto it = c.begin();
+  std::advance(it, pos - 1);
+
+  return std::make_pair(it,0);
+}
 
 //------------------------------------------------------------------------------
 //! Class AclCmd - class handling acl command from a client
@@ -102,6 +175,16 @@ public:
   //----------------------------------------------------------------------------
   bool GetRuleBitmask(const std::string& input, bool set = false);
 
+  //----------------------------------------------------------------------------
+  //! Generate the position to place the rule
+  //!
+  //! @param input rule_map size of the current rule_map
+  //! @param input rule_pos position to be inserted
+  //!
+  //! @return a pair of error, insert position
+  //----------------------------------------------------------------------------
+  static std::pair<int, size_t> GetRulePosition(size_t rule_map_sz, size_t rule_pos);
+
   //----------------------------------------------------------------------------
   //! Return mAddRule result after GetRuleBitmask call.
   //----------------------------------------------------------------------------
@@ -184,7 +267,7 @@ private:
   //!
   //! @param rules map of acl rules for the current entry (directory)
   //----------------------------------------------------------------------------
-  void ApplyRule(RuleMap& rules);
+  void ApplyRule(RuleMap& rules, size_t pos=0);
 
   //----------------------------------------------------------------------------
   //! Convert ACL bitmask to string representation
diff --git a/proto/common/cli_proto/Acl.proto b/proto/common/cli_proto/Acl.proto
index bdba4d1a59c7687cb31be6af94a5cb1e76a2ac7e..1ca90262413bd7be9e5e7ac807b183bd8d17901d 100644
--- a/proto/common/cli_proto/Acl.proto
+++ b/proto/common/cli_proto/Acl.proto
@@ -13,4 +13,5 @@ message AclProto {
   bool sys_acl   = 3;
   string rule    = 5;
   string path    = 6;
+  uint32 position = 7;
 }
diff --git a/test/eos-grpc-test b/test/eos-grpc-test
index a220617e9f67adecc56ad80562fe43bf4a0b2792..7269e4a171e08bac6443c30d64ce912cf251b6be 100755
--- a/test/eos-grpc-test
+++ b/test/eos-grpc-test
@@ -105,8 +105,15 @@ eos-grpc-ns --token $authkey -p $prefix/t_grpc/file unlink || exit -10
 #acls
 eos-grpc-ns --token $authkey -p $prefix/t_grpc --sysacl --acl u:adm=rwx acl || exit -11
 eos-grpc-ns --token $authkey -p $prefix/t_grpc --acl u:nobody=rwx acl || exit -11
-eos-grpc-ns --token $authkey -p $prefix/t_grpc --sysacl acl || grep "u:adm=rwx" || exit -11
-eos-grpc-ns --token $authkey -p $prefix/t_grpc acl || grep "u:nobody:rwx" || exit -11
+eos-grpc-ns --token $authkey -p $prefix/t_grpc --sysacl acl | grep "u:adm:rwx" || exit -11
+eos-grpc-ns --token $authkey -p $prefix/t_grpc acl |  grep "u:nobody:rwx" || exit -11
+eos-grpc-ns --token $authkey -p $prefix/t_grpc --acl u:adm=rwx --front acl || exit -11
+eos-grpc-ns --token $authkey -p $prefix/t_grpc acl |  grep "\"rule\": \"u:adm:rwx," || exit -11
+eos-grpc-ns --token $authkey -p $prefix/t_grpc --acl u:nobody=r --position 2 acl || exit -11
+eos-grpc-ns --token $authkey -p $prefix/t_grpc acl |  grep "\"rule\": \"u:adm:rwx,u:nobody:r" || exit -11
+eos-grpc-ns --token $authkey -p $prefix/t_grpc --acl u:1003=r --position 5 acl | grep "position cannot be met"  || exit -11
+
+
 eos rmdir $prefix/t_grpc/
 
 #quota
diff --git a/unit_tests/mgm/AclCmdTests.cc b/unit_tests/mgm/AclCmdTests.cc
index 16fbc11eb8a346f507aa03264616d4e3a03104f1..56e90ff86e6bfd8730648ac9332105a53b2ac36c 100644
--- a/unit_tests/mgm/AclCmdTests.cc
+++ b/unit_tests/mgm/AclCmdTests.cc
@@ -24,11 +24,10 @@
 #include "gtest/gtest.h"
 #include "mgm/proc/user/AclCmd.hh"
 
-EOSMGMNAMESPACE_BEGIN
+using namespace eos::mgm;
 
 TEST(AclCmd, RuleMap)
 {
-  using namespace eos::mgm;
   RuleMap expect_map = {
     { "u:99", 0b011111111111}, { "u:0", 0b01010101010}
   };
@@ -36,10 +35,262 @@ TEST(AclCmd, RuleMap)
   const std::string acl = "u:99:rwxm!m!d+d!u+uqc,u:0:wm!d!uq";
   AclCmd::GenerateRuleMap(acl, result_map);
   ASSERT_EQ(result_map.size(), expect_map.size());
+  ASSERT_EQ(result_map, expect_map);
+}
+
+TEST(AclCmd, key_position)
+{
+  RuleMap input_map {
+    {"u:99", 0b011111111111},
+    {"u:1001",0b01},
+    {"g:123",0b101},
+    {"u:100",0b11}
+  };
+
+  auto begin_it = input_map.begin();
+  auto end_it = input_map.end();
+  EXPECT_EQ(key_position(input_map, "u:123"),end_it);
+  EXPECT_EQ(key_position(input_map, "g:123"),std::next(begin_it,2));
+}
+
+TEST(AclCmd, insert_or_assign_simple)
+{
+  RuleMap input_map {
+    {"u:99", 0b011111111111},
+    {"u:1001",0b01},
+    {"g:123",0b101},
+    {"u:100",0b11}
+  };
+
+  RuleMap expected_map {
+    {"u:99", 0b011111111111},
+    {"u:1001",0b01},
+    {"g:123",0b101},
+    {"u:100",0b11},
+    {"u:123",0b100}
+  };
+
+  insert_or_assign(input_map, "u:123", 0b100);
+  EXPECT_EQ(input_map, expected_map);
+
+  insert_or_assign(input_map, "u:1001", 0b1001);
+
+  expected_map = {{"u:99", 0b011111111111},
+                  {"u:1001",0b1001},
+                  {"g:123",0b101},
+                  {"u:100",0b11},
+                  {"u:123",0b100}
+  };
+
+  EXPECT_EQ(input_map, expected_map);
+
+  {
+    std::string key1 = "u:9001";
+    unsigned short i = 100;
+    insert_or_assign(input_map, key1, i);
+    // Check that the values haven't moved
+    std::string key2 = "u:9001";
+    EXPECT_EQ(key1,key2);
+    expected_map.emplace_back(key1,i);
+    EXPECT_EQ(input_map, expected_map);
+  }
+
+  {
+    std::string key1 = "u:9002";
+    unsigned short val = 101;
+    insert_or_assign(input_map, std::move(key1), std::move(val));
+    // key was moved
+    EXPECT_EQ(key1,std::string());
+    EXPECT_EQ(val, 101);
+
+    expected_map.emplace_back("u:9002",val);
+    EXPECT_EQ(input_map, expected_map);
+  }
+
+  {
+    std::string key1 = "u:9002";
+    unsigned short val = 102;
+    insert_or_assign(input_map, std::move(key1), std::move(val));
+    // key will not be moved as it already exists
+    EXPECT_EQ(key1, "u:9002");
+    EXPECT_EQ(val, 102);
+
+    // There is no easy way to do this than one of our functions again ;)
+    expected_map.pop_back();
+    expected_map.emplace_back(key1, val);
+    EXPECT_EQ(input_map, expected_map);
+  }
+}
+
+TEST(AclCmd, get_iterator)
+{
+  RuleMap input_map = {{"u:99", 0b011111111111},
+                        {"u:1001",0b1001},
+                        {"g:123",0b101},
+                        {"u:100",0b11},
+                        {"u:123",0b100}
+  };
+
+  {
+    auto [it, err] = get_iterator(input_map, 1);
+    EXPECT_EQ(it, input_map.begin());
+  }
+
+  {
+    auto [it, err] = get_iterator(input_map, 6);
+    EXPECT_EQ(err, EINVAL);
+  }
+
+  {
+    auto [it, err] = get_iterator(input_map, 5);
+    ASSERT_EQ(err, 0);
+    EXPECT_EQ(it->first,"u:123");
+  }
+}
+
+TEST(AclCmd, insert_or_assign_iter)
+{
+  RuleMap input_map = {{"u:99", 0b011111111111},
+                       {"u:1001",0b1001},
+                       {"g:123",0b101},
+                       {"u:100",0b11},
+                       {"u:123",0b100}
+  };
+
+  {
+    auto [it, _] = get_iterator(input_map, 1);
+    insert_or_assign(input_map, "u:9001",0b1010, it);
+
+    RuleMap expected_map = {{"u:9001",0b1010},
+                            {"u:99", 0b011111111111},
+                            {"u:1001",0b1001},
+                            {"g:123",0b101},
+                            {"u:100",0b11},
+                            {"u:123",0b100}
+    };
+
+    EXPECT_EQ(expected_map, input_map);
+  }
+
+  {
+    // No movement of keys as we dont override move_existing
+    auto [it, _] = get_iterator(input_map, 3);
+    insert_or_assign(input_map, "u:9001",0b1011, it);
+
+    RuleMap expected_map = {{"u:9001",0b1011},
+                            {"u:99", 0b011111111111},
+                            {"u:1001",0b1001},
+                            {"g:123",0b101},
+                            {"u:100",0b11},
+                            {"u:123",0b100}
+    };
+
+    EXPECT_EQ(expected_map, input_map);
+  }
+
+  {
+    // In this case we move the keys as we are passing true, so we're promoting
+    // this val up one place
+    auto [it, _] = get_iterator(input_map, 4);
+    insert_or_assign(input_map, "u:100",0b11011, it, true);
+
+    RuleMap expected_map = {{"u:9001",0b1011},
+                            {"u:99", 0b011111111111},
+                            {"u:1001",0b1001},
+                            {"u:100",0b11011},
+                            {"g:123",0b101},
+                            {"u:123",0b100}
+    };
+
+    EXPECT_EQ(expected_map, input_map);
+  }
+  {
+    // we are demoting an element
+    auto [it, _] = get_iterator(input_map, 5);
+    insert_or_assign(input_map, "u:99",0b11011, it, true);
+
+    RuleMap expected_map = {{"u:9001",0b1011},
+                            {"u:1001",0b1001},
+                            {"u:100",0b11011},
+                            {"g:123",0b101},
+                            {"u:99", 0b11011},
+                            {"u:123",0b100}
+    };
+
+    EXPECT_EQ(expected_map, input_map);
+
+  }
+  {
+    // we are demoting the first element to the last
+    auto [it, _] = get_iterator(input_map, 6);
+    insert_or_assign(input_map, "u:9001",0b10011, it, true);
+
+    RuleMap expected_map = {{"u:1001",0b1001},
+                            {"u:100",0b11011},
+                            {"g:123",0b101},
+                            {"u:99", 0b11011},
+                            {"u:123",0b100},
+                            {"u:9001",0b10011}
+    };
+
+    EXPECT_EQ(expected_map, input_map);
+
+  }
+
+  {
+    // we are demoting a middle element to the last
+    auto [it, _] = get_iterator(input_map, 6);
+    insert_or_assign(input_map, "u:99",0b11011, it, true);
+
+    RuleMap expected_map = {{"u:1001",0b1001},
+                            {"u:100",0b11011},
+                            {"g:123",0b101},
+                            {"u:123",0b100},
+                            {"u:9001",0b10011},
+                            {"u:99", 0b11011}
+    };
+
+    EXPECT_EQ(expected_map, input_map);
+
+  }
+
+  {
+    // we are demoting the penultimate element to the last
+    auto [it, _] = get_iterator(input_map, 6);
+    insert_or_assign(input_map, "u:9001",0b10011, it, true);
+
+    RuleMap expected_map = {{"u:1001",0b1001},
+                            {"u:100",0b11011},
+                            {"g:123",0b101},
+                            {"u:123",0b100},
+                            {"u:99", 0b11011},
+                            {"u:9001",0b10011}
+    };
+
+    EXPECT_EQ(expected_map, input_map);
 
-  for (auto const& elem : result_map) {
-    ASSERT_EQ(elem.second, expect_map[elem.first]);
   }
+
 }
 
-EOSMGMNAMESPACE_END
+TEST(AclCmd, GetRulePosition)
+{
+  // first arg rule_map_sz, second_arg position
+  EXPECT_EQ(AclCmd::GetRulePosition(0,0), std::pair(0,0UL));
+  EXPECT_EQ(AclCmd::GetRulePosition(0,1), std::pair(0,0UL));
+  EXPECT_EQ(AclCmd::GetRulePosition(0,2), std::pair(EINVAL,0UL));
+  //no position argument was passed, so position should be 0
+  // regardless of map size
+
+  EXPECT_EQ(AclCmd::GetRulePosition(1,0), std::pair(0,0UL));
+  EXPECT_EQ(AclCmd::GetRulePosition(10,0), std::pair(0,0UL));
+
+  // For all the cases where there are acls and we're within boundaries
+  // we should return the second arg
+  EXPECT_EQ(AclCmd::GetRulePosition(2,2), std::pair(0,2UL));
+  EXPECT_EQ(AclCmd::GetRulePosition(2,1), std::pair(0,1UL));
+  EXPECT_EQ(AclCmd::GetRulePosition(8,4), std::pair(0,4UL));
+
+  // except in case of error
+  EXPECT_EQ(AclCmd::GetRulePosition(2,3), std::pair(EINVAL,3UL));
+}