• OPAGatekeeper实验:对特定用户的更新时间窗口做限制


    实验目的

    OPA-Gatekeeper可以在Kubernetes 中,通过策略来实现一些额外的管理、安全方面的限制,例如:限制特定用户在 Namespace 中的行为权限

    本次实验将在test命名空间内对开发人员的更新操作提供时间窗口限制

    说明:
    在自建的k8s集群实验成功。
    在rancher2.4.4中创建失败,原因是rego语法解析错误,已经提交到官方论坛,尚未解决。

    实现思路

    为了方便管理,开发人员将使用统一用户deploy,
    然后在k8s中添加基于角色的访问控制(RBAC),即使用role和rolebinding,限制deploy在test命名空间内的资源权限。
    最后使用gatekeeper做时间窗口限制。

    Namespace role user
    test manager deploy

    实现步骤

    1 创建用户

    1. 创建私钥
    openssl genrsa -out deploy.key 2048
    
    1. 创建csr(证书签名请求)文件
    openssl req -new -key deploy.key -out deploy.csr -subj "/CN=deploy/O=MGM"
    
    1. 通过集群的CA证书和deploy的csr文件,来为deploy颁发证书

    我的CA证书是在/etc/kubernetes/pki/目录下

    openssl x509 -req -in deploy.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out deploy.crt -days 3650
    
    1. 为用户配置credentials认证环境和context上下文环境
    kubectl config set-credentials deploy --client-certificate=deploy.crt --client-key=deploy.key
    kubectl config get-users
    
    kubectl config set-context deploy --cluster=kubernetes --namespace=test --user=deploy
    kubectl config get-contexts
    
    1. 测试切换用户环境
    kubectl config use-context deploy
    kubectl config use-context kubernetes-admin@kubernetes
    

    2 创建角色

    在RBAC中,角色有两种——普通角色(Role)和集群角色(ClusterRole),ClusterRole是特殊的Role:

    • Role属于某个命名空间,而ClusterRole属于整个集群,其中包括所有的命名空间
    • ClusterRole能够授予集群范围的权限,比如node资源的管理,比如非资源类型的接口请求(如"/health"),比如可以请求全命名空间的资源(通过指定 --all-namespaces)

    这里要在test命名空间内创建一个权限小的普通角色

    kind: Role
    metadata:
      namespace: test
      name: manager
    rules:
    - apiGroups: ["apps"]
      resources: ["*"]
      verbs: ["*"]
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["*"]
    
    kubectl apply -f role.yaml
    kubectl get role -n test
    

    以上涉及的api资源查看方式:

    kubectl api-resources|grep "apps/v1"
    kubectl api-resources|grep " v1"
    

    3 将前面的角色和用户绑定

    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: manager-binding
      namespace: test
    subjects:
    - kind: User
      name: deploy
    roleRef:
      kind: Role
      name: manager
      apiGroup: "rbac.authorization.k8s.io"
    
    kubectl apply -f Rolebinding.yaml
    kubectl get rolebinding -n test
    

    测试deploy用户创建pod

    kubectl get pods -n test  --context=deploy
    kubectl run nginx --image=nginx:latest -n default  --context=deploy
    kubectl run nginx --image=nginx:latest -n test  --context=deploy
    

    4 安装gatekeeper

    wget https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
    kubectl apply -f gatekeeper.yaml
    

    检查

    kubectl get ConstraintTemplate #等待出现 No resources found 才表示成功
    kubectl get crd #CustomResourceDefinitions #只有当AGE不为<Invalid>而是一个时间时,才表示这个资源对象可用
    

    5 ConstraintTemplate 约束模板

    在定义约束之前,必须先定义一个 ConstraintTemplate (相当于创造了自定义的api-resources类型)
    它主要内容描述的是 执行约束的Rego语句 和 约束的模式。

    约束的模式允许admin对约束行为进行微调,就像对一个函数传参。

    spec由两部分组成:
    - crd:CustomResourceDefinition 自定义资源
    - targets:一组target,是以 rego 代码块为主体

    模板参考

    以下模板提供了时间窗口限制(每周一、三,晚23:30至次日06:00)

    apiVersion: templates.gatekeeper.sh/v1beta1
    kind: ConstraintTemplate
    metadata:
      name: updatelimits
    spec:
      crd:
        spec:
          names:
            kind: UpdateLimits
      targets:
        - target: admission.k8s.gatekeeper.sh
          rego: |
            package updatelimit
    
           ###TIME check
            nanosec := time.now_ns()
            wday := time.weekday(nanosec)
            dhour :=time.clock(nanosec)[0]
            dmin :=time.clock(nanosec)[1]
    
           ###userAuth Check
           #ns := input.review.object.metadata.namespace
            uname := input.review.userInfo.username
    
    
            # 23:30至次日06:00,要考虑 k8s 的8h时差
            timeOK {
              dhour==15
              dmin>=30
            }
            timeOK {
              dhour>15
              dhour<22
            }
            weekdayOK{
              wday == "Wednesday"
            }
            weekdayOK{
              wday == "Monday"
            }
    
            #三种不同情况下的限制提示
    
            violation[{"msg": msgX}] {
              uname != "deploy"
              msgX = "\n>>>>>>>>>>>>>>>>>>>>>>>>>> Changes are only allowed for USER [deploy].\n"
            }
    
            violation[{"msg": msgX}] {
              uname == "deploy"
              not weekdayOK
              msgX = "\n%%%%%%%%%%%%%%%%%%%%%%%%%% Changes are only allowed on [Monday] or [Wednesday].\n"
            }
    
            violation[{"msg": msgX}] {
              uname == "deploy"
              weekdayOK
              not timeOK
              msgX = "\n************************** Changes are only allowed in [23:30-06:00].\n"
            }
    
    # kubectl apply -f constrainttemplateV1Beta1.yaml
    # kubectl get ConstraintTemplate
    # kubectl api-resources |grep gatekeeper
    NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
    updatelimits                                   constraints.gatekeeper.sh/v1beta1      false        UpdateLimits
    

    注意项

    1. spec.crd.spec.names.kind 小写后必须和 metadata.name 一致
    2. violation返回值是一个结构体切片:[{"msg": STRING}]
    violation[{"msg": message}] {
    	message := ""
    }
    

    6 Constraint 约束条件

    知识介绍(可以略过)

    Constraint负责通知Gatekeeper,admin想要一个什么样的template
    Constraint使用 K8sRequiredLabels 来约束上文中的模版,以便于确保 gatekeeper 标签被定义到所有namespace上
    可认为是对某一个 ConstraintTemplate 的实例化,其中对 ConstraintTemplate 的未指定参数进行了具体的配置。

    注意spec.match字段,它定义了 一个指定的约束 将要被应用到的 目标的范围
    Note the match field, which defines the scope of objects to which a given constraint will be applied.

    支持的匹配项目:

    • kinds:接受一个对象列表,包含 apiGroups和 kinds,用来指定 约束将应用到的 对象组/种类的字段。如果指定了多个对象,只要满足其中一个就会被匹配
      only one match is needed for the resource to be in scope.
    • 目标范围:允许 * ,Cluster 或者 Namespaced

    此外还有:

    • namespaces:指定ns列表
    • excludedNamespaces:指定ns排除列表
    • labelSelector
    • namespaceSelector

    注意:
    如果定义了多个matcher,则匹配资源必须满足所有顶级matcher
    空matcher匹配所有
    namespaces, excludedNamespaces, 和 namespaceSelector 将会匹配上没有ns所属的资源,为了避免这种情况,注意指定Namespace范围。

    约束参考

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: UpdateLimits
    metadata:
      name: updatelimit-for-test
    spec:
      match:
        namespaces: ["test"]
        kinds:
        - apiGroups: ["apps"]
          kinds:
          - "Deployment"
          - "DaemonSet"
          - "StatefulSet"
    

    部署

    kubectl apply -f ConstraintV1Beta1.yaml
    kubectl get constraint
    

    测试

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      creationTimestamp: null
      name: nginx
      namespace: depl
    spec:
      replicas: 0
      selector:
        matchLabels:
          io/os: linux
      template:
        metadata:
          labels:
            io/os: linux
        spec:
          containers:
          - image: nginx:latest
            name: nginx
    

    shell脚本:

    #!/bin/sh
    deployFile=nginx-deployment.yaml
    echo
    echo
    echo
    kubectl config use-context deploy
    kubectl apply -f ${deployFile} -n depl &&  kubectl delete -f ${deployFile} -n depl
    echo -e "\n\n\n"
    kubectl config use-context kubernetes-admin@kubernetes
    

    实验结果:

    root@master:~/OPAtest/MyTest# ./test.sh
    
    Switched to context "deploy".
    Error from server ([updatelimit-for-depl]
    %%%%%%%%%%%%%%%%%%%%%%%%%% Changes are only allowed on [Monday] or [Wednesday].
    ): error when creating "nginx-deployment.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [updatelimit-for-depl]
    %%%%%%%%%%%%%%%%%%%%%%%%%% Changes are only allowed on [Monday] or [Wednesday].
    
    
    

    参考资料:

    1. 用户与角色绑定:https://zhuanlan.zhihu.com/p/43237959
    2. Input对象:https://www.openpolicyagent.org/docs/latest/kubernetes-primer/#input-document
    3. 时间函数:https://www.openpolicyagent.org/docs/latest/policy-reference/#time
    4. rego实验室:https://play.openpolicyagent.org/
    ================# 水平有限 欢迎留言 批评指正 #=================
  • 相关阅读:
    memcached 高级机制(一)
    memcached 简介
    Hibernate
    Linux中的搜索命令
    Linux的常用命令
    Git清除用户名和密码
    关于Git的简单使用
    文件的上传与下载(2)
    关于文件的上传和后台接收
    验证码的制作
  • 原文地址:https://www.cnblogs.com/max27149/p/15573697.html
Copyright © 2020-2023  润新知