1
0
Fork 0
mirror of https://github.com/kyverno/policy-reporter.git synced 2024-12-14 11:57:32 +00:00

Implement dynamic priority configuration (#6)

* Implement dynamic priority configuration
This commit is contained in:
Frank Jogeleit 2021-02-22 12:27:10 +01:00 committed by GitHub
parent 62b19b48df
commit 11c32ad791
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 275 additions and 107 deletions

View file

@ -29,19 +29,12 @@ loki:
### Configure Policy Priorities
By default kyverno PolicyReports has no priority or severity for policies. So every passed rule validation will be processed as notice, a failed validation is processed as error. To customize this you can configure a mapping from policies to fail priorities. So you can send them as warnings instead of errors. To configure the priorities create a ConfigMap in the `policy-reporter` namespace with the name `policy-reporter-config`. This ConfigMap have to have a property `config.yaml` with the map as YAML content. See the Example for Detailes.
By default kyverno PolicyReports has no priority or severity for policies. So every passed rule validation will be processed as notice, a failed validation is processed as error. To customize this you can configure a mapping from policies to fail priorities. So you can send them as warnings instead of errors. To configure the priorities create a ConfigMap in the `policy-reporter` namespace with the name `policy-reporter-priorities`. Configure each priority as value with the Policyname as key and the Priority as value. This Configuration is loaded and synchronized during runtime. Any change to this configmap will automaticly synchronized, no new deployment needed.
#### Example
```yaml
# config.yaml
policy_priorities:
check-label-app: warning
require-ns-labels: warning
```
```bash
kubectl create configmap policy-reporter-config --from-file=config.yaml -n policy-reporter
kubectl create configmap policy-reporter-priorities --from-literal check-label-app=warning --from-literal require-ns-labels=warning -n policy-reporter
```
## Monitoring

View file

@ -3,5 +3,5 @@ name: policy-reporter
description: K8s PolicyReporter watches for wgpolicyk8s.io/v1alpha1.PolicyReport resources. It creates Prometheus Metrics and can send rule validation events to Loki
type: application
version: 0.4.0
appVersion: 0.3.0
version: 0.5.0
appVersion: 0.4.0

View file

@ -0,0 +1,18 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
name: {{ include "policyreporter.fullname" . }}
rules:
- apiGroups:
- '*'
resources:
- policyreports
- policyreports/status
- clusterpolicyreports
- clusterpolicyreports/status
verbs:
- get
- list
- watch

View file

@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "policyreporter.fullname" . }}
roleRef:
kind: ClusterRole
name: {{ include "policyreporter.fullname" . }}
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: "ServiceAccount"
name: {{ include "policyreporter.serviceAccountName" . }}
namespace: policy-reporter

View file

@ -52,8 +52,11 @@ spec:
- name: config-volume
mountPath: /app/config.yaml
subPath: config.yaml
env:
- name: NAMESPACE
value: {{ .Release.Namespace }}
volumes:
- name: config-volume
configMap:
name: policy-reporter-config
optional: true
optional: true

View file

@ -1,17 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
kind: Role
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
name: {{ include "policyreporter.fullname" . }}
rules:
- apiGroups:
- '*'
- ''
resources:
- policyreports
- policyreports/status
- clusterpolicyreports
- clusterpolicyreports/status
- configmaps
verbs:
- get
- list

View file

@ -1,9 +1,9 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
kind: RoleBinding
metadata:
name: {{ include "policyreporter.fullname" . }}
roleRef:
kind: ClusterRole
kind: Role
name: {{ include "policyreporter.fullname" . }}
apiGroup: rbac.authorization.k8s.io
subjects:

View file

@ -15,7 +15,7 @@ metrics:
image:
repository: fjogeleit/policy-reporter
pullPolicy: IfNotPresent
tag: 0.3.0
tag: 0.4.0
imagePullSecrets: []

View file

