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

Added Support for CSR in x509_decode() (#6744)

* fixes

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* err fix

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* added kuttl tests

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* updated files for test

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* updated tests

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* NIT

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* Update test/conformance/kuttl/validate/clusterpolicy/standard/enforce/csr/01-policy.yaml

Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
Signed-off-by: Vishal Choudhary <contactvishaltech@gmail.com>

* updated kuttl tests

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* added tests

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* updated readme

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* added requested changes

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* refactor

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* refactor

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* changes

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* refactor

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

---------

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>
Signed-off-by: Vishal Choudhary <contactvishaltech@gmail.com>
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Vishal Choudhary 2023-04-14 15:06:38 +05:30 committed by GitHub
parent e5a9148a75
commit 77bb5aca12
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 191 additions and 41 deletions

View file

@ -3,6 +3,7 @@ package jmespath
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/asn1"
"encoding/base64"
@ -1059,58 +1060,79 @@ func jpRandom(arguments []interface{}) (interface{}, error) {
return ans, nil
}
func jpX509Decode(arguments []interface{}) (interface{}, error) {
res := make(map[string]interface{})
input, err := validateArg(x509_decode, arguments, 0, reflect.String)
if err != nil {
func encode[T any](in T) (interface{}, error) {
buf := new(bytes.Buffer)
enc := json.NewEncoder(buf)
if err := enc.Encode(in); err != nil {
return nil, err
}
p, _ := pem.Decode([]byte(input.String()))
if p == nil {
return res, errors.New("invalid certificate")
res := map[string]interface{}{}
if err := json.Unmarshal(buf.Bytes(), &res); err != nil {
return nil, err
}
return res, nil
}
cert, err := x509.ParseCertificate(p.Bytes)
if err != nil {
return res, err
}
buf := new(bytes.Buffer)
if fmt.Sprint(cert.PublicKeyAlgorithm) == "RSA" {
spki := cryptobyte.String(cert.RawSubjectPublicKeyInfo)
func jpX509Decode(arguments []interface{}) (interface{}, error) {
parseSubjectPublicKeyInfo := func(data []byte) (*rsa.PublicKey, error) {
spki := cryptobyte.String(data)
if !spki.ReadASN1(&spki, cryptobyte_asn1.SEQUENCE) {
return res, errors.New("writing asn.1 element to 'spki' failed")
return nil, errors.New("writing asn.1 element to 'spki' failed")
}
var pkAISeq cryptobyte.String
if !spki.ReadASN1(&pkAISeq, cryptobyte_asn1.SEQUENCE) {
return res, errors.New("writing asn.1 element to 'pkAISeq' failed")
return nil, errors.New("writing asn.1 element to 'pkAISeq' failed")
}
var spk asn1.BitString
if !spki.ReadASN1BitString(&spk) {
return res, errors.New("writing asn.1 bit string to 'spk' failed")
return nil, errors.New("writing asn.1 bit string to 'spk' failed")
}
kk, err := x509.ParsePKCS1PublicKey(spk.Bytes)
if err != nil {
return res, err
}
cert.PublicKey = PublicKey{
N: kk.N.String(),
E: kk.E,
}
enc := json.NewEncoder(buf)
err = enc.Encode(cert)
if err != nil {
return res, err
if kk, err := x509.ParsePKCS1PublicKey(spk.Bytes); err != nil {
return nil, err
} else {
return kk, nil
}
}
if err := json.Unmarshal(buf.Bytes(), &res); err != nil {
return res, err
if input, err := validateArg(x509_decode, arguments, 0, reflect.String); err != nil {
return nil, err
} else if block, _ := pem.Decode([]byte(input.String())); block == nil {
return nil, errors.New("failed to decode PEM block")
} else {
switch block.Type {
case "CERTIFICATE":
var cert *x509.Certificate
if cert, err = x509.ParseCertificate(block.Bytes); err != nil {
return nil, err
} else if cert.PublicKeyAlgorithm != x509.RSA {
return nil, errors.New("certificate should use rsa algorithm")
} else if pk, err := parseSubjectPublicKeyInfo(cert.RawSubjectPublicKeyInfo); err != nil {
return nil, errors.New("failed to parse subject public key info")
} else {
cert.PublicKey = PublicKey{
N: pk.N.String(),
E: pk.E,
}
return encode(cert)
}
case "CERTIFICATE REQUEST":
var csr *x509.CertificateRequest
if csr, err = x509.ParseCertificateRequest(block.Bytes); err != nil {
return nil, err
} else if csr.PublicKeyAlgorithm != x509.RSA {
return nil, errors.New("certificate should use rsa algorithm")
} else if pk, err := parseSubjectPublicKeyInfo(csr.RawSubjectPublicKeyInfo); err != nil {
return nil, errors.New("failed to parse subject public key info")
} else {
csr.PublicKey = PublicKey{
N: pk.N.String(),
E: pk.E,
}
return encode(csr)
}
default:
return nil, errors.New("PEM block neither contains a CERTIFICATE or CERTIFICATE REQUEST")
}
}
return res, nil
}
func jpImageNormalize(configuration config.Configuration) gojmespath.JpFunction {

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,6 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
apply:
- policy.yaml
assert:
- policy-ready.yaml

View file

@ -0,0 +1,6 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
apply:
- csr.yaml
assert:
- csr-mutated.yaml

View file

@ -0,0 +1,12 @@
## Description
This test mainly verifies that the JMESPath path for x509decode works for CSR does work properly.
## Expected Behavior
1. A policy is created to check Certificate Signing Requests and a policy that adds labels to the CSR.
2. A CSR Resource is created and it is verified that it has the same labels.
## Reference Issue(s)
5858

View file

@ -0,0 +1,6 @@
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: myuser
labels:
name: angela

View file

@ -0,0 +1,10 @@
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: myuser
spec:
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 86400
usages:
- client auth

View file

@ -0,0 +1,19 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: validate-csr
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: mutate-csr
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -0,0 +1,46 @@
apiVersion: kyverno.io/v2beta1
kind: ClusterPolicy
metadata:
name: validate-csr
spec:
background: false
validationFailureAction: Enforce
rules:
- name: csr
match:
any:
- resources:
kinds:
- CertificateSigningRequest
validate:
message: >-
CSR created by {{ request.userInfo | to_string(@) }}
with ClusterRoles {{ request.clusterRoles | to_string(@) }}
and Roles {{ request.roles | to_string(@) }}.
Subjects and groups requested are "{{ x509_decode(base64_decode(request.object.spec.request)).Subject | to_string(@) }}"
deny:
conditions:
any:
- key: "{{ x509_decode(base64_decode(request.object.spec.request)).Subject.CommonName }}"
operator: NotEquals
value: "angela"
---
apiVersion: kyverno.io/v2beta1
kind: ClusterPolicy
metadata:
name: mutate-csr
spec:
background: false
validationFailureAction: Enforce
rules:
- name: csr
match:
any:
- resources:
kinds:
- CertificateSigningRequest
mutate:
patchStrategicMerge:
metadata:
labels:
name: "{{ x509_decode(base64_decode(request.object.spec.request)).Subject.CommonName | to_string(@) }}"