Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

升级到v1.8.0后mongodb无法连接实例 #952

Closed
solon-liu opened this issue Nov 2, 2020 · 26 comments
Closed

升级到v1.8.0后mongodb无法连接实例 #952

solon-liu opened this issue Nov 2, 2020 · 26 comments
Labels
question Further information is requested wontfix This will not be worked on

Comments

@solon-liu
Copy link

之前的mongodb实例在v1.7.13版本上连接正常,升级到v1.8.0之后连接报错无法连接实例,Authentication failed。但是数据库密码和页面密码配置都没有改过。
image

@solon-liu solon-liu added the question Further information is requested label Nov 2, 2020
@solon-liu
Copy link
Author

回退到v1.7.13版本后,实例连接正常,其他未做修改。
docker部署。

@LeoQuote
Copy link
Collaborator

LeoQuote commented Nov 2, 2020

感谢反馈, 1.8.0 有一个 pr 是关于 mongodb 的, 可能和这个相关 #900 后续我们再看看能不能复现解决.

@solon-liu
Copy link
Author

image
这一段代码没有获取到数据库列表,返回的值是捕获的异常

@solon-liu
Copy link
Author

就是在SQL查询,在线查询菜单里,mongodb选择实例后,获取到的数据库列表也有问题

@solon-liu
Copy link
Author

比如我的这个实例下创建的用户,只需要部分数据库的权限,用list_database_names()需要访问所有实例的数据库权限?

@LeoQuote
Copy link
Collaborator

LeoQuote commented Nov 4, 2020

self.db_name = 'admin'

这一行删掉看看

@solon-liu
Copy link
Author

这里面其实提了2个问题。
第一个是在添加实例的时候,即使配置了数据库,验证数据库写死了admin,也就是你上面给出的代码。
第二个是在上线和查询模块,选择实例之后,mongodb显示数据库列表(list_database_names())需要访问所有库的权限(至少为读),并显示所有数据库。是否考虑跟mysql类似的处理,用数据库登录账号的权限来显示数据库列表,即满足在一个实例下只显示出部分有权限访问的数据库。

@hhyo
Copy link
Owner

hhyo commented Nov 5, 2020

@fancy-lee 辛苦关注一下mongo相关的内容,看基于目前直接使用client的方案,是否有支持非admin认证的可能

@fancy-lee
Copy link
Contributor

这里面其实提了2个问题。
第一个是在添加实例的时候,即使配置了数据库,验证数据库写死了admin,也就是你上面给出的代码。
第二个是在上线和查询模块,选择实例之后,mongodb显示数据库列表(list_database_names())需要访问所有库的权限(至少为读),并显示所有数据库。是否考虑跟mysql类似的处理,用数据库登录账号的权限来显示数据库列表,即满足在一个实例下只显示出部分有权限访问的数据库。

你们会把一个实例,切分成多个账号,然后在archery上配置成多个实例吗?

@fancy-lee
Copy link
Contributor

在配置增加实例的时候,没有地方指定认证库,如果不写死的话,测试连接的时候应该也会报错

@solon-liu
Copy link
Author

这里面其实提了2个问题。
第一个是在添加实例的时候,即使配置了数据库,验证数据库写死了admin,也就是你上面给出的代码。
第二个是在上线和查询模块,选择实例之后,mongodb显示数据库列表(list_database_names())需要访问所有库的权限(至少为读),并显示所有数据库。是否考虑跟mysql类似的处理,用数据库登录账号的权限来显示数据库列表,即满足在一个实例下只显示出部分有权限访问的数据库。

你们会把一个实例,切分成多个账号,然后在archery上配置成多个实例吗?

的确是这样的

@solon-liu
Copy link
Author

在配置增加实例的时候,没有地方指定认证库,如果不写死的话,测试连接的时候应该也会报错

image
我们以为这个是验证数据库

@fancy-lee
Copy link
Contributor

