kubernetes 代理_使用开放策略代理在Kubernetes上保护您的服务

本文介绍如何在Kubernetes中使用Open Policy Agent(OPA)作为准入控制器,以实现策略的自动化、测试和重用。OPA作为一种开源策略引擎,能统一跨不同系统的策略实施,确保容器镜像仅来自企业镜像仓库,防止冲突的Ingress对象创建,及非root用户的策略执行。

kubernetes 代理

In this article, I will introduce the Open Policy Agent, Kubernetes Admission Controller, and how to apply a policy, with step-by-step guidelines.

在本文中,我将逐步介绍开放策略代理,Kubernetes准入控制器以及如何应用策略。

什么是开放策略代理(OPA)? (What Is Open Policy Agent (OPA)?)

The Open Policy Agent (OPA) is an open-source policy engine that decouples policy decision-making from service. It enables Policy as Code, which allows the policy to be automated, tested, and reused with version control. It can unify policy enforcement across different systems for proper management and review, for example, Linux, Kubernetes, CI/CD pipelines, API gateway, application, etc.

开放策略代理(OPA)是一种开放源代码策略引擎,可将策略决策与服务脱钩。 它启用“策略即代码”功能,从而可以通过版本控制将策略自动化,测试和重用。 它可以统一跨不同系统的策略实施以进行适当的管理和检查,例如Linux,Kubernetes,CI / CD管道,API网关,应用程序等。

Open Policy Agent can be deployed as an admission controller in Kubernetes. You can customize your own policy as code via Rego language and enforce policies in Kubernetes for security, cost, and management consideration.

可以在Kubernetes中将开放策略代理部署为准入控制器。 您可以通过Rego语言将自己的策略自定义为代码,并出于安全性,成本和管理考虑,在Kubernetes中实施策略。

You can learn more about Open Policy Agent at https://www.openpolicyagent.org/.

您可以在https://www.openpolicyagent.org/上了解有关Open Policy Agent的更多信息。

Kubernetes准入控制器 (Kubernetes Admission Controllers)

Kubernetes admission controllers enforce policies on objects during create, update, and delete operations. They intercept requests to the Kubernetes API server after the request is authenticated and authorized and before it happens and is stored in configuration.

Kubernetes准入控制器在创建,更新和删除操作期间对对象执行策略。 在对请求进行身份验证和授权之后,在请求发生并存储在配置中之前,它们拦截对Kubernetes API服务器的请求。

Deploying OPA as an admission controller in Kubernetes allows the requirement that container images come only from the corporate image registry, preventing conflicting Ingress objects from being created, enforcing policies for a non-root user, etc.

在Kubernetes中将OPA部署为准入控制器可以满足以下要求:容器映像仅来自公司映像注册表,防止创建冲突的Ingress对象,为非root用户强制执行策略等。

You can learn more about Kubernetes admission controllers and policies at https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/.

您可以在https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/上了解有关Kubernetes准入控制器和策略的更多信息。

开放式策略代理安装 (Open Policy Agent Installation)

先决条件 (Prerequisites)

Kubernetes cluster is up and running.

Kubernetes集群已启动并正在运行。

部署OPA (Deploy OPA)

Run the below command to create the OPA certificate authority and key pair.

运行以下命令以创建OPA证书颁发机构和密钥对。

openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -days 100000 -out ca.crt -subj "/CN=admission_ca"cat >server.conf <<EOF
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
EOFopenssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=opa.opa.svc" -config server.conf
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 100000 -extensions v3_req -extfile server.conf

Then, create a secret in Kubernetes to store OPA TLS credentials.

然后,在Kubernetes中创建一个秘密来存储OPA TLS凭据。

kubectl create secret tls opa-server --cert=server.crt --key=server.key

Create a namespace for OPA called “opa.”

为OPA创建一个名为“ opa”的命名空间。

kubectl create namespace opa

Deploy the below yaml file for installation.

部署以下yaml文件进行安装。

cat << EOF | kubectl apply -f -
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: opa-viewer
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
  name: system:serviceaccounts:opa
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: opa
  name: configmap-modifier
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: opa
  name: opa-configmap-modifier
