본문 바로가기

MongoDB/R&D

MongoDB Authentication Mechanism

1. MongoDB Authentication Mechanism

MongoDB 는 Login 시에 authentication mechanism 을 사용하게 되어있다.
여러 Mechanism 들이 사용 가능하지만, 사용되는 방식은 "MONGODB-CR / SCRAM-SHA-1" 크게 두가지이다.

 

2.x 버전에서는 "MONGODB-CR" 이라는 Mechanism 이 사용되다가, 3.0 version 부터 "SCRAM-SHA-1" 이라는 새로운 Mechanism 이 차용되었다.

 

MongoDB 3.6 version 까지는 "MONGODB-CR" 방식과 "SCRAM-SHA-1" 방식이 모두 사용 가능하지만, MongoDB 4.0 version 부터는 "SCRAM-SHA- 256" 방식이 생기면서 동시에 "MONGODB-CR" 방식이 없어진다.

 

문제는 "MONGODB-CR" 방식을 사용하던 서버에서 MongoDB 의 버전을 업그레이드를 진행하더라도,

Authentication Mechanism 을 업그레이드하지않는 한 그대로 "MONGODB-CR" 방식을 사용하게 된다는 점이다.

 

이는 MongoDB 4.0 version 으로 업그레이드 시 문제가 될 소지가 있어 최소한 MongoDB 3.6 version 에서는 authentication mechanism 을 업그레이드 해야 한다.

 

 

2. Authentication Mechanism Downgrade / Upgrade

서버의 admin DB 의 system.version collection 을 확인해보면 해당 서버의 authSchema version 을 확인할 수 있다.

uzi01:PRIMARY (admin) 15:09:01> db.system.version.find()
...

{ "_id" : "authSchema", "currentVersion" : 5 }
...

 

Authentication Mechanism Upgrade 를 진행하기위해, currentVersion 의 수치를 낮춰보자. ※ 참고로 해당 설정은 "__sytem" 이라는 role 이 필요하다.

 

uzi01:PRIMARY (admin) 15:12:25> db.grantRolesToUser("dba", [{"role":"__system", "db":" admin"}])

uzi01:PRIMARY (admin) 15:13:48> use admin
switched to db admin

uzi01:PRIMARY (admin) 15:14:08> v1 = db.system.version.findOne
({"_id":"authSchema"}) { "_id" : "authSchema", "currentVersion" : 5 }

uzi01:PRIMARY (admin) 15:14:27> v1.currentVersion=3
3

uzi01:PRIMARY (admin) 15:14:34> db.system.version.save(v1)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

uzi01:PRIMARY (admin) 15:14:43> db.system.version.find({"_id":"authSchema"})
{ "_id" : "authSchema", "currentVersion" : 3 }

 

"MONGODB-CR" 을 사용하는 계정을 생성한다. currentVersion 을 "3" 으로 낮추었기때문에, 계정 생성 시 "MONGODB-CR" 을 사용하도록 만들어질 것이다.

 

 

 

uzi01:PRIMARY (admin) 15:19:48> db.createUser({user:"u1", pwd:"p1", roles:[{role:"readWrite", db:"d1"}]})
Successfully added user: { 

   "user":"u1",
   "roles":[ 

      { 

         "role":"readWrite",
         "db":"d1"

      }

   ]

}

uzi01:PRIMARY (admin) 15:19:49> db.system.users.find().pretty()

   "_id":"admin.dba",
   "user":"dba",
   "db":"admin",
   "credentials":{ 
      "SCRAM-SHA-1":{ 
         "iterationCount":10000,
         "salt":"NxULcugEmfPhwGCE6+U0eg==",
         "storedKey":"IOqrdo2DKO27FaW1y48WHbouUKw=",
         "serverKey":"s2qFxWFMbTBEIKvFRZRuKChw7CY="
      }
   },
   "roles":[ 
      { 
         "role":"readWrite",
         "db":"local"
      },
      { 
         "role":"__system",
         "db":"admin"
      },
      { 
         "db":"admin"
      }
   ]
}{ 
   "_id":"admin.u1",
   "user":"u1",
   "db":"admin",
   "credentials":{ 
      "MONGODB-CR":"49062bb3a44c80ba399ce1534aa845b1"
   },
   "roles":[ 
      { 
         "role":"readWrite",
         "db":"d1"
      }
   ]
}

 

currentVersion 이 "5" 였을 때 생성된 계정을 보면, credentials 의 필드가 "SCRAM-SHA-1" 으로 설정된 것을 볼 수 있다.

