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

Possibility of disabling audit log functionality per landscape #367

Merged
merged 10 commits into from
Sep 10, 2024
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
7 changes: 4 additions & 3 deletions api/v1/runtime_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ const (
ConditionReasonSerializationError = RuntimeConditionReason("SerializationErr")
ConditionReasonDeleted = RuntimeConditionReason("Deleted")

ConditionReasonAdministratorsConfigured = RuntimeConditionReason("AdministratorsConfigured")
ConditionReasonAuditLogConfigured = RuntimeConditionReason("AuditLogConfigured")
ConditionReasonAuditLogError = RuntimeConditionReason("AuditLogErr")
ConditionReasonAdministratorsConfigured = RuntimeConditionReason("AdministratorsConfigured")
ConditionReasonAuditLogConfigured = RuntimeConditionReason("AuditLogConfigured")
ConditionReasonAuditLogError = RuntimeConditionReason("AuditLogErr")
ConditionReasonAuditLogMissingRegionMapping = RuntimeConditionReason("AuditLogMissingRegionMappingErr")
)

//+kubebuilder:object:root=true
Expand Down
62 changes: 59 additions & 3 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package main

import (
"encoding/json"
"flag"
"fmt"
"io"
Expand All @@ -27,6 +28,7 @@ import (
gardener_apis "github.com/gardener/gardener/pkg/client/core/clientset/versioned/typed/core/v1beta1"
"github.com/go-playground/validator/v10"
infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1"
"github.com/kyma-project/infrastructure-manager/internal/auditlogging"
kubeconfig_controller "github.com/kyma-project/infrastructure-manager/internal/controller/kubeconfig"
"github.com/kyma-project/infrastructure-manager/internal/controller/metrics"
runtime_controller "github.com/kyma-project/infrastructure-manager/internal/controller/runtime"
Expand Down Expand Up @@ -76,6 +78,7 @@ func main() {
var enableRuntimeReconciler bool
var converterConfigFilepath string
var shootSpecDumpEnabled bool
var auditLogMandatory bool

flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
Expand All @@ -90,6 +93,7 @@ func main() {
flag.BoolVar(&enableRuntimeReconciler, "runtime-reconciler-enabled", defaultRuntimeReconcilerEnabled, "Feature flag for all runtime reconciler functionalities")
flag.StringVar(&converterConfigFilepath, "converter-config-filepath", "/converter-config/converter_config.json", "A file path to the gardener shoot converter configuration.")
flag.BoolVar(&shootSpecDumpEnabled, "shoot-spec-dump-enabled", false, "Feature flag to allow persisting specs of created shoots")
flag.BoolVar(&auditLogMandatory, "audit-log-mandatory", true, "Feature flag to enable strict mode for audit log configuration")
Copy link
Member

Choose a reason for hiding this comment

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

Please document this new paramenter (link)


opts := zap.Options{
Development: true,
Expand Down Expand Up @@ -171,10 +175,17 @@ func main() {
os.Exit(1)
}

err = validateAuditLogConfiguration(converterConfig.AuditLog.TenantConfigPath)
if err != nil {
setupLog.Error(err, "invalid Audit Log configuration")
os.Exit(1)
}

cfg := fsm.RCCfg{
Finalizer: infrastructuremanagerv1.Finalizer,
ShootNamesapace: gardenerNamespace,
ConverterConfig: converterConfig,
Finalizer: infrastructuremanagerv1.Finalizer,
ShootNamesapace: gardenerNamespace,
ConverterConfig: converterConfig,
AuditLogMandatory: auditLogMandatory,
}
if shootSpecDumpEnabled {
cfg.PVCPath = "/testdata/kim"
Expand Down Expand Up @@ -238,3 +249,48 @@ func initGardenerClients(kubeconfigPath string, namespace string) (client.Client
}
return gardenerClient, shootClient, dynamicKubeconfigAPI, nil
}

func validateAuditLogConfiguration(tenantConfigPath string) error {
getReaderCloser := func() (io.ReadCloser, error) {
return os.Open(tenantConfigPath)
}

f, err := getReaderCloser()

defer func(f io.ReadCloser) {
_ = f.Close()
}(f)

if err != nil {
setupLog.Error(err, "unable to open Audit Log configuration file")
return err
}

var auditLogConfig map[string]map[string]auditlogging.AuditLogData

if err = json.NewDecoder(f).Decode(&auditLogConfig); err != nil {
setupLog.Error(err, "unable to decode Audit Log configuration")
return err
}

if err = validateAuditLogDataMap(auditLogConfig); err != nil {
setupLog.Error(err, "invalid audit log configuration")
return err
}

return err
}

func validateAuditLogDataMap(data map[string]map[string]auditlogging.AuditLogData) error {
validate := validator.New(validator.WithRequiredStructEnabled())

for _, nestedMap := range data {
for _, auditLogData := range nestedMap {
if err := validate.Struct(auditLogData); err != nil {
return err
}
}
}

return nil
}
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ You can configure the Infrastructure Manager deployment with the following argum
4. `gardener-request-timeout` - specifies the timeout for requests to Gardener. Default value is `60s`.
5. `runtime-reconciler-enabled` - feature flag responsible for enabling the runtime reconciler. Default value is `true`.
6. `shoot-spec-dump-enabled` - feature flag responsible for enabling the shoot spec dump. Default value is `false`.
7. `audit-log-mandatory` - feature flag responsible for enabling the Audit Log strict config. Default value is `true`.


See [manager_gardener_secret_patch.yaml](../config/default/manager_gardener_secret_patch.yaml) for default values.
Expand Down
10 changes: 6 additions & 4 deletions internal/auditlogging/auditlogging.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const (
auditlogExtensionType = "shoot-auditlog-service"
)

var ErrMissingMapping = errors.New("missing mapping for selected region in provider config")

//go:generate mockery --name=AuditLogging
type AuditLogging interface {
Enable(ctx context.Context, shoot *gardener.Shoot) (bool, error)
Expand All @@ -45,9 +47,9 @@ type auditLogConfig struct {
}

type AuditLogData struct {
TenantID string `json:"tenantID"`
ServiceURL string `json:"serviceURL"`
SecretName string `json:"secretName"`
TenantID string `json:"tenantID" validate:"required"`
ServiceURL string `json:"serviceURL" validate:"required,url"`
SecretName string `json:"secretName" validate:"required"`
}

type AuditlogExtensionConfig struct {
Expand Down Expand Up @@ -141,7 +143,7 @@ func ApplyAuditLogConfig(shoot *gardener.Shoot, auditConfigFromFile map[string]m

tenant, ok := providerConfig[auditID]
if !ok {
return false, fmt.Errorf("auditlog config for region %s, provider %s is empty", auditID, providerType)
return false, ErrMissingMapping
}

changedExt, err := configureExtension(shoot, tenant)
Expand Down
5 changes: 3 additions & 2 deletions internal/auditlogging/tests/auditlogging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package tests
import (
"context"
"fmt"
"testing"

gardener "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/kyma-project/infrastructure-manager/internal/auditlogging"
"github.com/kyma-project/infrastructure-manager/internal/auditlogging/mocks"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
"testing"
)

func TestEnable(t *testing.T) {
Expand Down Expand Up @@ -139,7 +140,7 @@ func TestApplyAuditLogConfig(t *testing.T) {

// then
require.False(t, annotated)
require.Equal(t, err, fmt.Errorf("auditlog config for region region, provider aws is empty"))
require.Equal(t, err, auditlogging.ErrMissingMapping)
})
}

Expand Down
7 changes: 4 additions & 3 deletions internal/controller/runtime/fsm/runtime_fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ type writerGetter = func(filePath string) (io.Writer, error)

// runtime reconciler specific configuration
type RCCfg struct {
Finalizer string
PVCPath string
ShootNamesapace string
Finalizer string
PVCPath string
ShootNamesapace string
AuditLogMandatory bool
shoot.ConverterConfig
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"

imv1 "github.com/kyma-project/infrastructure-manager/api/v1"
"github.com/kyma-project/infrastructure-manager/internal/auditlogging"
"github.com/pkg/errors"
ctrl "sigs.k8s.io/controller-runtime"
)

Expand All @@ -24,19 +26,45 @@ func sFnConfigureAuditLog(ctx context.Context, m *fsm, s *systemState) (stateFn,
return updateStatusAndRequeueAfter(gardenerRequeueDuration)
}

if err != nil {
m.log.Error(err, "Failed to configure Audit Log")
s.instance.UpdateStatePending(
imv1.ConditionTypeAuditLogConfigured,
imv1.ConditionReasonAuditLogError,
"False",
err.Error(),
)
if err != nil { //nolint:nestif
errorMessage := err.Error()
if errors.Is(err, auditlogging.ErrMissingMapping) {
if m.RCCfg.AuditLogMandatory {
m.log.Error(err, "Failed to configure Audit Log, missing region mapping for this shoot", "AuditLogMandatory", m.RCCfg.AuditLogMandatory, "providerType", s.shoot.Spec.Provider.Type, "region", s.shoot.Spec.Region)
s.instance.UpdateStatePending(
imv1.ConditionTypeAuditLogConfigured,
imv1.ConditionReasonAuditLogMissingRegionMapping,
"False",
errorMessage,
)
} else {
m.log.Info(errorMessage, "Audit Log was not configured, missing region mapping for this shoot.", "AuditLogMandatory", m.RCCfg.AuditLogMandatory, "providerType", s.shoot.Spec.Provider.Type, "region", s.shoot.Spec.Region)
s.instance.UpdateStateReady(
imv1.ConditionTypeAuditLogConfigured,
imv1.ConditionReasonAuditLogMissingRegionMapping,
"Missing region mapping for this shoot. Audit Log is not mandatory. Skipping configuration")
}
} else {
if m.RCCfg.AuditLogMandatory {
m.log.Error(err, "Failed to configure Audit Log", "AuditLogMandatory", m.RCCfg.AuditLogMandatory)
s.instance.UpdateStatePending(
imv1.ConditionTypeAuditLogConfigured,
imv1.ConditionReasonAuditLogError,
"False",
errorMessage)
} else {
m.log.Info(errorMessage, "AuditLogMandatory", m.RCCfg.AuditLogMandatory)
s.instance.UpdateStateReady(
imv1.ConditionTypeAuditLogConfigured,
imv1.ConditionReasonAuditLogError,
"Configuration of Audit Log is not mandatory, error for context: "+errorMessage)
}
}
} else {
s.instance.UpdateStateReady(
imv1.ConditionTypeAuditLogConfigured,
imv1.ConditionReasonAuditLogConfigured,
"Audit Log configured successfully",
"Audit Log state completed successfully",
)
}

Expand Down
Loading
Loading