这里面其实提了2个问题。
第一个是在添加实例的时候,即使配置了数据库,验证数据库写死了admin,也就是你上面给出的代码。
第二个是在上线和查询模块,选择实例之后,mongodb显示数据库列表(list_database_names())需要访问所有库的权限(至少为读),并显示所有数据库。是否考虑跟mysql类似的处理,用数据库登录账号的权限来显示数据库列表,即满足在一个实例下只显示出部分有权限访问的数据库。

你们会把一个实例,切分成多个账号,然后在archery上配置成多个实例吗?

在配置增加实例的时候,没有地方指定认证库,如果不写死的话,测试连接的时候应该也会报错

image
我们以为这个是验证数据库
我刚才看了一下demo,确实有这个数据库的选项,我用的是1.7.3旧的版本还没有这个,如果是这样的话,我看能不能修改一下代码逻辑

@fancy-lee
Copy link
Contributor

在配置增加实例的时候,没有地方指定认证库,如果不写死的话,测试连接的时候应该也会报错

image
我们以为这个是验证数据库

还有一个问题就是:如果你配置的这个账号没有执行修改权限,然后在这个实例上提交修改会报错,这个你怎么来控制呢?查询和提交各配置一个账号和一实例名?

@solon-liu
Copy link
Author

在配置增加实例的时候,没有地方指定认证库,如果不写死的话,测试连接的时候应该也会报错

image
我们以为这个是验证数据库

执行修改权限

use admin
db.createUser({user: "testuser", pwd: "1234", roles: [{ role: "dbOwner", db: "industry_bd" },{ role: "dbOwner", db: "spiderOrion" },{ role: "readAnyDatabase", db: "admin" }]})
比如这个用户testuser,在admin下面验证。但是读写权限在industry_bd和spiderOrion都有,同时这个实例还有其他数据库,且不想让用户看到。现在没办法,只有把readAnyDatabase权限也给出去。

@fancy-lee
Copy link
Contributor

fancy-lee commented Nov 5, 2020

在配置增加实例的时候,没有地方指定认证库,如果不写死的话,测试连接的时候应该也会报错

image
我们以为这个是验证数据库

还有一个问题就是:如果你配置的这个账号没有执行修改权限,然后在这个实例上提交修改会报错,这个你怎么来控制呢?查询和提交各配置一个账号和一实例名?

在配置增加实例的时候,没有地方指定认证库,如果不写死的话,测试连接的时候应该也会报错

image
我们以为这个是验证数据库

执行修改权限

use admin
db.createUser({user: "testuser", pwd: "1234", roles: [{ role: "dbOwner", db: "industry_bd" },{ role: "dbOwner", db: "spiderOrion" },{ role: "readAnyDatabase", db: "admin" }]})
比如这个用户testuser,在admin下面验证。但是读写权限在industry_bd和spiderOrion都有,同时这个实例还有其他数据库,且不想让用户看到。现在没办法,只有把readAnyDatabase权限也给出去。

1.请你把这个mongo.py文件方法对比修改一下

def exec_cmd(self, sql, db_name=None, slave_ok=''):
    """审核时执行的语句"""

    if self.user and self.password and self.port and self.host:
        msg = ""
        auth_db = self.instance.db_name or 'admin'
        try:
            if not sql.startswith('var host='): #在master节点执行的情况
                cmd = "{mongo} --quiet -u {uname} -p '{password}' {host}:{port}/{auth_db} <<\\EOF\ndb=db.getSiblingDB(\"{db_name}\");{slave_ok}printjson({sql})\nEOF".format(
                    mongo=mongo, uname=self.user, password=self.password, host=self.host, port=self.port, db_name=db_name, sql=sql, auth_db=auth_db, slave_ok=slave_ok)
            else:
                cmd = "{mongo} --quiet -u {user} -p '{password}' {host}:{port}/{auth_db} <<\\EOF\nrs.slaveOk();{sql}\nEOF".format(
                    mongo=mongo, user=self.user, password=self.password, host=self.host, port=self.port, db_name=db_name, sql=sql, auth_db=auth_db)
            logger.debug(cmd)
            p = subprocess.Popen(cmd, shell=True,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 universal_newlines=True)
            re_msg = []
            for line in iter(p.stdout.read, ''):
                re_msg.append(line)
            msg = '\n'.join(re_msg)
        except Exception as e:
            logger.warning(f"mongo语句执行报错,语句:{sql},{e}错误信息{traceback.format_exc()}")
    return msg

