1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-14 19:58:45 +00:00

Merge pull request #147 from nirmata/78_refactor

Go Report formatting and support
This commit is contained in:
shuting 2019-06-05 18:33:51 -07:00 committed by GitHub
commit 01d6af03bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 92 additions and 65 deletions

View file

@ -14,6 +14,9 @@ install: true
script: script:
- make build - make build
after_script:
- curl -d "repo=https://github.com/nirmata/kyverno" https://goreportcard.com/checks
after_success: after_success:
- docker login -u $DOCKER_USER -p $DOCKER_PASSWORD - docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
- make docker-publish - make docker-publish

View file

@ -1,6 +1,6 @@
# Kyverno - Kubernetes Native Policy Management # Kyverno - Kubernetes Native Policy Management
[![Build Status](https://travis-ci.org/nirmata/kyverno.svg?branch=master)](https://travis-ci.org/nirmata/kyverno) [![Build Status](https://travis-ci.org/nirmata/kyverno.svg?branch=master)](https://travis-ci.org/nirmata/kyverno) [![Go Report Card](https://goreportcard.com/badge/github.com/nirmata/kyverno)](https://goreportcard.com/report/github.com/nirmata/kyverno)
![logo](documentation/images/Kyverno_Horizontal.png) ![logo](documentation/images/Kyverno_Horizontal.png)

View file

@ -28,7 +28,7 @@ func createClientConfig(kubeconfig string) (*rest.Config, error) {
// Loads or creates PEM private key and TLS certificate for webhook server. // Loads or creates PEM private key and TLS certificate for webhook server.
// Created pair is stored in cluster's secret. // Created pair is stored in cluster's secret.
// Returns struct with key/certificate pair. // Returns struct with key/certificate pair.
func initTlsPemPair(configuration *rest.Config, client *client.Client) (*tls.TlsPemPair, error) { func initTLSPemPair(configuration *rest.Config, client *client.Client) (*tls.TlsPemPair, error) {
certProps, err := client.GetTLSCertProps(configuration) certProps, err := client.GetTLSCertProps(configuration)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -45,7 +45,7 @@ func main() {
violationBuilder, violationBuilder,
eventController) eventController)
tlsPair, err := initTlsPemPair(clientConfig, client) tlsPair, err := initTLSPemPair(clientConfig, client)
if err != nil { if err != nil {
glog.Fatalf("Failed to initialize TLS key/certificate pair: %v\n", err) glog.Fatalf("Failed to initialize TLS key/certificate pair: %v\n", err)
} }

View file

@ -85,7 +85,7 @@ type Violation struct {
Resource string `json:"resource,omitempty"` Resource string `json:"resource,omitempty"`
Rule string `json:"rule,omitempty"` Rule string `json:"rule,omitempty"`
Reason string `json:"reason,omitempty"` Reason string `json:"reason,omitempty"`
Message string `json:"message,omitempty` Message string `json:"message,omitempty"`
} }
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

View file

@ -102,6 +102,7 @@ func (pc *PolicyController) Run(stopCh <-chan struct{}) error {
return nil return nil
} }
//Stop to perform actions when controller is stopped
func (pc *PolicyController) Stop() { func (pc *PolicyController) Stop() {
glog.Info("shutting down policy controller workers") glog.Info("shutting down policy controller workers")
} }
@ -144,7 +145,7 @@ func (pc *PolicyController) handleErr(err error, key interface{}) {
} }
pc.queue.Forget(key) pc.queue.Forget(key)
utilruntime.HandleError(err) utilruntime.HandleError(err)
glog.Warning("Dropping the key %q out of the queue: %v", key, err) glog.Warningf("Dropping the key %q out of the queue: %v", key, err)
} }
func (pc *PolicyController) syncHandler(obj interface{}) error { func (pc *PolicyController) syncHandler(obj interface{}) error {

View file

@ -16,7 +16,7 @@ import (
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
) )
// Issues TLS certificate for webhook server using given PEM private key //GenerateTlsPemPair Issues TLS certificate for webhook server using given PEM private key
// Returns signed and approved TLS certificate in PEM format // Returns signed and approved TLS certificate in PEM format
func (c *Client) GenerateTlsPemPair(props tls.TlsCertificateProps) (*tls.TlsPemPair, error) { func (c *Client) GenerateTlsPemPair(props tls.TlsCertificateProps) (*tls.TlsPemPair, error) {
privateKey, err := tls.TlsGeneratePrivateKey() privateKey, err := tls.TlsGeneratePrivateKey()
@ -26,17 +26,17 @@ func (c *Client) GenerateTlsPemPair(props tls.TlsCertificateProps) (*tls.TlsPemP
certRequest, err := tls.TlsCertificateGenerateRequest(privateKey, props) certRequest, err := tls.TlsCertificateGenerateRequest(privateKey, props)
if err != nil { if err != nil {
return nil, errors.New(fmt.Sprintf("Unable to create certificate request: %v", err)) return nil, fmt.Errorf("Unable to create certificate request: %v", err)
} }
certRequest, err = c.submitAndApproveCertificateRequest(certRequest) certRequest, err = c.submitAndApproveCertificateRequest(certRequest)
if err != nil { if err != nil {
return nil, errors.New(fmt.Sprintf("Unable to submit and approve certificate request: %v", err)) return nil, fmt.Errorf("Unable to submit and approve certificate request: %v", err)
} }
tlsCert, err := c.fetchCertificateFromRequest(certRequest, 10) tlsCert, err := c.fetchCertificateFromRequest(certRequest, 10)
if err != nil { if err != nil {
return nil, errors.New(fmt.Sprintf("Failed to configure a certificate for the Kyverno controller. A CA certificate is required to allow the Kubernetes API Server to communicate with Kyverno. You can either provide a certificate or configure your cluster to allow certificate signing. Please refer to https://github.com/nirmata/kyverno/installation.md.: %v", err)) return nil, fmt.Errorf("Failed to configure a certificate for the Kyverno controller. A CA certificate is required to allow the Kubernetes API Server to communicate with Kyverno. You can either provide a certificate or configure your cluster to allow certificate signing. Please refer to https://github.com/nirmata/kyverno/installation.md.: %v", err)
} }
return &tls.TlsPemPair{ return &tls.TlsPemPair{
@ -53,14 +53,14 @@ func (c *Client) submitAndApproveCertificateRequest(req *certificates.Certificat
} }
csrList, err := c.ListResource(CSRs, "") csrList, err := c.ListResource(CSRs, "")
if err != nil { if err != nil {
return nil, errors.New(fmt.Sprintf("Unable to list existing certificate requests: %v", err)) return nil, fmt.Errorf("Unable to list existing certificate requests: %v", err)
} }
for _, csr := range csrList.Items { for _, csr := range csrList.Items {
if csr.GetName() == req.ObjectMeta.Name { if csr.GetName() == req.ObjectMeta.Name {
err := c.DeleteResouce(CSRs, "", csr.GetName()) err := c.DeleteResouce(CSRs, "", csr.GetName())
if err != nil { if err != nil {
return nil, errors.New(fmt.Sprintf("Unable to delete existing certificate request: %v", err)) return nil, fmt.Errorf("Unable to delete existing certificate request: %v", err)
} }
glog.Info("Old certificate request is deleted") glog.Info("Old certificate request is deleted")
break break
@ -84,7 +84,7 @@ func (c *Client) submitAndApproveCertificateRequest(req *certificates.Certificat
}) })
res, err = certClient.UpdateApproval(res) res, err = certClient.UpdateApproval(res)
if err != nil { if err != nil {
return nil, errors.New(fmt.Sprintf("Unable to approve certificate request: %v", err)) return nil, fmt.Errorf("Unable to approve certificate request: %v", err)
} }
glog.Infof("Certificate request %s is approved", res.ObjectMeta.Name) glog.Infof("Certificate request %s is approved", res.ObjectMeta.Name)
@ -115,9 +115,10 @@ func (c *Client) fetchCertificateFromRequest(req *certificates.CertificateSignin
} }
} }
} }
return nil, errors.New(fmt.Sprintf("Cerificate fetch timeout is reached: %d seconds", maxWaitSeconds)) return nil, fmt.Errorf("Cerificate fetch timeout is reached: %d seconds", maxWaitSeconds)
} }
//ReadRootCASecret returns the RootCA from the pre-defined secret
func (c *Client) ReadRootCASecret() (result []byte) { func (c *Client) ReadRootCASecret() (result []byte) {
certProps, err := c.GetTLSCertProps(c.clientConfig) certProps, err := c.GetTLSCertProps(c.clientConfig)
if err != nil { if err != nil {
@ -147,7 +148,7 @@ func (c *Client) ReadRootCASecret() (result []byte) {
const selfSignedAnnotation string = "self-signed-cert" const selfSignedAnnotation string = "self-signed-cert"
const rootCAKey string = "rootCA.crt" const rootCAKey string = "rootCA.crt"
// Reads the pair of TLS certificate and key from the specified secret. //ReadTlsPair Reads the pair of TLS certificate and key from the specified secret.
func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair { func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair {
sname := generateTLSPairSecretName(props) sname := generateTLSPairSecretName(props)
unstrSecret, err := c.GetResource(Secrets, props.Namespace, sname) unstrSecret, err := c.GetResource(Secrets, props.Namespace, sname)
@ -186,7 +187,7 @@ func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair {
return &pemPair return &pemPair
} }
// Writes the pair of TLS certificate and key to the specified secret. //WriteTlsPair Writes the pair of TLS certificate and key to the specified secret.
// Updates existing secret or creates new one. // Updates existing secret or creates new one.
func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPemPair) error { func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPemPair) error {
name := generateTLSPairSecretName(props) name := generateTLSPairSecretName(props)

View file

@ -25,6 +25,7 @@ import (
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
) )
//Client enables interaction with k8 resource
type Client struct { type Client struct {
client dynamic.Interface client dynamic.Interface
cachedClient discovery.CachedDiscoveryInterface cachedClient discovery.CachedDiscoveryInterface
@ -32,6 +33,7 @@ type Client struct {
kclient *kubernetes.Clientset kclient *kubernetes.Clientset
} }
//NewClient creates new instance of client
func NewClient(config *rest.Config) (*Client, error) { func NewClient(config *rest.Config) (*Client, error) {
client, err := dynamic.NewForConfig(config) client, err := dynamic.NewForConfig(config)
if err != nil { if err != nil {
@ -51,6 +53,7 @@ func NewClient(config *rest.Config) (*Client, error) {
}, nil }, nil
} }
//GetKubePolicyDeployment returns kube policy depoyment value
func (c *Client) GetKubePolicyDeployment() (*apps.Deployment, error) { func (c *Client) GetKubePolicyDeployment() (*apps.Deployment, error) {
kubePolicyDeployment, err := c.GetResource("deployments", config.KubePolicyNamespace, config.KubePolicyDeploymentName) kubePolicyDeployment, err := c.GetResource("deployments", config.KubePolicyNamespace, config.KubePolicyDeploymentName)
if err != nil { if err != nil {
@ -63,13 +66,14 @@ func (c *Client) GetKubePolicyDeployment() (*apps.Deployment, error) {
return &deploy, nil return &deploy, nil
} }
//GetEventsInterface provides typed interface for events
//TODO: can we use dynamic client to fetch the typed interface //TODO: can we use dynamic client to fetch the typed interface
// or generate a kube client value to access the interface // or generate a kube client value to access the interface
//GetEventsInterface provides typed interface for events
func (c *Client) GetEventsInterface() (event.EventInterface, error) { func (c *Client) GetEventsInterface() (event.EventInterface, error) {
return c.kclient.CoreV1().Events(""), nil return c.kclient.CoreV1().Events(""), nil
} }
//GetCSRInterface provides type interface for CSR
func (c *Client) GetCSRInterface() (csrtype.CertificateSigningRequestInterface, error) { func (c *Client) GetCSRInterface() (csrtype.CertificateSigningRequestInterface, error) {
return c.kclient.CertificatesV1beta1().CertificateSigningRequests(), nil return c.kclient.CertificatesV1beta1().CertificateSigningRequests(), nil
} }
@ -110,6 +114,7 @@ func (c *Client) ListResource(resource string, namespace string) (*unstructured.
return c.getResourceInterface(resource, namespace).List(meta.ListOptions{}) return c.getResourceInterface(resource, namespace).List(meta.ListOptions{})
} }
// DeleteResouce deletes the specified resource
func (c *Client) DeleteResouce(resource string, namespace string, name string) error { func (c *Client) DeleteResouce(resource string, namespace string, name string) error {
return c.getResourceInterface(resource, namespace).Delete(name, &meta.DeleteOptions{}) return c.getResourceInterface(resource, namespace).Delete(name, &meta.DeleteOptions{})
@ -228,7 +233,7 @@ func convertToCSR(obj *unstructured.Unstructured) (*certificates.CertificateSign
func (c *Client) waitUntilNamespaceIsCreated(name string) error { func (c *Client) waitUntilNamespaceIsCreated(name string) error {
timeStart := time.Now() timeStart := time.Now()
var lastError error = nil var lastError error
for time.Now().Sub(timeStart) < namespaceCreationMaxWaitTime { for time.Now().Sub(timeStart) < namespaceCreationMaxWaitTime {
_, lastError = c.GetResource(Namespaces, "", name) _, lastError = c.GetResource(Namespaces, "", name)
if lastError == nil { if lastError == nil {
@ -253,7 +258,7 @@ func (c *Client) getGVR(resource string) schema.GroupVersionResource {
} }
//TODO using cached client to support cache validation and invalidation //TODO using cached client to support cache validation and invalidation
// iterate over the key to compare the resource // iterate over the key to compare the resource
for gvr, _ := range resources { for gvr := range resources {
if gvr.Resource == resource { if gvr.Resource == resource {
return gvr return gvr
} }

View file

@ -5,9 +5,13 @@ import (
) )
const ( const (
CSRs string = "certificatesigningrequests" //CSRs certificatesigningrequests
Secrets string = "secrets" CSRs string = "certificatesigningrequests"
// Secrets secrets
Secrets string = "secrets"
// ConfigMaps configmaps
ConfigMaps string = "configmaps" ConfigMaps string = "configmaps"
// Namespaces namespaces
Namespaces string = "namespaces" Namespaces string = "namespaces"
) )
const namespaceCreationMaxWaitTime time.Duration = 30 * time.Second const namespaceCreationMaxWaitTime time.Duration = 30 * time.Second

View file

@ -13,7 +13,7 @@ import (
) )
// ProcessOverlay handles validating admission request // ProcessOverlay handles validating admission request
// Checks the target resourse for rules defined in the policy // Checks the target resources for rules defined in the policy
func ProcessOverlay(rule kubepolicy.Rule, rawResource []byte, gvk metav1.GroupVersionKind) ([]PatchBytes, result.RuleApplicationResult) { func ProcessOverlay(rule kubepolicy.Rule, rawResource []byte, gvk metav1.GroupVersionKind) ([]PatchBytes, result.RuleApplicationResult) {
overlayApplicationResult := result.NewRuleApplicationResult(rule.Name) overlayApplicationResult := result.NewRuleApplicationResult(rule.Name)
if rule.Mutation == nil || rule.Mutation.Overlay == nil { if rule.Mutation == nil || rule.Mutation.Overlay == nil {
@ -112,7 +112,7 @@ func applyOverlayToArray(resource, overlay []interface{}, path string, res *resu
case map[string]interface{}: case map[string]interface{}:
for _, overlayElement := range overlay { for _, overlayElement := range overlay {
typedOverlay := overlayElement.(map[string]interface{}) typedOverlay := overlayElement.(map[string]interface{})
anchors := GetAnchorsFromMap(typedOverlay) anchors := getAnchorsFromMap(typedOverlay)
if len(anchors) > 0 { if len(anchors) > 0 {
for i, resourceElement := range resource { for i, resourceElement := range resource {
typedResource := resourceElement.(map[string]interface{}) typedResource := resourceElement.(map[string]interface{})
@ -170,7 +170,7 @@ func fillEmptyArray(overlay []interface{}, path string, res *result.RuleApplicat
case map[string]interface{}: case map[string]interface{}:
for _, overlayElement := range overlay { for _, overlayElement := range overlay {
typedOverlay := overlayElement.(map[string]interface{}) typedOverlay := overlayElement.(map[string]interface{})
anchors := GetAnchorsFromMap(typedOverlay) anchors := getAnchorsFromMap(typedOverlay)
if len(anchors) == 0 { if len(anchors) == 0 {
patch := insertSubtree(overlayElement, path, res) patch := insertSubtree(overlayElement, path, res)
@ -287,7 +287,7 @@ func prepareJSONValue(overlay interface{}) string {
func hasOnlyAnchors(overlay interface{}) bool { func hasOnlyAnchors(overlay interface{}) bool {
switch typed := overlay.(type) { switch typed := overlay.(type) {
case map[string]interface{}: case map[string]interface{}:
if anchors := GetAnchorsFromMap(typed); len(anchors) == len(typed) { if anchors := getAnchorsFromMap(typed); len(anchors) == len(typed) {
return true return true
} }
@ -306,7 +306,7 @@ func hasOnlyAnchors(overlay interface{}) bool {
func hasNestedAnchors(overlay interface{}) bool { func hasNestedAnchors(overlay interface{}) bool {
switch typed := overlay.(type) { switch typed := overlay.(type) {
case map[string]interface{}: case map[string]interface{}:
if anchors := GetAnchorsFromMap(typed); len(anchors) > 0 { if anchors := getAnchorsFromMap(typed); len(anchors) > 0 {
return true return true
} }

View file

@ -18,7 +18,7 @@ func ResourceMeetsDescription(resourceRaw []byte, description kubepolicy.Resourc
} }
if resourceRaw != nil { if resourceRaw != nil {
meta := ParseMetadataFromObject(resourceRaw) meta := parseMetadataFromObject(resourceRaw)
name := ParseNameFromObject(resourceRaw) name := ParseNameFromObject(resourceRaw)
if description.Name != nil { if description.Name != nil {
@ -35,7 +35,7 @@ func ResourceMeetsDescription(resourceRaw []byte, description kubepolicy.Resourc
return false return false
} }
labelMap := ParseLabelsFromMetadata(meta) labelMap := parseLabelsFromMetadata(meta)
if !selector.Matches(labelMap) { if !selector.Matches(labelMap) {
return false return false
@ -46,21 +46,21 @@ func ResourceMeetsDescription(resourceRaw []byte, description kubepolicy.Resourc
return true return true
} }
func ParseMetadataFromObject(bytes []byte) map[string]interface{} { func parseMetadataFromObject(bytes []byte) map[string]interface{} {
var objectJSON map[string]interface{} var objectJSON map[string]interface{}
json.Unmarshal(bytes, &objectJSON) json.Unmarshal(bytes, &objectJSON)
return objectJSON["metadata"].(map[string]interface{}) return objectJSON["metadata"].(map[string]interface{})
} }
func ParseKindFromObject(bytes []byte) string { func parseKindFromObject(bytes []byte) string {
var objectJSON map[string]interface{} var objectJSON map[string]interface{}
json.Unmarshal(bytes, &objectJSON) json.Unmarshal(bytes, &objectJSON)
return objectJSON["kind"].(string) return objectJSON["kind"].(string)
} }
func ParseLabelsFromMetadata(meta map[string]interface{}) labels.Set { func parseLabelsFromMetadata(meta map[string]interface{}) labels.Set {
if interfaceMap, ok := meta["labels"].(map[string]interface{}); ok { if interfaceMap, ok := meta["labels"].(map[string]interface{}); ok {
labelMap := make(labels.Set, len(interfaceMap)) labelMap := make(labels.Set, len(interfaceMap))
@ -72,6 +72,7 @@ func ParseLabelsFromMetadata(meta map[string]interface{}) labels.Set {
return nil return nil
} }
//ParseNameFromObject extracts resource name from JSON obj
func ParseNameFromObject(bytes []byte) string { func ParseNameFromObject(bytes []byte) string {
var objectJSON map[string]interface{} var objectJSON map[string]interface{}
json.Unmarshal(bytes, &objectJSON) json.Unmarshal(bytes, &objectJSON)
@ -84,6 +85,7 @@ func ParseNameFromObject(bytes []byte) string {
return "" return ""
} }
// ParseNamespaceFromObject extracts the namespace from the JSON obj
func ParseNamespaceFromObject(bytes []byte) string { func ParseNamespaceFromObject(bytes []byte) string {
var objectJSON map[string]interface{} var objectJSON map[string]interface{}
json.Unmarshal(bytes, &objectJSON) json.Unmarshal(bytes, &objectJSON)
@ -105,7 +107,7 @@ func ParseRegexPolicyResourceName(policyResourceName string) (string, bool) {
return strings.Trim(regex[1], " "), true return strings.Trim(regex[1], " "), true
} }
func GetAnchorsFromMap(anchorsMap map[string]interface{}) map[string]interface{} { func getAnchorsFromMap(anchorsMap map[string]interface{}) map[string]interface{} {
result := make(map[string]interface{}) result := make(map[string]interface{})
for key, value := range anchorsMap { for key, value := range anchorsMap {

View file

@ -10,7 +10,7 @@ import (
) )
// Validate handles validating admission request // Validate handles validating admission request
// Checks the target resourse for rules defined in the policy // Checks the target resources for rules defined in the policy
func Validate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) result.Result { func Validate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) result.Result {
var resource interface{} var resource interface{}
json.Unmarshal(rawResource, &resource) json.Unmarshal(rawResource, &resource)
@ -116,7 +116,7 @@ func validateArray(resourceArray, patternArray []interface{}, path string) resul
switch pattern := patternArray[0].(type) { switch pattern := patternArray[0].(type) {
case map[string]interface{}: case map[string]interface{}:
anchors := GetAnchorsFromMap(pattern) anchors := getAnchorsFromMap(pattern)
for i, value := range resourceArray { for i, value := range resourceArray {
currentPath := path + strconv.Itoa(i) + "/" currentPath := path + strconv.Itoa(i) + "/"
resource, ok := value.(map[string]interface{}) resource, ok := value.(map[string]interface{})

View file

@ -206,7 +206,7 @@ func TestGetAnchorsFromMap_ThereAreAnchors(t *testing.T) {
var unmarshalled map[string]interface{} var unmarshalled map[string]interface{}
json.Unmarshal(rawMap, &unmarshalled) json.Unmarshal(rawMap, &unmarshalled)
actualMap := GetAnchorsFromMap(unmarshalled) actualMap := getAnchorsFromMap(unmarshalled)
assert.Equal(t, len(actualMap), 2) assert.Equal(t, len(actualMap), 2)
assert.Equal(t, actualMap["(name)"].(string), "nirmata-*") assert.Equal(t, actualMap["(name)"].(string), "nirmata-*")
assert.Equal(t, actualMap["(namespace)"].(string), "kube-?olicy") assert.Equal(t, actualMap["(namespace)"].(string), "kube-?olicy")
@ -227,7 +227,7 @@ func TestGetAnchorsFromMap_ThereAreNoAnchors(t *testing.T) {
var unmarshalled map[string]interface{} var unmarshalled map[string]interface{}
json.Unmarshal(rawMap, &unmarshalled) json.Unmarshal(rawMap, &unmarshalled)
actualMap := GetAnchorsFromMap(unmarshalled) actualMap := getAnchorsFromMap(unmarshalled)
assert.Assert(t, len(actualMap) == 0) assert.Assert(t, len(actualMap) == 0)
} }

View file

@ -17,6 +17,7 @@ type Info struct {
//MsgKey is an identified to determine the preset message formats //MsgKey is an identified to determine the preset message formats
type MsgKey int type MsgKey int
//Message id for pre-defined messages
const ( const (
FResourcePolcy MsgKey = iota FResourcePolcy MsgKey = iota
FProcessRule FProcessRule

View file

@ -4,9 +4,9 @@ package result
type Reason int type Reason int
const ( const (
//PolicyViolation there is a violation of policy
Success Reason = iota
//Success policy applied //Success policy applied
Success Reason = iota
//Violation there is a violation of policy
Violation Violation
//Failed the request to create/update the resource was blocked(generated from admission-controller) //Failed the request to create/update the resource was blocked(generated from admission-controller)
Failed Failed

View file

@ -37,6 +37,7 @@ type RuleApplicationResult struct {
Messages []string Messages []string
} }
//NewRuleApplicationResult creates a new rule application result
func NewRuleApplicationResult(ruleName string) RuleApplicationResult { func NewRuleApplicationResult(ruleName string) RuleApplicationResult {
return RuleApplicationResult{ return RuleApplicationResult{
PolicyRule: ruleName, PolicyRule: ruleName,
@ -67,6 +68,7 @@ func (e *RuleApplicationResult) String() string {
return e.StringWithIndent("") return e.StringWithIndent("")
} }
// ToError returns the error if reason is not success
func (e *RuleApplicationResult) ToError() error { func (e *RuleApplicationResult) ToError() error {
if e.Reason != Success { if e.Reason != Success {
return fmt.Errorf(e.String()) return fmt.Errorf(e.String())
@ -74,22 +76,23 @@ func (e *RuleApplicationResult) ToError() error {
return nil return nil
} }
//GetReason returns reason
func (e *RuleApplicationResult) GetReason() Reason { func (e *RuleApplicationResult) GetReason() Reason {
return e.Reason return e.Reason
} }
// Adds formatted message to this result //AddMessagef Adds formatted message to this result
func (rar *RuleApplicationResult) AddMessagef(message string, a ...interface{}) { func (e *RuleApplicationResult) AddMessagef(message string, a ...interface{}) {
rar.Messages = append(rar.Messages, fmt.Sprintf(message, a...)) e.Messages = append(e.Messages, fmt.Sprintf(message, a...))
} }
// Sets the Reason Failed and adds formatted message to this result //FailWithMessagef Sets the Reason Failed and adds formatted message to this result
func (rar *RuleApplicationResult) FailWithMessagef(message string, a ...interface{}) { func (e *RuleApplicationResult) FailWithMessagef(message string, a ...interface{}) {
rar.Reason = Failed e.Reason = Failed
rar.AddMessagef(message, a...) e.AddMessagef(message, a...)
} }
// Takes messages and higher reason from another RuleApplicationResult //MergeWith Takes messages and higher reason from another RuleApplicationResult
func (e *RuleApplicationResult) MergeWith(other *RuleApplicationResult) { func (e *RuleApplicationResult) MergeWith(other *RuleApplicationResult) {
if other != nil { if other != nil {
e.Messages = append(e.Messages, other.Messages...) e.Messages = append(e.Messages, other.Messages...)
@ -122,6 +125,7 @@ func (e *CompositeResult) String() string {
return e.StringWithIndent("") return e.StringWithIndent("")
} }
//ToError returns error if reason is not success
func (e *CompositeResult) ToError() error { func (e *CompositeResult) ToError() error {
if e.Reason != Success { if e.Reason != Success {
return fmt.Errorf(e.String()) return fmt.Errorf(e.String())
@ -129,10 +133,12 @@ func (e *CompositeResult) ToError() error {
return nil return nil
} }
//GetReason returns reason
func (e *CompositeResult) GetReason() Reason { func (e *CompositeResult) GetReason() Reason {
return e.Reason return e.Reason
} }
//NewPolicyApplicationResult creates a new policy application result
func NewPolicyApplicationResult(policyName string) Result { func NewPolicyApplicationResult(policyName string) Result {
return &CompositeResult{ return &CompositeResult{
Message: fmt.Sprintf("policy - %s:", policyName), Message: fmt.Sprintf("policy - %s:", policyName),
@ -140,6 +146,7 @@ func NewPolicyApplicationResult(policyName string) Result {
} }
} }
//NewAdmissionResult creates a new admission result
func NewAdmissionResult(requestUID string) Result { func NewAdmissionResult(requestUID string) Result {
return &CompositeResult{ return &CompositeResult{
Message: fmt.Sprintf("For resource with UID - %s:", requestUID), Message: fmt.Sprintf("For resource with UID - %s:", requestUID),

View file

@ -11,11 +11,13 @@ import (
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
) )
//PolicyInformer access policy informers
type PolicyInformer interface { type PolicyInformer interface {
GetLister() v1alpha1.PolicyLister GetLister() v1alpha1.PolicyLister
GetInfomer() cache.SharedIndexInformer GetInfomer() cache.SharedIndexInformer
} }
// SharedInfomer access shared informers
type SharedInfomer interface { type SharedInfomer interface {
PolicyInformer PolicyInformer
Run(stopCh <-chan struct{}) Run(stopCh <-chan struct{})
@ -25,7 +27,7 @@ type sharedInfomer struct {
policyInformerFactory informers.SharedInformerFactory policyInformerFactory informers.SharedInformerFactory
} }
//NewSharedInformer returns shared informer //NewSharedInformerFactory returns shared informer
func NewSharedInformerFactory(clientConfig *rest.Config) (SharedInfomer, error) { func NewSharedInformerFactory(clientConfig *rest.Config) (SharedInfomer, error) {
// create policy client // create policy client
policyClientset, err := policyclientset.NewForConfig(clientConfig) policyClientset, err := policyclientset.NewForConfig(clientConfig)

View file

@ -14,25 +14,25 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
// Properties of TLS certificate which should be issued for webhook server //TlsCertificateProps Properties of TLS certificate which should be issued for webhook server
type TlsCertificateProps struct { type TlsCertificateProps struct {
Service string Service string
Namespace string Namespace string
ApiServerHost string ApiServerHost string
} }
// The pair of TLS certificate corresponding private key, both in PEM format //TlsPemPair The pair of TLS certificate corresponding private key, both in PEM format
type TlsPemPair struct { type TlsPemPair struct {
Certificate []byte Certificate []byte
PrivateKey []byte PrivateKey []byte
} }
// Generates RSA private key //TlsGeneratePrivateKey Generates RSA private key
func TlsGeneratePrivateKey() (*rsa.PrivateKey, error) { func TlsGeneratePrivateKey() (*rsa.PrivateKey, error) {
return rsa.GenerateKey(rand.Reader, 2048) return rsa.GenerateKey(rand.Reader, 2048)
} }
// Creates PEM block from private key object //TlsPrivateKeyToPem Creates PEM block from private key object
func TlsPrivateKeyToPem(rsaKey *rsa.PrivateKey) []byte { func TlsPrivateKeyToPem(rsaKey *rsa.PrivateKey) []byte {
privateKey := &pem.Block{ privateKey := &pem.Block{
Type: "PRIVATE KEY", Type: "PRIVATE KEY",
@ -42,7 +42,7 @@ func TlsPrivateKeyToPem(rsaKey *rsa.PrivateKey) []byte {
return pem.EncodeToMemory(privateKey) return pem.EncodeToMemory(privateKey)
} }
// Creates PEM block from raw certificate request //TlsCertificateRequestToPem Creates PEM block from raw certificate request
func TlsCertificateRequestToPem(csrRaw []byte) []byte { func TlsCertificateRequestToPem(csrRaw []byte) []byte {
csrBlock := &pem.Block{ csrBlock := &pem.Block{
Type: "CERTIFICATE REQUEST", Type: "CERTIFICATE REQUEST",
@ -52,7 +52,7 @@ func TlsCertificateRequestToPem(csrRaw []byte) []byte {
return pem.EncodeToMemory(csrBlock) return pem.EncodeToMemory(csrBlock)
} }
// Generates raw certificate signing request //TlsCertificateGenerateRequest Generates raw certificate signing request
func TlsCertificateGenerateRequest(privateKey *rsa.PrivateKey, props TlsCertificateProps) (*certificates.CertificateSigningRequest, error) { func TlsCertificateGenerateRequest(privateKey *rsa.PrivateKey, props TlsCertificateProps) (*certificates.CertificateSigningRequest, error) {
dnsNames := make([]string, 3) dnsNames := make([]string, 3)
dnsNames[0] = props.Service dnsNames[0] = props.Service
@ -104,12 +104,12 @@ func TlsCertificateGenerateRequest(privateKey *rsa.PrivateKey, props TlsCertific
}, nil }, nil
} }
// The generated service name should be the common name for TLS certificate //GenerateInClusterServiceName The generated service name should be the common name for TLS certificate
func GenerateInClusterServiceName(props TlsCertificateProps) string { func GenerateInClusterServiceName(props TlsCertificateProps) string {
return props.Service + "." + props.Namespace + ".svc" return props.Service + "." + props.Namespace + ".svc"
} }
//Gets NotAfter property from raw certificate //TlsCertificateGetExpirationDate Gets NotAfter property from raw certificate
func TlsCertificateGetExpirationDate(certData []byte) (*time.Time, error) { func TlsCertificateGetExpirationDate(certData []byte) (*time.Time, error) {
block, _ := pem.Decode(certData) block, _ := pem.Decode(certData)
if block == nil { if block == nil {
@ -127,6 +127,7 @@ func TlsCertificateGetExpirationDate(certData []byte) (*time.Time, error) {
// an expired certificate in a controller that has been running for a long time // an expired certificate in a controller that has been running for a long time
const timeReserveBeforeCertificateExpiration time.Duration = time.Hour * 24 * 30 * 6 // About half a year const timeReserveBeforeCertificateExpiration time.Duration = time.Hour * 24 * 30 * 6 // About half a year
//IsTlsPairShouldBeUpdated checks if TLS pair has expited and needs to be updated
func IsTlsPairShouldBeUpdated(tlsPair *TlsPemPair) bool { func IsTlsPairShouldBeUpdated(tlsPair *TlsPemPair) bool {
if tlsPair == nil { if tlsPair == nil {
return true return true

View file

@ -163,13 +163,13 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) *v1be
Patch: engine.JoinPatches(allPatches), Patch: engine.JoinPatches(allPatches),
PatchType: &patchType, PatchType: &patchType,
} }
} else { }
return &v1beta1.AdmissionResponse{
Allowed: false, return &v1beta1.AdmissionResponse{
Result: &metav1.Status{ Allowed: false,
Message: message, Result: &metav1.Status{
}, Message: message,
} },
} }
} }
@ -249,7 +249,7 @@ func (ws *WebhookServer) bodyToAdmissionReview(request *http.Request, writer htt
glog.Errorf("Error: Can't decode body as AdmissionReview: %v", err) glog.Errorf("Error: Can't decode body as AdmissionReview: %v", err)
http.Error(writer, "Can't decode body as AdmissionReview", http.StatusExpectationFailed) http.Error(writer, "Can't decode body as AdmissionReview", http.StatusExpectationFailed)
return nil return nil
} else {
return admissionReview
} }
return admissionReview
} }