roleRef:
  kind: Role
  name: configmap-modifier
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
  name: system:serviceaccounts:opa
  apiGroup: rbac.authorization.k8s.io
---
kind: Service
apiVersion: v1
metadata:
  name: opa
  namespace: opa
spec:
  selector:
    app: opa
  ports:
  - name: https
    protocol: TCP
    port: 443
    targetPort: 443
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: opa
  namespace: opa
  name: opa
spec:
  replicas: 1
  selector:
    matchLabels:
      app: opa
  template:
    metadata:
      labels:
        app: opa
      name: opa
    spec:
      containers:
        - name: opa
          image: openpolicyagent/opa:latest
          args:
            - "run"
            - "--server"
            - "--tls-cert-file=/certs/tls.crt"
            - "--tls-private-key-file=/certs/tls.key"
            - "--addr=0.0.0.0:443"
            - "--addr=http://127.0.0.1:8181"
            - "--log-format=json-pretty"
            - "--set=decision_logs.console=true"
          volumeMounts:
            - readOnly: true
              mountPath: /certs
              name: opa-server
          readinessProbe:
            httpGet:
              path: /health?plugins&bundle
              scheme: HTTPS
              port: 443
            initialDelaySeconds: 3
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              scheme: HTTPS
              port: 443
            initialDelaySeconds: 3
            periodSeconds: 5
        - name: kube-mgmt
          image: openpolicyagent/kube-mgmt:0.11
          args:
            - "--replicate-cluster=v1/namespaces"
            - "--replicate=extensions/v1beta1/ingresses"
      volumes:
        - name: opa-server
          secret:
            secretName: opa-server
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: opa-default-system-main
  namespace: opa
data:
  main: |
    package system

    import data.kubernetes.admission

    main = {
      "apiVersion": "admission.k8s.io/v1beta1",
      "kind": "AdmissionReview",
      "response": response,
    }

    default uid = ""

    uid = input.request.uid

    response = {
        "allowed": false,
        "uid": uid,
        "status": {
            "reason": reason,
        },
    } {
        reason = concat(", ", admission.deny)
        reason != ""
    }
    else = {"allowed": true, "uid": uid}
EOF

Check your OPA status.

检查您的OPA状态。

kubectl get pod -n opa

You should be able to see the pods are up and running.

您应该能够看到Pod已启动并正在运行。

Image for post
opa pod status
opa pod状态
Image for post
opa container logs with kube-mgmt and opa
带有kube-mgmt和opa的opa容器日志

Label the namespaces that OPA will skip control of the resources. We are now skipping kube-system and opa with the below command.

标记名称空间,OPA将跳过该名称空间对资源的控制。 我们现在使用以下命令跳过kube-system和opa。

kubectl label ns kube-system openpolicyagent.org/webhook=ignore
kubectl label ns opa openpolicyagent.org/webhook=ignore

You can check the namespace label.

您可以检查名称空间标签。

kubectl get ns --show-labels | grep 
Image for post
Namespace label with openpolicyagent.org/webhook=ignore
具有 openpolicyagent.org/webhook = ignore命名空间标签 openpolicyagent.org/webhook = ignore

Register OPA as an admission controller.

将OPA注册为准入控制器。

cat << EOF | kubectl apply -f -
kind: ValidatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1beta1
metadata:
  name: opa-validating-webhook
webhooks:
  - name: validating-webhook.openpolicyagent.org
    namespaceSelector:
      matchExpressions:
      - key: openpolicyagent.org/webhook
        operator: NotIn
        values:
        - ignore
    rules:
      - operations: ["CREATE", "UPDATE"]
        apiGroups: ["*"]
        apiVersions: ["*"]
        resources: ["*"]
    clientConfig:
      caBundle: $(cat ca.crt | base64 | tr -d '\n')
      service:
        namespace: opa
        name: opa
EOF

定义和应用政策 (Define and Apply Policy)

We will use the below example to apply the policy of checking whether a valid Ingress host was annotated in the namespace.

