44 "encoding/json"
55 "fmt"
66 "os"
7+ "path/filepath"
8+ "regexp"
79 "strings"
810
911 extapi "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
@@ -40,21 +42,36 @@ func (d defaultConfigProvider) LoadConfig(cfgJSON *extapi.JSON) (StackitDnsProvi
4042 return cfg , err
4143 }
4244
43- if err := validateConfig (& cfg ); err != nil {
45+ setDefaultValues (& cfg )
46+
47+ webhookNamespace , err := determineNamespace (d .fileNamespaceName )
48+ if err != nil {
4449 return cfg , err
4550 }
4651
47- setDefaultValues (& cfg )
52+ if cfg .AuthTokenSecretNamespace == "" {
53+ cfg .AuthTokenSecretNamespace = webhookNamespace
54+ }
4855
49- namespace , err := determineNamespace (cfg .AuthTokenSecretNamespace , d .fileNamespaceName )
50- if err != nil {
56+ if err := validateSecretNamespace (cfg .AuthTokenSecretNamespace , webhookNamespace ); err != nil {
57+ return cfg , err
58+ }
59+
60+ if err := validateConfig (& cfg ); err != nil {
5161 return cfg , err
5262 }
53- cfg .AuthTokenSecretNamespace = namespace
5463
5564 return cfg , nil
5665}
5766
67+ func validateSecretNamespace (configuredNamespace , webhookNamespace string ) error {
68+ // Secrets must be in the same namespace as the webhook
69+ if configuredNamespace != webhookNamespace {
70+ return fmt .Errorf ("authTokenSecretNamespace must be %s, got: %s" , webhookNamespace , configuredNamespace )
71+ }
72+ return nil
73+ }
74+
5875func unmarshalConfig (cfgJSON * extapi.JSON , cfg * StackitDnsProviderConfig ) error {
5976 if err := json .Unmarshal (cfgJSON .Raw , cfg ); err != nil {
6077 return fmt .Errorf ("error decoding solver configProvider: %w" , err )
@@ -68,6 +85,38 @@ func validateConfig(cfg *StackitDnsProviderConfig) error {
6885 return fmt .Errorf ("projectId must be specified" )
6986 }
7087
88+ if err := validateApiBasePath (cfg .ApiBasePath ); err != nil {
89+ return err
90+ }
91+
92+ if cfg .ServiceAccountKeyPath != "" {
93+ if err := validateSaKeyPath (cfg .ServiceAccountKeyPath ); err != nil {
94+ return err
95+ }
96+ }
97+
98+ return nil
99+ }
100+
101+ func validateApiBasePath (apiBasePath string ) error {
102+ pattern := "^https://dns\\ .api(?:\\ .[a-z0-9-]+)?\\ .stackit\\ .cloud/?$"
103+
104+ if matched , err := regexp .MatchString (pattern , apiBasePath ); err == nil && matched {
105+ return nil
106+ }
107+
108+ return fmt .Errorf ("apiBasePath not allowed: %s" , apiBasePath )
109+ }
110+
111+ func validateSaKeyPath (keyPath string ) error {
112+ allowedPrefix := "/var/run/secrets/stackit/"
113+
114+ clean := filepath .Clean (keyPath )
115+
116+ if ! strings .HasPrefix (clean , allowedPrefix ) && clean != strings .TrimSuffix (allowedPrefix , "/" ) {
117+ return fmt .Errorf ("serviceAccountKeyPath must be within %s, got: %s" , allowedPrefix , clean )
118+ }
119+
71120 return nil
72121}
73122
@@ -86,11 +135,7 @@ func setDefaultValues(cfg *StackitDnsProviderConfig) {
86135 }
87136}
88137
89- func determineNamespace (currentNamespace string , fileNamespaceName string ) (string , error ) {
90- if currentNamespace != "" {
91- return currentNamespace , nil
92- }
93-
138+ func determineNamespace (fileNamespaceName string ) (string , error ) {
94139 data , err := os .ReadFile (fileNamespaceName )
95140 if err != nil {
96141 return "" , fmt .Errorf ("failed to find the webhook pod namespace: %w" , err )
0 commit comments