반면 currentVersion 을 "3" 으로 다운그레이드 후에 생성된 u1 계정을 보면, credentials 의 필드가 "MONGODB-CR" 로 생성되었다.

 

 

Upgrade 는 아래와 같은 커맨드로 실행이 가능하다.

uzi01:PRIMARY (admin) 15:20:12> db.adminCommand({authSchemaUpgrade:1})

   "done":true,
   "ok":1,
   "operationTime":Timestamp(1563258607,
   2),
   "$gleStats":{ 
      "lastOpTime":{ 
         "ts":Timestamp(1563258607,
         2),
         "t":NumberLong(1)
      },
      "electionId":ObjectId(      "7fffffff0000000000000001"      )
   },
   "$configServerState":{ 
      "opTime":{ 
         "ts":Timestamp(1563258606,
         3),
         "t":NumberLong(1)
      }
   },
   "$clusterTime":{ 
      "clusterTime":Timestamp(1563258607,
      2),
      "signature":{ 
         "hash":BinData(0,
         "AAAAAAAAAAAAAAAAAAAAAAAAAAA="         ),
         "keyId":NumberLong(0)
      }
   }
}



uzi01:PRIMARY (admin) 15:30:07> db.system.users.find().pretty() 
{
  "_id" : "admin.dba", 
  "user" : "dba",
  "db" : "admin", 
    "credentials" : {
      "SCRAM-SHA-1" : {
      "iterationCount" : 10000,
      "salt" : "NxULcugEmfPhwGCE6+U0eg==",
      "storedKey" : "IOqrdo2DKO27FaW1y48WHbouUKw=", "serverKey" : "s2qFxWFMbTBEIKvFRZRuKChw7CY="
    }
  },
  "roles" : [ 
    {
    "role" : "readWrite",
    "db" : "local" 
    },
    {
    "role" : "__system", "db" : "admin"
    "db" : "admin" 
    }
  ] 
}

{
  "_id": "admin.u1",
  "user": "u1",
  "db": "admin",
  "credentials": {
    "SCRAM-SHA-1": {
      "iterationCount": 10000,
      "salt": "aPT6rPu+jl1LMwC49fDE3A==",
      "storedKey": "r/PHFRoh4+miaz0+9LUbv3qTeJ8=",
      "serverKey": "LgHi8FB4zNUo/7QLYifDc3Hj1w4="
    }
  },
  "roles": [
    {
      "role": "readWrite",
      "db": "d1"
    }
  ]
}

업그레이드 후 "u1" 계정의 credentials 필드가 "SCRAM-SHA-1" 으로 변경된 것을 볼 수 있다.

 

3. Authentication Mechanism 에 따른 접속 가능 여부 테스트

"ROBO 3T" 라는 GUI Client Tool 에서는 접속 시에 mechanism 을 설정할 수 있다.

 

case 1. credentials 이 "MONGODB-CR" 일 경우

1) Auth Mechanism = MONGODB-CR

2) Auth Mechanism = SCRAM-SHA-1

credentials 의 필드가 "MONGODB-CR" 인 설정된 경우, Auth Mechanism 이 "MONGODB-CR", "SCRAM-SHA-1" 인 두 경우 모두 접속이 가능하다.

 

 

case 2. credentials 이 SCRAM-SHA-1 인 경우

1) Auth Mechanism = MONGODB-CR

 

2) Auth Mechanism = SCRAM-SHA-1

 

credentials 의 필드가 "SCRAM-SHA-1" 인 설정된 경우, Auth Mechanism 을 "MONGODB-CR" 으로 설정 시에는 인증에 실패하게 된다.

 

 

4. 결론

MongoDB 4.0 에서 "MONGODB-CR" 방식이 deprecated 됨에 따라,

최소 4.0 이전 버전 중 마지막 버전인 3.6 version 에서는 MONGODB-CR 방식을 제거하고 가야한다.

 

authSchema 의 version upgrade 는 어렵지않게 커맨드 한줄로 실행이 가능하다.

 

하지만 개발팀에서 auth mechanism 을 "MONGODB-CR" 로 설정해두고 사용하는 경우에는 서비스 장애가 불가피하다.

 

경험 상 보통은 해당 값을 null 로 사용해서 크게 문제가 될 것이라고 생각하지는 않지만, 확인해보는 것이 좋을 것 같다.

'MongoDB > R&D' 카테고리의 다른 글

MongoDB Replica Set Protocol Version (PV)  (0) 2020.02.12
MongoDB Plan Cache  (3) 2020.01.29
MongoDB Query Execution Plan  (1) 2020.01.29