我们将使用以下示例来应用检查名称空间中是否注释了有效Ingress主机的策略。

Create a Rego policy called ingress-whitelist.rego, for example.

例如,创建一个名为ingress-whitelist.rego的Rego策略。

Rego is declarative and supports structured data input such as JSON.

Rego是声明性的,并支持结构化数据输入,例如JSON。

You can learn more about Rego at https://www.openpolicyagent.org/docs/latest/policy-language/.

您可以在https://www.openpolicyagent.org/docs/latest/policy-language/上了解有关Rego的更多信息。

Rego Policy Playground: https://play.openpolicyagent.org/p/ikesWCFIH8.

Rego政策游乐场: https : //play.openpolicyagent.org/p/ikesWCFIH8

package kubernetes.admissionimport data.kubernetes.namespacesoperations = {"CREATE", "UPDATE"}deny[msg] {
input.request.kind.kind == "Ingress"
operations[input.request.operation]
host := input.request.object.spec.rules[_].host
not fqdn_matches_any(host, valid_ingress_hosts)
msg := sprintf("invalid ingress host %q", [host])
}
valid_ingress_hosts = {host |
whitelist := namespaces[input.request.namespace].metadata.annotations["ingress-whitelist"]
hosts := split(whitelist, ",")
host := hosts[_]
}
fqdn_matches_any(str, patterns) {
fqdn_matches(str, patterns[_])
}
fqdn_matches(str, pattern) {
pattern_parts := split(pattern, ".")
pattern_parts[0] == "*"
str_parts := split(str, ".")
n_pattern_parts := count(pattern_parts)
n_str_parts := count(str_parts)
suffix := trim(pattern, "*.")
endswith(str, suffix)
}
fqdn_matches(str, pattern) {
not contains(pattern, "*")
str == pattern
}

Store policy into configmap with label openpolicyagent.org/policy=rego

使用标签openpolicyagent.org/policy=rego将策略存储到configmap中

kubectl create configmap ingress-whitelist --from-file=ingress-whitelist.rego -n opakubectl label  configmap ingress-whitelist openpolicyagent.org/policy=rego -n opa

Then we can test if the policy is working.

然后,我们可以测试该政策是否有效。

测试政策 (Test Policy)

Use the below command to create a simple web service.

使用以下命令创建一个简单的Web服务。

kubectl create ns testkubectl create deployment web --image=gcr.io/google-samples/hello-app:1.0 -n test kubectl expose deployment web --type=NodePort --port=8080 -n test

Then try to apply the below Ingress setting.

然后尝试应用以下Ingress设置。

Note: Since we applied the policy of checking that only a valid Ingress host was annotated in the namespace, we should expect it to fail.

注意:由于我们应用了检查名称空间中仅注释了有效Ingress主机的策略,因此我们应该期望它会失败。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
namespace: test
spec:
rules:
— host: “test-hello.opa”
http:
paths:
— path: /
backend:
serviceName: web
servicePort: 8080

You should get the “denied request” that indicates it’s an invalid Ingress host.

您应该收到“拒绝的请求”,表明它是无效的Ingress主机。

Image for post
OPA denied the ingress creation request due to the invalid ingress host
由于无效的入口主机,OPA拒绝了入口创建请求

Try to add an annotation in the namespace to declare the host we allow.

尝试在名称空间中添加注释以声明我们允许的主机。

kubectl annotate ns test ingress-whitelist="*.opa"
Image for post
Describe namespace to view the annotation
描述名称空间以查看注释

Try again to apply the Ingress. This time, you should get a successful result.

再试一次应用Ingress。 这次,您应该获得成功的结果。

Image for post
Ingress created successfully
入口创建成功

Now you’ll be able to start customizing your own policy.

现在,您可以开始自定义自己的策略了。

我的工作版本 (My Working Version)

Image for post

Thanks for reading!

谢谢阅读!

翻译自: https://medium.com/better-programming/secure-your-service-on-kubernetes-with-open-policy-agent-38a800ca1696

kubernetes 代理

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值