策略实践:只允许部分账号创建公网 Ingress
创建策略
使用 kubectl apply 以下两个 YAML:
- ConstraintTemplate
- Constraint
constraint-template.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: blockpublicingress
spec:
crd:
spec:
names:
kind: BlockPublicIngress
validation:
openAPIV3Schema:
type: object
properties:
allowedUins:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package blockpublicingress
is_qcloud_ingress(ingress) = true {
not ingress.spec.ingressClassName
}
is_qcloud_ingress(ingress) = true {
ingress.spec.ingressClassName == ""
}
is_qcloud_ingress(ingress) = true {
ingress.spec.ingressClassName == "qcloud"
}
is_qcloud_ingress(ingress) = true {
not ingress.metadata.annotations["kubernetes.io/ingress.class"]
}
is_qcloud_ingress(ingress) = true {
ingress.metadata.annotations["kubernetes.io/ingress.class"] == ""
}
is_public_ingress(ingress) = true {
not ingress.metadata.annotations["kubernetes.io/ingress.subnetId"]
}
is_public_ingress(ingress) = true {
ingress.metadata.annotations["kubernetes.io/ingress.subnetId"] == ""
}
is_qcloud_ingress(ingress) = true {
ingress.metadata.annotations["kubernetes.io/ingress.class"] == "qcloud"
}
is_tke_user(userinfo) = true {
userinfo.groups[_] == "tke:users"
regex.match("^\\d+-\\d+$", userinfo.username)
}
get_uin(userinfo) = uin {
split(userinfo.username, "-", parts)
uin := parts[0]
}
is_uin_allowed(uin, allowed_uins) {
allowed_uins[_] == uin
}
violation[{"msg": msg}] {
input.review.kind.kind == "Ingress"
regex.match("^(extensions|networking.k8s.io)$", input.review.kind.group)
regex.match("^(CREATE|UPDATE)$", input.review.operation)
ingress := input.review.object
is_qcloud_ingress(ingress)
is_public_ingress(ingress)
userinfo := input.review.userInfo
is_tke_user(userinfo)
uin := get_uin(userinfo)
not is_uin_allowed(uin, input.parameters.allowedUins)
msg := sprintf("User '%v' is not allowed to create Ingress resources", [uin])
}
注意修改高亮部分
constraint.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: BlockPublicIngress
metadata:
name: block-public-ingress
spec:
match:
kinds:
- apiGroups: ["networking.k8s.io", "extensions"]
kinds: ["Ingress"]
parameters:
allowedUins: ["100000000001", "100000000002"] # 只允许该列表里的账号(UIN) 创建公网 Ingress
创建 Ingress 注意事项
- 如果在控制台创建 Ingress,且集群是当前子账号创建的,会使用 admin 权限,将不受此策略限制。
- 如果通过 kubectl 创建,获取 kubeconfig 时也需要使用子账号的 kubeconfig。
效果
如果使用的子账号不在 allowedUins
列表中,创建公网 Ingress 时将会报错。
控制台报错:
kubectl apply 报错:
Error from server (Forbidden): error when creating "STDIN": admission webhook "validation.gatekeeper.sh" denied the request: [block-public-ingress] User '100009022548' is not allowed to create Ingress resources