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 @@ -60,6 +60,11 @@ func (m *Forbid) IsMatched() bool {
return false
}

if strings.HasPrefix(m.event.User.Username, "system:") &&
!strings.HasPrefix(m.event.User.Username, "system:serviceaccount:d8-service-accounts") {
return false
}

if m.event.Annotations[annotations.AnnAuditDecision] == "forbid" {
return true
}
Expand All @@ -82,7 +87,7 @@ func (m *Forbid) Fill() error {
}

m.eventLog.Name = fmt.Sprintf(
"User (%s) attempted to perform a forbidden operation (%s) on resource (%s).",
"User '%s' attempted to perform a forbidden operation '%s' on resource '%s'.",
m.event.User.Username,
m.event.Verb,
resource)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ var _ = Describe("Forbid Events", func() {
Expect(eventLog.eventLog.Type).To(Equal("Forbidden operation"))
Expect(eventLog.eventLog.Level).To(Equal("warn"))

Expect(eventLog.eventLog.Name).To(Equal("User (test-user) attempted to perform a forbidden operation (create) on resource (pods/test/test-vmi)."))
Expect(eventLog.eventLog.Name).To(Equal("User 'test-user' attempted to perform a forbidden operation 'create' on resource 'pods/test/test-vmi'."))

Expect(eventLog.eventLog.Datetime).To(Equal(currentTime.Format(time.RFC3339)))
Expect(eventLog.eventLog.UID).To(Equal("0000-0000-0000"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package integrity

import (
"fmt"
"strings"

"k8s.io/apiserver/pkg/apis/audit"

Expand Down Expand Up @@ -54,6 +55,11 @@ func (m *IntegrityCheckVM) IsMatched() bool {
return false
}

if strings.HasPrefix(m.event.User.Username, "system:") &&
!strings.HasPrefix(m.event.User.Username, "system:serviceaccount:d8-service-accounts") {
return false
}

if (m.event.Verb == "patch" || m.event.Verb == "update") && m.event.ObjectRef.Resource == "internalvirtualizationvirtualmachineinstances" {
return true
}
Expand All @@ -64,25 +70,25 @@ func (m *IntegrityCheckVM) IsMatched() bool {
func (m *IntegrityCheckVM) Fill() error {
m.eventLog = NewIntegrityCheckEventLog(m.event)

m.eventLog.Name = "VM config integrity check failed"
vmi, err := util.GetInternalVMIFromInformer(m.ttlCache, m.informerList.GetInternalVMIInformer(), m.event.ObjectRef.Namespace+"/"+m.event.ObjectRef.Name)
if err != nil {
return fmt.Errorf("failed to get VMI from informer: %w", err)
}

m.eventLog.Name = fmt.Sprintf("Virtual machine '%s' config integrity check failed", vmi.Name)
m.eventLog.ObjectType = "Virtual machine configuration"
m.eventLog.ControlMethod = "Integrity Check"
m.eventLog.ReactionType = "info"
m.eventLog.IntegrityCheckAlgo = "sha256"

vmi, err := util.GetInternalVMIFromInformer(m.ttlCache, m.informerList.GetInternalVMIInformer(), m.event.ObjectRef.Namespace+"/"+m.event.ObjectRef.Name)
if err != nil {
return fmt.Errorf("failed to get VMI from informer: %w", err)
}
m.eventLog.VirtualMachineName = vmi.Name
m.eventLog.ReferenceChecksum = vmi.Annotations[annotations.AnnIntegrityCoreChecksum]
m.eventLog.CurrentChecksum = vmi.Annotations[annotations.AnnIntegrityCoreChecksumApplied]

if vmi.Annotations[annotations.AnnIntegrityCoreChecksum] == vmi.Annotations[annotations.AnnIntegrityCoreChecksumApplied] {
m.eventLog.shouldLog = false
return nil
}

m.eventLog.VirtualMachineName = vmi.Name
m.eventLog.ReferenceChecksum = vmi.Annotations[annotations.AnnIntegrityCoreChecksum]
m.eventLog.CurrentChecksum = vmi.Annotations[annotations.AnnIntegrityCoreChecksumApplied]

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ var _ = Describe("Integrity Check VM Events", func() {

Expect(eventLog.eventLog.Type).To(Equal("Integrity check"))
Expect(eventLog.eventLog.Level).To(Equal("critical"))
Expect(eventLog.eventLog.Name).To(Equal("VM config integrity check failed"))
Expect(eventLog.eventLog.Name).To(Equal("Virtual machine 'test-vm' config integrity check failed"))
Expect(eventLog.eventLog.Datetime).To(Equal(currentTime.Format(time.RFC3339)))
Expect(eventLog.eventLog.UID).To(Equal("0000-0000-0000"))
Expect(eventLog.eventLog.OperationResult).To(Equal("allow"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package module

import (
"fmt"
"strings"

"k8s.io/apiserver/pkg/apis/audit"
Expand Down Expand Up @@ -61,8 +62,8 @@ func (m *ModuleComponentControl) IsMatched() bool {
return false
}

// Skip control requests from internal k8s controllers because we get them with almost empty ObjectRef
if strings.Contains(m.event.User.Username, kubeSystemUsername) {
if strings.HasPrefix(m.event.User.Username, "system:") &&
!strings.HasPrefix(m.event.User.Username, "system:serviceaccount:d8-service-accounts") {
return false
}

Expand All @@ -84,11 +85,11 @@ func (m *ModuleComponentControl) Fill() error {
m.eventLog.Type = "Virtualization control"

if m.event.Verb == "create" {
m.eventLog.Name = "Component creation"
m.eventLog.Name = fmt.Sprintf("Component '%s' has been created by '%s'", m.event.ObjectRef.Name, m.event.User.Username)
m.eventLog.Level = "info"
m.eventLog.Component = m.event.ObjectRef.Name
} else {
m.eventLog.Name = "Component deletion"
m.eventLog.Name = fmt.Sprintf("Component '%s' has been deleted by '%s'", m.event.ObjectRef.Name, m.event.User.Username)
m.eventLog.Level = "warn"
m.eventLog.Component = m.event.ObjectRef.Name
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,33 +263,33 @@ var _ = Describe("Module component control events", func() {
}),
Entry("Module Control creation event shouldn't failed fill", moduleComponentControlTestArgs{
eventVerb: "create",
expectedName: "Component creation",
expectedName: "Component 'virt-handler' has been created by 'test-user'",
expectedLevel: "info",
expectedActionType: "create",
}),
Entry("Module Control creation event shouldn't failed fill", moduleComponentControlTestArgs{
eventVerb: "delete",
expectedName: "Component deletion",
expectedName: "Component 'virt-handler' has been deleted by 'test-user'",
expectedLevel: "warn",
expectedActionType: "delete",
}),
Entry("Module Control creation event shouldn't failed fill with losted module", moduleComponentControlTestArgs{
eventVerb: "delete",
expectedName: "Component deletion",
expectedName: "Component 'virt-handler' has been deleted by 'test-user'",
expectedLevel: "warn",
expectedActionType: "delete",
shouldLostModule: true,
}),
Entry("Module Control creation event shouldn't failed fill with losted node", moduleComponentControlTestArgs{
eventVerb: "delete",
expectedName: "Component deletion",
expectedName: "Component 'virt-handler' has been deleted by 'test-user'",
expectedLevel: "warn",
expectedActionType: "delete",
shouldLostNode: true,
}),
Entry("Module Control creation event shouldn't failed fill with losted pod", moduleComponentControlTestArgs{
eventVerb: "delete",
expectedName: "Component deletion",
expectedName: "Component 'virt-handler' has been deleted by 'test-user'",
expectedLevel: "warn",
expectedActionType: "delete",
shouldLostPod: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ func (m *ModuleControl) IsMatched() bool {
return false
}

if strings.HasPrefix(m.event.User.Username, "system:serviceaccount:d8") {
if strings.HasPrefix(m.event.User.Username, "system:") &&
!strings.HasPrefix(m.event.User.Username, "system:serviceaccount:d8-service-accounts") {
return false
}

Expand Down
28 changes: 19 additions & 9 deletions images/virtualization-artifact/pkg/audit/events/vm/vm_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package vm

import (
"fmt"
"strings"

"k8s.io/apiserver/pkg/apis/audit"

Expand Down Expand Up @@ -58,10 +59,19 @@ func (m *VMAccess) IsMatched() bool {
return false
}

if strings.HasPrefix(m.event.User.Username, "system:") &&
!strings.HasPrefix(m.event.User.Username, "system:serviceaccount:d8-service-accounts") {
return false
}

if m.event.ObjectRef.Resource != "virtualmachines" || m.event.ObjectRef.APIGroup != "subresources.virtualization.deckhouse.io" {
return false
}

if m.event.Stage == audit.StageResponseStarted {
return false
}

if m.event.ObjectRef.Subresource == "console" || m.event.ObjectRef.Subresource == "vnc" || m.event.ObjectRef.Subresource == "portforward" {
return true
}
Expand All @@ -73,24 +83,24 @@ func (m *VMAccess) Fill() error {
m.eventLog = NewVMEventLog(m.event)
m.eventLog.Type = "Access to VM"

switch m.event.ObjectRef.Subresource {
case "console":
m.eventLog.Name = "Access to VM via serial console"
case "vnc":
m.eventLog.Name = "Access to VM via VNC"
case "portforward":
m.eventLog.Name = "Access to VM via portforward"
stage := ""
switch m.event.Stage {
case audit.StageResponseComplete:
stage = "finished"
case audit.StageRequestReceived:
stage = "initiated"
}

m.eventLog.Name = fmt.Sprintf("%s: %s", m.eventLog.Name, m.event.Stage)

m.eventLog.Name = fmt.Sprintf("Virtual machine '%s' connection has been %s via %s by '%s'", m.event.ObjectRef.Name, stage, m.event.ObjectRef.Subresource, m.event.User.Username)
vm, err := util.GetVMFromInformer(m.ttlCache, m.informerList.GetVMInformer(), m.event.ObjectRef.Namespace+"/"+m.event.ObjectRef.Name)
if err != nil {
log.Debug("fail to get vm from informer", log.Err(err))

return nil
}

m.eventLog.Name = fmt.Sprintf("Virtual machine '%s' connection has been %s via %s by '%s'", vm.Name, stage, m.event.ObjectRef.Subresource, m.event.User.Username)

m.eventLog.QemuVersion = vm.Status.Versions.Qemu
m.eventLog.LibvirtVersion = vm.Status.Versions.Libvirt

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,33 +252,33 @@ var _ = Describe("VMOP Events", func() {
shouldFailMatch: true,
}),
Entry("VM Access with ResponseComplete should contain decision and fill without errors", vmAccessTestArgs{
expectedName: "Access to VM via serial console: ResponseComplete",
expectedName: "Virtual machine 'test-vm' connection has been finished via console by 'test-user'",
customSubresource: "console",
}),
Entry("VM Access with RequestReceived shouldn't contain decision and fill without errors", vmAccessTestArgs{
expectedName: "Access to VM via serial console: RequestReceived",
expectedName: "Virtual machine 'test-vm' connection has been initiated via console by 'test-user'",
customSubresource: "console",
isRequestReceived: true,
}),
Entry("VM Access by Console event should filled without errors", vmAccessTestArgs{
expectedName: "Access to VM via serial console: ResponseComplete",
expectedName: "Virtual machine 'test-vm' connection has been finished via console by 'test-user'",
customSubresource: "console",
}),
Entry("VM Access by VNC event should filled without errors", vmAccessTestArgs{
expectedName: "Access to VM via VNC: ResponseComplete",
expectedName: "Virtual machine 'test-vm' connection has been finished via vnc by 'test-user'",
customSubresource: "vnc",
}),
Entry("VM Access by Portforward event should filled without errors", vmAccessTestArgs{
expectedName: "Access to VM via portforward: ResponseComplete",
expectedName: "Virtual machine 'test-vm' connection has been finished via portforward by 'test-user'",
customSubresource: "portforward",
}),
Entry("VM Access with losted VM event should filled without errors", vmAccessTestArgs{
expectedName: "Access to VM via serial console: ResponseComplete",
expectedName: "Virtual machine 'virt-launcher-test-vm' connection has been finished via console by 'test-user'",
customSubresource: "console",
shouldLostVM: true,
}),
Entry("VM Access with losted VD and Node event should filled without errors", vmAccessTestArgs{
expectedName: "Access to VM via serial console: ResponseComplete",
expectedName: "Virtual machine 'test-vm' connection has been finished via console by 'test-user'",
customSubresource: "console",
shouldLostVD: true,
shouldLostNode: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func (m *VMControl) Fill() error {
}
}

vmName := pod.Labels["vm.kubevirt.internal.virtualization.deckhouse.io/name"]
isControllerAction := strings.HasPrefix(m.event.User.Username, "system:serviceaccount:d8-virtualization")
isNodeAction := strings.HasPrefix(m.event.User.Username, "system:node")

Expand All @@ -88,22 +89,22 @@ func (m *VMControl) Fill() error {

switch {
case strings.Contains(terminatedStatuses, "guest-shutdown"):
m.eventLog.Name = "VM stoped from OS"
m.eventLog.Name = fmt.Sprintf("Virtual machine '%s' has been stopped from OS", vmName)
case strings.Contains(terminatedStatuses, "guest-reset"):
m.eventLog.Name = "VM restarted from OS"
m.eventLog.Name = fmt.Sprintf("Virtual machine '%s' has been restarted from OS", vmName)
default:
m.eventLog.Name = "VM stopped by system"
m.eventLog.shouldLog = false
return nil
}
case isNodeAction:
m.eventLog.Name = "VM stopped by system"
m.eventLog.shouldLog = false
return nil
default:
m.eventLog.Level = "critical"
m.eventLog.Name = "VM killed abnormal way"
m.eventLog.Name = fmt.Sprintf("Virtual machine '%s' has been killed abnormal way by '%s'", vmName, m.event.User.Username)
}

vm, err := util.GetVMFromInformer(m.ttlCache, m.informerList.GetVMInformer(), pod.Namespace+"/"+pod.Labels["vm.kubevirt.internal.virtualization.deckhouse.io/name"])
vm, err := util.GetVMFromInformer(m.ttlCache, m.informerList.GetVMInformer(), pod.Namespace+"/"+vmName)
if err != nil {
log.Debug("fail to get vm from informer", log.Err(err))
return nil
Expand Down
Loading
Loading