Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
22 changes: 14 additions & 8 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,25 @@ func Init() {
NewBool(&ApplicationConfig.MetricsEnabled, "metrics-enabled", true, "Enable metrics. Optional.")
NewInt(&ApplicationConfig.MetricsPort, "metrics-port", 9090, "Metrics port. Optional.")

// JQ Configuration
NewBool(&ApplicationConfig.AllowAllEnvironmentVariablesInJQ, "allow-all-environment-variables-in-jq", true, "Allow access to all environment variables in jq queries. Optional.")
NewStringSlice(&ApplicationConfig.AllowedEnvironmentVariablesInJQ, "allowed-environment-variables-in-jq", []string{"PORT_*", "CLUSTER_NAME"}, "Comma-separated list of environment variables that are allowed in jq queries when allow-all-environment-variables-in-jq is false. Optional.")

flag.Parse()
}

func NewConfiguration() (*port.Config, error) {
config := &port.Config{
StateKey: ApplicationConfig.StateKey,
EventListenerType: ApplicationConfig.EventListenerType,
CreateDefaultResources: ApplicationConfig.CreateDefaultResources,
CreatePortResourcesOrigin: ApplicationConfig.CreatePortResourcesOrigin,
ResyncInterval: ApplicationConfig.ResyncInterval,
OverwriteConfigurationOnRestart: ApplicationConfig.OverwriteConfigurationOnRestart,
CreateMissingRelatedEntities: ApplicationConfig.CreateMissingRelatedEntities,
DeleteDependents: ApplicationConfig.DeleteDependents,
StateKey: ApplicationConfig.StateKey,
EventListenerType: ApplicationConfig.EventListenerType,
CreateDefaultResources: ApplicationConfig.CreateDefaultResources,
CreatePortResourcesOrigin: ApplicationConfig.CreatePortResourcesOrigin,
ResyncInterval: ApplicationConfig.ResyncInterval,
OverwriteConfigurationOnRestart: ApplicationConfig.OverwriteConfigurationOnRestart,
CreateMissingRelatedEntities: ApplicationConfig.CreateMissingRelatedEntities,
DeleteDependents: ApplicationConfig.DeleteDependents,
AllowAllEnvironmentVariablesInJQ: ApplicationConfig.AllowAllEnvironmentVariablesInJQ,
AllowedEnvironmentVariablesInJQ: ApplicationConfig.AllowedEnvironmentVariablesInJQ,
}

v, err := os.ReadFile(ApplicationConfig.ConfigFilePath)
Expand Down
3 changes: 3 additions & 0 deletions pkg/config/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,7 @@ type ApplicationConfiguration struct {
// Metrics Configuration
MetricsEnabled bool `json:"metricsEnabled,omitempty"`
MetricsPort int `json:"metricsPort,omitempty"`
// JQ Configuration
AllowAllEnvironmentVariablesInJQ bool `json:"allowAllEnvironmentVariablesInJQ,omitempty"`
AllowedEnvironmentVariablesInJQ []string `json:"allowedEnvironmentVariablesInJQ,omitempty"`
}
23 changes: 23 additions & 0 deletions pkg/config/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,29 @@ func NewBool(v *bool, key string, defaultValue bool, description string) {
flag.BoolVar(v, key, value, description)
}

func NewStringSlice(v *[]string, key string, defaultValue []string, description string) {
envValue := goutils.GetStringEnvOrDefault(prepareEnvKey(key), "")
var value []string
if envValue != "" {
value = strings.Split(envValue, ",")
// Trim whitespace from each element
for i, s := range value {
value[i] = strings.TrimSpace(s)
}
} else {
value = defaultValue
}
flag.Func(key, description, func(s string) error {
*v = strings.Split(s, ",")
// Trim whitespace from each element
for i, str := range *v {
(*v)[i] = strings.TrimSpace(str)
}
return nil
})
*v = value
}

func NewCreatePortResourcesOrigin(target *port.CreatePortResourcesOrigin, key, defaultValue, description string) {
var value string
flag.StringVar(&value, key, defaultValue, description)
Expand Down
7 changes: 6 additions & 1 deletion pkg/handlers/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,12 @@ func RunResync(exporterConfig *port.Config, k8sClient *k8s.Client, portClient *c
metrics.SetSuccessStatus(metrics.MetricKindResync, metrics.MetricPhaseResync, metrics.PhaseFailed)
return nil, errors.New("integration config is nil")
}

if i.Config.AllowAllEnvironmentVariablesInJQ {
config.ApplicationConfig.AllowAllEnvironmentVariablesInJQ = i.Config.AllowAllEnvironmentVariablesInJQ
}
if i.Config.AllowedEnvironmentVariablesInJQ != nil {
config.ApplicationConfig.AllowedEnvironmentVariablesInJQ = i.Config.AllowedEnvironmentVariablesInJQ
}
newHandler := NewControllersHandler(exporterConfig, i.Config, k8sClient, portClient)
newHandler.Handle(resyncType)
return newHandler, nil
Expand Down
46 changes: 25 additions & 21 deletions pkg/handlers/controllers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,19 +137,21 @@ func newFixture(t *testing.T, fixtureConfig *fixtureConfig) *fixture {
}

applicationConfig := &config.ApplicationConfiguration{
ConfigFilePath: config.ApplicationConfig.ConfigFilePath,
ResyncInterval: config.ApplicationConfig.ResyncInterval,
PortBaseURL: config.ApplicationConfig.PortBaseURL,
EventListenerType: config.ApplicationConfig.EventListenerType,
CreateDefaultResources: config.ApplicationConfig.CreateDefaultResources,
OverwriteConfigurationOnRestart: config.ApplicationConfig.OverwriteConfigurationOnRestart,
Resources: integrationConfig.Resources,
DeleteDependents: integrationConfig.DeleteDependents,
CreateMissingRelatedEntities: integrationConfig.CreateMissingRelatedEntities,
UpdateEntityOnlyOnDiff: config.ApplicationConfig.UpdateEntityOnlyOnDiff,
PortClientId: config.ApplicationConfig.PortClientId,
PortClientSecret: config.ApplicationConfig.PortClientSecret,
StateKey: config.ApplicationConfig.StateKey,
ConfigFilePath: config.ApplicationConfig.ConfigFilePath,
ResyncInterval: config.ApplicationConfig.ResyncInterval,
PortBaseURL: config.ApplicationConfig.PortBaseURL,
EventListenerType: config.ApplicationConfig.EventListenerType,
CreateDefaultResources: config.ApplicationConfig.CreateDefaultResources,
OverwriteConfigurationOnRestart: config.ApplicationConfig.OverwriteConfigurationOnRestart,
Resources: integrationConfig.Resources,
DeleteDependents: integrationConfig.DeleteDependents,
CreateMissingRelatedEntities: integrationConfig.CreateMissingRelatedEntities,
AllowAllEnvironmentVariablesInJQ: config.ApplicationConfig.AllowAllEnvironmentVariablesInJQ,
AllowedEnvironmentVariablesInJQ: config.ApplicationConfig.AllowedEnvironmentVariablesInJQ,
UpdateEntityOnlyOnDiff: config.ApplicationConfig.UpdateEntityOnlyOnDiff,
PortClientId: config.ApplicationConfig.PortClientId,
PortClientSecret: config.ApplicationConfig.PortClientSecret,
StateKey: config.ApplicationConfig.StateKey,
}

if fixtureConfig.portClientId != "" {
Expand All @@ -160,14 +162,16 @@ func newFixture(t *testing.T, fixtureConfig *fixtureConfig) *fixture {
}

exporterConfig := &port.Config{
StateKey: applicationConfig.StateKey,
EventListenerType: applicationConfig.EventListenerType,
CreateDefaultResources: applicationConfig.CreateDefaultResources,
ResyncInterval: applicationConfig.ResyncInterval,
OverwriteConfigurationOnRestart: applicationConfig.OverwriteConfigurationOnRestart,
Resources: applicationConfig.Resources,
DeleteDependents: applicationConfig.DeleteDependents,
CreateMissingRelatedEntities: applicationConfig.CreateMissingRelatedEntities,
StateKey: applicationConfig.StateKey,
EventListenerType: applicationConfig.EventListenerType,
CreateDefaultResources: applicationConfig.CreateDefaultResources,
ResyncInterval: applicationConfig.ResyncInterval,
OverwriteConfigurationOnRestart: applicationConfig.OverwriteConfigurationOnRestart,
Resources: applicationConfig.Resources,
DeleteDependents: applicationConfig.DeleteDependents,
CreateMissingRelatedEntities: applicationConfig.CreateMissingRelatedEntities,
AllowAllEnvironmentVariablesInJQ: applicationConfig.AllowAllEnvironmentVariablesInJQ,
AllowedEnvironmentVariablesInJQ: applicationConfig.AllowedEnvironmentVariablesInJQ,
}

groups := make([]metav1.APIGroup, 0)
Expand Down
41 changes: 41 additions & 0 deletions pkg/jq/parser.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package jq

import (
"encoding/json"
"fmt"
"os"
"reflect"
"strings"

"github.com/itchyny/gojq"
"github.com/port-labs/port-k8s-exporter/pkg/config"
"github.com/port-labs/port-k8s-exporter/pkg/goutils"
"github.com/port-labs/port-k8s-exporter/pkg/logger"
)
Expand All @@ -20,6 +22,27 @@
code, err := gojq.Compile(
query,
gojq.WithEnvironLoader(func() []string {
envQuery := fmt.Sprintf("def modified_env: [%s | .[] | split(\"=\")] | map({\"key\": .[0], \"value\": .[1]}) | from_entries; def patterns: %s | map(\"(\" + . + \")\") | join(\"|\"); if %t then modified_env else if ((patterns | length) > 0) then modified_env | with_entries(select(.key | test(patterns))) else {} end end | to_entries | map([.key,.value]) | [ .[] | join(\"=\")]", getSerializedEnvironmentVariables(), getAllowedEnvironmentVariables(), config.ApplicationConfig.AllowAllEnvironmentVariablesInJQ)
parsedEnvQuery, err := gojq.Parse(envQuery)
if err != nil {
logger.Warningf("failed to parse environment variables jq query: %s", err)
return os.Environ()
}
env, ok := parsedEnvQuery.Run(map[string]any{}).Next()
if !ok {
return os.Environ()
}
if err, ok := env.(error); ok {
logger.Warningf("failed to run environment variables jq query: %s", err)
return os.Environ()
}
if result, ok := env.([]interface{}); ok {
resultStrings := make([]string, len(result))
for i, v := range result {
resultStrings[i] = v.(string)
}
return resultStrings
}
return os.Environ()
}),
)
Expand Down Expand Up @@ -164,3 +187,21 @@

return mapInterface, nil
}

func getAllowedEnvironmentVariables() string {
return getSerializedVariablesArray(config.ApplicationConfig.AllowedEnvironmentVariablesInJQ, "failed to marshal allowed environment variables")
}

func getSerializedEnvironmentVariables() string {
return getSerializedVariablesArray(os.Environ(), "failed to marshal environment variables")
}

func getSerializedVariablesArray(input []string, errorMessage string) string {
jsonBytes, err := json.Marshal(input)
if err != nil {
logger.Warningf("%s: %v", errorMessage, err)
return "[]"
}

return string(jsonBytes)
}
Loading
Loading