Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ spec:
requestHandlerConfigName: request-handler-config
requestHandlerConfig: |
defaultConstraintAction:
mode: detect
mode: inform
sideEffect:
createDenyEvent: true
log:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ spec:
requestHandlerConfigName: request-handler-config
requestHandlerConfig: |
defaultConstraintAction:
mode: detect
mode: inform
sideEffect:
createDenyEvent: true
log:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ spec:
requestHandlerConfigName: request-handler-config
requestHandlerConfig: |
defaultConstraintAction:
mode: detect
mode: inform
sideEffect:
createDenyEvent: true
log:
Expand Down
4 changes: 4 additions & 0 deletions integrity-shield-operator/resources/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ func BuildDeploymentForIShieldAPI(cr *apiv1.IntegrityShield) *appsv1.Deployment
Name: "REKOR_SERVER",
Value: cr.Spec.RekorServerConfig.URL,
},
{
Name: "COSIGN_EXPERIMENTAL",
Value: "1",
},
}
if cr.Spec.OCIRegistryConfig.ManifestPullSecret != "" {
env = append(env, v1.EnvVar{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ spec:
- keySecretName: keyring-secret
keySecretNamespace: integrity-shield-operator-system
action:
mode: detect
mode: inform
2 changes: 1 addition & 1 deletion integrity-shield-operator/test/e2e/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ var (
observer_name = "integrity-shield-observer"
ac_server_name = "integrity-shield-validator"
constraint = deploy_dir + "test-manifest-integrity-constraint.yaml"
constraint_detect = deploy_dir + "test-manifest-integrity-constraint-detect.yaml"
constraint_detect = deploy_dir + "test-manifest-integrity-constraint-inform.yaml"
constraint_ac = deploy_dir + "test-manifest-integrity-profile.yaml"
constraint_name = "configmap-constraint"
gatekeeper_ns = "gatekeeper-system"
Expand Down
31 changes: 30 additions & 1 deletion observer/pkg/observer/observer.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const logLevelEnvKey = "LOG_LEVEL"
const k8sLogLevelEnvKey = "K8S_MANIFEST_SIGSTORE_LOG_LEVEL"

const VerifyResourceViolationLabel = "integrityshield.io/verifyResourceViolation"
const SignatureResourceLabel = "integrityshield.io/signatureResource"

var IgnoredKinds = []string{"Event", "Lease", "Endpoints", "TokenReview", "SubjectAccessReview", "SelfSubjectAccessReview", "LocalSubjectAccessReview"}

Expand Down Expand Up @@ -219,7 +220,22 @@ func (self *Observer) Run() {
results := []VerifyResultDetail{}
for _, resource := range resources {
log.Debugf("Observe new resource; ns:%s, kind:%s, name:%s", resource.GetNamespace(), resource.GetKind(), resource.GetName())
// skip object
// check if signature resource
signatureResource := isSignatureResource(resource)
if signatureResource {
result := VerifyResultDetail{
Time: time.Now().Format(timeFormat),
Kind: resource.GroupVersionKind().Kind,
ApiGroup: resource.GetObjectKind().GroupVersionKind().Group,
ApiVersion: resource.GetObjectKind().GroupVersionKind().Version,
Name: resource.GetName(),
Namespace: resource.GetNamespace(),
Message: "this resource is signatureResource",
Violation: false,
}
results = append(results, result)
continue
}
result := ObserveResource(resource, constraint.Parameters, ignoreFields, skipObjects, secrets)
imgAllow, imgMsg := ObserveImage(resource, constraint.Parameters.ImageProfile)
if !imgAllow {
Expand Down Expand Up @@ -522,3 +538,16 @@ func (self *Observer) loadConstraints() ([]ConstraintSpec, error) {
}
return micList, nil
}

func isSignatureResource(resource unstructured.Unstructured) bool {
var label bool
if !(resource.GetKind() == "ConfigMap") {
return label
}
labelsMap := resource.GetLabels()
_, found := labelsMap[SignatureResourceLabel]
if found {
label = true
}
return label
}
74 changes: 56 additions & 18 deletions shield/pkg/shield/request_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const defaultPodNamespace = "integrity-shield-operator-system"
const ImageRefAnnotationKeyShield = "integrityshield.io/signature"
const AnnotationKeyDomain = "integrityshield.io"
const SignatureAnnotationTypeShield = "IntegrityShield"
const SignatureResourceLabel = "integrityshield.io/signatureResource"
const (
EventTypeAnnotationKey = "integrityshield.io/eventType"
EventResultAnnotationKey = "integrityshield.io/eventResult"
Expand Down Expand Up @@ -113,14 +114,14 @@ func RequestHandler(req admission.Request, paramObj *k8smnfconfig.ParameterObjec
}
}
} else {
if paramObj.Action.Mode != "enforce" && paramObj.Action.Mode != "detect" {
if paramObj.Action.Mode != "enforce" && paramObj.Action.Mode != "inform" {
log.WithFields(log.Fields{
"namespace": req.Namespace,
"name": req.Name,
"kind": req.Kind.Kind,
"operation": req.Operation,
"userName": req.UserInfo.Username,
}).Warningf("run mode should be set to 'enforce' or 'detect' in rule,%s", paramObj.ConstraintName)
}).Warningf("run mode should be set to 'enforce' or 'inform' in rule,%s", paramObj.ConstraintName)
}
if paramObj.Action.Mode == "enforce" {
enforce = true
Expand All @@ -134,6 +135,10 @@ func RequestHandler(req admission.Request, paramObj *k8smnfconfig.ParameterObjec

commonSkipUserMatched := false
skipObjectMatched := false
signatureResource := false

// check if signature resource
signatureResource = isAllowedSignatureResource(resource, req.AdmissionRequest.OldObject.Raw, req.Operation)

//filter by user listed in common profile
commonSkipUserMatched = rhconfig.RequestFilterProfile.SkipUsers.Match(resource, req.AdmissionRequest.UserInfo.Username)
Expand All @@ -151,23 +156,12 @@ func RequestHandler(req admission.Request, paramObj *k8smnfconfig.ParameterObjec
//check scope
inScopeObjMatched := paramObj.InScopeObjects.Match(resource)

// mutation check
if isUpdateRequest(req.AdmissionRequest.Operation) {
ignoreFields := getMatchedIgnoreFields(paramObj.IgnoreFields, rhconfig.RequestFilterProfile.IgnoreFields, resource)
mutated, err := mutationCheck(req.AdmissionRequest.OldObject.Raw, req.AdmissionRequest.Object.Raw, ignoreFields)
if err != nil {
log.Errorf("failed to check mutation: %s", err.Error())
errMsg := "IntegrityShield failed to decide the response. Failed to check mutation: " + err.Error()
return makeResultFromRequestHandler(false, errMsg, enforce, req)
}
if !mutated {
return makeResultFromRequestHandler(true, "no mutation found", enforce, req)
}
}

allow := false
message := ""
if (skipUserMatched || commonSkipUserMatched) && !inScopeUserMatched {
if signatureResource {
allow = true
message = "allowed because this resource is signatureResource."
} else if (skipUserMatched || commonSkipUserMatched) && !inScopeUserMatched {
allow = true
message = "SkipUsers rule matched."
logRecord["reason"] = message
Expand All @@ -179,7 +173,20 @@ func RequestHandler(req admission.Request, paramObj *k8smnfconfig.ParameterObjec
} else if skipObjectMatched {
allow = true
message = "SkipObjects rule matched."
} else {
} else if isUpdateRequest(req.AdmissionRequest.Operation) {
// mutation check
ignoreFields := getMatchedIgnoreFields(paramObj.IgnoreFields, rhconfig.RequestFilterProfile.IgnoreFields, resource)
mutated, err := mutationCheck(req.AdmissionRequest.OldObject.Raw, req.AdmissionRequest.Object.Raw, ignoreFields)
if err != nil {
log.Errorf("failed to check mutation: %s", err.Error())
message = "IntegrityShield failed to decide the response. Failed to check mutation: " + err.Error()
}
if !mutated {
allow = true
message = "no mutation found"
}
}
if !allow { // signature check
var signatureAnnotationType string
annotations := resource.GetAnnotations()
_, found := annotations[ImageRefAnnotationKeyShield]
Expand Down Expand Up @@ -304,6 +311,37 @@ func isUpdateRequest(operation v1.Operation) bool {
return (operation == v1.Update)
}

func isAllowedSignatureResource(resource unstructured.Unstructured, oldObj []byte, operation v1.Operation) bool {
var currentResourceLabel bool
var label bool
if !(resource.GetKind() == "ConfigMap") {
return label
}
label = isSignatureResource(resource)
if operation == v1.Create {
currentResourceLabel = true
} else if operation == v1.Update {
// unmarshal admission request object
var oldRes unstructured.Unstructured
err := json.Unmarshal(oldObj, &oldRes)
if err != nil {
log.Errorf("failed to Unmarshal a requested object into %T; %s", resource, err.Error())
}
currentResourceLabel = isSignatureResource(oldRes)
}
return (label && currentResourceLabel)
}

func isSignatureResource(resource unstructured.Unstructured) bool {
var label bool
labelsMap := resource.GetLabels()
_, found := labelsMap[SignatureResourceLabel]
if found {
label = true
}
return label
}

func getMatchedIgnoreFields(pi, ci k8smanifest.ObjectFieldBindingList, resource unstructured.Unstructured) []string {
var allIgnoreFields []string
_, fields := pi.Match(resource)
Expand Down