2.然后把get_connection()中的self.db_name = "admin"删除
self.db_name = db_name or 'admin' 修改为
self.db_name = db_name or self.instance.db_name

@fancy-lee
Copy link
Contributor

辛苦关注一下mongo相关的内容,看

代码我已经修改了,在最后的回复中贴出来了,请辛苦提交一下pr

@solon-liu
Copy link
Author

辛苦了,非常感谢。
第二个是在上线和查询模块,选择实例之后,mongodb显示数据库列表(list_database_names())需要访问所有库的权限(至少为读),并显示所有数据库。是否考虑跟mysql类似的处理,用数据库登录账号的权限来显示数据库列表,即满足在一个实例下只显示出部分有权限访问的数据库。
这个需求有考虑吗~

@fancy-lee
Copy link
Contributor

辛苦了,非常感谢。
第二个是在上线和查询模块,选择实例之后,mongodb显示数据库列表(list_database_names())需要访问所有库的权限(至少为读),并显示所有数据库。是否考虑跟mysql类似的处理,用数据库登录账号的权限来显示数据库列表,即满足在一个实例下只显示出部分有权限访问的数据库。
这个需求有考虑吗~

请问mongodb普通用户怎么查看用户权限和角色?

@solon-liu
Copy link
Author

进入当前数据库
show users命令可以查看查看当前数据库下验证的用户信息
rs3:PRIMARY> show users;
{
"_id" : "industry_bd.testuser",
"userId" : UUID("5ce4da7e-0e7f-4342-9ba4-3be29f07aee9"),
"user" : "testuser",
"db" : "industry_bd",
"roles" : [
{
"role" : "dbOwner",
"db" : "industry_bd"
}
]
}

查询admin下的system.users,查看所有用户信息
use admin
db.system.users.find()
这个好像需要很高的权限,我是用的root?

@fancy-lee
Copy link
Contributor

进入当前数据库
show users命令可以查看查看当前数据库下验证的用户信息
rs3:PRIMARY> show users;
{
"_id" : "industry_bd.testuser",
"userId" : UUID("5ce4da7e-0e7f-4342-9ba4-3be29f07aee9"),
"user" : "testuser",
"db" : "industry_bd",
"roles" : [
{
"role" : "dbOwner",
"db" : "industry_bd"
}
]
}

查询admin下的system.users,查看所有用户信息
use admin
db.system.users.find()
这个好像需要很高的权限,我是用的root?

你用普通用户试试

@solon-liu
Copy link
Author

solon-liu commented Nov 5, 2020

比如我要创建一个用户testuser,对industry_bd1和industry_bd2有操作权限,在admin库验证,那在验证库至少有userAdmin的权限,也可以在其他库验证。
use admin
db.createUser({user: "testuser", pwd: "123456", roles: [{ role: "dbOwner", db: "industry_bd1" },{ role: "dbOwner", db: "industry_bd2" },{ role: "userAdmin", db: "admin" }]})
执行show users命令可以获取到该验证库下所有用户的角色和权限:
rs3:PRIMARY> use admin;
switched to db admin
rs3:PRIMARY> show users;
{
"_id" : "admin.testuser",
"userId" : UUID("f9a42df4-97de-4173-9bd6-a48b6983f667"),
"user" : "testuser",
"db" : "admin",
"roles" : [
{
"role" : "dbOwner",
"db" : "industry_bd1"
},
{
"role" : "dbOwner",
"db" : "industry_bd2"
},
{
"role" : "userAdmin",
"db" : "admin"
}
]
}
这个testuser算普通用户吧

@fancy-lee
Copy link
Contributor