@ -2,7 +2,6 @@ package cmd
import (
"flag"
"log"
"net/http"
"github.com/fjogeleit/policy-reporter/pkg/config"
@ -35,7 +34,7 @@ func NewCLI() *cobra.Command {
resolver := config.NewResolver(c)
client, err := resolver.KubernetesClient()
client, err := resolver.PolicyReportClient()
if err != nil {
return err
}
@ -83,26 +82,10 @@ func NewCLI() *cobra.Command {
func LoadConfig(cmd *cobra.Command) (*config.Config, error) {
v := viper.New()
cfgFile := ""
configFlag := cmd.Flags().Lookup("config")
if configFlag != nil {
cfgFile = configFlag.Value.String()
}
if cfgFile != "" {
v.SetConfigFile(cfgFile)
} else {
v.AddConfigPath(".")
v.SetConfigName("config")
}
v.SetDefault("namespace", "policy-reporter")
v.AutomaticEnv()
if err := v.ReadInConfig(); err != nil {
log.Println("no config provided")
}
if flag := cmd.Flags().Lookup("loki"); flag != nil {
v.BindPFlag("loki.host", flag)
}

View file

@ -1,8 +0,0 @@
# Mapping from policy -> priority
# Spported:
# error
# warning
# info
# debug
policy_priorities:
check-label-app: warning

6
go.mod
View file

@ -4,6 +4,8 @@ go 1.15
require (
github.com/davecgh/go-spew v1.1.1
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/magiconair/properties v1.8.4 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/pelletier/go-toml v1.8.1 // indirect
@ -13,9 +15,13 @@ require (
github.com/spf13/cobra v1.1.3
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/viper v1.7.1
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d // indirect
golang.org/x/sys v0.0.0-20210218155724-8ebf48af031b // indirect
golang.org/x/text v0.3.5 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
k8s.io/api v0.20.4
k8s.io/apimachinery v0.20.4
k8s.io/client-go v0.20.4
k8s.io/klog/v2 v2.5.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.0.3 // indirect
)

23
go.sum
View file

@ -128,6 +128,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
@ -143,6 +145,8 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -180,6 +184,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@ -252,6 +258,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -435,6 +442,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
@ -493,6 +502,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -521,8 +531,11 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d h1:1aflnvSoWWLI2k/dMUAl5lvU1YO4Mb4hz0gh+1rjcxU=
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -535,6 +548,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -573,9 +587,11 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210218155724-8ebf48af031b h1:lAZ0/chPUDWwjqosYR0X4M490zQhMsiJ4K3DbA7o+3g=
golang.org/x/sys v0.0.0-20210218155724-8ebf48af031b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -631,6 +647,8 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -729,6 +747,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.20.4 h1:xZjKidCirayzX6tHONRQyTNDVIR55TYVqgATqo6ZULY=
k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
k8s.io/apimachinery v0.20.4 h1:vhxQ0PPUUU2Ns1b9r4/UFp13UPs8cw2iOoTjnY9faa0=
k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
@ -738,6 +757,8 @@ k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.5.0 h1:8mOnjf1RmUPW6KRqQCfYSZq/K20Unmp3IhuZUhxl8KI=
k8s.io/klog/v2 v2.5.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
@ -746,6 +767,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.0.3 h1:4oyYo8NREp49LBBhKxEqCulFjg26rawYKrnCmg+Sr6c=
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View file

@ -6,6 +6,6 @@ type Config struct {
SkipExisting bool `mapstructure:"skipExistingOnStartup"`
MinimumPriority string `mapstructure:"minimumPriority"`
} `mapstructure:"loki"`
Kubeconfig string `mapstructure:"kubeconfig"`
PolicyPriorities map[string]string `mapstructure:"policy_priorities"`
Kubeconfig string `mapstructure:"kubeconfig"`
Namespace string `mapstructure:"namespace"`
}

View file

@ -1,16 +1,18 @@
package config
import (
"context"
"time"
"github.com/fjogeleit/policy-reporter/pkg/kubernetes"
"github.com/fjogeleit/policy-reporter/pkg/metrics"
"github.com/fjogeleit/policy-reporter/pkg/report"
"github.com/fjogeleit/policy-reporter/pkg/target"
"github.com/fjogeleit/policy-reporter/pkg/target/loki"
)
var (
kubeClient kubernetes.Client
kubeClient report.Client
lokiClient target.Client
policyReportMetrics metrics.Metrics
clusterPolicyReportMetrics metrics.Metrics
@ -20,16 +22,25 @@ type Resolver struct {
config *Config
}
func (r *Resolver) KubernetesClient() (kubernetes.Client, error) {
func (r *Resolver) PolicyReportClient() (report.Client, error) {
if kubeClient != nil {
return kubeClient, nil
}
return kubernetes.NewDynamicClient(r.config.Kubeconfig, r.config.PolicyPriorities, time.Now())
client, err := kubernetes.NewPolicyReportClient(
context.Background(),
r.config.Kubeconfig,
r.config.Namespace,
time.Now(),
)
kubeClient = client
return client, err
}
func (r *Resolver) LokiClient() target.Client {
if kubeClient != nil {
if lokiClient != nil {
return lokiClient
}
@ -37,10 +48,12 @@ func (r *Resolver) LokiClient() target.Client {
return nil
}
return loki.NewClient(
lokiClient = loki.NewClient(
r.config.Loki.Host,
r.config.Loki.MinimumPriority,
)
return lokiClient
}
func (r *Resolver) PolicyReportMetrics() (metrics.Metrics, error) {
@ -48,25 +61,29 @@ func (r *Resolver) PolicyReportMetrics() (metrics.Metrics, error) {
return policyReportMetrics, nil
}
client, err := r.KubernetesClient()
client, err := r.PolicyReportClient()
if err != nil {
return nil, err
}
return metrics.NewPolicyReportMetrics(client), nil
policyReportMetrics = metrics.NewPolicyReportMetrics(client)
return policyReportMetrics, nil
}
func (r *Resolver) ClusterPolicyReportMetrics() (metrics.Metrics, error) {
if policyReportMetrics != nil {
if clusterPolicyReportMetrics != nil {
return clusterPolicyReportMetrics, nil
}
client, err := r.KubernetesClient()
client, err := r.PolicyReportClient()
if err != nil {
return nil, err
}
return metrics.NewClusterPolicyMetrics(client), nil
clusterPolicyReportMetrics = metrics.NewClusterPolicyMetrics(client)
return clusterPolicyReportMetrics, nil
}
func NewResolver(config *Config) Resolver {

View file

@ -0,0 +1,65 @@
package kubernetes
import (
"context"
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
type CoreClient interface {
GetConfig(ctx context.Context, name string) (*apiv1.ConfigMap, error)
WatchConfigs(ctx context.Context, cb ConfigMapCallback) error
}
type ConfigMapCallback = func(watch.EventType, *apiv1.ConfigMap)
type coreClient struct {
cmClient v1.ConfigMapInterface
}
func (c coreClient) GetConfig(ctx context.Context, name string) (*apiv1.ConfigMap, error) {
return c.cmClient.Get(ctx, name, metav1.GetOptions{})
}
func (c coreClient) WatchConfigs(ctx context.Context, cb ConfigMapCallback) error {
watch, err := c.cmClient.Watch(ctx, metav1.ListOptions{})
if err != nil {
return err
}
for event := range watch.ResultChan() {
if cm, ok := event.Object.(*apiv1.ConfigMap); ok {
cb(event.Type, cm)
}
}
return nil
}
func NewCoreClient(kubeconfig, namespace string) (CoreClient, error) {
var config *rest.Config
var err error
if kubeconfig != "" {
config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
} else {
config, err = rest.InClusterConfig()
}
if err != nil {
return nil, err
}
client, err := v1.NewForConfig(config)
if err != nil {
return nil, err
}
return &coreClient{
cmClient: client.ConfigMaps(namespace),
}, nil
}

View file

@ -8,6 +8,7 @@ import (
"time"
"github.com/fjogeleit/policy-reporter/pkg/report"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -22,26 +23,20 @@ var (
clusterPolicyReports = schema.GroupVersionResource{Group: "wgpolicyk8s.io", Version: "v1alpha1", Resource: "clusterpolicyreports"}
)
type WatchPolicyReportCallback = func(watch.EventType, report.PolicyReport)
type WatchClusterPolicyReportCallback = func(watch.EventType, report.ClusterPolicyReport)
type WatchPolicyResultCallback = func(report.Result)
const (
prioriyConfig = "policy-reporter-priorities"
)
type Client interface {
FetchPolicyReports() []report.PolicyReport
WatchPolicyReports(WatchPolicyReportCallback)
WatchRuleValidation(WatchPolicyResultCallback, bool)
WatchClusterPolicyReports(WatchClusterPolicyReportCallback)
}
type DynamicClient struct {
type policyReportClient struct {
client dynamic.Interface
coreClient CoreClient
policyCache map[string]report.PolicyReport
clusterPolicyCache map[string]report.ClusterPolicyReport
priorityMap map[string]string
startUp time.Time
}
func (c *DynamicClient) FetchPolicyReports() []report.PolicyReport {
func (c *policyReportClient) FetchPolicyReports() []report.PolicyReport {
var reports []report.PolicyReport
result, err := c.client.Resource(policyReports).List(context.Background(), metav1.ListOptions{})
@ -57,7 +52,7 @@ func (c *DynamicClient) FetchPolicyReports() []report.PolicyReport {
return reports
}
func (c *DynamicClient) WatchClusterPolicyReports(cb WatchClusterPolicyReportCallback) {
func (c *policyReportClient) WatchClusterPolicyReports(cb report.WatchClusterPolicyReportCallback) {
result, err := c.client.Resource(clusterPolicyReports).Watch(context.Background(), metav1.ListOptions{})
if err != nil {
log.Printf("K8s Watch Error: %s\n", err.Error())
@ -71,7 +66,7 @@ func (c *DynamicClient) WatchClusterPolicyReports(cb WatchClusterPolicyReportCal
}
}
func (c *DynamicClient) WatchPolicyReports(cb WatchPolicyReportCallback) {
func (c *policyReportClient) WatchPolicyReports(cb report.WatchPolicyReportCallback) {
result, err := c.client.Resource(policyReports).Watch(context.Background(), metav1.ListOptions{})
if err != nil {
log.Printf("K8s Watch Error: %s\n", err.Error())
@ -85,7 +80,7 @@ func (c *DynamicClient) WatchPolicyReports(cb WatchPolicyReportCallback) {
}
}
func (c *DynamicClient) WatchRuleValidation(cb WatchPolicyResultCallback, skipExisting bool) {
func (c *policyReportClient) WatchRuleValidation(cb report.WatchPolicyResultCallback, skipExisting bool) {
wg := sync.WaitGroup{}
wg.Add(2)
@ -150,34 +145,46 @@ func (c *DynamicClient) WatchRuleValidation(cb WatchPolicyResultCallback, skipEx
wg.Wait()
}
func NewDynamicClient(kubeconfig string, prioties map[string]string, startUp time.Time) (Client, error) {
var config *rest.Config
var err error
if kubeconfig != "" {
config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
} else {
config, err = rest.InClusterConfig()
}
func (c *policyReportClient) fetchPriorities(ctx context.Context) error {
cm, err := c.coreClient.GetConfig(ctx, prioriyConfig)
if err != nil {
return nil, err
return err
}
client, err := dynamic.NewForConfig(config)
if err != nil {
return nil, err
if cm != nil {
c.priorityMap = cm.Data
log.Println("[INFO] Priorities loaded")
}
return &DynamicClient{
client: client,
policyCache: make(map[string]report.PolicyReport),
clusterPolicyCache: make(map[string]report.ClusterPolicyReport),
priorityMap: prioties,
startUp: startUp,
}, nil
return nil
}
func (c *DynamicClient) mapPolicyReport(reportMap map[string]interface{}) report.PolicyReport {
func (c *policyReportClient) syncPriorities(ctx context.Context) error {
err := c.coreClient.WatchConfigs(ctx, func(e watch.EventType, cm *v1.ConfigMap) {
if cm.Name != prioriyConfig {
return
}
switch e {
case watch.Added:
c.priorityMap = cm.Data
case watch.Modified:
c.priorityMap = cm.Data
case watch.Deleted:
c.priorityMap = map[string]string{}
}
log.Println("[INFO] Priorities synchronized")
})
if err != nil {
log.Printf("[INFO] Unable to sync Priorities: %s", err.Error())
}
return err
}
func (c *policyReportClient) mapPolicyReport(reportMap map[string]interface{}) report.PolicyReport {
summary := report.Summary{}
if s, ok := reportMap["summary"].(map[string]interface{}); ok {
@ -205,7 +212,7 @@ func (c *DynamicClient) mapPolicyReport(reportMap map[string]interface{}) report
return r
}
func (c *DynamicClient) mapClusterPolicyReport(reportMap map[string]interface{}) report.ClusterPolicyReport {
func (c *policyReportClient) mapClusterPolicyReport(reportMap map[string]interface{}) report.ClusterPolicyReport {
summary := report.Summary{}
if s, ok := reportMap["summary"].(map[string]interface{}); ok {
@ -239,7 +246,7 @@ func (c *DynamicClient) mapClusterPolicyReport(reportMap map[string]interface{})
return r
}
func (c *DynamicClient) mapCreationTime(result map[string]interface{}) (time.Time, error) {
func (c *policyReportClient) mapCreationTime(result map[string]interface{}) (time.Time, error) {
if metadata, ok := result["metadata"].(map[string]interface{}); ok {
if created, ok2 := metadata["creationTimestamp"].(string); ok2 {
return time.Parse("2006-01-02T15:04:05Z", created)
@ -251,7 +258,7 @@ func (c *DynamicClient) mapCreationTime(result map[string]interface{}) (time.Tim
return time.Time{}, errors.New("No metadata provided")
}
func (c *DynamicClient) mapResult(result map[string]interface{}) report.Result {
func (c *policyReportClient) mapResult(result map[string]interface{}) report.Result {
var resources []report.Resource
if ress, ok := result["resources"].([]interface{}); ok {
@ -304,3 +311,45 @@ func (c *DynamicClient) mapResult(result map[string]interface{}) report.Result {
return r
}
func NewPolicyReportClient(ctx context.Context, kubeconfig, namespace string, startUp time.Time) (report.Client, error) {
var config *rest.Config
var err error
if kubeconfig != "" {
config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
} else {
config, err = rest.InClusterConfig()
}
if err != nil {
return nil, err
}
dynamicClient, err := dynamic.NewForConfig(config)
if err != nil {
return nil, err
}
coreClient, err := NewCoreClient(kubeconfig, namespace)
if err != nil {
return nil, err
}
reportClient := &policyReportClient{
client: dynamicClient,
coreClient: coreClient,
policyCache: make(map[string]report.PolicyReport),
clusterPolicyCache: make(map[string]report.ClusterPolicyReport),
priorityMap: make(map[string]string),
startUp: startUp,
}
err = reportClient.fetchPriorities(ctx)
if err != nil {
log.Printf("[INFO] No PriorityConfig found: %s", err.Error())
}
go reportClient.syncPriorities(ctx)
return reportClient, nil
}

View file

@ -3,7 +3,6 @@ package metrics
import (
"sync"
"github.com/fjogeleit/policy-reporter/pkg/kubernetes"
"github.com/fjogeleit/policy-reporter/pkg/report"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
@ -11,7 +10,7 @@ import (
)
type ClusterPolicyReportMetrics struct {
client kubernetes.Client
client report.Client
cache map[string]report.ClusterPolicyReport
rwmutex *sync.RWMutex
}
@ -137,7 +136,7 @@ func updateClusterPolicyGauge(policyGauge *prometheus.GaugeVec, report report.Cl
Set(float64(report.Summary.Skip))
}
func NewClusterPolicyMetrics(client kubernetes.Client) *ClusterPolicyReportMetrics {
func NewClusterPolicyMetrics(client report.Client) *ClusterPolicyReportMetrics {
return &ClusterPolicyReportMetrics{
client: client,
cache: make(map[string]report.ClusterPolicyReport),

View file

@ -3,7 +3,6 @@ package metrics
import (
"sync"
"github.com/fjogeleit/policy-reporter/pkg/kubernetes"
"github.com/fjogeleit/policy-reporter/pkg/report"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
@ -11,7 +10,7 @@ import (
)
type PolicyReportMetrics struct {
client kubernetes.Client
client report.Client
cache map[string]report.PolicyReport
rwmutex *sync.RWMutex
}
@ -150,7 +149,7 @@ func updatePolicyGauge(policyGauge *prometheus.GaugeVec, report report.PolicyRep
Set(float64(report.Summary.Skip))
}
func NewPolicyReportMetrics(client kubernetes.Client) *PolicyReportMetrics {
func NewPolicyReportMetrics(client report.Client) *PolicyReportMetrics {
return &PolicyReportMetrics{
client: client,
cache: make(map[string]report.PolicyReport),

14
pkg/report/client.go Normal file
View file

@ -0,0 +1,14 @@
package report
import "k8s.io/apimachinery/pkg/watch"
type WatchPolicyReportCallback = func(watch.EventType, PolicyReport)
type WatchClusterPolicyReportCallback = func(watch.EventType, ClusterPolicyReport)
type WatchPolicyResultCallback = func(Result)
type Client interface {
FetchPolicyReports() []PolicyReport
WatchPolicyReports(WatchPolicyReportCallback)
WatchRuleValidation(WatchPolicyResultCallback, bool)
WatchClusterPolicyReports(WatchClusterPolicyReportCallback)
}