Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented validation logic for the webhook #593

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b407e51
Fix workflow for autogenerating docs (#592)
Sig00rd Jul 7, 2021
52fe5fe
Implemented validation logic for the webhook
sharmapulkit04 Jul 8, 2021
db0978c
Configure bot for labelling new issues as needing triage (#597)
Sig00rd Jul 16, 2021
800c1a7
Configure bot for managing stale issues (#598)
Sig00rd Jul 19, 2021
35dfd47
Docs: explanation what is backed up and why (#599)
prryb Jul 20, 2021
7ce9d1f
Auto-updated docs (#600)
github-actions[bot] Jul 20, 2021
463cad3
Docs: clarification of description of get latest command in backup (#…
Sig00rd Jul 20, 2021
bd32624
Auto-updated docs (#602)
github-actions[bot] Jul 21, 2021
9d5c525
Bump seedjobs agent image version to 4.9-1 (#604)
Sig00rd Jul 23, 2021
935b60b
Add GitLFS pull after checkout behaviour to SeedJob GroovyScript Temp…
rcosnita Jul 29, 2021
dfd25e8
Docs: minor fixes (#608)
Sig00rd Aug 2, 2021
17dba08
Auto-updated docs (#610)
github-actions[bot] Aug 2, 2021
37d0eac
Reimplemented the validation logic with caching the security warnings
sharmapulkit04 Aug 4, 2021
8453b3e
Add an issue template for documentation (#613)
Sig00rd Aug 5, 2021
858f0f4
Docs: add info on restricted volumeMounts other than jenkins-home(#612)
Sig00rd Aug 5, 2021
b82fc7c
Auto-updated docs (#616)
github-actions[bot] Aug 6, 2021
b400a42
Auto-updated docs (#617)
github-actions[bot] Aug 6, 2021
1d2651d
Updated Validation logic
sharmapulkit04 Aug 6, 2021
853f485
Helm Chart: Remove empty priorityClassName from Jenkins template (#618)
mortenbirkelund Aug 9, 2021
9106582
Merge branch 'master' of github.com:jenkinsci/kubernetes-operator int…
sharmapulkit04 Aug 9, 2021
90b685d
Merge branch 'security-validator' of github.com:jenkinsci/kubernetes-…
sharmapulkit04 Aug 12, 2021
b11ca32
Added unit test cases for webhook
sharmapulkit04 Aug 12, 2021
5ca4e0a
Updated Helm Charts
sharmapulkit04 Aug 15, 2021
e2ec2ea
Updated unit tests, helm charts and validation logic
sharmapulkit04 Aug 18, 2021
f527a8c
Completed helm e2e tests and updated helm charts
sharmapulkit04 Aug 20, 2021
9594c8e
Code optimization and cleanup
sharmapulkit04 Aug 21, 2021
95c29d4
Modified helm tests
sharmapulkit04 Aug 21, 2021
ba66ba4
code cleanup and optimization
sharmapulkit04 Aug 23, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ e2e: deepcopy-gen manifests ## Runs e2e tests, you can use EXTRA_ARGS

.PHONY: helm-e2e
IMAGE_NAME := $(DOCKER_REGISTRY):$(GITCOMMIT)
helm-e2e: helm container-runtime-build ## Runs helm e2e tests, you can use EXTRA_ARGS
#TODO: install cert-manager before running helm charts
helm-e2e: helm install-cert-manager container-runtime-build ## Runs helm e2e tests, you can use EXTRA_ARGS

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
helm-e2e: helm install-cert-manager container-runtime-build ## Runs helm e2e tests, you can use EXTRA_ARGS
helm-e2e: helm install-cert-manager container-runtime-build ## Runs helm e2e tests, you can use EXTRA_ARGS

Also please add a TODO to refactor the logic for deploying cert manager in the helm charts later :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sure.

@echo "+ $@"
RUNNING_TESTS=1 go test -parallel=1 "./test/helm/" -ginkgo.v -tags "$(BUILDTAGS) cgo" -v -timeout 60m -run "$(E2E_TEST_SELECTOR)" -image-name=$(IMAGE_NAME) $(E2E_TEST_ARGS)

Expand Down
140 changes: 135 additions & 5 deletions api/v1alpha2/jenkins_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ limitations under the License.
package v1alpha2

import (
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"time"

"github.com/jenkinsci/kubernetes-operator/pkg/plugins"

"golang.org/x/mod/semver"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
Expand All @@ -41,21 +50,142 @@ var _ webhook.Validator = &Jenkins{}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (in *Jenkins) ValidateCreate() error {
jenkinslog.Info("validate create", "name", in.Name)
if in.Spec.ValidateSecurityWarnings {
jenkinslog.Info("validate create", "name", in.Name)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these logs useful in any way?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah for debugging purposes I was checking if the function is being called and get a look the the reconciller object.

return Validate(*in)
}

// TODO(user): fill in your validation logic upon object creation.
return nil
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (in *Jenkins) ValidateUpdate(old runtime.Object) error {
jenkinslog.Info("validate update", "name", in.Name)
if in.Spec.ValidateSecurityWarnings {
jenkinslog.Info("validate update", "name", in.Name)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these logs useful in any way?

return Validate(*in)
}

// TODO(user): fill in your validation logic upon object update.
return nil
}

func (in *Jenkins) ValidateDelete() error {
// TODO(user): fill in your validation logic upon object deletion.
return nil
}

type Warnings struct {
Warnings []Warning `json:"securityWarnings"`
}

type Warning struct {
Versions []Version `json:"versions"`
ID string `json:"id"`
Message string `json:"message"`
URL string `json:"url"`
Active bool `json:"active"`
}
type Version struct {
FirstVersion string `json:"firstVersion"`
LastVersion string `json:"lastVersion"`
}

const APIURL string = "https://plugins.jenkins.io/api/plugin/"

func MakeSemanticVersion(version string) string {
version = "v" + version
return semver.Canonical(version)
}

func CompareVersions(firstVersion string, lastVersion string, pluginVersion string) bool {
firstSemVer := MakeSemanticVersion(firstVersion)
lastSemVer := MakeSemanticVersion(lastVersion)
pluginSemVer := MakeSemanticVersion(pluginVersion)
if semver.Compare(pluginSemVer, firstSemVer) == -1 || semver.Compare(pluginSemVer, lastSemVer) == 1 {
return false
}
return true
}

func CheckSecurityWarnings(pluginName string, pluginVersion string) (bool, error) {
jenkinslog.Info("checking security warnings", "plugin: ", pluginName)
pluginURL := APIURL + pluginName
client := &http.Client{
Timeout: time.Second * 30,
}
request, err := http.NewRequest("GET", pluginURL, nil)
if err != nil {
return false, err
}
request.Header.Add("Accept", "application/json")
request.Header.Add("Content-Type", "application/json")
response, err := client.Do(request)
if err != nil {
return false, err
}
defer response.Body.Close()
bodyBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
return false, err
}
securityWarnings := Warnings{}

jsonErr := json.Unmarshal(bodyBytes, &securityWarnings)
if jsonErr != nil {
return false, err
}

jenkinslog.Info("Validate()", "warnings", securityWarnings)

for _, warning := range securityWarnings.Warnings {
for _, version := range warning.Versions {
firstVersion := version.FirstVersion
lastVersion := version.LastVersion
if len(firstVersion) == 0 {
firstVersion = "0" // setting default value in case of empty string
}
if len(lastVersion) == 0 {
lastVersion = pluginVersion // setting default value in case of empty string
}

if CompareVersions(firstVersion, lastVersion, pluginVersion) {
jenkinslog.Info("security Vulnerabilities detected", "message", warning.Message, "Check security Advisory", warning.URL)
return true, nil
}
}
}

return false, nil
}

func Validate(r Jenkins) error {
basePlugins := plugins.BasePlugins()
var warnings string = ""

for _, plugin := range basePlugins {
name := plugin.Name
version := plugin.Version
hasWarnings, err := CheckSecurityWarnings(name, version)
if err != nil {
return err
}
if hasWarnings {
warnings += "Security Vulnerabilities detected in base plugin:" + name
}
}

for _, plugin := range r.Spec.Master.Plugins {
name := plugin.Name
version := plugin.Version
hasWarnings, err := CheckSecurityWarnings(name, version)
if err != nil {
return err
}
if hasWarnings {
warnings += "Security Vulnerabilities detected in the user defined plugin: " + name
}
}
if len(warnings) > 0 {
return errors.New(warnings)
}

return nil
}
Loading