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

【安全】用户修改密码以及重置密码时密码需加密传输 #808

Closed
pagezz-canway opened this issue Nov 21, 2022 · 12 comments
Closed
Assignees
Labels
Layer: api Api module related
Milestone

Comments

@pagezz-canway
Copy link

pagezz-canway commented Nov 21, 2022

功能需求背景,例如你遇到了什么问题
用户修改密码和重置密码时,密码需要加密存储,不能明文传输

image

image

image

描述你觉得更好的解决方案

在前端传输密码字段时,使用RSA进行非对称加密,避免明文传输。

额外信息

测试版本:2.2.6(最新代码已确认,和该版本逻辑一样,同样存在问题)

@wklken
Copy link
Collaborator

wklken commented Nov 22, 2022

参考原先登录的处理方式

  • 渲染变量给前端, 包括是否加密/密钥(需要配置一个默认的)
  • 前端提交时直接将输入内容加密
  • 后台对应的slz解密(其他模块不需要处理)

  • 难易度: 简单
  • 工作量�: M
  • 需要前端配合

@neronkl
Copy link
Contributor

neronkl commented Nov 25, 2022

image

@Canway-shiisa
Copy link
Contributor

image

方案可以完善一些哩~ 除了流程图可以增加文字方案,包括实现思路及伪代码这样;避免后续的实现过程有过多拉扯,例如:
1.加密相关配置:在user_settings模块下新增 migration文件实现【这里具体实现比较简单,也可以忽略伪代码,就把思路这样写一下就可以】
2.password配置接口增加加密相关返回:对应的key是xxx。。。
3.加密逻辑部分:可以增加一些伪代码,包括标清楚会新增在哪个模块下等

@neronkl
Copy link
Contributor

neronkl commented Nov 25, 2022

数据插入:新增local目录类型的meta数据[enable_rsa_encrypted, rsa_public_key,rsa_private_key], 对已存local类型目录进行更新

  1. 点击重置密码,触发接口返回该目录下命名空间为password的配置(/api/v1/web/categories/{}/settings/namespaces/password/)
    该接口对应返回enable_rsa_encrypted(rsa启用状态)rsa_public_key(rsa公钥)
  2. 前端根据enable_rsa_encrypted 决定,是否对密码字段进行加密
  3. api端据enable_rsa_encrypted 决定,在对应的slz是否对密码字段进行解密
def validate_password(self, passowrd):
       if enable_rsa_encrypted:
              password = rsa_decrypt_password(password)
       return password

@wklken wklken added Layer: api Api module related todo 进入开发排期的状态,纳入了最近的迭代 labels Nov 28, 2022
@wklken wklken added this to the Y2022M48 milestone Nov 28, 2022
@nannan00
Copy link
Collaborator

默认enable_rsa_encrypted=False,如果企业需要,那再生成rsa_public_key和rsa_private_key配置

@wklken
Copy link
Collaborator

wklken commented Nov 28, 2022

通过环境变量注入, 数据初始化时对所有category.type=local的目录生效, 使用一致的配置? 无法做到目录差异化?
并且, 安全考虑每个环境的密钥需要有差异, 不能是一样的

两个问题:

  1. 存量环境并没有配置, 升级的时候也没有开启, 后来又需要了
  2. 开启后, 新增目录类型为local的, 如何初始化

本质上, 一旦放在namespace=password的配置中, 意味着是可以暴露到前端表单改的;

不默认初始化, 没有配置的目录就没有这几个配置; 只通过django command手工按照目录自行开启?

@neronkl
Copy link
Contributor

neronkl commented Nov 28, 2022

meta数据源初始化rsa系列字段,存量的目录以及新建的目录不进行rsa初始化。通过command对某个local目录启动rsa,并进行私钥以及密钥的导入形成差异。

class Command(BaseCommand):
    help = "enable category rsa"

    def add_arguments(self, parser):
        parser.add_argument("--category_id", type=str, help="目录ID")
        parser.add_argument("--private_key_file", type=str, help="rsa私钥文件目录")
        parser.add_argument("--public_key_file", type=str, help="rsa公钥文件目录")

    def handle(self, *args, **options):
        category_id = options.get("category_id")
        
        self.stdout.write(f"enable category rsa: category_id={str(category_id)}")
        
        if private_key and public_key:
        	# 获取meta数据
        	# 获取用户目录 = category_id, 判断是否local目录
        	# 新增该目录的usersetting设置:rsa配置
        
        else
        	self.stdout.write("Private key and public key is in need")

rsa启用,屏蔽私钥数据返回

@wklken
Copy link
Collaborator

wklken commented Nov 28, 2022

没啥问题了, 可以按照这个方案开发


@neronkl
Copy link
Contributor

neronkl commented Dec 2, 2022

新增接口通过token获取usersettings
api/v1/web/passwords/settings/namespaces/password/by_token/
(协议类比/api/v1/web/categories/{int:id}/settings/namespaces/{str:namespace}/)
前端通过token 获取相关的密码配置

@Canway-shiisa

@wklken
Copy link
Collaborator

wklken commented Dec 2, 2022

/api/v1/web/passwords/settings/by_token/
=> 只能拿到namespace=password的settings配置

@neronkl
Copy link
Contributor

neronkl commented Dec 2, 2022

api/v1/web/passwords/settings/namespaces/password/by_token/ => api/v1/web/passwords/settings/by_token/?token=
method: GET

输入序列化器

class PasswordSettingByTokenInputSLZ(serializers.Serializer):
    token = serializers.CharField(required=True, max_length=254)

视图类

classPasswordSettingsByTokenApi(generics.ListAPIView):
    serializer_class = CategorySettingOutputSLZ

    def get(self, request, *args, **kwargs):
          # 通过token 获取token_handler (ProfileTokenHolder)
         #  获取 namespace=password 的meta_key
         metas = list_setting_metas(category.type, None, PASSWORD_NAMESPACE) 
         #  Settings 获取相关配置
         settings = Settings.objects.filter(meta)
        return Repsonse(self.serializer_class(settings, many=True).data)

@wklken wklken modified the milestones: Y2022M48, Y2022M49 Dec 5, 2022
@wklken
Copy link
Collaborator

wklken commented Dec 5, 2022

#818

@wklken wklken mentioned this issue Dec 5, 2022
@Xmandon Xmandon modified the milestones: Y2022M49, Y2022M50 Dec 12, 2022
@wklken wklken closed this as completed Dec 14, 2022
yuri0528 added a commit to yuri0528/bk-user that referenced this issue Dec 16, 2022
yuri0528 added a commit to yuri0528/bk-user that referenced this issue Dec 16, 2022
EmilyMei pushed a commit that referenced this issue Dec 16, 2022
@nannan00 nannan00 removed the todo 进入开发排期的状态,纳入了最近的迭代 label Jul 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Layer: api Api module related
Projects
None yet
Development

No branches or pull requests

6 participants