-
Notifications
You must be signed in to change notification settings - Fork 121
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
Introduce gosec
for Static Application Security Testing (SAST)
#954
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,3 +31,6 @@ tags | |
|
||
# dont check in tool binariess | ||
hack/tools/bin/ | ||
|
||
# gosec | ||
gosec-report.sarif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -170,7 +170,16 @@ generate: $(VGOPATH) $(DEEPCOPY_GEN) $(DEFAULTER_GEN) $(CONVERSION_GEN) $(OPENAP | |
@./hack/generate-code | ||
@./hack/api-reference/generate-spec-doc.sh | ||
|
||
|
||
.PHONY: add-license-headers | ||
add-license-headers: $(GO_ADD_LICENSE) | ||
@./hack/add_license_headers.sh | ||
|
||
.PHONY: sast | ||
sast: $(GOSEC) | ||
@chmod +xw hack/sast.sh | ||
@./hack/sast.sh | ||
|
||
.PHONY: sast-report | ||
sast-report:$(GOSEC) | ||
@chmod +xw hack/sast.sh | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as the comment for |
||
@./hack/sast.sh --gosec-report true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#!/usr/bin/env bash | ||
# | ||
# SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
set -e | ||
|
||
root_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." &> /dev/null && pwd )" | ||
|
||
gosec_report="false" | ||
gosec_report_parse_flags="" | ||
|
||
parse_flags() { | ||
while test $# -gt 1; do | ||
case "$1" in | ||
--gosec-report) | ||
shift; gosec_report="$1" | ||
;; | ||
*) | ||
echo "Unknown argument: $1" | ||
exit 1 | ||
;; | ||
esac | ||
shift | ||
done | ||
} | ||
|
||
parse_flags "$@" | ||
|
||
echo "> Running gosec" | ||
gosec --version | ||
if [[ "$gosec_report" != "false" ]]; then | ||
echo "Exporting report to $root_dir/gosec-report.sarif" | ||
gosec_report_parse_flags="-track-suppressions -fmt=sarif -out=gosec-report.sarif -stdout" | ||
fi | ||
|
||
# MCM uses code-generators https://github.com/kubernetes/code-generator which create lots of G103 (CWE-242: | ||
# Use of unsafe calls should be audited) & G104 (CWE-703: Errors unhandled) errors. | ||
# However, those generators are best-pratice in Kubernetes environment and their results are tested well. | ||
# Thus, generated code is excluded from gosec scan. | ||
# Nested go modules are not supported by gosec (see https://github.com/securego/gosec/issues/501), so the ./hack folder | ||
# is excluded too. It does not contain productive code anyway. | ||
gosec -exclude-generated -exclude-dir=hack $gosec_report_parse_flags ./... |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#!/usr/bin/env bash | ||
# | ||
# SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
set -e | ||
|
||
echo "> Installing gosec" | ||
|
||
TOOLS_BIN_DIR=${TOOLS_BIN_DIR:-$(dirname $0)/bin} | ||
|
||
platform=$(uname -s | tr '[:upper:]' '[:lower:]') | ||
version=$GOSEC_VERSION | ||
echo "gosec version:$GOSEC_VERSION" | ||
case $(uname -m) in | ||
aarch64 | arm64) | ||
arch="arm64" | ||
;; | ||
x86_64) | ||
arch="amd64" | ||
;; | ||
*) | ||
echo "Unknown architecture" | ||
exit -1 | ||
;; | ||
esac | ||
|
||
archive_name="gosec_${version#v}_${platform}_${arch}" | ||
file_name="${archive_name}.tar.gz" | ||
|
||
temp_dir="$(mktemp -d)" | ||
function cleanup { | ||
rm -rf "${temp_dir}" | ||
} | ||
trap cleanup EXIT ERR INT TERM | ||
echo "Downloading from: https://github.com/securego/gosec/releases/download/${version}/${file_name}" | ||
curl -L -o ${temp_dir}/${file_name} "https://github.com/securego/gosec/releases/download/${version}/${file_name}" | ||
|
||
|
||
tar -xzm -C "${temp_dir}" -f "${temp_dir}/${file_name}" | ||
mv "${temp_dir}/gosec" $TOOLS_BIN_DIR | ||
chmod +x $TOOLS_BIN_DIR/gosec |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,14 @@ | |
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
|
||
// Package validation is used to validate all the machine CRD objects | ||
package validation | ||
|
||
import ( | ||
"github.com/gardener/machine-controller-manager/pkg/apis/machine" | ||
"k8s.io/apimachinery/pkg/util/intstr" | ||
"k8s.io/apimachinery/pkg/util/validation/field" | ||
"math" | ||
) | ||
|
||
// ValidateMachineDeployment and returns a list of errors. | ||
|
@@ -22,24 +23,49 @@ func internalValidateMachineDeployment(machineDeployment *machine.MachineDeploym | |
return allErrs | ||
} | ||
|
||
func validateMachineDeploymentSpec(spec *machine.MachineDeploymentSpec, fldPath *field.Path) field.ErrorList { | ||
allErrs := field.ErrorList{} | ||
|
||
if spec.Replicas < 0 { | ||
allErrs = append(allErrs, field.Required(fldPath.Child("replicas"), "Replicas has to be a whole number")) | ||
func canConvertIntOrStringToInt32(val *intstr.IntOrString, replicas int) bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a very generic function, can we move elsewhere? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's used here only. If we feel like it is required elsewhere, then we'll put it in separate location |
||
intVal, err := intstr.GetScaledValueFromIntOrPercent(val, replicas, true) | ||
if err != nil { | ||
return false | ||
} | ||
if intVal < math.MinInt32 || intVal > math.MaxInt32 { | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
func validateUpdateStrategy(spec *machine.MachineDeploymentSpec, fldPath *field.Path) field.ErrorList { | ||
allErrs := field.ErrorList{} | ||
if spec.Strategy.Type != "RollingUpdate" && spec.Strategy.Type != "Recreate" { | ||
allErrs = append(allErrs, field.Required(fldPath.Child("strategy.type"), "Type can either be RollingUpdate or Recreate")) | ||
} | ||
if spec.Strategy.Type == "RollingUpdate" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should use: if spec.Strategy.Type == v1alpha1.MachineDeploymentStrategyType instead |
||
if spec.Strategy.RollingUpdate == nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this check done? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The doc string is incorrect. If both are zero then we use |
||
allErrs = append(allErrs, field.Required(fldPath.Child("strategy.rollingUpdate"), "RollingUpdate parameter cannot be nil for rolling update strategy")) | ||
} else { | ||
if !canConvertIntOrStringToInt32(spec.Strategy.RollingUpdate.MaxUnavailable, int(spec.Replicas)) { | ||
allErrs = append(allErrs, field.Required(fldPath.Child("strategy.rollingUpdate.maxUnavailable"), "unable to convert maxUnavailable to int32")) | ||
} | ||
if !canConvertIntOrStringToInt32(spec.Strategy.RollingUpdate.MaxSurge, int(spec.Replicas)) { | ||
allErrs = append(allErrs, field.Required(fldPath.Child("strategy.rollingUpdate.maxSurge"), "unable to convert maxSurge to int32")) | ||
} | ||
} | ||
} | ||
return allErrs | ||
} | ||
|
||
func validateMachineDeploymentSpec(spec *machine.MachineDeploymentSpec, fldPath *field.Path) field.ErrorList { | ||
allErrs := field.ErrorList{} | ||
if spec.Replicas < 0 { | ||
allErrs = append(allErrs, field.Required(fldPath.Child("replicas"), "Replicas has to be a whole number")) | ||
} | ||
allErrs = append(allErrs, validateUpdateStrategy(spec, fldPath)...) | ||
for k, v := range spec.Selector.MatchLabels { | ||
if spec.Template.Labels[k] != v { | ||
allErrs = append(allErrs, field.Required(fldPath.Child("selector.matchLabels"), "is not matching with spec.template.metadata.labels")) | ||
break | ||
} | ||
} | ||
|
||
allErrs = append(allErrs, validateClassReference(&spec.Template.Spec.Class, field.NewPath("spec.template.spec.class"))...) | ||
return allErrs | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this required? When you introduce a new script you already give it execute permissions and then onwards those permissions are preserved and therefore there is no real need to add this as part of the make target.