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

LOG-2869: Simplify sending audit-logs to LokiStack #1583

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions apis/logging/v1/clusterlogging_types.go
Expand Up @@ -221,6 +221,12 @@ type LokiStackStoreSpec struct {
//
// +required
Name string `json:"name"`

// SendAuditLogs controls whether audit-logs will be sent to the LokiStack log store.
// By default, only application and infrastructure logs will be sent to the store.
//
// +optional
SendAuditLogs bool `json:"sendAuditLogs,omitempty"`
}

// This is the struct that will contain information pertinent to Log and event collection
Expand Down
5 changes: 5 additions & 0 deletions bundle/manifests/logging.openshift.io_clusterloggings.yaml
Expand Up @@ -686,6 +686,11 @@ spec:
name:
description: Name of the LokiStack resource.
type: string
sendAuditLogs:
description: SendAuditLogs controls whether audit-logs will
be sent to the LokiStack log store. By default, only application
and infrastructure logs will be sent to the store.
type: boolean
required:
- name
type: object
Expand Down
5 changes: 5 additions & 0 deletions config/crd/bases/logging.openshift.io_clusterloggings.yaml
Expand Up @@ -682,6 +682,11 @@ spec:
name:
description: Name of the LokiStack resource.
type: string
sendAuditLogs:
description: SendAuditLogs controls whether audit-logs will
be sent to the LokiStack log store. By default, only application
and infrastructure logs will be sent to the store.
type: boolean
required:
- name
type: object
Expand Down
15 changes: 15 additions & 0 deletions internal/k8shandler/forwarding.go
Expand Up @@ -148,6 +148,13 @@ func (clusterRequest *ClusterLoggingRequest) NormalizeForwarder() (*logging.Clus
OutputRefs: []string{logging.OutputNameDefault + "-infra"},
},
}

if logStore.LokiStack.SendAuditLogs {
clusterRequest.ForwarderSpec.Pipelines = append(clusterRequest.ForwarderSpec.Pipelines, logging.PipelineSpec{
InputRefs: []string{logging.InputNameAudit},
OutputRefs: []string{logging.OutputNameDefault + "-audit"},
})
}
}
// Continue with normalization to fill out spec and status.
} else if clusterRequest.ForwarderRequest == nil {
Expand Down Expand Up @@ -411,6 +418,14 @@ func (clusterRequest *ClusterLoggingRequest) verifyOutputs(spec *logging.Cluster
Type: logging.OutputTypeLoki,
URL: clusterRequest.LokiStackURL("infrastructure"),
})

if logStore.LokiStack.SendAuditLogs {
spec.Outputs = append(spec.Outputs, logging.OutputSpec{
Name: logging.OutputNameDefault + "-audit",
Type: logging.OutputTypeLoki,
URL: clusterRequest.LokiStackURL("audit"),
})
}
default:
status.Outputs.Set(name, condInvalid(fmt.Sprintf("unknown log store type: %s", clusterRequest.Cluster.Spec.LogStore.Type)))
}
Expand Down
40 changes: 40 additions & 0 deletions internal/k8shandler/forwarding_test.go
Expand Up @@ -661,6 +661,46 @@ pipelines:
`))
})

It("generates default configuration for empty spec with LokiStack log store and audit logs enabled", func() {
cluster.Spec.LogStore = &logging.LogStoreSpec{
Type: logging.LogStoreTypeLokiStack,
LokiStack: logging.LokiStackStoreSpec{
Name: "lokistack-testing",
SendAuditLogs: true,
},
}

spec, _ := request.NormalizeForwarder()
Expect(YAMLString(spec)).To(EqualLines(`
outputs:
- name: default
type: loki
url: https://lokistack-testing-gateway-http.aNamespace.svc:8080/api/logs/v1/application
- name: default-infra
type: loki
url: https://lokistack-testing-gateway-http.aNamespace.svc:8080/api/logs/v1/infrastructure
- name: default-audit
type: loki
url: https://lokistack-testing-gateway-http.aNamespace.svc:8080/api/logs/v1/audit
pipelines:
- inputRefs:
- application
name: pipeline_0_
outputRefs:
- default
- inputRefs:
- infrastructure
name: pipeline_1_
outputRefs:
- default-infra
- inputRefs:
- audit
name: pipeline_2_
outputRefs:
- default-audit
`))
})

It("forwards logs to an explicit default logstore", func() {
cluster.Spec.LogStore = &logging.LogStoreSpec{
Type: logging.LogStoreTypeElasticsearch,
Expand Down
17 changes: 13 additions & 4 deletions internal/k8shandler/logstore_lokistack.go
Expand Up @@ -29,21 +29,24 @@ func (clusterRequest *ClusterLoggingRequest) createOrUpdateLokiStackLogStore() e
}

func (clusterRequest *ClusterLoggingRequest) createOrUpdateLokiStackClusterRole() error {
logStore := clusterRequest.Cluster.Spec.LogStore
auditEnabled := logStore != nil && logStore.LokiStack.SendAuditLogs

clusterRole := &rbacv1.ClusterRole{}
if err := clusterRequest.Get(lokiStackClusterRoleName, clusterRole); err != nil {
if !apierrors.IsNotFound(err) {
return fmt.Errorf("failed to get ClusterRole: %w", err)
}

clusterRole = newLokiStackClusterRole()
clusterRole = newLokiStackClusterRole(auditEnabled)
if err := clusterRequest.Create(clusterRole); err != nil {
return fmt.Errorf("failed to create ClusterRole: %w", err)
}

return nil
}

wantRole := newLokiStackClusterRole()
wantRole := newLokiStackClusterRole(auditEnabled)
if compareLokiStackClusterRole(clusterRole, wantRole) {
log.V(9).Info("LokiStack collector ClusterRole matches.")
return nil
Expand Down Expand Up @@ -114,8 +117,8 @@ func (clusterRequest *ClusterLoggingRequest) removeLokiStackRbac() error {
return nil
}

func newLokiStackClusterRole() *rbacv1.ClusterRole {
return &rbacv1.ClusterRole{
func newLokiStackClusterRole(auditEnabled bool) *rbacv1.ClusterRole {
role := &rbacv1.ClusterRole{
ObjectMeta: metav1.ObjectMeta{
Name: lokiStackClusterRoleName,
},
Expand All @@ -137,6 +140,12 @@ func newLokiStackClusterRole() *rbacv1.ClusterRole {
},
},
}

if auditEnabled {
role.Rules[0].Resources = append(role.Rules[0].Resources, "audit")
}

return role
}

func newLokiStackClusterRoleBinding() *rbacv1.ClusterRoleBinding {
Expand Down