比如我要创建一个用户testuser,对industry_bd1和industry_bd2有操作权限,在admin库验证,那在验证库至少有userAdmin的权限,也可以在其他库验证。
use admin
db.createUser({user: "testuser", pwd: "123456", roles: [{ role: "dbOwner", db: "industry_bd1" },{ role: "dbOwner", db: "industry_bd2" },{ role: "userAdmin", db: "admin" }]})
执行show users命令可以获取到该验证库下所有用户的角色和权限:
rs3:PRIMARY> use admin;
switched to db admin
rs3:PRIMARY> show users;
{
"_id" : "admin.testuser",
"userId" : UUID("f9a42df4-97de-4173-9bd6-a48b6983f667"),
"user" : "testuser",
"db" : "admin",
"roles" : [
{
"role" : "dbOwner",
"db" : "industry_bd1"
},
{
"role" : "dbOwner",
"db" : "industry_bd2"
},
{
"role" : "userAdmin",
"db" : "admin"
}
]
}
这个testuser算普通用户吧

要配置userAdmin的用户,我理解的普通用户就是像mysql一样只有curd权限的用户,我觉得你这个需求有点特殊,辛苦你自己在list_database_names()修改一下,或者为每个db to user创建对应实例来满足你说的需求

@solon-liu
Copy link
Author

好的,谢谢。辛苦了~

@stale
Copy link

stale bot commented Nov 21, 2020

你已经很久没有回复这个issue了,如果没有进一步的信息的话, 会作为不活跃issue关闭, 感谢你对本项目的贡献。
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix This will not be worked on label Nov 21, 2020
@stale stale bot closed this as completed Nov 24, 2020
@doing-cr7
Copy link

在配置增加实例的时候,没有地方指定认证库,如果不写死的话,测试连接的时候应该也会报错

image
我们以为这个是验证数据库

还有一个问题就是:如果你配置的这个账号没有执行修改权限,然后在这个实例上提交修改会报错,这个你怎么来控制呢?查询和提交各配置一个账号和一实例名?

在配置增加实例的时候,没有地方指定认证库,如果不写死的话,测试连接的时候应该也会报错

image
我们以为这个是验证数据库

执行修改权限

use admin
db.createUser({user: "testuser", pwd: "1234", roles: [{ role: "dbOwner", db: "industry_bd" },{ role: "dbOwner", db: "spiderOrion" },{ role: "readAnyDatabase", db: "admin" }]})
比如这个用户testuser,在admin下面验证。但是读写权限在industry_bd和spiderOrion都有,同时这个实例还有其他数据库,且不想让用户看到。现在没办法,只有把readAnyDatabase权限也给出去。

1.请你把这个mongo.py文件方法对比修改一下

def exec_cmd(self, sql, db_name=None, slave_ok=''):
    """审核时执行的语句"""

    if self.user and self.password and self.port and self.host:
        msg = ""
        auth_db = self.instance.db_name or 'admin'
        try:
            if not sql.startswith('var host='): #在master节点执行的情况
                cmd = "{mongo} --quiet -u {uname} -p '{password}' {host}:{port}/{auth_db} <<\\EOF\ndb=db.getSiblingDB(\"{db_name}\");{slave_ok}printjson({sql})\nEOF".format(
                    mongo=mongo, uname=self.user, password=self.password, host=self.host, port=self.port, db_name=db_name, sql=sql, auth_db=auth_db, slave_ok=slave_ok)
            else:
                cmd = "{mongo} --quiet -u {user} -p '{password}' {host}:{port}/{auth_db} <<\\EOF\nrs.slaveOk();{sql}\nEOF".format(
                    mongo=mongo, user=self.user, password=self.password, host=self.host, port=self.port, db_name=db_name, sql=sql, auth_db=auth_db)
            logger.debug(cmd)
            p = subprocess.Popen(cmd, shell=True,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 universal_newlines=True)
            re_msg = []
            for line in iter(p.stdout.read, ''):
                re_msg.append(line)
            msg = '\n'.join(re_msg)
        except Exception as e:
            logger.warning(f"mongo语句执行报错,语句:{sql},{e}错误信息{traceback.format_exc()}")
    return msg

2.然后把get_connection()中的self.db_name = "admin"删除
self.db_name = db_name or 'admin' 修改为
self.db_name = db_name or self.instance.db_name

解决了我的问题 太棒了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

5 participants