diff --git a/README.md b/README.md index 82ca760..8918d6f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # tconfigd -tconfigd is a central daemon responsible for distributing configurations, rules, and trust bundles to Tratteria agents. It streamlines the management of transaction token verification across microservices systems. +tconfigd is a central daemon responsible for distributing configurations and trust bundles to Tratteria agents. It streamlines the management of transaction token verification across microservices systems. ## Documentation For detailed documentation and setup guides please visit our official documentation page: [tratteria.io](https://tratteria.io) diff --git a/installation/INSTALL.md b/installation/INSTALL.md new file mode 100644 index 0000000..e3b7f23 --- /dev/null +++ b/installation/INSTALL.md @@ -0,0 +1,103 @@ +# Installation Guide for tconfigd + +## Prerequisites +- **Kubernetes Cluster**: Ensure your Kubernetes cluster is active and accessible. +- **kubectl**: Confirm `kubectl` is installed and configured to interact with your Kubernetes cluster. + +## Installation Steps + +tconfigd requires SPIRE for its operation. If your infrastructure already has SPIRE installed, follow the [instructions for environments with existing SPIRE](#environment-with-existing-spire-installation) to install tconfigd. If SPIRE is not present, the steps below will include its installation as part of the tconfigd setup. + + +### 1. Clone the Repository +Clone the tconfigd repository and navigate to the installation directory: + +```bash +git clone https://github.com/tratteria/tconfigd.git +``` + +```bash +cd tconfigd/installation +``` + +Alternatively, perform a shallow clone of just the installation subdirectory. + + +### 2. Configure tconfigd + +Update the `config.yaml` file to match your specific deployment settings: + +- **Configure the settings as described below:** + - `enableTratInterception`: "`true`" + - **Description**: Set to "`true`" to enable interception of incoming requests for TraT verification. Set to "`false`" if using the [delegation method](https://github.com/tratteria/tratteria-agent) for TraT verification. + - `agentApiPort`: "`9040`" + - **Description**: The port number for the tratteria agent API. Do not change this unless you have some specific need. + - `agentInterceptorPort`: "`9050`" + - **Description**: The port number for the tratteria agent's incoming requests interceptor. Do not change this unless you have some specific need. + - `spiffeEndpointSocket`: "`unix:///run/spire/sockets/agent.sock`" + - **Description**: Path to the SPIFFE Workload API Unix socket. Do not change this if you are using the tconfigd SPIRE installation. + - `tconfigdSpiffeId`: "`spiffe://tratteria.io/tconfigd`" + - **Description**: SPIFFE ID for tconfigd. Do not change this if you are using the tconfigd SPIRE installation. + + +### 3. Run the Installation Script + +Deploy the tconfigd to your Kubernetes cluster by running the installation script: + +```bash +./install.sh +``` + +### 4. Verification + +Verify the installation by checking the status of the tconfigd pod in the `tratteria-system` namespace. Use the following command to view the pod: + +```bash +kubectl get pods -n tratteria-system +``` + +For a practical example of installing tconfigd on a microservice application, refer to the [example-application](https://github.com/tratteria/example-application). + +## Environment with Existing SPIRE Installation +If you already have SPIRE installed, follow these steps to install tconfigd: + +### 1. Register tconfigd with your running SPIRE: +Below is a sample registartion command: + +```bash +kubectl exec -n spire spire-server-0 -- \ + /opt/spire/bin/spire-server entry create --dns tconfigd tratteria-system.svc \ + -spiffeID spiffe:///tconfigd \ + -parentID spiffe:///ns/spire/sa/spire-agent \ + -selector k8s:ns:tratteria-system \ + -selector k8s:sa:tconfigd-service-account +``` + +### 2. Clone the tconfig Repository: + +Follow the [instructions to clone the repository](#1-clone-the-repository) from the general installation guide. + +### 3. Configure tconfigd: + +Adjust the following fields in your `config.yaml` file to align with your SPIRE settings. + +```yaml +spiffeEndpointSocket: "unix:///run/spire/sockets/agent.sock" # Path to the SPIFFE Workload API Unix socket, replace this if your installation settings differ. +tconfigdSpiffeId: "spiffe:///tconfigd" # SPIFFE ID used in the registration command above. +``` + +For configuring other fields, refer to the [general installation configuration guide above](#2-configure-tconfigd). + +### 4. Run the Installation Script: + +When installing tconfigd, add the `--no-spire` flag to the installation script to prevent reinstalling SPIRE in your environment. Similarly, use this flag when running the uninstallation script to keep SPIRE intact. + +```bash +./install.sh --no-spire +``` + +### 5. Verify Installation: + +Follow the [verification steps](#4-verification) provided in the general installation guide. + +For a practical example of installing tconfigd on a microservice application with existing SPIRE setup, refer to the [example-application-with-existing-spire](https://github.com/tratteria/example-application-with-existing-spire). diff --git a/installation/config.yaml b/installation/config.yaml new file mode 100644 index 0000000..7517050 --- /dev/null +++ b/installation/config.yaml @@ -0,0 +1,5 @@ +enableTratInterception: "true" # Enable or disable incoming requests interception for TraT verification +agentApiPort: "9040" # Port number for the tratteria agent API +agentInterceptorPort: "9050" # Port number for the tratteria agent incoming requests interceptor +spiffeEndpointSocket: "unix:///run/spire/sockets/agent.sock" # Don't change this if you are using tconfigd SPIRE installation +tconfigdSpiffeId: "spiffe://tratteria.io/tconfigd" # Don't change this if you are using tconfigd SPIRE installation diff --git a/installation/install.sh b/installation/install.sh new file mode 100755 index 0000000..5b65247 --- /dev/null +++ b/installation/install.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +info() { + printf "\e[34m%s\n\e[0m" "$1" +} + +error() { + printf "\e[31m%s\n\e[0m" "$1" +} + +success() { + printf "\e[32m%s\n\e[0m" "$1" +} + +usage() { + echo "Usage: $0 [OPTIONS]" + echo "Options:" + echo " --no-spire Skips the installation of SPIRE." + echo " -h, --help Displays this help message." +} + +apply_k8s_config() { + kubectl apply -f $1 || { error "Failed to apply configuration for $1"; exit 1; } +} + +validate_resource() { + resource_type=$1 + resource_name=$2 + if ! kubectl get ${resource_type} ${resource_name} -n tratteria-system > /dev/null 2>&1; then + error "${resource_type} ${resource_name} is not configured properly." + exit 1 + fi +} + +install_spire=true + +while [[ "$#" -gt 0 ]]; do + case $1 in + --no-spire) install_spire=false ;; + -h|--help) usage; exit 0 ;; + *) echo "Unknown option: $1"; usage; exit 1 ;; + esac + shift +done + +if kubectl get namespace tratteria-system > /dev/null 2>&1; then + error "tconfigd is already installed. Please uninstall the existing installation before proceeding." + exit 1 +fi + +if [ "$install_spire" = true ]; then + cd resources/spire + chmod +x install.sh + ./install.sh + cd ../../ +fi + +info "Installing tconfigd..." + +apply_k8s_config resources/namespaces.yaml +apply_k8s_config resources/crds +apply_k8s_config resources/service-account.yaml +apply_k8s_config resources/role.yaml +apply_k8s_config resources/rolebinding.yaml +apply_k8s_config resources/deployment.yaml +apply_k8s_config resources/service.yaml +apply_k8s_config resources/tratteria-agent-injector-mutating-webhook.yaml + +kubectl create configmap config --from-file=config.yaml=config.yaml -n tratteria-system || { + error "Failed to create static configuration config map" + exit 1 +} + +info "Checking for the readiness of tconfigd..." +attempts=0 +max_attempts=5 +while ! kubectl get pods -n tratteria-system | grep -q '1/1.*Running'; do + if [ $attempts -ge $max_attempts ]; then + error "Failed to verify the readiness of tconfigd." + exit 1 + fi + attempts=$((attempts + 1)) + info "Waiting for tconfigd to be ready..." + sleep 10 +done + +validate_resource namespace tratteria-system +validate_resource crd trats.tratteria.io +validate_resource crd tratteriaconfigs.tratteria.io +validate_resource serviceaccount tconfigd-service-account +validate_resource clusterrole tconfigd-service-account-role +validate_resource clusterrolebinding tconfigd-service-account-binding +validate_resource deployment tconfigd +validate_resource service tconfigd +validate_resource mutatingwebhookconfiguration tratteria-agent-injector + +success "tconfigd installation completed successfully." diff --git a/kubernetes/crd/trat-crd.yaml b/installation/resources/crds/trat-crd.yaml similarity index 100% rename from kubernetes/crd/trat-crd.yaml rename to installation/resources/crds/trat-crd.yaml diff --git a/kubernetes/crd/tratteriacfg-crd.yaml b/installation/resources/crds/tratteriacfg-crd.yaml similarity index 100% rename from kubernetes/crd/tratteriacfg-crd.yaml rename to installation/resources/crds/tratteriacfg-crd.yaml diff --git a/kubernetes/tconfigd/deployment.yaml b/installation/resources/deployment.yaml similarity index 78% rename from kubernetes/tconfigd/deployment.yaml rename to installation/resources/deployment.yaml index a1ccab2..c18c7c3 100644 --- a/kubernetes/tconfigd/deployment.yaml +++ b/installation/resources/deployment.yaml @@ -2,7 +2,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: tconfigd - namespace: tratteria + namespace: tratteria-system spec: replicas: 1 selector: @@ -12,17 +12,12 @@ spec: metadata: labels: app: tconfigd - namespace: tratteria + namespace: tratteria-system spec: dnsPolicy: ClusterFirstWithHostNet serviceAccountName: tconfigd-service-account containers: - - env: - - name: SPIFFE_ENDPOINT_SOCKET - value: unix:///run/spire/sockets/agent.sock - - name: TRATTERIA_SPIFFE_ID - value: spiffe://tratteria.io/tratteria - image: tconfigd + - image: tconfigd name: tconfigd args: ["/etc/tconfigd/config/config.yaml"] imagePullPolicy: Never diff --git a/installation/resources/namespaces.yaml b/installation/resources/namespaces.yaml new file mode 100644 index 0000000..afb83cc --- /dev/null +++ b/installation/resources/namespaces.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: List +items: +- apiVersion: v1 + kind: Namespace + metadata: + name: tratteria-system diff --git a/kubernetes/tconfigd/role.yaml b/installation/resources/role.yaml similarity index 100% rename from kubernetes/tconfigd/role.yaml rename to installation/resources/role.yaml diff --git a/kubernetes/tconfigd/rolebinding.yaml b/installation/resources/rolebinding.yaml similarity index 90% rename from kubernetes/tconfigd/rolebinding.yaml rename to installation/resources/rolebinding.yaml index 30cf1c9..481093d 100644 --- a/kubernetes/tconfigd/rolebinding.yaml +++ b/installation/resources/rolebinding.yaml @@ -5,7 +5,7 @@ metadata: subjects: - kind: ServiceAccount name: tconfigd-service-account - namespace: tratteria + namespace: tratteria-system roleRef: kind: ClusterRole name: tconfigd-service-account-role diff --git a/kubernetes/tconfigd/service-account.yaml b/installation/resources/service-account.yaml similarity index 72% rename from kubernetes/tconfigd/service-account.yaml rename to installation/resources/service-account.yaml index 749687b..321074a 100644 --- a/kubernetes/tconfigd/service-account.yaml +++ b/installation/resources/service-account.yaml @@ -2,4 +2,4 @@ apiVersion: v1 kind: ServiceAccount metadata: name: tconfigd-service-account - namespace: tratteria + namespace: tratteria-system diff --git a/kubernetes/tconfigd/service.yaml b/installation/resources/service.yaml similarity index 90% rename from kubernetes/tconfigd/service.yaml rename to installation/resources/service.yaml index 705d21d..34b64f9 100644 --- a/kubernetes/tconfigd/service.yaml +++ b/installation/resources/service.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Service metadata: name: tconfigd - namespace: tratteria + namespace: tratteria-system spec: type: ClusterIP ports: diff --git a/kubernetes/spire/agent/agent-account.yaml b/installation/resources/spire/agent/agent-account.yaml similarity index 100% rename from kubernetes/spire/agent/agent-account.yaml rename to installation/resources/spire/agent/agent-account.yaml diff --git a/kubernetes/spire/agent/agent-cluster-role.yaml b/installation/resources/spire/agent/agent-cluster-role.yaml similarity index 100% rename from kubernetes/spire/agent/agent-cluster-role.yaml rename to installation/resources/spire/agent/agent-cluster-role.yaml diff --git a/kubernetes/spire/agent/agent-configmap.yaml b/installation/resources/spire/agent/agent-configmap.yaml similarity index 100% rename from kubernetes/spire/agent/agent-configmap.yaml rename to installation/resources/spire/agent/agent-configmap.yaml diff --git a/kubernetes/spire/agent/agent-daemonset.yaml b/installation/resources/spire/agent/agent-daemonset.yaml similarity index 100% rename from kubernetes/spire/agent/agent-daemonset.yaml rename to installation/resources/spire/agent/agent-daemonset.yaml diff --git a/kubernetes/spire/deploy.sh b/installation/resources/spire/install.sh similarity index 89% rename from kubernetes/spire/deploy.sh rename to installation/resources/spire/install.sh index 9544f39..d061963 100755 --- a/kubernetes/spire/deploy.sh +++ b/installation/resources/spire/install.sh @@ -1,7 +1,6 @@ -# Applying Spire Configurations -echo "\nApplying Spire Configurations...\n" +echo "\nDeploying Spire...\n" -kubectl create namespace spire +kubectl apply -f namespaces.yaml # Create Server Bundle Configmap, Role & ClusterRoleBinding kubectl apply \ @@ -52,8 +51,8 @@ kubectl exec -n spire spire-server-0 -- \ -node kubectl exec -n spire spire-server-0 -- \ - /opt/spire/bin/spire-server entry create --dns tconfigd.tratteria.svc\ - -spiffeID spiffe://tratteria.io/tratteria \ + /opt/spire/bin/spire-server entry create --dns tconfigd.tratteria-system.svc\ + -spiffeID spiffe://tratteria.io/tconfigd \ -parentID spiffe://tratteria.io/ns/spire/sa/spire-agent \ - -selector k8s:ns:tratteria \ + -selector k8s:ns:tratteria-system \ -selector k8s:sa:tconfigd-service-account diff --git a/installation/resources/spire/namespaces.yaml b/installation/resources/spire/namespaces.yaml new file mode 100644 index 0000000..442bf2f --- /dev/null +++ b/installation/resources/spire/namespaces.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: List +items: +- apiVersion: v1 + kind: Namespace + metadata: + name: spire diff --git a/kubernetes/spire/server/server-account.yaml b/installation/resources/spire/server/server-account.yaml similarity index 100% rename from kubernetes/spire/server/server-account.yaml rename to installation/resources/spire/server/server-account.yaml diff --git a/kubernetes/spire/server/server-cluster-role.yaml b/installation/resources/spire/server/server-cluster-role.yaml similarity index 100% rename from kubernetes/spire/server/server-cluster-role.yaml rename to installation/resources/spire/server/server-cluster-role.yaml diff --git a/kubernetes/spire/server/server-configmap.yaml b/installation/resources/spire/server/server-configmap.yaml similarity index 100% rename from kubernetes/spire/server/server-configmap.yaml rename to installation/resources/spire/server/server-configmap.yaml diff --git a/kubernetes/spire/server/server-service.yaml b/installation/resources/spire/server/server-service.yaml similarity index 100% rename from kubernetes/spire/server/server-service.yaml rename to installation/resources/spire/server/server-service.yaml diff --git a/kubernetes/spire/server/server-statefulset.yaml b/installation/resources/spire/server/server-statefulset.yaml similarity index 100% rename from kubernetes/spire/server/server-statefulset.yaml rename to installation/resources/spire/server/server-statefulset.yaml diff --git a/kubernetes/spire/server/spire-bundle-configmap.yaml b/installation/resources/spire/server/spire-bundle-configmap.yaml similarity index 100% rename from kubernetes/spire/server/spire-bundle-configmap.yaml rename to installation/resources/spire/server/spire-bundle-configmap.yaml diff --git a/kubernetes/spire/destroy.sh b/installation/resources/spire/uninstall.sh similarity index 100% rename from kubernetes/spire/destroy.sh rename to installation/resources/spire/uninstall.sh diff --git a/kubernetes/tconfigd/tratteria-agent-injector-mutating-webhook.yaml b/installation/resources/tratteria-agent-injector-mutating-webhook.yaml similarity index 87% rename from kubernetes/tconfigd/tratteria-agent-injector-mutating-webhook.yaml rename to installation/resources/tratteria-agent-injector-mutating-webhook.yaml index f3d9bb1..acb1d02 100644 --- a/kubernetes/tconfigd/tratteria-agent-injector-mutating-webhook.yaml +++ b/installation/resources/tratteria-agent-injector-mutating-webhook.yaml @@ -5,11 +5,11 @@ metadata: labels: tratteria.io/webhook: "true" webhooks: - - name: tratteria-agent-injector.tratteria.com + - name: tratteria-agent-injector.tratteria.io clientConfig: service: name: tconfigd - namespace: tratteria + namespace: tratteria-system path: "/inject-tratteria-agents" caBundle: rules: diff --git a/installation/uninstall.sh b/installation/uninstall.sh new file mode 100755 index 0000000..2499d32 --- /dev/null +++ b/installation/uninstall.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +info() { + printf "\e[34m%s\n\e[0m" "$1" +} + +error() { + printf "\e[31m%s\n\e[0m" "$1" +} + +success() { + printf "\e[32m%s\n\e[0m" "$1" +} + +usage() { + echo "Usage: $0 [OPTIONS]" + echo "Options:" + echo " --no-spire Skips the uninstallation of SPIRE." + echo " -h, --help Displays this help message." +} + +resource_exists() { + resource_type=$1 + resource_name=$2 + kubectl get ${resource_type} ${resource_name} > /dev/null 2>&1 +} + +delete_k8s_resource() { + resource_type=$1 + resource_name=$2 + if resource_exists ${resource_type} ${resource_name}; then + kubectl delete ${resource_type} ${resource_name} || { error "Failed to delete ${resource_type} ${resource_name}"; exit 1; } + else + info "${resource_type} ${resource_name} does not exist, skipping deletion." + fi +} + +uninstall_spire=true + +while [[ "$#" -gt 0 ]]; do + case $1 in + --no-spire) uninstall_spire=false ;; + -h|--help) usage; exit 0 ;; + *) echo "Unknown option: $1"; usage; exit 1 ;; + esac + shift +done + +if [ "$uninstall_spire" = true ]; then + info "Uninstalling spire..." + cd resources/spire + chmod +x uninstall.sh + ./uninstall.sh + cd ../../ +fi + +info "Uninstalling tconfigd..." + +delete_k8s_resource namespace tratteria-system +delete_k8s_resource clusterrole tconfigd-service-account-role +delete_k8s_resource clusterrolebinding tconfigd-service-account-binding +delete_k8s_resource mutatingwebhookconfiguration tratteria-agent-injector +delete_k8s_resource crd trats.tratteria.io +delete_k8s_resource crd tratteriaconfigs.tratteria.io + +success "tconfigd uninstalled successfully." diff --git a/kubernetes/README.md b/kubernetes/README.md deleted file mode 100644 index 545aec6..0000000 --- a/kubernetes/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# tconfigd Kubernetes Configurations -This directory contains Kubernetes manifest files and installation scripts for tconfigd. Below is an overview of each component: - -### crd -This directory includes custom resource definitions(CRDs) and example custom resources(CRs) for `tratteria.io` custom resources. - -### spire -This directory includes the Kubernetes setup for SPIRE. - -### tconfigd -This directory includes the Kubernetes setup for the tconfigd server components. - -## Contribute -Contributions to the project are welcome, including feature enhancements, bug fixes, and documentation improvements. diff --git a/kubernetes/deploy.sh b/kubernetes/deploy.sh deleted file mode 100755 index 5602e20..0000000 --- a/kubernetes/deploy.sh +++ /dev/null @@ -1,13 +0,0 @@ -cd crd -chmod +x deploy.sh -./deploy.sh -cd .. - -cd spire -chmod +x deploy.sh -./deploy.sh -cd .. - -cd tconfigd -chmod +x deploy.sh -./deploy.sh \ No newline at end of file diff --git a/kubernetes/destroy.sh b/kubernetes/destroy.sh deleted file mode 100755 index e192266..0000000 --- a/kubernetes/destroy.sh +++ /dev/null @@ -1,14 +0,0 @@ -cd tconfigd -chmod +x destroy.sh -./destroy.sh -cd .. - -cd spire -chmod +x destroy.sh -./destroy.sh -cd .. - -cd crd -chmod +x destroy.sh -./destroy.sh -cd .. \ No newline at end of file diff --git a/kubernetes/tconfigd/config.yaml b/kubernetes/tconfigd/config.yaml deleted file mode 100644 index 4d9c759..0000000 --- a/kubernetes/tconfigd/config.yaml +++ /dev/null @@ -1,3 +0,0 @@ -enableTratInterception: "true" -agentApiPort: "9040" -agentInterceptorPort: "9050" \ No newline at end of file diff --git a/kubernetes/tconfigd/deploy.sh b/kubernetes/tconfigd/deploy.sh deleted file mode 100755 index 21ac68c..0000000 --- a/kubernetes/tconfigd/deploy.sh +++ /dev/null @@ -1,10 +0,0 @@ -kubectl create namespace tratteria - -kubectl create configmap config --from-file=config.yaml=config.yaml -n tratteria - -kubectl apply -f service-account.yaml -kubectl apply -f role.yaml -kubectl apply -f rolebinding.yaml -kubectl apply -f deployment.yaml -kubectl apply -f service.yaml -kubectl apply -f tratteria-agent-injector-mutating-webhook.yaml diff --git a/kubernetes/tconfigd/destroy.sh b/kubernetes/tconfigd/destroy.sh deleted file mode 100755 index 0197f0e..0000000 --- a/kubernetes/tconfigd/destroy.sh +++ /dev/null @@ -1,4 +0,0 @@ -kubectl delete namespace tratteria -kubectl delete clusterrole tconfigd-service-account-role -kubectl delete clusterrolebinding tconfigd-service-account-binding -kubectl delete mutatingwebhookconfiguration tratteria-agent-injector \ No newline at end of file diff --git a/service/cmd/main.go b/service/cmd/main.go index 5a2bcc8..344f9d8 100644 --- a/service/cmd/main.go +++ b/service/cmd/main.go @@ -71,6 +71,7 @@ func main() { EnableTratInterception: bool(appConfig.EnableTratInterception), AgentApiPort: int(appConfig.AgentApiPort), AgentInterceptorPort: int(appConfig.AgentInterceptorPort), + SpiffeEndpointSocket: appConfig.SpiffeEndpointSocket, Logger: logger, } diff --git a/service/config/config.go b/service/config/config.go index 4ae23a2..d61c034 100644 --- a/service/config/config.go +++ b/service/config/config.go @@ -3,10 +3,9 @@ package config import ( "fmt" "os" - "reflect" - "regexp" "strconv" + "github.com/spiffe/go-spiffe/v2/spiffeid" "gopkg.in/yaml.v2" ) @@ -22,27 +21,12 @@ func (b *BoolFromString) UnmarshalYAML(unmarshal func(interface{}) error) error case bool: *b = BoolFromString(value) case string: - if matched, envVarName := extractEnvVarName(value); matched { - envValue, err := getEnvVarValue(envVarName) - if err != nil { - return err - } - - boolVal, err := strconv.ParseBool(envValue) - - if err != nil { - return fmt.Errorf("error parsing boolean from environment variable: %v", err) - } - - *b = BoolFromString(boolVal) - } else { - boolVal, err := strconv.ParseBool(value) - if err != nil { - return fmt.Errorf("error parsing boolean from string: %v", err) - } - - *b = BoolFromString(boolVal) + boolVal, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("error parsing boolean from string: %v", err) } + + *b = BoolFromString(boolVal) default: return fmt.Errorf("invalid type for a bool variable, expected bool or string, got %T", tmp) } @@ -69,10 +53,30 @@ func (i *IntFromString) UnmarshalYAML(unmarshal func(interface{}) error) error { return nil } +type SPIFFEIDFromString spiffeid.ID + +func (s *SPIFFEIDFromString) UnmarshalYAML(unmarshal func(interface{}) error) error { + var strValue string + if err := unmarshal(&strValue); err != nil { + return err + } + + spiffeID, err := spiffeid.FromString(strValue) + if err != nil { + return fmt.Errorf("error parsing SPIFFE ID from string: %v", err) + } + + *s = SPIFFEIDFromString(spiffeID) + + return nil +} + type AppConfig struct { - EnableTratInterception BoolFromString `yaml:"enableTratInterception"` - AgentApiPort IntFromString `yaml:"agentApiPort"` - AgentInterceptorPort IntFromString `yaml:"agentInterceptorPort"` + EnableTratInterception BoolFromString `yaml:"enableTratInterception"` + AgentApiPort IntFromString `yaml:"agentApiPort"` + AgentInterceptorPort IntFromString `yaml:"agentInterceptorPort"` + SpiffeEndpointSocket string `yaml:"spiffeEndpointSocket"` + TconfigdSpiffeId SPIFFEIDFromString `yaml:"tconfigdSpiffeId"` } func GetAppConfig(configPath string) (*AppConfig, error) { @@ -86,57 +90,5 @@ func GetAppConfig(configPath string) (*AppConfig, error) { return nil, fmt.Errorf("failed to unmarshal YAML configuration: %w", err) } - resolveEnvVariables(&cfg) - return &cfg, nil } - -func extractEnvVarName(s string) (bool, string) { - envVarRegex := regexp.MustCompile(`^\$\{([^}]+)\}$`) - matches := envVarRegex.FindStringSubmatch(s) - - if len(matches) > 1 { - return true, matches[1] - } - - return false, "" -} - -func getEnvVarValue(envVarName string) (string, error) { - if envValue, exists := os.LookupEnv(envVarName); exists { - return envValue, nil - } - - return "", fmt.Errorf("environment variable %s not set", envVarName) -} - -func resolveEnvVariablesUtil(v reflect.Value) { - if v.Kind() == reflect.Ptr { - v = v.Elem() - } - - for i := 0; i < v.NumField(); i++ { - field := v.Field(i) - if field.Kind() == reflect.String { - fieldValue := field.String() - - if matched, envVarName := extractEnvVarName(fieldValue); matched { - envValue, err := getEnvVarValue(envVarName) - if err != nil { - panic(err.Error()) - } - - field.SetString(envValue) - } - } else if field.Kind() == reflect.Struct { - resolveEnvVariablesUtil(field) - } else if field.Kind() == reflect.Ptr && field.Elem().Kind() == reflect.Struct { - resolveEnvVariablesUtil(field.Elem()) - } - } -} - -func resolveEnvVariables(cfg *AppConfig) { - v := reflect.ValueOf(cfg) - resolveEnvVariablesUtil(v) -} diff --git a/service/webhook/pkg/tlscreds/tlscreds.go b/service/webhook/pkg/tlscreds/tlscreds.go index 2d6d1c0..de0f5ed 100644 --- a/service/webhook/pkg/tlscreds/tlscreds.go +++ b/service/webhook/pkg/tlscreds/tlscreds.go @@ -23,8 +23,8 @@ const ( JWTSourceTimeout = 15 * time.Second ) -func SetupTLSCertAndKeyFromSPIRE() error { - spireClient, err := GetSPIREWorkLoadApiClient() +func SetupTLSCertAndKeyFromSPIRE(spiffeEndpointSocket string) error { + spireClient, err := GetSPIREWorkLoadApiClient(spiffeEndpointSocket) if err != nil { return fmt.Errorf("unable to create spire workload api client: %w", err) } @@ -51,11 +51,11 @@ func SetupTLSCertAndKeyFromSPIRE() error { return nil } -func GetSPIREWorkLoadApiClient() (*workloadapi.Client, error) { +func GetSPIREWorkLoadApiClient(socketPath string) (*workloadapi.Client, error) { ctx, cancel := context.WithTimeout(context.Background(), JWTSourceTimeout) defer cancel() - spireClient, err := workloadapi.New(ctx) + spireClient, err := workloadapi.New(ctx, workloadapi.WithAddr(socketPath)) if err != nil { return nil, err } @@ -65,7 +65,7 @@ func GetSPIREWorkLoadApiClient() (*workloadapi.Client, error) { func WaitForCertificates() error { sleep := 500 * time.Millisecond - maxRetries := 360 + maxRetries := 30 for i := 1; i <= maxRetries; i++ { time.Sleep(sleep) diff --git a/service/webhook/setup.go b/service/webhook/setup.go index 7448296..b86314d 100644 --- a/service/webhook/setup.go +++ b/service/webhook/setup.go @@ -16,11 +16,12 @@ type Webhook struct { EnableTratInterception bool AgentApiPort int AgentInterceptorPort int + SpiffeEndpointSocket string Logger *zap.Logger } -func (webhook *Webhook) Run() error { - handler := handler.NewHandlers(webhook.EnableTratInterception, webhook.AgentApiPort, webhook.AgentInterceptorPort, webhook.Logger) +func (wh *Webhook) Run() error { + handler := handler.NewHandlers(wh.EnableTratInterception, wh.AgentApiPort, wh.AgentInterceptorPort, wh.Logger) router := mux.NewRouter() initializeRoutes(router, handler) @@ -32,16 +33,16 @@ func (webhook *Webhook) Run() error { ReadTimeout: 15 * time.Second, } - if err := tlscreds.SetupTLSCertAndKeyFromSPIRE(); err != nil { - webhook.Logger.Error("Error setting up TLS creds", zap.Error(err)) + if err := tlscreds.SetupTLSCertAndKeyFromSPIRE(wh.SpiffeEndpointSocket); err != nil { + wh.Logger.Error("Error setting up TLS creds", zap.Error(err)) return fmt.Errorf("error setting up TLS creds: %w", err) } - webhook.Logger.Info("Starting webhook server with TLS on port 443") + wh.Logger.Info("Starting webhook server with TLS on port 443") if err := srv.ListenAndServeTLS(tlscreds.CertPath, tlscreds.KeyPath); err != nil && err != http.ErrServerClosed { - webhook.Logger.Error("Failed to start the webhook server", zap.Error(err)) + wh.Logger.Error("Failed to start the webhook server", zap.Error(err)) return fmt.Errorf("failed to start the webhook server: %w", err) }