From 931d7cd47c5668d02cf97f70573bff09556835ad Mon Sep 17 00:00:00 2001 From: shuting Date: Thu, 3 Sep 2020 08:54:37 -0700 Subject: [PATCH 1/2] Set mutating webhhok reinvocationPolicy to IfNeeded (#1097) * add watch policy to clusterrole kyverno:customresources * fix build * fix nil pointer * skip json patches if the mutation is re-invoked * set resource mutating webhook invocation policy to IfNeeded --- go.mod | 1 + go.sum | 46 +++++ pkg/engine/mutate/generatePatches.go | 27 --- pkg/engine/mutate/mutation.go | 31 +++- pkg/engine/mutate/patchJson6902.go | 21 +++ pkg/engine/mutate/patchesUtils.go | 167 ++++++++++++++++++ ...tePatches_test.go => patchesUtils_test.go} | 160 +++++++++++++++++ pkg/webhookconfig/common.go | 2 +- pkg/webhookconfig/resource.go | 25 ++- 9 files changed, 437 insertions(+), 43 deletions(-) delete mode 100644 pkg/engine/mutate/generatePatches.go create mode 100644 pkg/engine/mutate/patchesUtils.go rename pkg/engine/mutate/{generatePatches_test.go => patchesUtils_test.go} (52%) diff --git a/go.mod b/go.mod index 518ee2350e..f433d94967 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/cenkalti/backoff v2.2.1+incompatible github.com/evanphx/json-patch v4.5.0+incompatible github.com/evanphx/json-patch/v5 v5.0.0 // indirect + github.com/gardener/controller-manager-library v0.2.0 github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/go-logr/logr v0.1.0 github.com/go-openapi/spec v0.19.5 diff --git a/go.sum b/go.sum index ee7e43e6da..c1c6bb5356 100644 --- a/go.sum +++ b/go.sum @@ -28,7 +28,9 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.16.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= @@ -48,6 +50,7 @@ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrU github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/ahmetb/gen-crd-api-reference-docs v0.1.5/go.mod h1:P/XzJ+c2+khJKNKABcm2biRwk2QAuwbLf8DlXuaL7WM= github.com/ahmetb/gen-crd-api-reference-docs v0.2.0 h1:YI/cAcRdNAHArfhGKcmCY5qMa32k/UyCZagLgabC5JY= github.com/ahmetb/gen-crd-api-reference-docs v0.2.0/go.mod h1:P/XzJ+c2+khJKNKABcm2biRwk2QAuwbLf8DlXuaL7WM= github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= @@ -57,6 +60,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= +github.com/appscode/jsonpatch v0.0.0-20190108182946-7c0e3b262f30/go.mod h1:4AJxUpXUhv4N+ziTvIcWWXgeorXpxPZOfk9HdEVr96M= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= @@ -103,10 +108,13 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/coredns/coredns v1.4.0/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= +github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -153,6 +161,7 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.0.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -166,6 +175,8 @@ github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.4.1/go.mod h1:36zfPVQyHxymz4cH7wlDmVwDrJuljRB60qkgn7rorfQ= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gardener/controller-manager-library v0.2.0 h1:MyxL0k10lwBf8TXkbnuN+oEOkHwCNhp3SKj+ad2w62s= +github.com/gardener/controller-manager-library v0.2.0/go.mod h1:oCK7fW2VpsMhmUh5c6cOhsN8p9Tth1OM3rRtogDF11k= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= @@ -312,6 +323,7 @@ github.com/gobuffalo/flect v0.0.0-20181114183036-47375f6d8328/go.mod h1:0HvNbHdf github.com/gobuffalo/flect v0.0.0-20181210151238-24a2b68e0316/go.mod h1:en58vff74S9b99Eg42Dr+/9yPu437QjlNsO/hBYPuOk= github.com/gobuffalo/flect v0.0.0-20190104192022-4af577e09bf2/go.mod h1:en58vff74S9b99Eg42Dr+/9yPu437QjlNsO/hBYPuOk= github.com/gobuffalo/flect v0.0.0-20190117212819-a62e61d96794/go.mod h1:397QT6v05LkZkn07oJXXT6y9FCfwC8Pug0WA2/2mE9k= +github.com/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/gobuffalo/genny v0.0.0-20180924032338-7af3a40f2252/go.mod h1:tUTQOogrr7tAQnhajMSH6rv1BVev34H2sa1xNHMy94g= github.com/gobuffalo/genny v0.0.0-20181003150629-3786a0744c5d/go.mod h1:WAd8HmjMVrnkAZbmfgH5dLBUchsZfqzp/WS5sQz+uTM= github.com/gobuffalo/genny v0.0.0-20181005145118-318a41a134cc/go.mod h1:WAd8HmjMVrnkAZbmfgH5dLBUchsZfqzp/WS5sQz+uTM= @@ -503,6 +515,7 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= @@ -524,11 +537,14 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= @@ -565,6 +581,7 @@ github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKe github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= @@ -666,6 +683,7 @@ github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qo github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= @@ -758,6 +776,7 @@ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:v github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -766,6 +785,7 @@ github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuB github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34= github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= @@ -881,6 +901,7 @@ github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3/go.mod h1 github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= @@ -954,6 +975,7 @@ github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= @@ -973,9 +995,12 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= +go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180830192347-182538f80094/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1053,6 +1078,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1222,6 +1248,7 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1266,6 +1293,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM= gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo= @@ -1277,24 +1305,34 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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= +k8s.io/api v0.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48= +k8s.io/api v0.16.4/go.mod h1:AtzMnsR45tccQss5q8RnF+W8L81DH6XwXwo/joEx9u0= k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4= k8s.io/api v0.17.4 h1:HbwOhDapkguO8lTAE8OX3hdF2qp8GtpC9CW/MQATXXo= k8s.io/api v0.17.4/go.mod h1:5qxx6vjmwUVG2nHQTKGlLts8Tbok8PzHl4vHtVFuZCA= +k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY= +k8s.io/apiextensions-apiserver v0.16.4/go.mod h1:HYQwjujEkXmQNhap2C9YDdIVOSskGZ3et0Mvjcyjbto= k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs= k8s.io/apiextensions-apiserver v0.17.4 h1:ZKFnw3cJrGZ/9s6y+DerTF4FL+dmK0a04A++7JkmMho= k8s.io/apiextensions-apiserver v0.17.4/go.mod h1:rCbbbaFS/s3Qau3/1HbPlHblrWpFivoaLYccCffvQGI= k8s.io/apimachinery v0.0.0-20190612125636-6a5db36e93ad/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= +k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4= +k8s.io/apimachinery v0.16.4/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ= k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.17.4 h1:UzM+38cPUJnzqSQ+E1PY4YxMHIzQyCg29LOoGfo79Zw= k8s.io/apimachinery v0.17.4/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g= k8s.io/apimachinery v0.18.6 h1:RtFHnfGNfd1N0LeSrKCUznz5xtUP1elRGvHJbL3Ntag= +k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg= +k8s.io/apiserver v0.16.4/go.mod h1:kbLJOak655g6W7C+muqu1F76u9wnEycfKMqbVaXIdAc= k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo= k8s.io/apiserver v0.17.4 h1:bYc9LvDPEF9xAL3fhbDzqNOQOAnNF2ZYCrMW8v52/mE= k8s.io/apiserver v0.17.4/go.mod h1:5ZDQ6Xr5MNBxyi3iUZXS84QOhZl+W7Oq2us/29c0j9I= k8s.io/cli-runtime v0.17.4 h1:ZIJdxpBEszZqUhydrCoiI5rLXS2J/1AF5xFok2QJ9bc= k8s.io/cli-runtime v0.17.4/go.mod h1:IVW4zrKKx/8gBgNNkhiUIc7nZbVVNhc1+HcQh+PiNHc= +k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk= +k8s.io/client-go v0.16.4/go.mod h1:ZgxhFDxSnoKY0J0U2/Y1C8obKDdlhGPZwA7oHH863Ok= k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= k8s.io/client-go v0.17.2/go.mod h1:QAzRgsa0C2xl4/eVpeVAZMvikCn8Nm81yqVx3Kk9XYI= k8s.io/code-generator v0.0.0-20200306081859-6a048a382944/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= @@ -1302,18 +1340,23 @@ k8s.io/component-base v0.0.0-20190612130303-4062e14deebe h1:GHRdxwv4/80MA+Yy/YVy k8s.io/component-base v0.0.0-20190612130303-4062e14deebe/go.mod h1:MmIDXnint3qMN0cqXHKrSiJ2XQKo3J1BPIz7in7NvO0= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/helm v2.11.0+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +k8s.io/metrics v0.16.4/go.mod h1:dckkfqvaASo+NrzEmp8ST8yCc9hGt7lx9ABAILyDHx8= k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= +k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= @@ -1322,6 +1365,7 @@ mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZI rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/controller-runtime v0.5.0 h1:CbqIy5fbUX+4E9bpnBFd204YAzRYlM9SWW77BbrcDQo= sigs.k8s.io/controller-runtime v0.5.0/go.mod h1:REiJzC7Y00U+2YkMbT8wxgrsX5USpXKGhb2sCtAXiT8= +sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA= sigs.k8s.io/kustomize v1.0.11 h1:Yb+6DDt9+aR2AvQApvUaKS/ugteeG4MPyoFeUHiPOjk= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= @@ -1332,7 +1376,9 @@ sigs.k8s.io/kustomize/kyaml v0.4.1/go.mod h1:XJL84E6sOFeNrQ7CADiemc1B0EjIxHo3OhW sigs.k8s.io/kustomize/kyaml v0.6.1 h1:mwffj5vt3MPdbWV3fZnnwol8SO7sUoGdgejBlvseyak= sigs.k8s.io/kustomize/kyaml v0.6.1/go.mod h1:bEzbO5pN9OvlEeCLvFHo8Pu7SA26Herc2m60UeWZBdI= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= +sigs.k8s.io/structured-merge-diff v1.0.1/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= diff --git a/pkg/engine/mutate/generatePatches.go b/pkg/engine/mutate/generatePatches.go deleted file mode 100644 index 75102f17a8..0000000000 --- a/pkg/engine/mutate/generatePatches.go +++ /dev/null @@ -1,27 +0,0 @@ -package mutate - -import ( - "fmt" - - "github.com/mattbaird/jsonpatch" -) - -func generatePatches(src, dst []byte) ([][]byte, error) { - var patchesBytes [][]byte - pp, err := jsonpatch.CreatePatch(src, dst) - for _, p := range pp { - // TODO: handle remove nil value, i.e., - // {remove /spec/securityContext } - // {remove /status/conditions/0/lastProbeTime } - - pbytes, err := p.MarshalJSON() - if err != nil { - return patchesBytes, err - } - - patchesBytes = append(patchesBytes, pbytes) - fmt.Printf("generated patch %s\n", p) - } - - return patchesBytes, err -} diff --git a/pkg/engine/mutate/mutation.go b/pkg/engine/mutate/mutation.go index c6e85fd23a..fc34ced2ac 100644 --- a/pkg/engine/mutate/mutation.go +++ b/pkg/engine/mutate/mutation.go @@ -5,6 +5,7 @@ import ( kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/context" "github.com/nirmata/kyverno/pkg/engine/response" + "github.com/nirmata/kyverno/pkg/engine/utils" "github.com/nirmata/kyverno/pkg/engine/variables" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -102,7 +103,20 @@ func newPatchesJSON6902Handler(ruleName string, mutate *kyverno.Mutation, patche } } -func (h patchesJSON6902Handler) Handle() (response.RuleResponse, unstructured.Unstructured) { +func (h patchesJSON6902Handler) Handle() (resp response.RuleResponse, patchedResource unstructured.Unstructured) { + resp.Name = h.ruleName + resp.Type = utils.Mutation.String() + + skip, err := preProcessJSONPatches(*h.mutation, h.patchedResource, h.logger) + if err != nil { + h.logger.Error(err, "failed to preProcessJSONPatches") + } + + if skip { + resp.Success = true + return resp, h.patchedResource + } + return ProcessPatchJSON6902(h.ruleName, *h.mutation, h.patchedResource, h.logger) } @@ -141,7 +155,20 @@ func newpatchesHandler(ruleName string, mutate *kyverno.Mutation, patchedResourc } } -func (h patchesHandler) Handle() (response.RuleResponse, unstructured.Unstructured) { +func (h patchesHandler) Handle() (resp response.RuleResponse, patchedResource unstructured.Unstructured) { + resp.Name = h.ruleName + resp.Type = utils.Mutation.String() + + skip, err := preProcessJSONPatches(*h.mutation, h.patchedResource, h.logger) + if err != nil { + h.logger.Error(err, "failed to preProcessJSONPatches") + } + + if skip { + resp.Success = true + return resp, h.patchedResource + } + return ProcessPatches(h.logger, h.ruleName, *h.mutation, h.patchedResource) } diff --git a/pkg/engine/mutate/patchJson6902.go b/pkg/engine/mutate/patchJson6902.go index ca52517ac0..d78aa49b3b 100644 --- a/pkg/engine/mutate/patchJson6902.go +++ b/pkg/engine/mutate/patchJson6902.go @@ -4,8 +4,10 @@ import ( "bytes" "encoding/json" "fmt" + "strings" "time" + jsonpatch "github.com/evanphx/json-patch" "github.com/go-logr/logr" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/response" @@ -101,3 +103,22 @@ func patchJSON6902(base, patches string) ([]byte, error) { return baseObj.Bytes(), err } + +func decodePatch(patch string) (jsonpatch.Patch, error) { + // If the patch doesn't look like a JSON6902 patch, we + // try to parse it to json. + if !strings.HasPrefix(patch, "[") { + p, err := yaml.YAMLToJSON([]byte(patch)) + if err != nil { + return nil, err + } + patch = string(p) + } + + decodedPatch, err := jsonpatch.DecodePatch([]byte(patch)) + if err != nil { + return nil, err + } + + return decodedPatch, nil +} diff --git a/pkg/engine/mutate/patchesUtils.go b/pkg/engine/mutate/patchesUtils.go new file mode 100644 index 0000000000..e339a860d7 --- /dev/null +++ b/pkg/engine/mutate/patchesUtils.go @@ -0,0 +1,167 @@ +package mutate + +import ( + "fmt" + "path/filepath" + "reflect" + "strconv" + "strings" + + "github.com/mattbaird/jsonpatch" + + evanjsonpatch "github.com/evanphx/json-patch" + "github.com/go-logr/logr" + kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +func generatePatches(src, dst []byte) ([][]byte, error) { + var patchesBytes [][]byte + pp, err := jsonpatch.CreatePatch(src, dst) + for _, p := range pp { + // TODO: handle remove nil value, i.e., + // {remove /spec/securityContext } + // {remove /status/conditions/0/lastProbeTime } + + pbytes, err := p.MarshalJSON() + if err != nil { + return patchesBytes, err + } + + patchesBytes = append(patchesBytes, pbytes) + fmt.Printf("generated patch %s\n", p) + } + + return patchesBytes, err +} + +// preProcessJSONPatchesgo deals with the JsonPatch when reinvocation +// policy is set in webhook, to avoid generating duplicate values. +// This duplicate error only occurs on type array, if it's adding to a map +// the value will be added to the map if nil, otherwise it overwrites the old value +// return skip == true to skip the json patch application +func preProcessJSONPatches(mutation kyverno.Mutation, resource unstructured.Unstructured, + log logr.Logger) (skip bool, err error) { + var patches evanjsonpatch.Patch + log = log.WithName("preProcessJSONPatches") + + if len(mutation.PatchesJSON6902) > 0 { + patches, err = decodePatch(mutation.PatchesJSON6902) + if err != nil { + return false, fmt.Errorf("failed to process JSON patches: %v", err) + } + } + + for _, patch := range patches { + if patch.Kind() != "add" { + continue + } + + path, err := patch.Path() + if err != nil { + return false, fmt.Errorf("failed to get path in JSON Patch: %v", err) + } + + // check if the target is the list + if tail := filepath.Base(path); tail != "-" { + _, err := strconv.Atoi(tail) + if err != nil { + log.V(4).Info("JSON patch does not add to the list, skipping", "path", path) + continue + } + } + + resourceObj, err := getObject(path, resource.UnstructuredContent()) + if err != nil { + log.V(4).Info("failed to get object by the given path", "path", path, "error", err.Error()) + continue + } + + val, err := patch.ValueInterface() + if err != nil { + log.V(4).Info("failed to get value by the given path", "path", path, "error", err.Error()) + continue + } + + // if there's one patch exist in the resource, which indicates + // this is re-invoked JSON patches, skip application + if isSubsetObject(val, resourceObj) { + return true, nil + } + } + + return false, nil +} + +// - insert to the end of the list +// {"op": "add", "path": "/spec/containers/-", {"value": "{"name":"busyboxx","image":"busybox:latest"}"} + +// - insert value to the certain element of the list +// {"op": "add", "path": "/spec/containers/1", {"value": "{"name":"busyboxx","image":"busybox:latest"}"} +func getObject(path string, resource map[string]interface{}) (interface{}, error) { + var strippedResource interface{} + strippedResource = resource + var ok bool + + if strings.HasPrefix(path, "/") { + path = path[1:] + } + paths := strings.Split(path, "/") + + for i, key := range paths { + switch strippedResource.(type) { + case map[string]interface{}: + strippedResource, ok = strippedResource.(map[string]interface{})[key] + if !ok { + return nil, fmt.Errorf("referenced value does not exist at %s", strings.Join(paths[:i+1], "/")) + } + + case []interface{}: + var idx int + + if key == "-" { + idx = len(strippedResource.([]interface{})) - 1 + } else { + var err error + idx, err = strconv.Atoi(key) + if err != nil { + return nil, fmt.Errorf("cannot parse index in JSON Patch at %s: %v", strings.Join(paths[:i+1], "/"), err) + } + } + + if len(strippedResource.([]interface{})) <= idx { + return nil, nil + } + + strippedResource = strippedResource.([]interface{})[idx] + } + } + return strippedResource, nil +} + +// isSubsetObject returns true if object is subset of resource +// the object/resource is the element inside the list, return false +// if the type is mismatched (not map) +func isSubsetObject(object, resource interface{}) bool { + objectMap, ok := object.(map[string]interface{}) + if !ok { + return false + } + + resourceMap, ok := resource.(map[string]interface{}) + if !ok { + return false + } + + for objKey, objVal := range objectMap { + rsrcVal, ok := resourceMap[objKey] + if !ok { + return false + } + + if !reflect.DeepEqual(objVal, rsrcVal) { + return false + } + } + return true +} diff --git a/pkg/engine/mutate/generatePatches_test.go b/pkg/engine/mutate/patchesUtils_test.go similarity index 52% rename from pkg/engine/mutate/generatePatches_test.go rename to pkg/engine/mutate/patchesUtils_test.go index 1ee4e18cf0..484700edf7 100644 --- a/pkg/engine/mutate/generatePatches_test.go +++ b/pkg/engine/mutate/patchesUtils_test.go @@ -4,10 +4,13 @@ import ( "encoding/json" "testing" + v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/utils" assertnew "github.com/stretchr/testify/assert" "gotest.tools/assert" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "sigs.k8s.io/controller-runtime/pkg/log" + yaml "sigs.k8s.io/yaml" ) func Test_GeneratePatches(t *testing.T) { @@ -229,3 +232,160 @@ var expectBytes = []byte(` } } `) + +var podBytes = []byte(` +{ + "kind": "Pod", + "apiVersion": "v1", + "metadata": { + "name": "nginx" + }, + "spec": { + "containers": [ + { + "name": "nginx", + "image": "nginx:latest" + }, + { + "name": "nginx-new", + "image": "nginx:latest" + } + ] + } +} +`) + +func Test_preProcessJSONPatches_skip(t *testing.T) { + var policyBytes = []byte(` +{ + "apiVersion": "kyverno.io/v1", + "kind": "ClusterPolicy", + "metadata": { + "name": "insert-container" + }, + "spec": { + "rules": [ + { + "name": "insert-container", + "match": { + "resources": { + "kinds": [ + "Pod" + ] + } + }, + "mutate": { + "patchesJson6902": "- op: add\n path: /spec/containers/1\n value: {\"name\":\"nginx-new\",\"image\":\"nginx:latest\"}" + } + } + ] + } +} +`) + + var pod unstructured.Unstructured + var policy v1.ClusterPolicy + + assertnew.Nil(t, json.Unmarshal(podBytes, &pod)) + assertnew.Nil(t, yaml.Unmarshal(policyBytes, &policy)) + + skip, err := preProcessJSONPatches(policy.Spec.Rules[0].Mutation, pod, log.Log) + assertnew.Nil(t, err) + assertnew.Equal(t, true, skip) +} + +func Test_preProcessJSONPatches_not_skip(t *testing.T) { + var policyBytes = []byte(` +{ + "apiVersion": "kyverno.io/v1", + "kind": "ClusterPolicy", + "metadata": { + "name": "insert-container" + }, + "spec": { + "rules": [ + { + "name": "insert-container", + "match": { + "resources": { + "kinds": [ + "Pod" + ] + } + }, + "mutate": { + "patchesJson6902": "- op: add\n path: /spec/containers/1\n value: {\"name\":\"my-new-container\",\"image\":\"nginx:latest\"}" + } + } + ] + } +} +`) + + var pod unstructured.Unstructured + var policy v1.ClusterPolicy + + assertnew.Nil(t, json.Unmarshal(podBytes, &pod)) + assertnew.Nil(t, yaml.Unmarshal(policyBytes, &policy)) + + skip, err := preProcessJSONPatches(policy.Spec.Rules[0].Mutation, pod, log.Log) + assertnew.Nil(t, err) + assertnew.Equal(t, false, skip) +} + +func Test_isSubsetObject_true(t *testing.T) { + var object, resource interface{} + + objectRaw := []byte(`{"image": "nginx:latest","name": "nginx-new"}`) + resourceRaw := []byte(`{"image": "nginx:latest","name": "random-name"}`) + assertnew.Nil(t, json.Unmarshal(objectRaw, &object)) + assertnew.Nil(t, json.Unmarshal(resourceRaw, &resource)) + assertnew.Equal(t, false, isSubsetObject(object, resource)) + + resourceRawNew := []byte(`{"image": "nginx:latest","name": "nginx-new"}`) + assertnew.Nil(t, json.Unmarshal(resourceRawNew, &resource)) + assertnew.Equal(t, true, isSubsetObject(object, resource)) +} + +func Test_getObject_notPresent(t *testing.T) { + path := "/spec/random/1" + var pod unstructured.Unstructured + + assertnew.Nil(t, json.Unmarshal(podBytes, &pod)) + _, err := getObject(path, pod.UnstructuredContent()) + expectedErr := "referenced value does not exist at spec/random" + assertnew.Equal(t, err.Error(), expectedErr) +} + +func Test_getObject_outOfIndex(t *testing.T) { + path := "/spec/containers/2" + var pod unstructured.Unstructured + + assertnew.Nil(t, json.Unmarshal(podBytes, &pod)) + object, err := getObject(path, pod.UnstructuredContent()) + assertnew.Nil(t, err) + assertnew.Nil(t, object) + +} + +func Test_getObject_success(t *testing.T) { + path := "/spec/containers/1" + var pod unstructured.Unstructured + expectedObject := map[string]interface{}{"image": "nginx:latest", "name": "nginx-new"} + + assertnew.Nil(t, json.Unmarshal(podBytes, &pod)) + object, err := getObject(path, pod.UnstructuredContent()) + assertnew.Nil(t, err) + assertnew.Equal(t, expectedObject, object) +} + +func Test_getObject_get_last_element(t *testing.T) { + path := "/spec/containers/-" + var pod unstructured.Unstructured + expectedObject := map[string]interface{}{"image": "nginx:latest", "name": "nginx-new"} + + assertnew.Nil(t, json.Unmarshal(podBytes, &pod)) + object, err := getObject(path, pod.UnstructuredContent()) + assertnew.Nil(t, err) + assertnew.Equal(t, expectedObject, object) +} diff --git a/pkg/webhookconfig/common.go b/pkg/webhookconfig/common.go index 253b6685f3..7a7cee0512 100644 --- a/pkg/webhookconfig/common.go +++ b/pkg/webhookconfig/common.go @@ -181,7 +181,7 @@ func generateMutatingWebhook(name, servicePath string, caData []byte, validation }, SideEffects: &sideEffect, Rules: []admregapi.RuleWithOperations{ - admregapi.RuleWithOperations{ + { Operations: operationTypes, Rule: admregapi.Rule{ APIGroups: []string{ diff --git a/pkg/webhookconfig/resource.go b/pkg/webhookconfig/resource.go index df7e943bbc..f9d65fe730 100644 --- a/pkg/webhookconfig/resource.go +++ b/pkg/webhookconfig/resource.go @@ -34,6 +34,17 @@ func (wrc *WebhookRegistrationClient) constructDebugMutatingWebhookConfig(caData } func (wrc *WebhookRegistrationClient) constructMutatingWebhookConfig(caData []byte) *admregapi.MutatingWebhookConfiguration { + + webhookCfg := generateMutatingWebhook( + config.MutatingWebhookName, + config.MutatingWebhookServicePath, + caData, false, wrc.timeoutSeconds, + []string{"*/*"}, "*", "*", + []admregapi.OperationType{admregapi.Create, admregapi.Update}) + + reinvoke := admregapi.IfNeededReinvocationPolicy + webhookCfg.ReinvocationPolicy = &reinvoke + return &admregapi.MutatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ Name: config.MutatingWebhookConfigurationName, @@ -41,19 +52,7 @@ func (wrc *WebhookRegistrationClient) constructMutatingWebhookConfig(caData []by wrc.constructOwner(), }, }, - Webhooks: []admregapi.MutatingWebhook{ - generateMutatingWebhook( - config.MutatingWebhookName, - config.MutatingWebhookServicePath, - caData, - false, - wrc.timeoutSeconds, - []string{"*/*"}, - "*", - "*", - []admregapi.OperationType{admregapi.Create, admregapi.Update}, - ), - }, + Webhooks: []admregapi.MutatingWebhook{webhookCfg}, } } From 118b40c64437c9bdbf8302997c96f77023ebacc0 Mon Sep 17 00:00:00 2001 From: Mohan B E <54951236+b-entangled@users.noreply.github.com> Date: Thu, 3 Sep 2020 22:14:54 +0530 Subject: [PATCH 2/2] added invalid field validation for policy (#1094) --- pkg/generate/cleanup/controller.go | 6 ++--- pkg/generate/controller.go | 6 ++--- pkg/generate/generate.go | 12 +++++----- pkg/policy/validate.go | 36 +++++++++++++++++++++++++++++- pkg/webhooks/generation.go | 4 ++-- 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/pkg/generate/cleanup/controller.go b/pkg/generate/cleanup/controller.go index e5f7c7e3bc..95f5e3c60e 100644 --- a/pkg/generate/cleanup/controller.go +++ b/pkg/generate/cleanup/controller.go @@ -172,14 +172,14 @@ func (c *Controller) deleteGR(obj interface{}) { return } } - for _,resource := range gr.Status.GeneratedResources { - r,err := c.client.GetResource(resource.APIVersion,resource.Kind,resource.Namespace,resource.Name) + for _, resource := range gr.Status.GeneratedResources { + r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name) if err != nil { logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName()) } labels := r.GetLabels() if labels["policy.kyverno.io/synchronize"] == "enable" { - if err := c.client.DeleteResource(r.GetAPIVersion(), r.GetKind(),r.GetNamespace(), r.GetName(), false); err != nil { + if err := c.client.DeleteResource(r.GetAPIVersion(), r.GetKind(), r.GetNamespace(), r.GetName(), false); err != nil { logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName()) } } diff --git a/pkg/generate/controller.go b/pkg/generate/controller.go index 0b502e483e..4bbdcf2ffa 100644 --- a/pkg/generate/controller.go +++ b/pkg/generate/controller.go @@ -201,14 +201,14 @@ func (c *Controller) deleteGR(obj interface{}) { return } } - for _,resource := range gr.Status.GeneratedResources { - r,err := c.client.GetResource(resource.APIVersion,resource.Kind,resource.Namespace,resource.Name) + for _, resource := range gr.Status.GeneratedResources { + r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name) if err != nil { logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName()) } labels := r.GetLabels() if labels["policy.kyverno.io/synchronize"] == "enable" { - if err := c.client.DeleteResource(r.GetAPIVersion(), r.GetKind(),r.GetNamespace(), r.GetName(), false); err != nil { + if err := c.client.DeleteResource(r.GetAPIVersion(), r.GetKind(), r.GetNamespace(), r.GetName(), false); err != nil { logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName()) } } diff --git a/pkg/generate/generate.go b/pkg/generate/generate.go index 6d62a4f07f..03f3fd80aa 100644 --- a/pkg/generate/generate.go +++ b/pkg/generate/generate.go @@ -116,8 +116,8 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern continue } for _, v := range grList.Items { - if engineResponse.PolicyResponse.Policy == v.Spec.Policy && engineResponse.PolicyResponse.Resource.Name == v.Spec.Resource.Name && engineResponse.PolicyResponse.Resource.Kind == v.Spec.Resource.Kind && engineResponse.PolicyResponse.Resource.Namespace == v.Spec.Resource.Namespace{ - err :=c.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).Delete(v.GetName(),&metav1.DeleteOptions{}) + if engineResponse.PolicyResponse.Policy == v.Spec.Policy && engineResponse.PolicyResponse.Resource.Name == v.Spec.Resource.Name && engineResponse.PolicyResponse.Resource.Kind == v.Spec.Resource.Kind && engineResponse.PolicyResponse.Resource.Namespace == v.Spec.Resource.Namespace { + err := c.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).Delete(v.GetName(), &metav1.DeleteOptions{}) if err != nil { logger.Error(err, " failed to delete generate request") } @@ -126,7 +126,7 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern if len(engineResponse.PolicyResponse.Rules) > 1 { engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules[:i], engineResponse.PolicyResponse.Rules[i+1:]...) continue - }else if len(engineResponse.PolicyResponse.Rules) == 1 { + } else if len(engineResponse.PolicyResponse.Rules) == 1 { engineResponse.PolicyResponse.Rules = []response.RuleResponse{} } } @@ -160,7 +160,7 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P continue } startTime := time.Now() - genResource, err := applyRule(log, c.client, rule, resource, ctx, policy.Name,gr) + genResource, err := applyRule(log, c.client, rule, resource, ctx, policy.Name, gr) if err != nil { return nil, err } @@ -217,7 +217,7 @@ func updateGenerateExecutionTime(newTime time.Duration, oldAverageTimeString str return time.Duration(newAverageTimeInNanoSeconds) * time.Nanosecond } -func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string,gr kyverno.GenerateRequest) (kyverno.ResourceSpec, error) { +func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, gr kyverno.GenerateRequest) (kyverno.ResourceSpec, error) { var rdata map[string]interface{} var err error var mode ResourceMode @@ -287,10 +287,8 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou return newGenResource, nil } - logger := log.WithValues("genKind", genKind, "genAPIVersion", genAPIVersion, "genNamespace", genNamespace, "genName", genName) - // build the resource template newResource := &unstructured.Unstructured{} newResource.SetUnstructuredContent(rdata) diff --git a/pkg/policy/validate.go b/pkg/policy/validate.go index 3d157b13c3..136ca94705 100644 --- a/pkg/policy/validate.go +++ b/pkg/policy/validate.go @@ -22,8 +22,14 @@ import ( // - One operation per rule // - ResourceDescription mandatory checks func Validate(policyRaw []byte, client *dclient.Client, mock bool, openAPIController *openapi.Controller) error { + // check for invalid fields + err := checkInvalidFields(policyRaw) + if err != nil { + return err + } + var p kyverno.ClusterPolicy - err := json.Unmarshal(policyRaw, &p) + err = json.Unmarshal(policyRaw, &p) if err != nil { return fmt.Errorf("failed to unmarshal policy admission request err %v", err) } @@ -119,6 +125,34 @@ func Validate(policyRaw []byte, client *dclient.Client, mock bool, openAPIContro return nil } +// checkInvalidFields - checks invalid fields in webhook policy request +// policy supports 5 json fields in types.go i.e. "apiVersion", "kind", "metadata", "spec", "status" +// If the webhook request policy contains new fields then block creation of policy +func checkInvalidFields(policyRaw []byte) error { + // hardcoded supported fields by policy + var allowedKeys = []string{"apiVersion", "kind", "metadata", "spec", "status"} + var data interface{} + err := json.Unmarshal(policyRaw, &data) + if err != nil { + return fmt.Errorf("failed to unmarshal policy admission request err %v", err) + } + mapData := data.(map[string]interface{}) + // validate any new fields in the admission request against the supported fields and block the request with any new fields + for requestField, _ := range mapData { + ok := false + for _, allowedField := range allowedKeys { + if requestField == allowedField { + ok = true + break + } + } + if !ok { + return fmt.Errorf("unknown field \"%s\" in policy admission request", requestField) + } + } + return nil +} + // doesMatchAndExcludeConflict checks if the resultant // of match and exclude block is not an empty set func doesMatchAndExcludeConflict(rule kyverno.Rule) bool { diff --git a/pkg/webhooks/generation.go b/pkg/webhooks/generation.go index c56f256a0d..dab3ef07eb 100644 --- a/pkg/webhooks/generation.go +++ b/pkg/webhooks/generation.go @@ -58,7 +58,7 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic } for _, v := range grList.Items { if engineResponse.PolicyResponse.Policy == v.Spec.Policy && engineResponse.PolicyResponse.Resource.Name == v.Spec.Resource.Name && engineResponse.PolicyResponse.Resource.Kind == v.Spec.Resource.Kind && engineResponse.PolicyResponse.Resource.Namespace == v.Spec.Resource.Namespace { - err := ws.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).Delete(v.GetName(),&metav1.DeleteOptions{}) + err := ws.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).Delete(v.GetName(), &metav1.DeleteOptions{}) if err != nil { logger.Error(err, "failed to update gr") } @@ -67,7 +67,7 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic if len(engineResponse.PolicyResponse.Rules) > 1 { engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules[:i], engineResponse.PolicyResponse.Rules[i+1:]...) continue - }else if len(engineResponse.PolicyResponse.Rules) == 1 { + } else if len(engineResponse.PolicyResponse.Rules) == 1 { engineResponse.PolicyResponse.Rules = []response.RuleResponse{} } }