From 56e4f76912a4d7f129ec23c996ed5dc12f4bec2d Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Fri, 6 Mar 2026 11:36:11 -0500 Subject: [PATCH 01/12] updated ingress docs --- charts/iap/values-na-perf-traefix.yml | 813 ++++++++++++++++++++++++++ docs/ingress.md | 256 +++++++- 2 files changed, 1042 insertions(+), 27 deletions(-) create mode 100644 charts/iap/values-na-perf-traefix.yml diff --git a/charts/iap/values-na-perf-traefix.yml b/charts/iap/values-na-perf-traefix.yml new file mode 100644 index 0000000..83d2b73 --- /dev/null +++ b/charts/iap/values-na-perf-traefix.yml @@ -0,0 +1,813 @@ +# Copyright (c) 2024, Itential, Inc +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +# Default values for iap. +# Ingress controller: Traefik +# +# PREREQUISITE - apply the ServersTransport resource before installing: +# +# kubectl apply -f - < +# spec: +# insecureSkipVerify: true # IAP uses self-signed certs; skip backend cert verification +# EOF +# +# This tells Traefik to connect to IAP pods over HTTPS without validating their certificate. + +# -- The number of pods to start +replicaCount: 1 +# -- The port that the application will run on. +applicationPort: 3443 +# -- The port that the Gateway Manager will listen on. +websocketPort: 8080 +# -- Toggle to enable TLS features and configuration. +useTLS: true +# -- Toggle the use of websockets (IAG5 integration) +useWebSockets: true +# -- Toggle a volume mount which contains adapter code. When this is set to false it is assumed that +# all adapters will be layered into the Itential provided container. +mountAdapterVolume: true +# -- Toggle a volume with will contain log files. Not required if log data is being captured from +# Stdout. +mountLogVolume: true + +certManager: + # -- Toggles the use of cert-manager for managing the TLS certificates. Setting this to false + # means that creation of the TLS certificates will be manual and outside of the chart. + enabled: false + +external-dns: + # -- Optional dependency to generate a static external DNS name + enabled: false + +# The Itential image to use, its version, and its location +# The image name will depend on the entitlement that has been granted. +image: + # -- The image repository + repository: 497639811223.dkr.ecr.us-east-2.amazonaws.com/automation-platform-config + # -- The image pull policy + pullPolicy: IfNotPresent + + # Individual test toggles + healthEndpointTest: + enabled: true # Our new test # -- The image tag + tag: "6.1.2" + +# -- The secrets object used to pull the image from the repo +imagePullSecrets: + - name: ecr-registry-secret + +serviceAccount: + # -- Enable creation of ServiceAccount + enabled: true # Enable for IAM authentication via proxy + # -- Create a new ServiceAccount or use existing one + create: true + # -- Name of the ServiceAccount to use (auto-generated if not specified) + name: "iap-serviceaccount" + # -- Additional annotations for the ServiceAccount + annotations: {} + # -- Whether to automount the ServiceAccount token + automountServiceAccountToken: true + +postInstallTests: + enabled: true + readinessTimeout: 300 + # Time to live after test completion (in seconds) - pod will be cleaned up automatically + ttlSecondsAfterFinished: 300 # 5 minutes default + # Process count configuration + processCountTest: + # Optional processes - won't fail test if missing, but will be reported + optionalProcesses: + - "Pronghorn_LifecycleManager_Application" + - "Pronghorn_ConfigurationManager_Application" + - "Pronghorn_NSOManager_Application" + - "Pronghorn_AppArtifacts_Application" + +# AWS IAM Role configurations (disabled for local deployment) +# aws: +# elasticache: +# roleArn: "arn:aws:iam::207567785584:role/IAP-ElastiCache-Role" + + +# The issuer to be used if using cert-manager to generate the TLS certificates +issuer: + # -- Toggle to use the issuer object or not + enabled: true + # -- The type of issuer + kind: ClusterIssuer + # -- The name of this issuer. + name: iap-ca-issuer + # -- The CA secret to be used by this issuer when creating TLS certificates. + caSecretName: itential-ca + +# The certificate object to use by cert-manager to generate the TLS certificates. +certificate: + # -- Toggle to use the certificate object or not + enabled: true + secretName: iap-tls-secret + issuerRef: + # -- The name of the issuer with the CA reference. + name: iap-ca-issuer + # -- The issuer type + kind: ClusterIssuer + # -- Specifies how long before the certificate expires that cert-manager should try to renew. + renewBefore: 48h + # -- Specifies how long the certificate should be valid for (its lifetime). + duration: 2160h + # -- The Common Name to use when creating certificates + commonName: iap-na-k8s.pe.itential.io + # -- The domain to use when creating certificates. This will be used by the templates to build a + # complete list of hosts to enable direct access to individual pods. Some UI actions in Itential + # require direct access to pods. + domain: pe.itential.io + # -- Specifies any private key properties + privateKey: {} # include all required properties, passed to the template as is + # -- Specifies any key store properties + keyStores: {} # include all required properties, passed to the template as is + # -- Specifies any subject fields required + subject: {} # include all required properties, passed to the template as is + +# Additional TLS secrets to mount as optional volumes +# Each secret will be mounted at /etc/ssl// +additionalTLSSecrets: [] # Empty list - should not cause any failures + +# Used to configure the storage class object which governs how the mounted volumes are created. +storageClass: + # -- Toggle the use of storageClass + enabled: false + # -- The name of the storageClass + name: "longhorn" + # -- Specifies which volume plugin provisions the storage + provisioner: "driver.longhorn.io" + # -- What happens to PersistentVolumes when released. Itential recommends "retain". + reclaimPolicy: "Retain" + # -- Controls when volume binding occurs + volumeBindingMode: "Immediate" + # -- Key-value pairs passed to the provisioner + parameters: + numberOfReplicas: "3" + staleReplicaTimeout: "30" + fromBackup: "" + +# Persistent volumes and persistent volume claims. These are used for Itential application logs and +# for Itential adapters. +persistentVolumeClaims: + # -- Toggle the use of persistentVolumeClaims + enabled: true + # -- This represents the claim for the persistence for the adapters and other custom applications + # that may have been developed by the customer. + assetClaim: + # -- The requested amount of storage + storage: "10Gi" + # -- This represents the claim for the persistence for the log files created and written to by the + # IAP application. + logClaim: + # -- The requested amount of storage + storage: "10Gi" + +# The Kubernetes service object for this application +service: + # -- The service type. + type: "ClusterIP" + # -- The name of this Kubernetes service object. + name: "iap-service" + # -- The port that this service object is listening on. + port: 443 + # Service annotations for metrics port + annotations: {} + +# The Kubernetes ingress object for this application. +ingress: + # -- The ingress object can be disabled and will not be created with this set to false + enabled: true + # -- The name of this Kubernetes ingress object + name: "iap-ingress" + # -- The ingress controller class name + className: "traefik" + # -- The ingress controller path type + pathType: Prefix + # Load balancer configuration + loadBalancer: + # -- Enable a load balancer that will distribute request to all Itential pods + enabled: true + # -- The Load balancer host name + host: iap-na-k8s.pe.itential.io + # -- The path + path: / + # Direct access configuration + directAccess: + # -- Enable direct access to all Itential pods. + enabled: true + # -- The base domain for each Itential pod, used by the templates to create host names. + baseDomain: pe.itential.io + # -- The path + path: / + + # -- Traefik ingress annotations. + # Traefik terminates TLS at the ingress (re-encryption), then connects to IAP pods over HTTPS. + # WebSocket support is native in Traefik — no annotation required. + annotations: + # Route incoming traffic through the HTTPS (websecure) entrypoint + traefik.ingress.kubernetes.io/router.entrypoints: websecure + # Enable TLS on this router — Traefik will use the cert from the tls.secretName below + traefik.ingress.kubernetes.io/router.tls: "true" + # Connect to backend IAP pods over HTTPS, using the ServersTransport defined in the prerequisite above + # Format: -@kubernetescrd (Traefik v3 requires namespace prefix) + traefik.ingress.kubernetes.io/service.serversTransport: na-iap-servers-transport@kubernetescrd + + # Traefik uses the cert-manager managed secret for frontend TLS termination. + tls: + - hosts: + - iap-na-k8s.pe.itential.io + secretName: iap-tls-secret + +statefulset: + enabled: true + +# -- Additional pod annotations +podAnnotations: {} +# -- Additional pod labels +podLabels: {} +# -- Additional pod security context. The pods will mount some persistent volumes. These settings +# allow for that to happen. +podSecurityContext: + fsGroup: 1001 + runAsGroup: 1001 + runAsUser: 1001 # run as the 'itential' user + runAsNonRoot: true +# -- Additional security context +securityContext: {} + +# Container resources +resources: + limits: + memory: "14Gi" + requests: + cpu: "3" + memory: "14Gi" + +# The liveness probe used to determine if the container is alive. If the liveness probe fails, +# the kubelet kills the container, and the container is subjected to its restart policy. If a +# container does not provide a liveness probe, the default state is Success. +livenessProbe: + enabled: false + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + successThreshold: 1 + path: "/health/status?exclude-service=true" + +# The readiness probe used to determine if the container is ready to accept requests. If the +# readiness probe fails, the endpoints controller removes the pod's IP address from the +# endpoints of all services that match the pod. The default state of readiness before the +# initial delay is failure. If a container does not provide a readiness probe, the default +# state is success. +readinessProbe: + enabled: false + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + successThreshold: 1 + path: "/health/status?exclude-service=true" + +# The startup probe used to allow some time for the application to start up. The application +# will have a maximum of 3 minutes (18 * 10 = 180s) to finish its startup. Once the startup +# probe has succeeded once, the liveness probe takes over. +startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 18 + successThreshold: 1 + path: "/health/status?exclude-service=true" + +# -- Additional volumes to output on the Statefulset definition. +volumes: [] + +# -- Additional volumeMounts to output on the Statefulset definition. +volumeMounts: [] + +# -- Additional nodeSelectors +nodeSelector: {} + +# -- Host aliases for DNS resolution +hostAliases: + - ip: "172.85.0.20" + hostnames: + - "pe-redis01" + - ip: "172.85.0.21" + hostnames: + - "pe-redis02" + - ip: "172.85.0.22" + hostnames: + - "pe-redis03" + +# -- Additonal tolerations +tolerations: [] + +# -- Additional affinities +affinity: {} + +# Configuration properties for Itential Automation Platform. +# In most cases, the default values are sufficient. If the property is commented that means that +# the default value is being used. This is a list of all possible values for convenience. The +# values listed are the defaults where commented. +env: + ############## + #SERVER + ############## + # The name of the profile document to load from the MongoDB where legacy configuration + # properties are stored. Not required for installations that are using environment + # variables or a properties file. + # ITENTIAL_PROFILE_ID: "" + + # An identifier for the server instance. This is used to uniquely identify the server in a + # multi-server environment. If not provided, the server will generate one on startup. This will + # be populated by the chart to the pod id and should not be used in a containerized deployment. + # ITENTIAL_SERVER_ID: "" + + # The file path to the directory containing additional services (applications and adapters). + # The chart will impose this value with an opinionated volume mount directory and should not be + # used in a containerized deployment. + # ITENTIAL_SERVICE_DIRECTORY: "" + + # Indicates whether the platform is using encrypted code files. + # ITENTIAL_PLATFORM_ENCRYPTED: "true" + + # 64-length hex string describing a 256 bit encryption key. + # ITENTIAL_ENCRYPTION_KEY: "" + + # A whitelist of services (applications/adapters) to initialize on startup of the platform. + # If no value is given, all services will be initialized. + # ITENTIAL_SERVICES: "" + + # The service type that will be denied CRUD operation access. + # ITENTIAL_SERVICE_BLACKLIST : "" + + # The amount of time a service should wait before shutting down, in seconds. + # ITENTIAL_PLATFORM_SHUTDOWN_TIMEOUT: "3" + + # How often to update service health, measured in seconds. + # ITENTIAL_SERVICE_HEALTH_CHECK_INTERVAL : "5" + + # The number of failed health checks in a row before a service is considered to be "unhealthy". + # ITENTIAL_SERVICE_HEALTH_CHECK_UNHEALTHY_THRESHOLD: "3" + + # If true, the platform will periodically check for dead processes. + # ITENTIAL_DEAD_PROCESS_CHECK_ENABLED: "true" + + # How often to check if application/adapter stopped sending healthcheck pings, in seconds. + # ITENTIAL_DEAD_PROCESS_CHECK_INTERVAL: "5" + + # Maximum time period for application/adapter without sending healthcheck ping, in seconds. + # ITENTIAL_DEAD_PROCESS_MAX_PERIOD: "15" + + # Specifies the amount of times services will retry on crash before stopping. + # ITENTIAL_SERVICE_CRASH_RECOVERY_MAX_RETRIES: "10" + + # Specifies the amount of times between each retry before the count will reset in milliseconds. + # ITENTIAL_SERVICE_CRASH_RECOVERY_RESET_RETRIES_AFTER_MS: "60000" + + # The timeout for external API requests, in seconds. + # ITENTIAL_EXTERNAL_REQUEST_TIMEOUT : "5" + + # The interval for how often IAP polls for the number of devices, in hours. + # ITENTIAL_DEVICE_COUNT_POLLING_INTERVAL : "24" + + # If true, the platform will track detailed audit events. + # ITENTIAL_AUDIT_ENABLED: "true" + + ############################# + # MONGO DATABASE CONNECTION # + ############################# + # -- Instructs the MongoDB driver to use the provided user/password when connecting to MongoDB. + ITENTIAL_MONGO_AUTH_ENABLED: "false" + + # -- The username to use when connecting to MongoDB. + ITENTIAL_MONGO_USER: "itential" + + # The password to use when connecting to MongoDB. + # ITENTIAL_MONGO_PASSWORD: "" + + # The name of the database that the MongoDB user must authenticate against. + ITENTIAL_MONGO_AUTH_DB: "itential" + + # If true, the server will not check if it is connecting to a compatible MongoDB version. + # ITENTIAL_MONGO_BYPASS_VERSION_CHECK: "true" + + # -- The name of the MongoDB logical database to connect to. + ITENTIAL_MONGO_DB_NAME: "itential_k8_na" + + # The MongoDB connection string. For a replica set this will include all members of the + # replica set. For Mongo Atlas this will be the SRV connection format. + # ITENTIAL_MONGO_URL: "" + + # -- Instruct the MongoDB driver to use TLS protocols when connecting to the database. + ITENTIAL_MONGO_TLS_ENABLED: "true" + + # -- If true, disables the validation checks for TLS certificates on other servers in the cluster + # and allows the use of invalid or self-signed certificates to connect. + ITENTIAL_MONGO_TLS_ALLOW_INVALID_CERTIFICATES: "true" + + # The .pem file that contains the root certificate chain from the Certificate Authority. + # Specify the file name of the .pem file using absolute paths. + # ITENTIAL_MONGO_TLS_CA_FILE: "" + + # The maximum number of connections in a connection pool. + # Each application/adapter has its own connection pool. + # ITENTIAL_MONGO_MAX_POOL_SIZE: "" + + #################### + # REDIS CONNECTION # + #################### + # The Redis keyspace (database number) to use for the connection. + ITENTIAL_REDIS_DB: "3" + + # -- The username to use when connecting to Redis. + ITENTIAL_REDIS_USERNAME: "itential" + + # The password to use when connecting to Redis. + # ITENTIAL_REDIS_PASSWORD: "" # Set via secret key + + # The maximum number of times to retry a request to Redis when the connection is lost. + # ITENTIAL_REDIS_MAX_RETRIES_PER_REQUEST : "20" + + # The maximum number of times to retry writing a heartbeat message to Redis from a service. + # ITENTIAL_REDIS_MAX_HEARTBEAT_WRITE_RETRIES: "20" + + # -- The hostname of the Redis server. Not used when connecting to Redis Sentinels. + # ITENTIAL_REDIS_HOST: "172.85.0.20" # Temporarily use direct connection + + # -- The port to use when connecting to this Redis instance. + ITENTIAL_REDIS_PORT: "6379" + + # The username to use when authenticating with a Redis Sentinel cluster. + ITENTIAL_REDIS_SENTINEL_USERNAME: "sentineluser" + + # The password to use when authenticating with a Redis Sentinel cluster + # ITENTIAL_REDIS_SENTINEL_PASSWORD: "" # Set via secret key + + # The list of Redis Sentinel servers (hostnames and ports) to use for high availability. + # Sample: [{"host": "172.85.0.20", "port": 26379}] + ITENTIAL_REDIS_SENTINELS: '[{"host": "172.85.0.20", "port": 26379}, {"host": "172.85.0.21", "port": 26379}, {"host": "172.85.0.22", "port": 26379}]' + + # The Redis primary name. This only has meaning when Redis is running with replication enabled. + # The sentinels will monitor this node and consider it down only when the sentinels agree. + # Note: The primary name should not include special characters other than: .-_ and no whitespaces. + ITENTIAL_REDIS_NAME: "itentialmaster" + + # Set the domain for session cookies to match ingress hostname + ITENTIAL_WEBSERVER_COOKIE_DOMAIN: "pe.itential.io" + + # Redis TLS configuration options for secure connections. + # Refer to NodeJS TLS library for all supported options. + # This must be set to "{}" if connecting to elasticache + # ITENTIAL_REDIS_TLS: '{}' + + ############################## + # HASHICORP VAULT CONNECTION # + ############################## + # The URL to the Hashicorp Vault server. + # ITENTIAL_VAULT_URL: "" + + # The authorization method to connect to Hashicorp Vault. Either token or approle. + # ITENTIAL_VAULT_AUTH_METHOD: "" + + # Hashicorp Vault Role ID used for AppRole authentication. + # ITENTIAL_VAULT_ROLE_ID: "" + + # Hashicorp Vault Secret ID used for AppRole login. + # ITENTIAL_VAULT_SECRET_ID: "" + + # The path where the AppRole was enabled. + # ITENTIAL_VAULT_APPROLE_PATH: "" + + # The file path to a token file. The token is used for authentication to access Vault secrets. + # ITENTIAL_VAULT_TOKEN: "" + + # The endpoint for the Secrets Engine that is used. + # ITENTIAL_VAULT_SECRETS_ENDPOINT: "" + + # If true, only reads secrets from Hashicorp Vault. Otherwise, the platform can write secrets + # to Vault for storage. + # ITENTIAL_VAULT_READ_ONLY: "true" + + ################### + # WORKFLOW WORKER # + ################### + # If true, will start working tasks immediately after the server startup process is complete. + # If false, the task worker must be enabled manually via the UI/API. + # ITENTIAL_TASK_WORKER_ENABLED: "true" + + # If true, will allow jobs to be started after the server startup process is complete. + # If false, API calls to start Jobs will return an error until enabled manually via the UI/API. + # ITENTIAL_JOB_WORKER_ENABLED: "true" + + ###################### + # INTEGRATION WORKER # + ###################### + # The number of threads available for API requests. + # ITENTIAL_INTEGRATION_THREAD_COUNT: "5" + + # The number of milliseconds until an integration request times out. + # ITENTIAL_INTEGRATION_TIMEOUT: "15000" + + ############### + # PLATFORM UI # + ############### + # Path to the layout file extended in pug templates. + # ITENTIAL_UI_LAYOUT_FILE: "" + + # Path to the HTML file that will be displayed as the home page for the UI. + # ITENTIAL_UI_HOME_FILE: "node_modules/@itential/iap-ui/build/index.html" + + # Path to the HTML file that will be displayed as the login page for the UI. + # ITENTIAL_UI_LOGIN_FILE: "node_modules/@itential/iap-ui/build/index.html" + + # Path to the HTML file that will be displayed as the profile page for the UI. + # ITENTIAL_UI_PROFILE_FILE: "node_modules/@itential/iap-ui/build/index.html" + + # Path to the favicon file that will be displayed in the browser tab. + # ITENTIAL_UI_FAVICON: "ui/img/favicon.ico" + + # Path to the apple touch icon file that will be displayed on iOS devices. + # ITENTIAL_UI_APPLE_TOUCH_ICON_FILE: "ui/img/apple-touch-icon.png" + + ################## + # AUTHENTICATION # + ################## + # If true, logs out existing sessions for a user when they log in with a new session. + # ITENTIAL_AUTH_UNIQUE_SESSIONS_ENABLED: "false" + + # Members of these groups will be implicitly assigned with admin permissions. + # ITENTIAL_AUTH_ADMIN_GROUPS: '[]' + + # Enables a AAA adapter to custom build the principal object for a user with + # a "buildPrincipal" method. + # ITENTIAL_AUTH_BROKER_PRINCIPAL_ENABLED: "false" + + # The name of the cookie used for a user session. + # ITENTIAL_AUTH_SESSION_COOKIE_NAME: "token" + + # The time in minutes before a user session expires. + # ITENTIAL_AUTH_SESSION_TTL: "60" + + # Enables a default user to be used for login when SSO is not configured and no AAA Adapter exists. + # ITENTIAL_DEFAULT_USER_ENABLED: "true" + + # The username of the default user. + # ITENTIAL_DEFAULT_USER_USERNAME: "admin" + + # The password of the default user. + # ITENTIAL_DEFAULT_USER_PASSWORD: "" + + ############# + # WEBSERVER # + ############# + # A toggle to instruct the webserver to include HTTP cache control headers on the response. + # ITENTIAL_WEBSERVER_CACHE_CONTROL_ENABLED: "false" + + # Timeout to use for incoming HTTP requests to the platform API, in milliseconds. + # ITENTIAL_WEBSERVER_TIMEOUT: "300000" + + # The value of the HTTP Access-Control-Allow-Origin header returned to clients. + # ITENTIAL_WEBSERVER_RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN: "*" + + # If true, allows the webserver to respond to insecure HTTP requests. + # ITENTIAL_WEBSERVER_HTTP_ENABLED: "false" + + # If true, allows the webserver to respond to secure HTTPS requests. + # ITENTIAL_WEBSERVER_HTTPS_ENABLED: "true" + + # The path to the public key file used for HTTPS connections. + # ITENTIAL_WEBSERVER_HTTPS_KEY: "/etc/ssl/certs/platform/server.key" + + # The passphrase for the private key used to enable TLS sessions. + # ITENTIAL_WEBSERVER_HTTPS_PASSPHRASE: "" + + # The path to the certificate file used for HTTPS connections. + # ITENTIAL_WEBSERVER_HTTPS_CERT: "/etc/ssl/certs/platform/server.crt" + + # The set of allowed SSL/TLS protocol versions. + ITENTIAL_WEBSERVER_HTTPS_SECURE_PROTOCOL: "TLS_method" + + # The allowed SSL/TLS cipher suite. + # ITENTIAL_WEBSERVER_HTTPS_CIPHERS: "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA" + + # Specifies the number of renegotiations that are allowed in a single HTTPS connection. + # ITENTIAL_WEBSERVER_HTTPS_CLIENT_RENEG_LIMIT: "3" + + # Specifies the time renegotiation window in seconds for a single HTTPS connection. + # ITENTIAL_WEBSERVER_HTTPS_CLIENT_RENEG_WINDOW: "600" + + # The set of allowed HTTP verbs in addition to those defined in the standard HTTP/1.1 protocol. + # ITENTIAL_WEBSERVER_HTTP_ALLOWED_OPTIONAL_VERBS: "" + + ########### + # LOGGING # + ########### + # The maximum number of each log file to keep as rotation occurs. + # ITENTIAL_LOG_MAX_FILES: "100" + + # The maximum file size in bytes of each log file before rotation occurs. + # ITENTIAL_LOG_MAX_FILE_SIZE: "1048576" + + # The minimum log level to display in the log file. + ITENTIAL_LOG_LEVEL: "warn" + + # The absolute directory path where log files are written. + # ITENTIAL_LOG_DIRECTORY: "/var/log/itential/platform" + + # The name of the primary platform log file. + # ITENTIAL_LOG_FILENAME: "platform.log" + + # The minimum log level to display in the console (stdout). + ITENTIAL_LOG_LEVEL_CONSOLE: "warn" + + # The absolute directory path where webserver log files are written. + # ITENTIAL_WEBSERVER_LOG_DIRECTORY: "/var/log/itential/platform" + + # The name of the webserver log file. + # ITENTIAL_WEBSERVER_LOG_FILENAME: "webserver.log" + + # The minimum log level to send to the syslog server. + ITENTIAL_LOG_LEVEL_SYSLOG: "warning" + + # The hostname or IP address of the syslog server. + # ITENTIAL_SYSLOG_HOST: "localhost" + + # The port number of the syslog server. + # ITENTIAL_SYSLOG_PORT: "514" + + # The protocol to use when sending logs to the syslog server. + # ITENTIAL_SYSLOG_PROTOCOL: "udp4" + + # The syslog facility to use when sending logs to the syslog server. + # ITENTIAL_SYSLOG_FACILITY: "local0" + + # The syslog message format to use when sending logs to the syslog server. + # ITENTIAL_SYSLOG_TYPE: "BSD" + + # The path to the syslog server file. + # ITENTIAL_SYSLOG_PATH: "/dev/log" + + # The process property to include as the process id in the syslog message. + # ITENTIAL_SYSLOG_PID: "process.pid" + + # The hostname to include in the syslog message. + # ITENTIAL_SYSLOG_LOCALHOST: "localhost" + + # The process property to include as the application name in the syslog message. + # ITENTIAL_SYSLOG_APP_NAME: "process.title" + + # The end of line character to include in the syslog message. + # ITENTIAL_SYSLOG_EOL: "" + + ########### + # BROKERS # + ########### + # A list of adapter types that manages the devices. + # ITENTIAL_DEVICE_BROKER_DEFAULT_ADAPTER_PRIORITY: "" + + # Runs a command on a device. + # ITENTIAL_DEVICE_BROKER_RUN_COMMAND_ADAPTER_PREFERENCE: "" + + # If true, the platform will perform strict JSON Schema validation on messages into the brokers + # and coming back to the broker layer from adapters. + # ITENTIAL_BROKER_VALIDATION_ENABLED: "false" + + ######## + # SNMP # + ######## + # Remote SNMP destination configuration objects. + # ITENTIAL_SNMP_ALARM_CONFIGS: '[{"ip": "localhost", "community": "public", "type": "trap", "properties": {"port": 161, "retries": 1, "timeout": 5000, "transport": "udp4", "trapPort": 162, "version": "V1"}}]' + + # + # END IAP CONFIGURATION PROPERTIES + # + +processExporter: + enabled: true + image: + repository: ncabatoff/process-exporter + tag: latest + port: 9256 + +mongoqueryExporter: + enabled: true + existingConfig: + name: mongodb-query-exporter + image: + pullPolicy: Always + podMonitor: + enabled: true + namespace: na + interval: 60s + scrapeTimeout: 15s + replicas: 1 + resources: + limits: + memory: 250Mi + ephemeral-storage: 50Mi + requests: + cpu: 50m + memory: 250Mi + ephemeral-storage: 50Mi + env: + MDBEXPORTER_MONGODB_QUERY_TIMEOUT: 15s + +# Loki configuration for log aggregation +loki: + # -- Enable Loki for log collection + enabled: true + image: + # -- Loki image repository + repository: grafana/loki + # -- Loki image tag + tag: 2.9.0 + # -- Image pull policy + pullPolicy: IfNotPresent + # -- Loki HTTP port + httpPort: 3100 + # -- Loki GRPC port + grpcPort: 9095 + # -- Storage configuration + storage: + # -- Storage class for Loki data persistence + storageClass: "iap-ebs-gp3-na" + # -- Storage size for Loki data + size: "20Gi" + # -- Resource limits and requests + resources: + limits: + memory: "1Gi" + cpu: "500m" + requests: + memory: "512Mi" + cpu: "100m" + # -- Ingress configuration for external access + ingress: + # -- Enable Ingress for Loki + enabled: true + # -- Ingress class name + className: "traefik" + # -- Hostname for Loki access + host: "loki-local.pe.itential.io" + # -- Additional annotations for the Ingress + # Loki uses plain HTTP (port 3100) — no backend HTTPS or ServersTransport needed + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: web + +# Promtail configuration for log collection +promtail: + # -- Enable Promtail for log shipping to Loki + enabled: true + image: + # -- Promtail image repository + repository: grafana/promtail + # -- Promtail image tag + tag: 2.9.0 + # -- Image pull policy + pullPolicy: IfNotPresent + # -- Loki endpoint for Promtail to send logs to + lokiUrl: "http://iap-loki:3100/loki/api/v1/push" + # -- Resource limits and requests + resources: + limits: + memory: "128Mi" + cpu: "100m" + requests: + memory: "64Mi" + cpu: "50m" + + +# Init container for installing adapters +initAdapterInstaller: + # -- Enable the init container that installs adapters to the persistent volume + enabled: false + image: + # -- The repository for the adapter installer init container image + repository: node + # -- The tag for the adapter installer init container image + tag: "18-bullseye" + # -- The image pull policy for the adapter installer init container + pullPolicy: IfNotPresent + securityContext: + runAsUser: 1001 + runAsGroup: 1001 + runAsNonRoot: true + allowPrivilegeEscalation: false + npmInstallOptions: + - "--silent" + - "--no-audit" + - "--no-fund" + - "--ignore-scripts" + repositories: + - url: "https://gitlab.com/itentialopensource/adapters/adapter-aruba_central.git" + branch: "v2.3.0" + - url: "https://gitlab.com/itentialopensource/adapters/adapter-github.git" diff --git a/docs/ingress.md b/docs/ingress.md index 9a267bc..7cab74f 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -35,9 +35,9 @@ ingress: The chart supports multiple ingress controllers. Choose the one that best fits your environment. -#### AWS Application Load Balancer (ALB) - Default Option +#### AWS Application Load Balancer (ALB) -The default load balancing solution uses AWS Application Load Balancer through the AWS Load Balancer Controller. +This load balancing solution uses AWS Application Load Balancer through the AWS Load Balancer Controller. **ALB Configuration Example:** @@ -94,43 +94,245 @@ ingress: alb.ingress.kubernetes.io/ssl-policy: "ELBSecurityPolicy-TLS-1-2-2017-01" ``` -#### NGINX Ingress Controller - Alternative Option +#### GKE HTTP(S) Load Balancer - GKE Option -For environments where ALB is not available or preferred, NGINX Ingress Controller can be used as an alternative. +On Google Kubernetes Engine, the native ingress controller provisions a Google Cloud HTTP(S) Load Balancer. Because IAP terminates TLS at the pod (port 443), GKE requires a `BackendConfig` custom resource to configure HTTPS backend health checks and session affinity, and a `cloud.google.com/app-protocols` annotation on the Service to tell the load balancer to use HTTPS when communicating with pods. -**NGINX Configuration Example:** +> **Note:** The `BackendConfig` and `ManagedCertificate` resources must be created separately — they are not rendered by this chart. Apply them to your cluster before or alongside the Helm release. + +**BackendConfig (apply separately):** + +```yaml +apiVersion: cloud.google.com/v1 +kind: BackendConfig +metadata: + name: iap-backend-config +spec: + healthCheck: + checkIntervalSec: 15 + timeoutSec: 5 + healthyThreshold: 2 + unhealthyThreshold: 2 + type: HTTPS + requestPath: /health/status + port: 3443 + sessionAffinity: + affinityType: GENERATED_COOKIE + affinityCookieTtlSec: 3600 + timeoutSec: 60 + connectionDraining: + drainingTimeoutSec: 60 +``` + +**ManagedCertificate (apply separately):** + +```yaml +apiVersion: networking.gke.io/v1 +kind: ManagedCertificate +metadata: + name: iap-managed-cert +spec: + domains: + - iap.example.com + - iap-prod-0.example.com + - iap-prod-1.example.com +``` + +**Helm values configuration:** ```yaml +service: + type: ClusterIP + name: iap-service + port: 443 + annotations: + # Tell GKE LB to use HTTPS when communicating with pods + cloud.google.com/app-protocols: '{"https":"HTTPS"}' + # Enable container-native load balancing (pod-level routing, equivalent to ALB target-type: ip) + cloud.google.com/neg: '{"ingress": true}' + # Reference the BackendConfig for health checks and session affinity + cloud.google.com/backend-config: '{"default": "iap-backend-config"}' + ingress: enabled: true - className: "nginx" + className: "gce" loadBalancer: enabled: true - host: "iap.example.com" - annotations: - nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" - nginx.ingress.kubernetes.io/ssl-redirect: "true" - nginx.ingress.kubernetes.io/use-regex: "true" - nginx.ingress.kubernetes.io/proxy-read-timeout: "60" - nginx.ingress.kubernetes.io/proxy-send-timeout: "60" - nginx.ingress.kubernetes.io/proxy-connect-timeout: "60" - nginx.ingress.kubernetes.io/proxy-body-size: "0" - nginx.ingress.kubernetes.io/affinity: "cookie" - nginx.ingress.kubernetes.io/affinity-mode: "persistent" - nginx.ingress.kubernetes.io/session-cookie-name: "iap-server" - nginx.ingress.kubernetes.io/session-cookie-max-age: "3600" - nginx.ingress.kubernetes.io/websocket-services: "iap-service" + host: iap.example.com + path: / + directAccess: + enabled: true + baseDomain: example.com + path: / + annotations: + # Reference the ManagedCertificate for SSL + networking.gke.io/managed-certificates: "iap-managed-cert" + # Use a static external IP (reserve one in GCP Console first) + kubernetes.io/ingress.global-static-ip-name: "iap-static-ip" + # Force HTTPS + kubernetes.io/ingress.allow-http: "false" + external-dns.alpha.kubernetes.io/hostname: iap.example.com + external-dns.alpha.kubernetes.io/ttl: "300" + # TLS block is not used with GKE ManagedCertificates — leave empty + tls: [] +``` + +> **WebSocket support:** GKE HTTP(S) LB supports WebSockets natively. No additional annotation is required. Ensure port 8080 is exposed via a separate Service or NodePort if using IAG5/Gateway Manager. + +--- + +#### Azure Application Gateway Ingress Controller (AGIC) - AKS Option + +On Azure Kubernetes Service, the Application Gateway Ingress Controller (AGIC) provisions an Azure Application Gateway. AGIC uses annotation-based configuration similar to NGINX but with `appgw.ingress.kubernetes.io/` prefixed annotations. + +Because IAP terminates TLS at the pod (port 443), the `backend-protocol: "https"` annotation is required. SSL certificates are attached to the Application Gateway frontend, not managed through Kubernetes secrets. + +**Helm values configuration:** + +```yaml +service: + type: ClusterIP + name: iap-service + port: 443 + +ingress: + enabled: true + className: "azure-application-gateway" + loadBalancer: + enabled: true + host: iap.example.com + path: / + directAccess: + enabled: true + baseDomain: example.com + path: / + annotations: + # Use HTTPS when communicating with backend pods (TLS terminates at the pod) + appgw.ingress.kubernetes.io/backend-protocol: "https" + # Force HTTPS redirect on the frontend + appgw.ingress.kubernetes.io/ssl-redirect: "true" + # Reference an SSL certificate pre-uploaded to Application Gateway + appgw.ingress.kubernetes.io/appgw-ssl-certificate: "iap-ssl-cert" + # Health probe configuration + appgw.ingress.kubernetes.io/health-probe-path: "/health/status" + appgw.ingress.kubernetes.io/health-probe-port: "3443" + appgw.ingress.kubernetes.io/health-probe-status-codes: "200-399" + appgw.ingress.kubernetes.io/health-probe-interval: "15" + appgw.ingress.kubernetes.io/health-probe-timeout: "5" + appgw.ingress.kubernetes.io/health-probe-unhealthy-threshold: "2" + # Session affinity (equivalent to ALB stickiness) + appgw.ingress.kubernetes.io/cookie-based-affinity: "Enabled" + appgw.ingress.kubernetes.io/cookie-based-affinity-distinct-name: "true" + # Request and connection timeouts + appgw.ingress.kubernetes.io/request-timeout: "60" + appgw.ingress.kubernetes.io/connection-draining: "true" + appgw.ingress.kubernetes.io/connection-draining-timeout: "30" + external-dns.alpha.kubernetes.io/hostname: iap.example.com + external-dns.alpha.kubernetes.io/ttl: "300" + # TLS block is not used with AGIC frontend certificates — leave empty + tls: [] +``` + +> **SSL Certificate:** The `appgw-ssl-certificate` annotation references a certificate by name that must already be uploaded to the Application Gateway in Azure. This is separate from Kubernetes secrets or cert-manager. Alternatively, you can integrate with Azure Key Vault via the AGIC add-on. + +> **WebSocket support:** Azure Application Gateway supports WebSockets natively. Ensure port 8080 is included in the Application Gateway listener configuration if using IAG5/Gateway Manager. + +--- + +#### Traefik - Bare-Metal / On-Premises Option + +Traefik is a cloud-native ingress controller well suited to bare-metal and on-premises Kubernetes clusters. Because IAP terminates TLS at the pod (port 443), Traefik must be configured to re-encrypt the backend connection — it terminates TLS from the client, then reconnects to the IAP pod over HTTPS. + +**Step 1 — Install Traefik:** + +```bash +helm repo add traefik https://traefik.github.io/charts +helm repo update +helm install traefik traefik/traefik \ + --namespace traefik \ + --create-namespace \ + --set ingressClass.enabled=true \ + --set ingressClass.isDefaultClass=false \ + --set "additionalArguments[0]=--serversTransport.insecureSkipVerify=true" ``` +The `--serversTransport.insecureSkipVerify=true` flag tells Traefik to skip TLS certificate verification when connecting to backend pods. This is required because IAP pods use self-signed certificates that do not include pod IP SANs. + +> **Note:** In Traefik v3, the `ServersTransport` CRD annotation (`traefik.ingress.kubernetes.io/service.serversTransport`) on standard Kubernetes Ingress objects does not reliably apply per-service backend TLS settings. The global `--serversTransport.insecureSkipVerify=true` flag is the recommended approach for IAP deployments. + +**Step 2 — Apply the ServersTransport CRD** (namespace-scoped, required for Traefik to identify the backend transport configuration): + +```bash +kubectl apply -f - < +spec: + insecureSkipVerify: true +EOF +``` + +**Step 3 — Helm values configuration:** + +```yaml +ingress: + enabled: true + className: "traefik" + loadBalancer: + enabled: true + host: iap.example.com + path: / + directAccess: + enabled: true + baseDomain: example.com + path: / + annotations: + # Route incoming traffic through the HTTPS (websecure) entrypoint + traefik.ingress.kubernetes.io/router.entrypoints: websecure + # Enable TLS on this router + traefik.ingress.kubernetes.io/router.tls: "true" + # Reference the ServersTransport CRD — format: -@kubernetescrd + traefik.ingress.kubernetes.io/service.serversTransport: -iap-servers-transport@kubernetescrd + tls: + - hosts: + - iap.example.com + secretName: iap-tls-secret +``` + +**NodePort and external load balancer:** + +In bare-metal environments, Traefik's `LoadBalancer` service will remain in `` state without a cloud provider or MetalLB. Traffic reaches Traefik via NodePort. When the external load balancer routes to a fixed port (e.g., 443 or a custom port), configure Traefik with a matching fixed NodePort to avoid reconfiguring the LB on each install: + +```bash +helm install traefik traefik/traefik \ + --namespace traefik \ + --create-namespace \ + --set ingressClass.enabled=true \ + --set ingressClass.isDefaultClass=false \ + --set "additionalArguments[0]=--serversTransport.insecureSkipVerify=true" \ + --set "ports.websecure.nodePort=" +``` + +> **WebSocket support:** Traefik supports WebSockets natively. No additional annotation is required. + +--- + #### Load Balancer Comparison -| Feature | ALB | NGINX | -|---------|-----|-------| -| **Provider** | AWS Native | Third-party | -| **SSL Termination** | At load balancer | At load balancer or pod | -| **WebSocket Support** | Native | Requires annotation | -| **Session Affinity** | Target group level | Cookie-based | -| **Health Checks** | Advanced AWS health checks | HTTP/HTTPS probes | +> **Note:** Ingress NGINX is not included below. Kubernetes SIG Network has announced its retirement — best-effort maintenance ended in March 2026, with no further releases or security fixes. Existing deployments will continue to function, but new deployments should use one of the supported options below. + +| Feature | ALB | GKE HTTP(S) LB | Azure AGIC | Traefik | +|---------|-----|----------------|------------|---------| +| **Provider** | AWS Native | GCP Native | Azure Native | Self-hosted | +| **Backend HTTPS** | Annotation | Service annotation + BackendConfig | Annotation | Global flag | +| **SSL Termination** | At load balancer | At load balancer | At load balancer | At ingress (re-encrypt) | +| **WebSocket Support** | Native | Native | Native | Native | +| **Session Affinity** | Target group level | BackendConfig (cookie) | Annotation (cookie) | Middleware (sticky sessions) | +| **Health Checks** | Annotations | BackendConfig CRD | Annotations | Passive (via response codes) | +| **Pod-Level Routing** | `target-type: ip` | NEG (`cloud.google.com/neg`) | Default | Default | +| **Best For** | AWS EKS | GKE | AKS | Bare-metal / on-prem | ## Direct Access From 54de697b8e035fdf10cc495168eed4369c6917a4 Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Mon, 9 Mar 2026 13:51:24 -0400 Subject: [PATCH 02/12] haproxy and traefik --- docs/ingress.md | 186 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 167 insertions(+), 19 deletions(-) diff --git a/docs/ingress.md b/docs/ingress.md index 7cab74f..60e31d7 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -260,6 +260,17 @@ The `--serversTransport.insecureSkipVerify=true` flag tells Traefik to skip TLS > **Note:** In Traefik v3, the `ServersTransport` CRD annotation (`traefik.ingress.kubernetes.io/service.serversTransport`) on standard Kubernetes Ingress objects does not reliably apply per-service backend TLS settings. The global `--serversTransport.insecureSkipVerify=true` flag is the recommended approach for IAP deployments. +**TLS certificate considerations:** + +`insecureSkipVerify` only affects the **backend connection** (Traefik → IAP pod). It has no effect on the **frontend connection** (client browser → Traefik), which uses the certificate from `iap-tls-secret`. Clients only ever see the frontend certificate. + +| Connection | Certificate | Verified by | +|---|---|---| +| Client → Traefik | `iap-tls-secret` (customer-provided or CA-signed) | Client browser | +| Traefik → IAP pod | Self-signed (pod-level) | Skipped via `insecureSkipVerify` | + +This is a common and accepted pattern. If a customer provides a CA-signed certificate that includes pod DNS names as SANs, `insecureSkipVerify` can be removed. However, pod IPs and their derived DNS names (e.g., `10-200-2-131.na.pod.cluster.local`) are ephemeral — they change on every pod restart — making it impractical to maintain a static certificate for them. The recommended approach is to keep `insecureSkipVerify=true` for the backend and ensure the frontend certificate presented to clients is properly signed. + **Step 2 — Apply the ServersTransport CRD** (namespace-scoped, required for Traefik to identify the backend transport configuration): ```bash @@ -294,6 +305,7 @@ ingress: # Enable TLS on this router traefik.ingress.kubernetes.io/router.tls: "true" # Reference the ServersTransport CRD — format: -@kubernetescrd + # If deploying to the default namespace, use: default-iap-servers-transport@kubernetescrd traefik.ingress.kubernetes.io/service.serversTransport: -iap-servers-transport@kubernetescrd tls: - hosts: @@ -301,21 +313,154 @@ ingress: secretName: iap-tls-secret ``` -**NodePort and external load balancer:** +> **Cloud environments:** On EKS, GKE, or AKS, Traefik's `LoadBalancer` service is automatically assigned an external IP by the cloud provider. No additional configuration is needed. + +> **Bare-metal environments:** Without a cloud provider, the `LoadBalancer` service will remain in `` state. Install [MetalLB](https://metallb.universe.tf/) to assign external IPs, or consult your cluster administrator for how external traffic is routed to the cluster. + +> **WebSocket support:** Traefik supports WebSockets natively. No additional annotation is required. + +--- -In bare-metal environments, Traefik's `LoadBalancer` service will remain in `` state without a cloud provider or MetalLB. Traffic reaches Traefik via NodePort. When the external load balancer routes to a fixed port (e.g., 443 or a custom port), configure Traefik with a matching fixed NodePort to avoid reconfiguring the LB on each install: +#### HAProxy - Bare-Metal / On-Premises Option + +The HAProxy Kubernetes Ingress Controller is a high-performance, enterprise-grade ingress controller well suited to bare-metal and on-premises clusters. Because IAP terminates TLS at the pod (port 443), HAProxy must be configured to re-encrypt the backend connection — it terminates TLS from the client, then reconnects to the IAP pod over HTTPS. + +Unlike Traefik, HAProxy does not require a global startup flag or a separate CRD prerequisite. Backend TLS behavior is controlled entirely through annotations on the Ingress object. + +**Step 1 — Install HAProxy Kubernetes Ingress Controller:** ```bash -helm install traefik traefik/traefik \ - --namespace traefik \ +helm repo add haproxytech https://haproxytech.github.io/helm-charts +helm repo update +helm install haproxy-ingress haproxytech/kubernetes-ingress \ + --namespace haproxy-controller \ --create-namespace \ - --set ingressClass.enabled=true \ - --set ingressClass.isDefaultClass=false \ - --set "additionalArguments[0]=--serversTransport.insecureSkipVerify=true" \ - --set "ports.websecure.nodePort=" + --set controller.ingressClass=haproxy \ + --set controller.ingressClassResource.enabled=true \ + --set controller.ingressClassResource.name=haproxy \ + --set controller.ingressClassResource.isDefaultClass=false ``` -> **WebSocket support:** Traefik supports WebSockets natively. No additional annotation is required. +**TLS certificate considerations:** + +`haproxy.org/server-ssl-verify: "none"` only affects the **backend connection** (HAProxy → IAP pod). It has no effect on the **frontend connection** (client browser → HAProxy), which uses the certificate from `iap-tls-secret`. Clients only ever see the frontend certificate. + +| Connection | Certificate | Verified by | +|---|---|---| +| Client → HAProxy | `iap-tls-secret` (customer-provided or CA-signed) | Client browser | +| HAProxy → IAP pod | Self-signed (pod-level) | Skipped via `server-ssl-verify: none` | + +This is a common and accepted pattern. Pod IPs and their derived DNS names are ephemeral — they change on every pod restart — making it impractical to maintain a static certificate for backend pods. The recommended approach is to skip verification for the backend and ensure the frontend certificate presented to clients is properly signed. + +**Step 2 — Helm values configuration:** + +```yaml +ingress: + enabled: true + className: "haproxy" + loadBalancer: + enabled: true + host: iap.example.com + path: / + directAccess: + enabled: true + baseDomain: example.com + path: / + annotations: + # Re-encrypt to backend IAP pods over HTTPS (IAP terminates TLS at the pod) + haproxy.org/server-ssl: "true" + # Skip backend certificate verification — IAP pods use self-signed certs without pod IP SANs + haproxy.org/server-ssl-verify: "none" + # Redirect HTTP to HTTPS + haproxy.org/ssl-redirect: "true" + # Cookie-based session affinity — required for IAP UI actions that must reach the same pod + haproxy.org/cookie-persistence: "iap-server" + # Connection and request timeouts + haproxy.org/timeout-connect: "5s" + haproxy.org/timeout-client: "300s" + haproxy.org/timeout-server: "300s" + # WebSocket tunnel timeout — keep alive for long-lived WebSocket connections + haproxy.org/timeout-tunnel: "3600s" + # Health check path for backend IAP pods + haproxy.org/check: "true" + haproxy.org/check-http: "/health/status?exclude-services=true" + tls: + - hosts: + - iap.example.com + secretName: iap-tls-secret +``` + +> **Cloud environments:** On EKS, GKE, or AKS, HAProxy's `LoadBalancer` service is automatically assigned an external IP by the cloud provider. No additional configuration is needed. + +> **Bare-metal environments:** Without a cloud provider, the `LoadBalancer` service will remain in `` state. Install [MetalLB](https://metallb.universe.tf/) to assign external IPs, or consult your cluster administrator for how external traffic is routed to the cluster. + +--- + +### Backend SSL Behavior by Controller + +IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every ingress controller must re-encrypt the backend connection — it terminates TLS from the client and then reconnects to the IAP pod over HTTPS. How each controller handles this, and how granular that configuration is, differs significantly. + +| Controller | How Backend SSL is Configured | Granularity | +|---|---|---| +| **ALB** | `alb.ingress.kubernetes.io/backend-protocol: HTTPS` annotation | Per-Ingress | +| **GKE** | `cloud.google.com/app-protocols` on the Service | Per-Service port | +| **Azure AGIC** | `appgw.ingress.kubernetes.io/backend-protocol: https` annotation | Per-Ingress | +| **Traefik** | Global `--serversTransport.insecureSkipVerify=true` startup flag | Global (all backends) | +| **HAProxy** | `haproxy.org/server-ssl: "true"` annotation | Per-Ingress object (applies to all backends in the Ingress) | + +**Why this matters for WebSocket (IAG5/Gateway Manager):** + +When `useWebSockets: true` is set, the IAP chart renders a single Ingress with two backends: + +- `/` → `iap-service:443` — speaks HTTPS, needs `server-ssl: true` +- `/ws` → `iap-service:8080` — speaks plain WebSocket (HTTP), must NOT use SSL + +**Traefik** avoids this conflict because backend SSL is a global setting applied at the controller level — it re-encrypts port 443 but routes port 8080 as plain HTTP based on the path, without SSL. No per-path configuration is needed. + +**HAProxy** applies `haproxy.org/server-ssl: "true"` to every backend in the Ingress object — there is no per-path SSL override. With both `/` and `/ws` in the same Ingress, HAProxy attempts an SSL handshake to port 8080, which fails with `SSL handshake failure (Connection refused)` and marks the WebSocket backend as DOWN. + +**Fix: Separate Ingress for the WebSocket path** + +Create a second Ingress for `/ws` without `server-ssl: true`. HAProxy will route `/ws` to port 8080 as plain HTTP while the main Ingress continues to use SSL for port 443. + +**NA environment example** (`iap-na-k8s.pe.itential.io`): + +Apply this manually alongside the Helm-rendered Ingress: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: iap-ingress-ws + namespace: na + annotations: + kubernetes.io/description: "IAP WebSocket ingress for Gateway Manager (IAG5). Plain HTTP — no server-ssl." + haproxy.org/server-ssl: "false" + haproxy.org/timeout-connect: "5s" + haproxy.org/timeout-client: "300s" + haproxy.org/timeout-server: "300s" + haproxy.org/timeout-tunnel: "3600s" + haproxy.org/cookie-persistence: "iap-server" +spec: + ingressClassName: haproxy + tls: + - hosts: + - iap-na-k8s.pe.itential.io + secretName: iap-tls-secret + rules: + - host: iap-na-k8s.pe.itential.io + http: + paths: + - backend: + service: + name: iap-service + port: + number: 8080 + path: /ws + pathType: Prefix +``` + +> **Note:** Do not add `haproxy.org/check` or `haproxy.org/check-http` to the WebSocket Ingress. Health checks over port 8080 use a different protocol than the IAP health endpoint (port 3443). HAProxy will verify backend availability through the WebSocket connection itself. --- @@ -323,16 +468,19 @@ helm install traefik traefik/traefik \ > **Note:** Ingress NGINX is not included below. Kubernetes SIG Network has announced its retirement — best-effort maintenance ended in March 2026, with no further releases or security fixes. Existing deployments will continue to function, but new deployments should use one of the supported options below. -| Feature | ALB | GKE HTTP(S) LB | Azure AGIC | Traefik | -|---------|-----|----------------|------------|---------| -| **Provider** | AWS Native | GCP Native | Azure Native | Self-hosted | -| **Backend HTTPS** | Annotation | Service annotation + BackendConfig | Annotation | Global flag | -| **SSL Termination** | At load balancer | At load balancer | At load balancer | At ingress (re-encrypt) | -| **WebSocket Support** | Native | Native | Native | Native | -| **Session Affinity** | Target group level | BackendConfig (cookie) | Annotation (cookie) | Middleware (sticky sessions) | -| **Health Checks** | Annotations | BackendConfig CRD | Annotations | Passive (via response codes) | -| **Pod-Level Routing** | `target-type: ip` | NEG (`cloud.google.com/neg`) | Default | Default | -| **Best For** | AWS EKS | GKE | AKS | Bare-metal / on-prem | +| Feature | ALB | GKE HTTP(S) LB | Azure AGIC | Traefik | HAProxy | +|---------|-----|----------------|------------|---------|---------| +| **Provider** | AWS Native | GCP Native | Azure Native | Self-hosted | Self-hosted | +| **Backend HTTPS** | Annotation | Service annotation + BackendConfig | Annotation | Global flag | Annotation | +| **Backend SSL Granularity** | Per-Ingress | Per-Service port | Per-Ingress | Global (all backends) | Per-Ingress object | +| **SSL Termination** | At load balancer | At load balancer | At load balancer | At ingress (re-encrypt) | At ingress (re-encrypt) | +| **WebSocket + SSL mix** | Supported natively | Supported natively | Supported natively | Supported natively | Requires separate Ingress for `/ws` | +| **WebSocket Support** | Native | Native | Native | Native | Native (tunnel timeout annotation) | +| **Session Affinity** | Target group level | BackendConfig (cookie) | Annotation (cookie) | Middleware (sticky sessions) | Annotation (cookie) | +| **Health Checks** | Annotations | BackendConfig CRD | Annotations | Passive (via response codes) | Annotations | +| **Pod-Level Routing** | `target-type: ip` | NEG (`cloud.google.com/neg`) | Default | Default | Default | +| **Prerequisite CRD** | None | BackendConfig (out-of-band) | None | ServersTransport CRD | None | +| **Best For** | AWS EKS | GKE | AKS | Bare-metal / on-prem | Bare-metal / on-prem | ## Direct Access From 80f0ee5edd7c8ac2fce3bc092d6f824c25aec0e9 Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Tue, 10 Mar 2026 13:50:34 -0400 Subject: [PATCH 03/12] contour ignress --- docs/ingress.md | 109 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 13 deletions(-) diff --git a/docs/ingress.md b/docs/ingress.md index 60e31d7..554dbac 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -396,6 +396,88 @@ ingress: --- +#### Contour (Envoy) - Bare-Metal / On-Premises Option + +Contour is a CNCF-graduated ingress controller that uses Envoy as its data plane. It is well suited to bare-metal and on-premises clusters and works with the standard `networking.k8s.io/v1` Ingress resource — no chart changes required. Because IAP terminates TLS at the pod (port 443), Contour must re-encrypt the backend connection. + +Contour's key advantage over HAProxy for IAP is how it scopes backend TLS: the `projectcontour.io/upstream-protocol.tls` annotation is placed on the **Service** and lists only the ports that should use TLS. Port 8080 (WebSocket) is not listed, so Contour routes it as plain HTTP — the WebSocket SSL conflict present in HAProxy does not occur. + +> **Session affinity:** Cookie-based sticky sessions are not supported for standard Kubernetes Ingress resources in Contour. Session affinity requires Contour's `HTTPProxy` CRD. For testing, IAP's own session tokens function across pods. Production deployments should evaluate `HTTPProxy` if same-pod routing is required. + +**Step 1 — Install Contour:** + +```bash +helm repo add bitnami https://charts.bitnami.com/bitnami +helm repo update +helm install contour bitnami/contour \ + --namespace projectcontour \ + --create-namespace \ + --set envoy.service.type=NodePort \ + --set ingressClass.name=contour \ + --set ingressClass.create=true \ + --set ingressClass.default=false +``` + +After install, retrieve the Envoy HTTPS NodePort for nginx LB wiring: + +```bash +kubectl get svc -n projectcontour contour-envoy \ + -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}' +``` + +**TLS certificate considerations:** + +The `projectcontour.io/upstream-protocol.tls` annotation on the Service tells Contour's Envoy to use TLS only for the listed ports. For standard Ingress resources, Envoy does not validate backend certificates when no CA is explicitly configured — self-signed pod certificates work without additional configuration. + +| Connection | Certificate | Verified by | +|---|---|---| +| Client → Contour | `iap-tls-secret` (customer-provided or CA-signed) | Client browser | +| Contour → IAP pod (port 443) | Self-signed (pod-level) | Not verified (no CA configured) | +| Contour → IAP pod (port 8080) | None — plain HTTP | N/A | + +**Step 2 — Helm values configuration:** + +```yaml +service: + type: ClusterIP + name: iap-service + port: 443 + annotations: + # Tell Contour/Envoy to use TLS only for port 443. + # Port 8080 (WebSocket) is intentionally excluded — it uses plain HTTP. + projectcontour.io/upstream-protocol.tls: "443" + +ingress: + enabled: true + className: "contour" + loadBalancer: + enabled: true + host: iap.example.com + path: / + directAccess: + enabled: true + baseDomain: example.com + hostOverride: "iap-{ns}-contour" + path: / + annotations: + # Redirect HTTP to HTTPS + ingress.kubernetes.io/force-ssl-redirect: "true" + # Response timeout — set high for long-lived WebSocket connections + projectcontour.io/response-timeout: "3600s" + tls: + - hosts: + - iap.example.com + secretName: iap-tls-secret +``` + +> **Cloud environments:** On EKS, GKE, or AKS, Contour's Envoy `LoadBalancer` service is automatically assigned an external IP by the cloud provider. No additional configuration is needed. + +> **Bare-metal environments:** Without a cloud provider, the `LoadBalancer` service will remain in `` state. Install [MetalLB](https://metallb.universe.tf/) to assign external IPs, or consult your cluster administrator for how external traffic is routed to the cluster. + +> **WebSocket support:** Contour supports WebSockets natively. No annotation is required. The `projectcontour.io/response-timeout` annotation controls the idle timeout for long-lived connections including WebSocket. + +--- + ### Backend SSL Behavior by Controller IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every ingress controller must re-encrypt the backend connection — it terminates TLS from the client and then reconnects to the IAP pod over HTTPS. How each controller handles this, and how granular that configuration is, differs significantly. @@ -407,6 +489,7 @@ IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every | **Azure AGIC** | `appgw.ingress.kubernetes.io/backend-protocol: https` annotation | Per-Ingress | | **Traefik** | Global `--serversTransport.insecureSkipVerify=true` startup flag | Global (all backends) | | **HAProxy** | `haproxy.org/server-ssl: "true"` annotation | Per-Ingress object (applies to all backends in the Ingress) | +| **Contour** | `projectcontour.io/upstream-protocol.tls: ""` on the Service | Per-Service port | **Why this matters for WebSocket (IAG5/Gateway Manager):** @@ -468,19 +551,19 @@ spec: > **Note:** Ingress NGINX is not included below. Kubernetes SIG Network has announced its retirement — best-effort maintenance ended in March 2026, with no further releases or security fixes. Existing deployments will continue to function, but new deployments should use one of the supported options below. -| Feature | ALB | GKE HTTP(S) LB | Azure AGIC | Traefik | HAProxy | -|---------|-----|----------------|------------|---------|---------| -| **Provider** | AWS Native | GCP Native | Azure Native | Self-hosted | Self-hosted | -| **Backend HTTPS** | Annotation | Service annotation + BackendConfig | Annotation | Global flag | Annotation | -| **Backend SSL Granularity** | Per-Ingress | Per-Service port | Per-Ingress | Global (all backends) | Per-Ingress object | -| **SSL Termination** | At load balancer | At load balancer | At load balancer | At ingress (re-encrypt) | At ingress (re-encrypt) | -| **WebSocket + SSL mix** | Supported natively | Supported natively | Supported natively | Supported natively | Requires separate Ingress for `/ws` | -| **WebSocket Support** | Native | Native | Native | Native | Native (tunnel timeout annotation) | -| **Session Affinity** | Target group level | BackendConfig (cookie) | Annotation (cookie) | Middleware (sticky sessions) | Annotation (cookie) | -| **Health Checks** | Annotations | BackendConfig CRD | Annotations | Passive (via response codes) | Annotations | -| **Pod-Level Routing** | `target-type: ip` | NEG (`cloud.google.com/neg`) | Default | Default | Default | -| **Prerequisite CRD** | None | BackendConfig (out-of-band) | None | ServersTransport CRD | None | -| **Best For** | AWS EKS | GKE | AKS | Bare-metal / on-prem | Bare-metal / on-prem | +| Feature | ALB | GKE HTTP(S) LB | Azure AGIC | Traefik | HAProxy | Contour | +|---------|-----|----------------|------------|---------|---------|---------| +| **Provider** | AWS Native | GCP Native | Azure Native | Self-hosted | Self-hosted | Self-hosted | +| **Backend HTTPS** | Annotation | Service annotation + BackendConfig | Annotation | Global flag | Annotation | Service annotation | +| **Backend SSL Granularity** | Per-Ingress | Per-Service port | Per-Ingress | Global (all backends) | Per-Ingress object | Per-Service port | +| **SSL Termination** | At load balancer | At load balancer | At load balancer | At ingress (re-encrypt) | At ingress (re-encrypt) | At ingress (re-encrypt) | +| **WebSocket + SSL mix** | Supported natively | Supported natively | Supported natively | Supported natively | Requires separate Ingress for `/ws` | Supported natively | +| **WebSocket Support** | Native | Native | Native | Native | Native (tunnel timeout annotation) | Native (response-timeout annotation) | +| **Session Affinity** | Target group level | BackendConfig (cookie) | Annotation (cookie) | Middleware (sticky sessions) | Annotation (cookie) | HTTPProxy CRD only | +| **Health Checks** | Annotations | BackendConfig CRD | Annotations | Passive (via response codes) | Annotations | Passive (Envoy) | +| **Pod-Level Routing** | `target-type: ip` | NEG (`cloud.google.com/neg`) | Default | Default | Default | Default | +| **Prerequisite CRD** | None | BackendConfig (out-of-band) | None | ServersTransport CRD | None | None | +| **Best For** | AWS EKS | GKE | AKS | Bare-metal / on-prem | Bare-metal / on-prem | Bare-metal / on-prem | ## Direct Access From 10f8344ab548259c761da3f8d894688105557fed Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Tue, 10 Mar 2026 14:16:58 -0400 Subject: [PATCH 04/12] ignress.md updates --- docs/ingress.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/ingress.md b/docs/ingress.md index 554dbac..1cac55f 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -390,6 +390,8 @@ ingress: secretName: iap-tls-secret ``` +> **WebSocket support (IAG5/Gateway Manager):** When `useWebSockets: true` is set, the IAP chart renders a single Ingress with two backends: `/` → port 443 (HTTPS) and `/ws` → port 8080 (plain WebSocket). HAProxy applies `haproxy.org/server-ssl: "true"` to every backend in the Ingress object — there is no per-path SSL override. This causes HAProxy to attempt an SSL handshake to port 8080, which fails. The fix is a second Ingress for `/ws` with `haproxy.org/server-ssl: "false"`. See the [WebSocket SSL Conflict](#why-this-matters-for-websocket-iag5gateway-manager) section below for the full example. + > **Cloud environments:** On EKS, GKE, or AKS, HAProxy's `LoadBalancer` service is automatically assigned an external IP by the cloud provider. No additional configuration is needed. > **Bare-metal environments:** Without a cloud provider, the `LoadBalancer` service will remain in `` state. Install [MetalLB](https://metallb.universe.tf/) to assign external IPs, or consult your cluster administrator for how external traffic is routed to the cluster. @@ -407,21 +409,19 @@ Contour's key advantage over HAProxy for IAP is how it scopes backend TLS: the ` **Step 1 — Install Contour:** ```bash -helm repo add bitnami https://charts.bitnami.com/bitnami -helm repo update -helm install contour bitnami/contour \ - --namespace projectcontour \ - --create-namespace \ - --set envoy.service.type=NodePort \ - --set ingressClass.name=contour \ - --set ingressClass.create=true \ - --set ingressClass.default=false +kubectl apply -f https://projectcontour.io/quickstart/contour.yaml +``` + +If your cluster does not have a cloud load balancer, patch the Envoy service to NodePort: + +```bash +kubectl patch svc envoy -n projectcontour -p '{"spec":{"type":"NodePort"}}' ``` -After install, retrieve the Envoy HTTPS NodePort for nginx LB wiring: +To retrieve the assigned HTTPS NodePort: ```bash -kubectl get svc -n projectcontour contour-envoy \ +kubectl get svc envoy -n projectcontour \ -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}' ``` From 7c3f3069304491c701a3432a6ce359b44715356d Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Tue, 10 Mar 2026 14:26:32 -0400 Subject: [PATCH 05/12] ignress.md updates --- docs/ingress.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/docs/ingress.md b/docs/ingress.md index 1cac55f..0fd2467 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -412,18 +412,12 @@ Contour's key advantage over HAProxy for IAP is how it scopes backend TLS: the ` kubectl apply -f https://projectcontour.io/quickstart/contour.yaml ``` -If your cluster does not have a cloud load balancer, patch the Envoy service to NodePort: - -```bash -kubectl patch svc envoy -n projectcontour -p '{"spec":{"type":"NodePort"}}' -``` - -To retrieve the assigned HTTPS NodePort: - -```bash -kubectl get svc envoy -n projectcontour \ - -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}' -``` +> **Bare-metal environments:** Without a cloud provider, the Envoy service will remain in `` state. Patch it to NodePort and retrieve the assigned port for wiring to your external load balancer: +> ```bash +> kubectl patch svc envoy -n projectcontour -p '{"spec":{"type":"NodePort"}}' +> kubectl get svc envoy -n projectcontour \ +> -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}' +> ``` **TLS certificate considerations:** From 30f49b4017ff44b5de0e3fd2263cc8c9c8b1d265 Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Tue, 10 Mar 2026 14:37:43 -0400 Subject: [PATCH 06/12] ignress.md updates --- docs/ingress.md | 65 +++++++++---------------------------------------- 1 file changed, 11 insertions(+), 54 deletions(-) diff --git a/docs/ingress.md b/docs/ingress.md index 0fd2467..906b38c 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -440,7 +440,9 @@ service: # Tell Contour/Envoy to use TLS only for port 443. # Port 8080 (WebSocket) is intentionally excluded — it uses plain HTTP. projectcontour.io/upstream-protocol.tls: "443" +``` +```yaml ingress: enabled: true className: "contour" @@ -474,7 +476,7 @@ ingress: ### Backend SSL Behavior by Controller -IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every ingress controller must re-encrypt the backend connection — it terminates TLS from the client and then reconnects to the IAP pod over HTTPS. How each controller handles this, and how granular that configuration is, differs significantly. +IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every ingress controller must re-encrypt the backend connection it terminates TLS from the client and then reconnects to the IAP pod over HTTPS. How each controller handles this, and how granular that configuration is, differs significantly. | Controller | How Backend SSL is Configured | Granularity | |---|---|---| @@ -499,65 +501,20 @@ When `useWebSockets: true` is set, the IAP chart renders a single Ingress with t **Fix: Separate Ingress for the WebSocket path** Create a second Ingress for `/ws` without `server-ssl: true`. HAProxy will route `/ws` to port 8080 as plain HTTP while the main Ingress continues to use SSL for port 443. - -**NA environment example** (`iap-na-k8s.pe.itential.io`): - -Apply this manually alongside the Helm-rendered Ingress: - -```yaml -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: iap-ingress-ws - namespace: na - annotations: - kubernetes.io/description: "IAP WebSocket ingress for Gateway Manager (IAG5). Plain HTTP — no server-ssl." - haproxy.org/server-ssl: "false" - haproxy.org/timeout-connect: "5s" - haproxy.org/timeout-client: "300s" - haproxy.org/timeout-server: "300s" - haproxy.org/timeout-tunnel: "3600s" - haproxy.org/cookie-persistence: "iap-server" -spec: - ingressClassName: haproxy - tls: - - hosts: - - iap-na-k8s.pe.itential.io - secretName: iap-tls-secret - rules: - - host: iap-na-k8s.pe.itential.io - http: - paths: - - backend: - service: - name: iap-service - port: - number: 8080 - path: /ws - pathType: Prefix -``` - -> **Note:** Do not add `haproxy.org/check` or `haproxy.org/check-http` to the WebSocket Ingress. Health checks over port 8080 use a different protocol than the IAP health endpoint (port 3443). HAProxy will verify backend availability through the WebSocket connection itself. - --- #### Load Balancer Comparison > **Note:** Ingress NGINX is not included below. Kubernetes SIG Network has announced its retirement — best-effort maintenance ended in March 2026, with no further releases or security fixes. Existing deployments will continue to function, but new deployments should use one of the supported options below. -| Feature | ALB | GKE HTTP(S) LB | Azure AGIC | Traefik | HAProxy | Contour | -|---------|-----|----------------|------------|---------|---------|---------| -| **Provider** | AWS Native | GCP Native | Azure Native | Self-hosted | Self-hosted | Self-hosted | -| **Backend HTTPS** | Annotation | Service annotation + BackendConfig | Annotation | Global flag | Annotation | Service annotation | -| **Backend SSL Granularity** | Per-Ingress | Per-Service port | Per-Ingress | Global (all backends) | Per-Ingress object | Per-Service port | -| **SSL Termination** | At load balancer | At load balancer | At load balancer | At ingress (re-encrypt) | At ingress (re-encrypt) | At ingress (re-encrypt) | -| **WebSocket + SSL mix** | Supported natively | Supported natively | Supported natively | Supported natively | Requires separate Ingress for `/ws` | Supported natively | -| **WebSocket Support** | Native | Native | Native | Native | Native (tunnel timeout annotation) | Native (response-timeout annotation) | -| **Session Affinity** | Target group level | BackendConfig (cookie) | Annotation (cookie) | Middleware (sticky sessions) | Annotation (cookie) | HTTPProxy CRD only | -| **Health Checks** | Annotations | BackendConfig CRD | Annotations | Passive (via response codes) | Annotations | Passive (Envoy) | -| **Pod-Level Routing** | `target-type: ip` | NEG (`cloud.google.com/neg`) | Default | Default | Default | Default | -| **Prerequisite CRD** | None | BackendConfig (out-of-band) | None | ServersTransport CRD | None | None | -| **Best For** | AWS EKS | GKE | AKS | Bare-metal / on-prem | Bare-metal / on-prem | Bare-metal / on-prem | +| Controller | Provider | Backend HTTPS | Backend SSL Granularity | SSL Termination | WebSocket + SSL mix | WebSocket Support | Session Affinity | Health Checks | Pod-Level Routing | Prerequisite CRD | Best For | +|------------|----------|---------------|-------------------------|-----------------|---------------------|-------------------|------------------|---------------|-------------------|------------------|----------| +| **ALB** | AWS Native | Annotation | Per-Ingress | At load balancer | Supported natively | Native | Target group level | Annotations | `target-type: ip` | None | AWS EKS | +| **GKE HTTP(S) LB** | GCP Native | Service annotation + BackendConfig | Per-Service port | At load balancer | Supported natively | Native | BackendConfig (cookie) | BackendConfig CRD | NEG (`cloud.google.com/neg`) | BackendConfig (out-of-band) | GKE | +| **Azure AGIC** | Azure Native | Annotation | Per-Ingress | At load balancer | Supported natively | Native | Annotation (cookie) | Annotations | Default | None | AKS | +| **Traefik** | Self-hosted | Global flag | Global (all backends) | At ingress (re-encrypt) | Supported natively | Native | Middleware (sticky sessions) | Passive (via response codes) | Default | ServersTransport CRD | Bare-metal / on-prem | +| **HAProxy** | Self-hosted | Annotation | Per-Ingress object | At ingress (re-encrypt) | Requires separate Ingress for `/ws` | Native (tunnel timeout annotation) | Annotation (cookie) | Annotations | Default | None | Bare-metal / on-prem | +| **Contour** | Self-hosted | Service annotation | Per-Service port | At ingress (re-encrypt) | Supported natively | Native (response-timeout annotation) | HTTPProxy CRD only | Passive (Envoy) | Default | None | Bare-metal / on-prem | ## Direct Access From edb9316b996f7ef0f39a339d52e1a9091ef3d31b Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Tue, 10 Mar 2026 14:47:28 -0400 Subject: [PATCH 07/12] ignress.md updates --- docs/ingress.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/ingress.md b/docs/ingress.md index 906b38c..569510c 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -487,7 +487,7 @@ IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every | **HAProxy** | `haproxy.org/server-ssl: "true"` annotation | Per-Ingress object (applies to all backends in the Ingress) | | **Contour** | `projectcontour.io/upstream-protocol.tls: ""` on the Service | Per-Service port | -**Why this matters for WebSocket (IAG5/Gateway Manager):** +#### Why this matters for WebSocket (IAG5/Gateway Manager) When `useWebSockets: true` is set, the IAP chart renders a single Ingress with two backends: @@ -501,11 +501,12 @@ When `useWebSockets: true` is set, the IAP chart renders a single Ingress with t **Fix: Separate Ingress for the WebSocket path** Create a second Ingress for `/ws` without `server-ssl: true`. HAProxy will route `/ws` to port 8080 as plain HTTP while the main Ingress continues to use SSL for port 443. + --- #### Load Balancer Comparison -> **Note:** Ingress NGINX is not included below. Kubernetes SIG Network has announced its retirement — best-effort maintenance ended in March 2026, with no further releases or security fixes. Existing deployments will continue to function, but new deployments should use one of the supported options below. +> **Note:** Ingress NGINX is not included below. Kubernetes SIG Network has announced its retirement — best-effort maintenance has ended as of March 2026, with no further releases or security fixes. Existing deployments will continue to function, but new deployments should use one of the supported options below. | Controller | Provider | Backend HTTPS | Backend SSL Granularity | SSL Termination | WebSocket + SSL mix | WebSocket Support | Session Affinity | Health Checks | Pod-Level Routing | Prerequisite CRD | Best For | |------------|----------|---------------|-------------------------|-----------------|---------------------|-------------------|------------------|---------------|-------------------|------------------|----------| @@ -543,7 +544,7 @@ ingress: **Generated Hostnames** (with `replicaCount: 3`, namespace `production`): - `iap-production-0.example.com` -- `iap-production-1.example.com` +- `iap-production-1.example.com` - `iap-production-2.example.com` ### Custom Hostname Override From 2d2cc858a9795284478cd34d5683853233a42951 Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Wed, 11 Mar 2026 13:24:14 -0400 Subject: [PATCH 08/12] ignress.md updates --- docs/ingress.md | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/docs/ingress.md b/docs/ingress.md index 569510c..84335b9 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -390,7 +390,7 @@ ingress: secretName: iap-tls-secret ``` -> **WebSocket support (IAG5/Gateway Manager):** When `useWebSockets: true` is set, the IAP chart renders a single Ingress with two backends: `/` → port 443 (HTTPS) and `/ws` → port 8080 (plain WebSocket). HAProxy applies `haproxy.org/server-ssl: "true"` to every backend in the Ingress object — there is no per-path SSL override. This causes HAProxy to attempt an SSL handshake to port 8080, which fails. The fix is a second Ingress for `/ws` with `haproxy.org/server-ssl: "false"`. See the [WebSocket SSL Conflict](#why-this-matters-for-websocket-iag5gateway-manager) section below for the full example. +> **WebSocket support (IAG5/Gateway Manager):** When `useWebSockets: true` is set, the IAP chart renders a single Ingress with two backends: `/` → port 443 (HTTPS) and `/ws` → port 8080 (WSS). HAProxy applies `haproxy.org/server-ssl: "true"` to every backend in the Ingress object — this correctly re-encrypts both the main application traffic and the WebSocket traffic to the IAP pod. > **Cloud environments:** On EKS, GKE, or AKS, HAProxy's `LoadBalancer` service is automatically assigned an external IP by the cloud provider. No additional configuration is needed. @@ -402,7 +402,7 @@ ingress: Contour is a CNCF-graduated ingress controller that uses Envoy as its data plane. It is well suited to bare-metal and on-premises clusters and works with the standard `networking.k8s.io/v1` Ingress resource — no chart changes required. Because IAP terminates TLS at the pod (port 443), Contour must re-encrypt the backend connection. -Contour's key advantage over HAProxy for IAP is how it scopes backend TLS: the `projectcontour.io/upstream-protocol.tls` annotation is placed on the **Service** and lists only the ports that should use TLS. Port 8080 (WebSocket) is not listed, so Contour routes it as plain HTTP — the WebSocket SSL conflict present in HAProxy does not occur. +Contour's key advantage over HAProxy for IAP is how it scopes backend TLS: the `projectcontour.io/upstream-protocol.tls` annotation is placed on the **Service** and lists the ports that should use TLS. Both port 443 (HTTPS) and port 8080 (WSS) must be listed to ensure Contour re-encrypts traffic to both backends. > **Session affinity:** Cookie-based sticky sessions are not supported for standard Kubernetes Ingress resources in Contour. Session affinity requires Contour's `HTTPProxy` CRD. For testing, IAP's own session tokens function across pods. Production deployments should evaluate `HTTPProxy` if same-pod routing is required. @@ -427,7 +427,7 @@ The `projectcontour.io/upstream-protocol.tls` annotation on the Service tells Co |---|---|---| | Client → Contour | `iap-tls-secret` (customer-provided or CA-signed) | Client browser | | Contour → IAP pod (port 443) | Self-signed (pod-level) | Not verified (no CA configured) | -| Contour → IAP pod (port 8080) | None — plain HTTP | N/A | +| Contour → IAP pod (port 8080) | Self-signed (pod-level) | Not verified (no CA configured) | **Step 2 — Helm values configuration:** @@ -437,9 +437,8 @@ service: name: iap-service port: 443 annotations: - # Tell Contour/Envoy to use TLS only for port 443. - # Port 8080 (WebSocket) is intentionally excluded — it uses plain HTTP. - projectcontour.io/upstream-protocol.tls: "443" + # Tell Contour/Envoy to use TLS for both the main application port and the WebSocket port. + projectcontour.io/upstream-protocol.tls: "443,8080" ``` ```yaml @@ -487,20 +486,14 @@ IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every | **HAProxy** | `haproxy.org/server-ssl: "true"` annotation | Per-Ingress object (applies to all backends in the Ingress) | | **Contour** | `projectcontour.io/upstream-protocol.tls: ""` on the Service | Per-Service port | -#### Why this matters for WebSocket (IAG5/Gateway Manager) +#### WebSocket (IAG5/Gateway Manager) Backend SSL When `useWebSockets: true` is set, the IAP chart renders a single Ingress with two backends: -- `/` → `iap-service:443` — speaks HTTPS, needs `server-ssl: true` -- `/ws` → `iap-service:8080` — speaks plain WebSocket (HTTP), must NOT use SSL +- `/` → `iap-service:443` — speaks HTTPS +- `/ws` → `iap-service:8080` — speaks WSS (WebSocket Secure) -**Traefik** avoids this conflict because backend SSL is a global setting applied at the controller level — it re-encrypts port 443 but routes port 8080 as plain HTTP based on the path, without SSL. No per-path configuration is needed. - -**HAProxy** applies `haproxy.org/server-ssl: "true"` to every backend in the Ingress object — there is no per-path SSL override. With both `/` and `/ws` in the same Ingress, HAProxy attempts an SSL handshake to port 8080, which fails with `SSL handshake failure (Connection refused)` and marks the WebSocket backend as DOWN. - -**Fix: Separate Ingress for the WebSocket path** - -Create a second Ingress for `/ws` without `server-ssl: true`. HAProxy will route `/ws` to port 8080 as plain HTTP while the main Ingress continues to use SSL for port 443. +Both backends require backend SSL re-encryption. All supported controllers handle this correctly in a single Ingress — no separate Ingress or special per-path configuration is needed. --- @@ -514,7 +507,7 @@ Create a second Ingress for `/ws` without `server-ssl: true`. HAProxy will route | **GKE HTTP(S) LB** | GCP Native | Service annotation + BackendConfig | Per-Service port | At load balancer | Supported natively | Native | BackendConfig (cookie) | BackendConfig CRD | NEG (`cloud.google.com/neg`) | BackendConfig (out-of-band) | GKE | | **Azure AGIC** | Azure Native | Annotation | Per-Ingress | At load balancer | Supported natively | Native | Annotation (cookie) | Annotations | Default | None | AKS | | **Traefik** | Self-hosted | Global flag | Global (all backends) | At ingress (re-encrypt) | Supported natively | Native | Middleware (sticky sessions) | Passive (via response codes) | Default | ServersTransport CRD | Bare-metal / on-prem | -| **HAProxy** | Self-hosted | Annotation | Per-Ingress object | At ingress (re-encrypt) | Requires separate Ingress for `/ws` | Native (tunnel timeout annotation) | Annotation (cookie) | Annotations | Default | None | Bare-metal / on-prem | +| **HAProxy** | Self-hosted | Annotation | Per-Ingress object | At ingress (re-encrypt) | Supported natively | Native (tunnel timeout annotation) | Annotation (cookie) | Annotations | Default | None | Bare-metal / on-prem | | **Contour** | Self-hosted | Service annotation | Per-Service port | At ingress (re-encrypt) | Supported natively | Native (response-timeout annotation) | HTTPProxy CRD only | Passive (Envoy) | Default | None | Bare-metal / on-prem | ## Direct Access From 42ec2211e7ed4ab382c20ee16b87008e79bbc607 Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Wed, 11 Mar 2026 13:37:47 -0400 Subject: [PATCH 09/12] ignress.md updates --- docs/ingress.md | 149 ------------------------------------------------ 1 file changed, 149 deletions(-) diff --git a/docs/ingress.md b/docs/ingress.md index 84335b9..9f10840 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -94,151 +94,6 @@ ingress: alb.ingress.kubernetes.io/ssl-policy: "ELBSecurityPolicy-TLS-1-2-2017-01" ``` -#### GKE HTTP(S) Load Balancer - GKE Option - -On Google Kubernetes Engine, the native ingress controller provisions a Google Cloud HTTP(S) Load Balancer. Because IAP terminates TLS at the pod (port 443), GKE requires a `BackendConfig` custom resource to configure HTTPS backend health checks and session affinity, and a `cloud.google.com/app-protocols` annotation on the Service to tell the load balancer to use HTTPS when communicating with pods. - -> **Note:** The `BackendConfig` and `ManagedCertificate` resources must be created separately — they are not rendered by this chart. Apply them to your cluster before or alongside the Helm release. - -**BackendConfig (apply separately):** - -```yaml -apiVersion: cloud.google.com/v1 -kind: BackendConfig -metadata: - name: iap-backend-config -spec: - healthCheck: - checkIntervalSec: 15 - timeoutSec: 5 - healthyThreshold: 2 - unhealthyThreshold: 2 - type: HTTPS - requestPath: /health/status - port: 3443 - sessionAffinity: - affinityType: GENERATED_COOKIE - affinityCookieTtlSec: 3600 - timeoutSec: 60 - connectionDraining: - drainingTimeoutSec: 60 -``` - -**ManagedCertificate (apply separately):** - -```yaml -apiVersion: networking.gke.io/v1 -kind: ManagedCertificate -metadata: - name: iap-managed-cert -spec: - domains: - - iap.example.com - - iap-prod-0.example.com - - iap-prod-1.example.com -``` - -**Helm values configuration:** - -```yaml -service: - type: ClusterIP - name: iap-service - port: 443 - annotations: - # Tell GKE LB to use HTTPS when communicating with pods - cloud.google.com/app-protocols: '{"https":"HTTPS"}' - # Enable container-native load balancing (pod-level routing, equivalent to ALB target-type: ip) - cloud.google.com/neg: '{"ingress": true}' - # Reference the BackendConfig for health checks and session affinity - cloud.google.com/backend-config: '{"default": "iap-backend-config"}' - -ingress: - enabled: true - className: "gce" - loadBalancer: - enabled: true - host: iap.example.com - path: / - directAccess: - enabled: true - baseDomain: example.com - path: / - annotations: - # Reference the ManagedCertificate for SSL - networking.gke.io/managed-certificates: "iap-managed-cert" - # Use a static external IP (reserve one in GCP Console first) - kubernetes.io/ingress.global-static-ip-name: "iap-static-ip" - # Force HTTPS - kubernetes.io/ingress.allow-http: "false" - external-dns.alpha.kubernetes.io/hostname: iap.example.com - external-dns.alpha.kubernetes.io/ttl: "300" - # TLS block is not used with GKE ManagedCertificates — leave empty - tls: [] -``` - -> **WebSocket support:** GKE HTTP(S) LB supports WebSockets natively. No additional annotation is required. Ensure port 8080 is exposed via a separate Service or NodePort if using IAG5/Gateway Manager. - ---- - -#### Azure Application Gateway Ingress Controller (AGIC) - AKS Option - -On Azure Kubernetes Service, the Application Gateway Ingress Controller (AGIC) provisions an Azure Application Gateway. AGIC uses annotation-based configuration similar to NGINX but with `appgw.ingress.kubernetes.io/` prefixed annotations. - -Because IAP terminates TLS at the pod (port 443), the `backend-protocol: "https"` annotation is required. SSL certificates are attached to the Application Gateway frontend, not managed through Kubernetes secrets. - -**Helm values configuration:** - -```yaml -service: - type: ClusterIP - name: iap-service - port: 443 - -ingress: - enabled: true - className: "azure-application-gateway" - loadBalancer: - enabled: true - host: iap.example.com - path: / - directAccess: - enabled: true - baseDomain: example.com - path: / - annotations: - # Use HTTPS when communicating with backend pods (TLS terminates at the pod) - appgw.ingress.kubernetes.io/backend-protocol: "https" - # Force HTTPS redirect on the frontend - appgw.ingress.kubernetes.io/ssl-redirect: "true" - # Reference an SSL certificate pre-uploaded to Application Gateway - appgw.ingress.kubernetes.io/appgw-ssl-certificate: "iap-ssl-cert" - # Health probe configuration - appgw.ingress.kubernetes.io/health-probe-path: "/health/status" - appgw.ingress.kubernetes.io/health-probe-port: "3443" - appgw.ingress.kubernetes.io/health-probe-status-codes: "200-399" - appgw.ingress.kubernetes.io/health-probe-interval: "15" - appgw.ingress.kubernetes.io/health-probe-timeout: "5" - appgw.ingress.kubernetes.io/health-probe-unhealthy-threshold: "2" - # Session affinity (equivalent to ALB stickiness) - appgw.ingress.kubernetes.io/cookie-based-affinity: "Enabled" - appgw.ingress.kubernetes.io/cookie-based-affinity-distinct-name: "true" - # Request and connection timeouts - appgw.ingress.kubernetes.io/request-timeout: "60" - appgw.ingress.kubernetes.io/connection-draining: "true" - appgw.ingress.kubernetes.io/connection-draining-timeout: "30" - external-dns.alpha.kubernetes.io/hostname: iap.example.com - external-dns.alpha.kubernetes.io/ttl: "300" - # TLS block is not used with AGIC frontend certificates — leave empty - tls: [] -``` - -> **SSL Certificate:** The `appgw-ssl-certificate` annotation references a certificate by name that must already be uploaded to the Application Gateway in Azure. This is separate from Kubernetes secrets or cert-manager. Alternatively, you can integrate with Azure Key Vault via the AGIC add-on. - -> **WebSocket support:** Azure Application Gateway supports WebSockets natively. Ensure port 8080 is included in the Application Gateway listener configuration if using IAG5/Gateway Manager. - ---- - #### Traefik - Bare-Metal / On-Premises Option Traefik is a cloud-native ingress controller well suited to bare-metal and on-premises Kubernetes clusters. Because IAP terminates TLS at the pod (port 443), Traefik must be configured to re-encrypt the backend connection — it terminates TLS from the client, then reconnects to the IAP pod over HTTPS. @@ -480,8 +335,6 @@ IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every | Controller | How Backend SSL is Configured | Granularity | |---|---|---| | **ALB** | `alb.ingress.kubernetes.io/backend-protocol: HTTPS` annotation | Per-Ingress | -| **GKE** | `cloud.google.com/app-protocols` on the Service | Per-Service port | -| **Azure AGIC** | `appgw.ingress.kubernetes.io/backend-protocol: https` annotation | Per-Ingress | | **Traefik** | Global `--serversTransport.insecureSkipVerify=true` startup flag | Global (all backends) | | **HAProxy** | `haproxy.org/server-ssl: "true"` annotation | Per-Ingress object (applies to all backends in the Ingress) | | **Contour** | `projectcontour.io/upstream-protocol.tls: ""` on the Service | Per-Service port | @@ -504,8 +357,6 @@ Both backends require backend SSL re-encryption. All supported controllers handl | Controller | Provider | Backend HTTPS | Backend SSL Granularity | SSL Termination | WebSocket + SSL mix | WebSocket Support | Session Affinity | Health Checks | Pod-Level Routing | Prerequisite CRD | Best For | |------------|----------|---------------|-------------------------|-----------------|---------------------|-------------------|------------------|---------------|-------------------|------------------|----------| | **ALB** | AWS Native | Annotation | Per-Ingress | At load balancer | Supported natively | Native | Target group level | Annotations | `target-type: ip` | None | AWS EKS | -| **GKE HTTP(S) LB** | GCP Native | Service annotation + BackendConfig | Per-Service port | At load balancer | Supported natively | Native | BackendConfig (cookie) | BackendConfig CRD | NEG (`cloud.google.com/neg`) | BackendConfig (out-of-band) | GKE | -| **Azure AGIC** | Azure Native | Annotation | Per-Ingress | At load balancer | Supported natively | Native | Annotation (cookie) | Annotations | Default | None | AKS | | **Traefik** | Self-hosted | Global flag | Global (all backends) | At ingress (re-encrypt) | Supported natively | Native | Middleware (sticky sessions) | Passive (via response codes) | Default | ServersTransport CRD | Bare-metal / on-prem | | **HAProxy** | Self-hosted | Annotation | Per-Ingress object | At ingress (re-encrypt) | Supported natively | Native (tunnel timeout annotation) | Annotation (cookie) | Annotations | Default | None | Bare-metal / on-prem | | **Contour** | Self-hosted | Service annotation | Per-Service port | At ingress (re-encrypt) | Supported natively | Native (response-timeout annotation) | HTTPProxy CRD only | Passive (Envoy) | Default | None | Bare-metal / on-prem | From 5e787b8d66053dcaadde7274493f212b00655038 Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Wed, 11 Mar 2026 13:58:49 -0400 Subject: [PATCH 10/12] removed values file --- charts/iap/values-na-perf-traefix.yml | 813 -------------------------- 1 file changed, 813 deletions(-) delete mode 100644 charts/iap/values-na-perf-traefix.yml diff --git a/charts/iap/values-na-perf-traefix.yml b/charts/iap/values-na-perf-traefix.yml deleted file mode 100644 index 83d2b73..0000000 --- a/charts/iap/values-na-perf-traefix.yml +++ /dev/null @@ -1,813 +0,0 @@ -# Copyright (c) 2024, Itential, Inc -# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) ---- -# Default values for iap. -# Ingress controller: Traefik -# -# PREREQUISITE - apply the ServersTransport resource before installing: -# -# kubectl apply -f - < -# spec: -# insecureSkipVerify: true # IAP uses self-signed certs; skip backend cert verification -# EOF -# -# This tells Traefik to connect to IAP pods over HTTPS without validating their certificate. - -# -- The number of pods to start -replicaCount: 1 -# -- The port that the application will run on. -applicationPort: 3443 -# -- The port that the Gateway Manager will listen on. -websocketPort: 8080 -# -- Toggle to enable TLS features and configuration. -useTLS: true -# -- Toggle the use of websockets (IAG5 integration) -useWebSockets: true -# -- Toggle a volume mount which contains adapter code. When this is set to false it is assumed that -# all adapters will be layered into the Itential provided container. -mountAdapterVolume: true -# -- Toggle a volume with will contain log files. Not required if log data is being captured from -# Stdout. -mountLogVolume: true - -certManager: - # -- Toggles the use of cert-manager for managing the TLS certificates. Setting this to false - # means that creation of the TLS certificates will be manual and outside of the chart. - enabled: false - -external-dns: - # -- Optional dependency to generate a static external DNS name - enabled: false - -# The Itential image to use, its version, and its location -# The image name will depend on the entitlement that has been granted. -image: - # -- The image repository - repository: 497639811223.dkr.ecr.us-east-2.amazonaws.com/automation-platform-config - # -- The image pull policy - pullPolicy: IfNotPresent - - # Individual test toggles - healthEndpointTest: - enabled: true # Our new test # -- The image tag - tag: "6.1.2" - -# -- The secrets object used to pull the image from the repo -imagePullSecrets: - - name: ecr-registry-secret - -serviceAccount: - # -- Enable creation of ServiceAccount - enabled: true # Enable for IAM authentication via proxy - # -- Create a new ServiceAccount or use existing one - create: true - # -- Name of the ServiceAccount to use (auto-generated if not specified) - name: "iap-serviceaccount" - # -- Additional annotations for the ServiceAccount - annotations: {} - # -- Whether to automount the ServiceAccount token - automountServiceAccountToken: true - -postInstallTests: - enabled: true - readinessTimeout: 300 - # Time to live after test completion (in seconds) - pod will be cleaned up automatically - ttlSecondsAfterFinished: 300 # 5 minutes default - # Process count configuration - processCountTest: - # Optional processes - won't fail test if missing, but will be reported - optionalProcesses: - - "Pronghorn_LifecycleManager_Application" - - "Pronghorn_ConfigurationManager_Application" - - "Pronghorn_NSOManager_Application" - - "Pronghorn_AppArtifacts_Application" - -# AWS IAM Role configurations (disabled for local deployment) -# aws: -# elasticache: -# roleArn: "arn:aws:iam::207567785584:role/IAP-ElastiCache-Role" - - -# The issuer to be used if using cert-manager to generate the TLS certificates -issuer: - # -- Toggle to use the issuer object or not - enabled: true - # -- The type of issuer - kind: ClusterIssuer - # -- The name of this issuer. - name: iap-ca-issuer - # -- The CA secret to be used by this issuer when creating TLS certificates. - caSecretName: itential-ca - -# The certificate object to use by cert-manager to generate the TLS certificates. -certificate: - # -- Toggle to use the certificate object or not - enabled: true - secretName: iap-tls-secret - issuerRef: - # -- The name of the issuer with the CA reference. - name: iap-ca-issuer - # -- The issuer type - kind: ClusterIssuer - # -- Specifies how long before the certificate expires that cert-manager should try to renew. - renewBefore: 48h - # -- Specifies how long the certificate should be valid for (its lifetime). - duration: 2160h - # -- The Common Name to use when creating certificates - commonName: iap-na-k8s.pe.itential.io - # -- The domain to use when creating certificates. This will be used by the templates to build a - # complete list of hosts to enable direct access to individual pods. Some UI actions in Itential - # require direct access to pods. - domain: pe.itential.io - # -- Specifies any private key properties - privateKey: {} # include all required properties, passed to the template as is - # -- Specifies any key store properties - keyStores: {} # include all required properties, passed to the template as is - # -- Specifies any subject fields required - subject: {} # include all required properties, passed to the template as is - -# Additional TLS secrets to mount as optional volumes -# Each secret will be mounted at /etc/ssl// -additionalTLSSecrets: [] # Empty list - should not cause any failures - -# Used to configure the storage class object which governs how the mounted volumes are created. -storageClass: - # -- Toggle the use of storageClass - enabled: false - # -- The name of the storageClass - name: "longhorn" - # -- Specifies which volume plugin provisions the storage - provisioner: "driver.longhorn.io" - # -- What happens to PersistentVolumes when released. Itential recommends "retain". - reclaimPolicy: "Retain" - # -- Controls when volume binding occurs - volumeBindingMode: "Immediate" - # -- Key-value pairs passed to the provisioner - parameters: - numberOfReplicas: "3" - staleReplicaTimeout: "30" - fromBackup: "" - -# Persistent volumes and persistent volume claims. These are used for Itential application logs and -# for Itential adapters. -persistentVolumeClaims: - # -- Toggle the use of persistentVolumeClaims - enabled: true - # -- This represents the claim for the persistence for the adapters and other custom applications - # that may have been developed by the customer. - assetClaim: - # -- The requested amount of storage - storage: "10Gi" - # -- This represents the claim for the persistence for the log files created and written to by the - # IAP application. - logClaim: - # -- The requested amount of storage - storage: "10Gi" - -# The Kubernetes service object for this application -service: - # -- The service type. - type: "ClusterIP" - # -- The name of this Kubernetes service object. - name: "iap-service" - # -- The port that this service object is listening on. - port: 443 - # Service annotations for metrics port - annotations: {} - -# The Kubernetes ingress object for this application. -ingress: - # -- The ingress object can be disabled and will not be created with this set to false - enabled: true - # -- The name of this Kubernetes ingress object - name: "iap-ingress" - # -- The ingress controller class name - className: "traefik" - # -- The ingress controller path type - pathType: Prefix - # Load balancer configuration - loadBalancer: - # -- Enable a load balancer that will distribute request to all Itential pods - enabled: true - # -- The Load balancer host name - host: iap-na-k8s.pe.itential.io - # -- The path - path: / - # Direct access configuration - directAccess: - # -- Enable direct access to all Itential pods. - enabled: true - # -- The base domain for each Itential pod, used by the templates to create host names. - baseDomain: pe.itential.io - # -- The path - path: / - - # -- Traefik ingress annotations. - # Traefik terminates TLS at the ingress (re-encryption), then connects to IAP pods over HTTPS. - # WebSocket support is native in Traefik — no annotation required. - annotations: - # Route incoming traffic through the HTTPS (websecure) entrypoint - traefik.ingress.kubernetes.io/router.entrypoints: websecure - # Enable TLS on this router — Traefik will use the cert from the tls.secretName below - traefik.ingress.kubernetes.io/router.tls: "true" - # Connect to backend IAP pods over HTTPS, using the ServersTransport defined in the prerequisite above - # Format: -@kubernetescrd (Traefik v3 requires namespace prefix) - traefik.ingress.kubernetes.io/service.serversTransport: na-iap-servers-transport@kubernetescrd - - # Traefik uses the cert-manager managed secret for frontend TLS termination. - tls: - - hosts: - - iap-na-k8s.pe.itential.io - secretName: iap-tls-secret - -statefulset: - enabled: true - -# -- Additional pod annotations -podAnnotations: {} -# -- Additional pod labels -podLabels: {} -# -- Additional pod security context. The pods will mount some persistent volumes. These settings -# allow for that to happen. -podSecurityContext: - fsGroup: 1001 - runAsGroup: 1001 - runAsUser: 1001 # run as the 'itential' user - runAsNonRoot: true -# -- Additional security context -securityContext: {} - -# Container resources -resources: - limits: - memory: "14Gi" - requests: - cpu: "3" - memory: "14Gi" - -# The liveness probe used to determine if the container is alive. If the liveness probe fails, -# the kubelet kills the container, and the container is subjected to its restart policy. If a -# container does not provide a liveness probe, the default state is Success. -livenessProbe: - enabled: false - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - successThreshold: 1 - path: "/health/status?exclude-service=true" - -# The readiness probe used to determine if the container is ready to accept requests. If the -# readiness probe fails, the endpoints controller removes the pod's IP address from the -# endpoints of all services that match the pod. The default state of readiness before the -# initial delay is failure. If a container does not provide a readiness probe, the default -# state is success. -readinessProbe: - enabled: false - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - successThreshold: 1 - path: "/health/status?exclude-service=true" - -# The startup probe used to allow some time for the application to start up. The application -# will have a maximum of 3 minutes (18 * 10 = 180s) to finish its startup. Once the startup -# probe has succeeded once, the liveness probe takes over. -startupProbe: - enabled: false - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 18 - successThreshold: 1 - path: "/health/status?exclude-service=true" - -# -- Additional volumes to output on the Statefulset definition. -volumes: [] - -# -- Additional volumeMounts to output on the Statefulset definition. -volumeMounts: [] - -# -- Additional nodeSelectors -nodeSelector: {} - -# -- Host aliases for DNS resolution -hostAliases: - - ip: "172.85.0.20" - hostnames: - - "pe-redis01" - - ip: "172.85.0.21" - hostnames: - - "pe-redis02" - - ip: "172.85.0.22" - hostnames: - - "pe-redis03" - -# -- Additonal tolerations -tolerations: [] - -# -- Additional affinities -affinity: {} - -# Configuration properties for Itential Automation Platform. -# In most cases, the default values are sufficient. If the property is commented that means that -# the default value is being used. This is a list of all possible values for convenience. The -# values listed are the defaults where commented. -env: - ############## - #SERVER - ############## - # The name of the profile document to load from the MongoDB where legacy configuration - # properties are stored. Not required for installations that are using environment - # variables or a properties file. - # ITENTIAL_PROFILE_ID: "" - - # An identifier for the server instance. This is used to uniquely identify the server in a - # multi-server environment. If not provided, the server will generate one on startup. This will - # be populated by the chart to the pod id and should not be used in a containerized deployment. - # ITENTIAL_SERVER_ID: "" - - # The file path to the directory containing additional services (applications and adapters). - # The chart will impose this value with an opinionated volume mount directory and should not be - # used in a containerized deployment. - # ITENTIAL_SERVICE_DIRECTORY: "" - - # Indicates whether the platform is using encrypted code files. - # ITENTIAL_PLATFORM_ENCRYPTED: "true" - - # 64-length hex string describing a 256 bit encryption key. - # ITENTIAL_ENCRYPTION_KEY: "" - - # A whitelist of services (applications/adapters) to initialize on startup of the platform. - # If no value is given, all services will be initialized. - # ITENTIAL_SERVICES: "" - - # The service type that will be denied CRUD operation access. - # ITENTIAL_SERVICE_BLACKLIST : "" - - # The amount of time a service should wait before shutting down, in seconds. - # ITENTIAL_PLATFORM_SHUTDOWN_TIMEOUT: "3" - - # How often to update service health, measured in seconds. - # ITENTIAL_SERVICE_HEALTH_CHECK_INTERVAL : "5" - - # The number of failed health checks in a row before a service is considered to be "unhealthy". - # ITENTIAL_SERVICE_HEALTH_CHECK_UNHEALTHY_THRESHOLD: "3" - - # If true, the platform will periodically check for dead processes. - # ITENTIAL_DEAD_PROCESS_CHECK_ENABLED: "true" - - # How often to check if application/adapter stopped sending healthcheck pings, in seconds. - # ITENTIAL_DEAD_PROCESS_CHECK_INTERVAL: "5" - - # Maximum time period for application/adapter without sending healthcheck ping, in seconds. - # ITENTIAL_DEAD_PROCESS_MAX_PERIOD: "15" - - # Specifies the amount of times services will retry on crash before stopping. - # ITENTIAL_SERVICE_CRASH_RECOVERY_MAX_RETRIES: "10" - - # Specifies the amount of times between each retry before the count will reset in milliseconds. - # ITENTIAL_SERVICE_CRASH_RECOVERY_RESET_RETRIES_AFTER_MS: "60000" - - # The timeout for external API requests, in seconds. - # ITENTIAL_EXTERNAL_REQUEST_TIMEOUT : "5" - - # The interval for how often IAP polls for the number of devices, in hours. - # ITENTIAL_DEVICE_COUNT_POLLING_INTERVAL : "24" - - # If true, the platform will track detailed audit events. - # ITENTIAL_AUDIT_ENABLED: "true" - - ############################# - # MONGO DATABASE CONNECTION # - ############################# - # -- Instructs the MongoDB driver to use the provided user/password when connecting to MongoDB. - ITENTIAL_MONGO_AUTH_ENABLED: "false" - - # -- The username to use when connecting to MongoDB. - ITENTIAL_MONGO_USER: "itential" - - # The password to use when connecting to MongoDB. - # ITENTIAL_MONGO_PASSWORD: "" - - # The name of the database that the MongoDB user must authenticate against. - ITENTIAL_MONGO_AUTH_DB: "itential" - - # If true, the server will not check if it is connecting to a compatible MongoDB version. - # ITENTIAL_MONGO_BYPASS_VERSION_CHECK: "true" - - # -- The name of the MongoDB logical database to connect to. - ITENTIAL_MONGO_DB_NAME: "itential_k8_na" - - # The MongoDB connection string. For a replica set this will include all members of the - # replica set. For Mongo Atlas this will be the SRV connection format. - # ITENTIAL_MONGO_URL: "" - - # -- Instruct the MongoDB driver to use TLS protocols when connecting to the database. - ITENTIAL_MONGO_TLS_ENABLED: "true" - - # -- If true, disables the validation checks for TLS certificates on other servers in the cluster - # and allows the use of invalid or self-signed certificates to connect. - ITENTIAL_MONGO_TLS_ALLOW_INVALID_CERTIFICATES: "true" - - # The .pem file that contains the root certificate chain from the Certificate Authority. - # Specify the file name of the .pem file using absolute paths. - # ITENTIAL_MONGO_TLS_CA_FILE: "" - - # The maximum number of connections in a connection pool. - # Each application/adapter has its own connection pool. - # ITENTIAL_MONGO_MAX_POOL_SIZE: "" - - #################### - # REDIS CONNECTION # - #################### - # The Redis keyspace (database number) to use for the connection. - ITENTIAL_REDIS_DB: "3" - - # -- The username to use when connecting to Redis. - ITENTIAL_REDIS_USERNAME: "itential" - - # The password to use when connecting to Redis. - # ITENTIAL_REDIS_PASSWORD: "" # Set via secret key - - # The maximum number of times to retry a request to Redis when the connection is lost. - # ITENTIAL_REDIS_MAX_RETRIES_PER_REQUEST : "20" - - # The maximum number of times to retry writing a heartbeat message to Redis from a service. - # ITENTIAL_REDIS_MAX_HEARTBEAT_WRITE_RETRIES: "20" - - # -- The hostname of the Redis server. Not used when connecting to Redis Sentinels. - # ITENTIAL_REDIS_HOST: "172.85.0.20" # Temporarily use direct connection - - # -- The port to use when connecting to this Redis instance. - ITENTIAL_REDIS_PORT: "6379" - - # The username to use when authenticating with a Redis Sentinel cluster. - ITENTIAL_REDIS_SENTINEL_USERNAME: "sentineluser" - - # The password to use when authenticating with a Redis Sentinel cluster - # ITENTIAL_REDIS_SENTINEL_PASSWORD: "" # Set via secret key - - # The list of Redis Sentinel servers (hostnames and ports) to use for high availability. - # Sample: [{"host": "172.85.0.20", "port": 26379}] - ITENTIAL_REDIS_SENTINELS: '[{"host": "172.85.0.20", "port": 26379}, {"host": "172.85.0.21", "port": 26379}, {"host": "172.85.0.22", "port": 26379}]' - - # The Redis primary name. This only has meaning when Redis is running with replication enabled. - # The sentinels will monitor this node and consider it down only when the sentinels agree. - # Note: The primary name should not include special characters other than: .-_ and no whitespaces. - ITENTIAL_REDIS_NAME: "itentialmaster" - - # Set the domain for session cookies to match ingress hostname - ITENTIAL_WEBSERVER_COOKIE_DOMAIN: "pe.itential.io" - - # Redis TLS configuration options for secure connections. - # Refer to NodeJS TLS library for all supported options. - # This must be set to "{}" if connecting to elasticache - # ITENTIAL_REDIS_TLS: '{}' - - ############################## - # HASHICORP VAULT CONNECTION # - ############################## - # The URL to the Hashicorp Vault server. - # ITENTIAL_VAULT_URL: "" - - # The authorization method to connect to Hashicorp Vault. Either token or approle. - # ITENTIAL_VAULT_AUTH_METHOD: "" - - # Hashicorp Vault Role ID used for AppRole authentication. - # ITENTIAL_VAULT_ROLE_ID: "" - - # Hashicorp Vault Secret ID used for AppRole login. - # ITENTIAL_VAULT_SECRET_ID: "" - - # The path where the AppRole was enabled. - # ITENTIAL_VAULT_APPROLE_PATH: "" - - # The file path to a token file. The token is used for authentication to access Vault secrets. - # ITENTIAL_VAULT_TOKEN: "" - - # The endpoint for the Secrets Engine that is used. - # ITENTIAL_VAULT_SECRETS_ENDPOINT: "" - - # If true, only reads secrets from Hashicorp Vault. Otherwise, the platform can write secrets - # to Vault for storage. - # ITENTIAL_VAULT_READ_ONLY: "true" - - ################### - # WORKFLOW WORKER # - ################### - # If true, will start working tasks immediately after the server startup process is complete. - # If false, the task worker must be enabled manually via the UI/API. - # ITENTIAL_TASK_WORKER_ENABLED: "true" - - # If true, will allow jobs to be started after the server startup process is complete. - # If false, API calls to start Jobs will return an error until enabled manually via the UI/API. - # ITENTIAL_JOB_WORKER_ENABLED: "true" - - ###################### - # INTEGRATION WORKER # - ###################### - # The number of threads available for API requests. - # ITENTIAL_INTEGRATION_THREAD_COUNT: "5" - - # The number of milliseconds until an integration request times out. - # ITENTIAL_INTEGRATION_TIMEOUT: "15000" - - ############### - # PLATFORM UI # - ############### - # Path to the layout file extended in pug templates. - # ITENTIAL_UI_LAYOUT_FILE: "" - - # Path to the HTML file that will be displayed as the home page for the UI. - # ITENTIAL_UI_HOME_FILE: "node_modules/@itential/iap-ui/build/index.html" - - # Path to the HTML file that will be displayed as the login page for the UI. - # ITENTIAL_UI_LOGIN_FILE: "node_modules/@itential/iap-ui/build/index.html" - - # Path to the HTML file that will be displayed as the profile page for the UI. - # ITENTIAL_UI_PROFILE_FILE: "node_modules/@itential/iap-ui/build/index.html" - - # Path to the favicon file that will be displayed in the browser tab. - # ITENTIAL_UI_FAVICON: "ui/img/favicon.ico" - - # Path to the apple touch icon file that will be displayed on iOS devices. - # ITENTIAL_UI_APPLE_TOUCH_ICON_FILE: "ui/img/apple-touch-icon.png" - - ################## - # AUTHENTICATION # - ################## - # If true, logs out existing sessions for a user when they log in with a new session. - # ITENTIAL_AUTH_UNIQUE_SESSIONS_ENABLED: "false" - - # Members of these groups will be implicitly assigned with admin permissions. - # ITENTIAL_AUTH_ADMIN_GROUPS: '[]' - - # Enables a AAA adapter to custom build the principal object for a user with - # a "buildPrincipal" method. - # ITENTIAL_AUTH_BROKER_PRINCIPAL_ENABLED: "false" - - # The name of the cookie used for a user session. - # ITENTIAL_AUTH_SESSION_COOKIE_NAME: "token" - - # The time in minutes before a user session expires. - # ITENTIAL_AUTH_SESSION_TTL: "60" - - # Enables a default user to be used for login when SSO is not configured and no AAA Adapter exists. - # ITENTIAL_DEFAULT_USER_ENABLED: "true" - - # The username of the default user. - # ITENTIAL_DEFAULT_USER_USERNAME: "admin" - - # The password of the default user. - # ITENTIAL_DEFAULT_USER_PASSWORD: "" - - ############# - # WEBSERVER # - ############# - # A toggle to instruct the webserver to include HTTP cache control headers on the response. - # ITENTIAL_WEBSERVER_CACHE_CONTROL_ENABLED: "false" - - # Timeout to use for incoming HTTP requests to the platform API, in milliseconds. - # ITENTIAL_WEBSERVER_TIMEOUT: "300000" - - # The value of the HTTP Access-Control-Allow-Origin header returned to clients. - # ITENTIAL_WEBSERVER_RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN: "*" - - # If true, allows the webserver to respond to insecure HTTP requests. - # ITENTIAL_WEBSERVER_HTTP_ENABLED: "false" - - # If true, allows the webserver to respond to secure HTTPS requests. - # ITENTIAL_WEBSERVER_HTTPS_ENABLED: "true" - - # The path to the public key file used for HTTPS connections. - # ITENTIAL_WEBSERVER_HTTPS_KEY: "/etc/ssl/certs/platform/server.key" - - # The passphrase for the private key used to enable TLS sessions. - # ITENTIAL_WEBSERVER_HTTPS_PASSPHRASE: "" - - # The path to the certificate file used for HTTPS connections. - # ITENTIAL_WEBSERVER_HTTPS_CERT: "/etc/ssl/certs/platform/server.crt" - - # The set of allowed SSL/TLS protocol versions. - ITENTIAL_WEBSERVER_HTTPS_SECURE_PROTOCOL: "TLS_method" - - # The allowed SSL/TLS cipher suite. - # ITENTIAL_WEBSERVER_HTTPS_CIPHERS: "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA" - - # Specifies the number of renegotiations that are allowed in a single HTTPS connection. - # ITENTIAL_WEBSERVER_HTTPS_CLIENT_RENEG_LIMIT: "3" - - # Specifies the time renegotiation window in seconds for a single HTTPS connection. - # ITENTIAL_WEBSERVER_HTTPS_CLIENT_RENEG_WINDOW: "600" - - # The set of allowed HTTP verbs in addition to those defined in the standard HTTP/1.1 protocol. - # ITENTIAL_WEBSERVER_HTTP_ALLOWED_OPTIONAL_VERBS: "" - - ########### - # LOGGING # - ########### - # The maximum number of each log file to keep as rotation occurs. - # ITENTIAL_LOG_MAX_FILES: "100" - - # The maximum file size in bytes of each log file before rotation occurs. - # ITENTIAL_LOG_MAX_FILE_SIZE: "1048576" - - # The minimum log level to display in the log file. - ITENTIAL_LOG_LEVEL: "warn" - - # The absolute directory path where log files are written. - # ITENTIAL_LOG_DIRECTORY: "/var/log/itential/platform" - - # The name of the primary platform log file. - # ITENTIAL_LOG_FILENAME: "platform.log" - - # The minimum log level to display in the console (stdout). - ITENTIAL_LOG_LEVEL_CONSOLE: "warn" - - # The absolute directory path where webserver log files are written. - # ITENTIAL_WEBSERVER_LOG_DIRECTORY: "/var/log/itential/platform" - - # The name of the webserver log file. - # ITENTIAL_WEBSERVER_LOG_FILENAME: "webserver.log" - - # The minimum log level to send to the syslog server. - ITENTIAL_LOG_LEVEL_SYSLOG: "warning" - - # The hostname or IP address of the syslog server. - # ITENTIAL_SYSLOG_HOST: "localhost" - - # The port number of the syslog server. - # ITENTIAL_SYSLOG_PORT: "514" - - # The protocol to use when sending logs to the syslog server. - # ITENTIAL_SYSLOG_PROTOCOL: "udp4" - - # The syslog facility to use when sending logs to the syslog server. - # ITENTIAL_SYSLOG_FACILITY: "local0" - - # The syslog message format to use when sending logs to the syslog server. - # ITENTIAL_SYSLOG_TYPE: "BSD" - - # The path to the syslog server file. - # ITENTIAL_SYSLOG_PATH: "/dev/log" - - # The process property to include as the process id in the syslog message. - # ITENTIAL_SYSLOG_PID: "process.pid" - - # The hostname to include in the syslog message. - # ITENTIAL_SYSLOG_LOCALHOST: "localhost" - - # The process property to include as the application name in the syslog message. - # ITENTIAL_SYSLOG_APP_NAME: "process.title" - - # The end of line character to include in the syslog message. - # ITENTIAL_SYSLOG_EOL: "" - - ########### - # BROKERS # - ########### - # A list of adapter types that manages the devices. - # ITENTIAL_DEVICE_BROKER_DEFAULT_ADAPTER_PRIORITY: "" - - # Runs a command on a device. - # ITENTIAL_DEVICE_BROKER_RUN_COMMAND_ADAPTER_PREFERENCE: "" - - # If true, the platform will perform strict JSON Schema validation on messages into the brokers - # and coming back to the broker layer from adapters. - # ITENTIAL_BROKER_VALIDATION_ENABLED: "false" - - ######## - # SNMP # - ######## - # Remote SNMP destination configuration objects. - # ITENTIAL_SNMP_ALARM_CONFIGS: '[{"ip": "localhost", "community": "public", "type": "trap", "properties": {"port": 161, "retries": 1, "timeout": 5000, "transport": "udp4", "trapPort": 162, "version": "V1"}}]' - - # - # END IAP CONFIGURATION PROPERTIES - # - -processExporter: - enabled: true - image: - repository: ncabatoff/process-exporter - tag: latest - port: 9256 - -mongoqueryExporter: - enabled: true - existingConfig: - name: mongodb-query-exporter - image: - pullPolicy: Always - podMonitor: - enabled: true - namespace: na - interval: 60s - scrapeTimeout: 15s - replicas: 1 - resources: - limits: - memory: 250Mi - ephemeral-storage: 50Mi - requests: - cpu: 50m - memory: 250Mi - ephemeral-storage: 50Mi - env: - MDBEXPORTER_MONGODB_QUERY_TIMEOUT: 15s - -# Loki configuration for log aggregation -loki: - # -- Enable Loki for log collection - enabled: true - image: - # -- Loki image repository - repository: grafana/loki - # -- Loki image tag - tag: 2.9.0 - # -- Image pull policy - pullPolicy: IfNotPresent - # -- Loki HTTP port - httpPort: 3100 - # -- Loki GRPC port - grpcPort: 9095 - # -- Storage configuration - storage: - # -- Storage class for Loki data persistence - storageClass: "iap-ebs-gp3-na" - # -- Storage size for Loki data - size: "20Gi" - # -- Resource limits and requests - resources: - limits: - memory: "1Gi" - cpu: "500m" - requests: - memory: "512Mi" - cpu: "100m" - # -- Ingress configuration for external access - ingress: - # -- Enable Ingress for Loki - enabled: true - # -- Ingress class name - className: "traefik" - # -- Hostname for Loki access - host: "loki-local.pe.itential.io" - # -- Additional annotations for the Ingress - # Loki uses plain HTTP (port 3100) — no backend HTTPS or ServersTransport needed - annotations: - traefik.ingress.kubernetes.io/router.entrypoints: web - -# Promtail configuration for log collection -promtail: - # -- Enable Promtail for log shipping to Loki - enabled: true - image: - # -- Promtail image repository - repository: grafana/promtail - # -- Promtail image tag - tag: 2.9.0 - # -- Image pull policy - pullPolicy: IfNotPresent - # -- Loki endpoint for Promtail to send logs to - lokiUrl: "http://iap-loki:3100/loki/api/v1/push" - # -- Resource limits and requests - resources: - limits: - memory: "128Mi" - cpu: "100m" - requests: - memory: "64Mi" - cpu: "50m" - - -# Init container for installing adapters -initAdapterInstaller: - # -- Enable the init container that installs adapters to the persistent volume - enabled: false - image: - # -- The repository for the adapter installer init container image - repository: node - # -- The tag for the adapter installer init container image - tag: "18-bullseye" - # -- The image pull policy for the adapter installer init container - pullPolicy: IfNotPresent - securityContext: - runAsUser: 1001 - runAsGroup: 1001 - runAsNonRoot: true - allowPrivilegeEscalation: false - npmInstallOptions: - - "--silent" - - "--no-audit" - - "--no-fund" - - "--ignore-scripts" - repositories: - - url: "https://gitlab.com/itentialopensource/adapters/adapter-aruba_central.git" - branch: "v2.3.0" - - url: "https://gitlab.com/itentialopensource/adapters/adapter-github.git" From ba9a771b1e35f671d4e8a22d4ebbaf8fc4f3e236 Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Wed, 11 Mar 2026 14:02:25 -0400 Subject: [PATCH 11/12] changed order --- docs/ingress.md | 156 ++++++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 79 deletions(-) diff --git a/docs/ingress.md b/docs/ingress.md index 9f10840..c94ce40 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -94,6 +94,81 @@ ingress: alb.ingress.kubernetes.io/ssl-policy: "ELBSecurityPolicy-TLS-1-2-2017-01" ``` +#### HAProxy - Bare-Metal / On-Premises Option + +The HAProxy Kubernetes Ingress Controller is a high-performance, enterprise-grade ingress controller well suited to bare-metal and on-premises clusters. Because IAP terminates TLS at the pod (port 443), HAProxy must be configured to re-encrypt the backend connection — it terminates TLS from the client, then reconnects to the IAP pod over HTTPS. + +**Step 1 — Install HAProxy Kubernetes Ingress Controller:** + +```bash +helm repo add haproxytech https://haproxytech.github.io/helm-charts +helm repo update +helm install haproxy-ingress haproxytech/kubernetes-ingress \ + --namespace haproxy-controller \ + --create-namespace \ + --set controller.ingressClass=haproxy \ + --set controller.ingressClassResource.enabled=true \ + --set controller.ingressClassResource.name=haproxy \ + --set controller.ingressClassResource.isDefaultClass=false +``` + +**TLS certificate considerations:** + +`haproxy.org/server-ssl-verify: "none"` only affects the **backend connection** (HAProxy → IAP pod). It has no effect on the **frontend connection** (client browser → HAProxy), which uses the certificate from `iap-tls-secret`. Clients only ever see the frontend certificate. + +| Connection | Certificate | Verified by | +|---|---|---| +| Client → HAProxy | `iap-tls-secret` (customer-provided or CA-signed) | Client browser | +| HAProxy → IAP pod | Self-signed (pod-level) | Skipped via `server-ssl-verify: none` | + +This is a common and accepted pattern. Pod IPs and their derived DNS names are ephemeral — they change on every pod restart — making it impractical to maintain a static certificate for backend pods. The recommended approach is to skip verification for the backend and ensure the frontend certificate presented to clients is properly signed. + +**Step 2 — Helm values configuration:** + +```yaml +ingress: + enabled: true + className: "haproxy" + loadBalancer: + enabled: true + host: iap.example.com + path: / + directAccess: + enabled: true + baseDomain: example.com + path: / + annotations: + # Re-encrypt to backend IAP pods over HTTPS (IAP terminates TLS at the pod) + haproxy.org/server-ssl: "true" + # Skip backend certificate verification — IAP pods use self-signed certs without pod IP SANs + haproxy.org/server-ssl-verify: "none" + # Redirect HTTP to HTTPS + haproxy.org/ssl-redirect: "true" + # Cookie-based session affinity — required for IAP UI actions that must reach the same pod + haproxy.org/cookie-persistence: "iap-server" + # Connection and request timeouts + haproxy.org/timeout-connect: "5s" + haproxy.org/timeout-client: "300s" + haproxy.org/timeout-server: "300s" + # WebSocket tunnel timeout — keep alive for long-lived WebSocket connections + haproxy.org/timeout-tunnel: "3600s" + # Health check path for backend IAP pods + haproxy.org/check: "true" + haproxy.org/check-http: "/health/status?exclude-services=true" + tls: + - hosts: + - iap.example.com + secretName: iap-tls-secret +``` + +> **WebSocket support (IAG5/Gateway Manager):** When `useWebSockets: true` is set, the IAP chart renders a single Ingress with two backends: `/` → port 443 (HTTPS) and `/ws` → port 8080 (WSS). HAProxy applies `haproxy.org/server-ssl: "true"` to every backend in the Ingress object — this correctly re-encrypts both the main application traffic and the WebSocket traffic to the IAP pod. + +> **Cloud environments:** On EKS, GKE, or AKS, HAProxy's `LoadBalancer` service is automatically assigned an external IP by the cloud provider. No additional configuration is needed. + +> **Bare-metal environments:** Without a cloud provider, the `LoadBalancer` service will remain in `` state. Install [MetalLB](https://metallb.universe.tf/) to assign external IPs, or consult your cluster administrator for how external traffic is routed to the cluster. + +--- + #### Traefik - Bare-Metal / On-Premises Option Traefik is a cloud-native ingress controller well suited to bare-metal and on-premises Kubernetes clusters. Because IAP terminates TLS at the pod (port 443), Traefik must be configured to re-encrypt the backend connection — it terminates TLS from the client, then reconnects to the IAP pod over HTTPS. @@ -176,83 +251,6 @@ ingress: --- -#### HAProxy - Bare-Metal / On-Premises Option - -The HAProxy Kubernetes Ingress Controller is a high-performance, enterprise-grade ingress controller well suited to bare-metal and on-premises clusters. Because IAP terminates TLS at the pod (port 443), HAProxy must be configured to re-encrypt the backend connection — it terminates TLS from the client, then reconnects to the IAP pod over HTTPS. - -Unlike Traefik, HAProxy does not require a global startup flag or a separate CRD prerequisite. Backend TLS behavior is controlled entirely through annotations on the Ingress object. - -**Step 1 — Install HAProxy Kubernetes Ingress Controller:** - -```bash -helm repo add haproxytech https://haproxytech.github.io/helm-charts -helm repo update -helm install haproxy-ingress haproxytech/kubernetes-ingress \ - --namespace haproxy-controller \ - --create-namespace \ - --set controller.ingressClass=haproxy \ - --set controller.ingressClassResource.enabled=true \ - --set controller.ingressClassResource.name=haproxy \ - --set controller.ingressClassResource.isDefaultClass=false -``` - -**TLS certificate considerations:** - -`haproxy.org/server-ssl-verify: "none"` only affects the **backend connection** (HAProxy → IAP pod). It has no effect on the **frontend connection** (client browser → HAProxy), which uses the certificate from `iap-tls-secret`. Clients only ever see the frontend certificate. - -| Connection | Certificate | Verified by | -|---|---|---| -| Client → HAProxy | `iap-tls-secret` (customer-provided or CA-signed) | Client browser | -| HAProxy → IAP pod | Self-signed (pod-level) | Skipped via `server-ssl-verify: none` | - -This is a common and accepted pattern. Pod IPs and their derived DNS names are ephemeral — they change on every pod restart — making it impractical to maintain a static certificate for backend pods. The recommended approach is to skip verification for the backend and ensure the frontend certificate presented to clients is properly signed. - -**Step 2 — Helm values configuration:** - -```yaml -ingress: - enabled: true - className: "haproxy" - loadBalancer: - enabled: true - host: iap.example.com - path: / - directAccess: - enabled: true - baseDomain: example.com - path: / - annotations: - # Re-encrypt to backend IAP pods over HTTPS (IAP terminates TLS at the pod) - haproxy.org/server-ssl: "true" - # Skip backend certificate verification — IAP pods use self-signed certs without pod IP SANs - haproxy.org/server-ssl-verify: "none" - # Redirect HTTP to HTTPS - haproxy.org/ssl-redirect: "true" - # Cookie-based session affinity — required for IAP UI actions that must reach the same pod - haproxy.org/cookie-persistence: "iap-server" - # Connection and request timeouts - haproxy.org/timeout-connect: "5s" - haproxy.org/timeout-client: "300s" - haproxy.org/timeout-server: "300s" - # WebSocket tunnel timeout — keep alive for long-lived WebSocket connections - haproxy.org/timeout-tunnel: "3600s" - # Health check path for backend IAP pods - haproxy.org/check: "true" - haproxy.org/check-http: "/health/status?exclude-services=true" - tls: - - hosts: - - iap.example.com - secretName: iap-tls-secret -``` - -> **WebSocket support (IAG5/Gateway Manager):** When `useWebSockets: true` is set, the IAP chart renders a single Ingress with two backends: `/` → port 443 (HTTPS) and `/ws` → port 8080 (WSS). HAProxy applies `haproxy.org/server-ssl: "true"` to every backend in the Ingress object — this correctly re-encrypts both the main application traffic and the WebSocket traffic to the IAP pod. - -> **Cloud environments:** On EKS, GKE, or AKS, HAProxy's `LoadBalancer` service is automatically assigned an external IP by the cloud provider. No additional configuration is needed. - -> **Bare-metal environments:** Without a cloud provider, the `LoadBalancer` service will remain in `` state. Install [MetalLB](https://metallb.universe.tf/) to assign external IPs, or consult your cluster administrator for how external traffic is routed to the cluster. - ---- - #### Contour (Envoy) - Bare-Metal / On-Premises Option Contour is a CNCF-graduated ingress controller that uses Envoy as its data plane. It is well suited to bare-metal and on-premises clusters and works with the standard `networking.k8s.io/v1` Ingress resource — no chart changes required. Because IAP terminates TLS at the pod (port 443), Contour must re-encrypt the backend connection. @@ -335,8 +333,8 @@ IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every | Controller | How Backend SSL is Configured | Granularity | |---|---|---| | **ALB** | `alb.ingress.kubernetes.io/backend-protocol: HTTPS` annotation | Per-Ingress | -| **Traefik** | Global `--serversTransport.insecureSkipVerify=true` startup flag | Global (all backends) | | **HAProxy** | `haproxy.org/server-ssl: "true"` annotation | Per-Ingress object (applies to all backends in the Ingress) | +| **Traefik** | Global `--serversTransport.insecureSkipVerify=true` startup flag | Global (all backends) | | **Contour** | `projectcontour.io/upstream-protocol.tls: ""` on the Service | Per-Service port | #### WebSocket (IAG5/Gateway Manager) Backend SSL @@ -357,8 +355,8 @@ Both backends require backend SSL re-encryption. All supported controllers handl | Controller | Provider | Backend HTTPS | Backend SSL Granularity | SSL Termination | WebSocket + SSL mix | WebSocket Support | Session Affinity | Health Checks | Pod-Level Routing | Prerequisite CRD | Best For | |------------|----------|---------------|-------------------------|-----------------|---------------------|-------------------|------------------|---------------|-------------------|------------------|----------| | **ALB** | AWS Native | Annotation | Per-Ingress | At load balancer | Supported natively | Native | Target group level | Annotations | `target-type: ip` | None | AWS EKS | -| **Traefik** | Self-hosted | Global flag | Global (all backends) | At ingress (re-encrypt) | Supported natively | Native | Middleware (sticky sessions) | Passive (via response codes) | Default | ServersTransport CRD | Bare-metal / on-prem | | **HAProxy** | Self-hosted | Annotation | Per-Ingress object | At ingress (re-encrypt) | Supported natively | Native (tunnel timeout annotation) | Annotation (cookie) | Annotations | Default | None | Bare-metal / on-prem | +| **Traefik** | Self-hosted | Global flag | Global (all backends) | At ingress (re-encrypt) | Supported natively | Native | Middleware (sticky sessions) | Passive (via response codes) | Default | ServersTransport CRD | Bare-metal / on-prem | | **Contour** | Self-hosted | Service annotation | Per-Service port | At ingress (re-encrypt) | Supported natively | Native (response-timeout annotation) | HTTPProxy CRD only | Passive (Envoy) | Default | None | Bare-metal / on-prem | ## Direct Access From 386dcca188f1bc01f54f0bfa2f8959d37d2d39b7 Mon Sep 17 00:00:00 2001 From: Nick Andreano Date: Fri, 13 Mar 2026 11:49:48 -0400 Subject: [PATCH 12/12] removed Contour --- docs/ingress.md | 77 ------------------------------------------------- 1 file changed, 77 deletions(-) diff --git a/docs/ingress.md b/docs/ingress.md index c94ce40..c498445 100644 --- a/docs/ingress.md +++ b/docs/ingress.md @@ -251,81 +251,6 @@ ingress: --- -#### Contour (Envoy) - Bare-Metal / On-Premises Option - -Contour is a CNCF-graduated ingress controller that uses Envoy as its data plane. It is well suited to bare-metal and on-premises clusters and works with the standard `networking.k8s.io/v1` Ingress resource — no chart changes required. Because IAP terminates TLS at the pod (port 443), Contour must re-encrypt the backend connection. - -Contour's key advantage over HAProxy for IAP is how it scopes backend TLS: the `projectcontour.io/upstream-protocol.tls` annotation is placed on the **Service** and lists the ports that should use TLS. Both port 443 (HTTPS) and port 8080 (WSS) must be listed to ensure Contour re-encrypts traffic to both backends. - -> **Session affinity:** Cookie-based sticky sessions are not supported for standard Kubernetes Ingress resources in Contour. Session affinity requires Contour's `HTTPProxy` CRD. For testing, IAP's own session tokens function across pods. Production deployments should evaluate `HTTPProxy` if same-pod routing is required. - -**Step 1 — Install Contour:** - -```bash -kubectl apply -f https://projectcontour.io/quickstart/contour.yaml -``` - -> **Bare-metal environments:** Without a cloud provider, the Envoy service will remain in `` state. Patch it to NodePort and retrieve the assigned port for wiring to your external load balancer: -> ```bash -> kubectl patch svc envoy -n projectcontour -p '{"spec":{"type":"NodePort"}}' -> kubectl get svc envoy -n projectcontour \ -> -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}' -> ``` - -**TLS certificate considerations:** - -The `projectcontour.io/upstream-protocol.tls` annotation on the Service tells Contour's Envoy to use TLS only for the listed ports. For standard Ingress resources, Envoy does not validate backend certificates when no CA is explicitly configured — self-signed pod certificates work without additional configuration. - -| Connection | Certificate | Verified by | -|---|---|---| -| Client → Contour | `iap-tls-secret` (customer-provided or CA-signed) | Client browser | -| Contour → IAP pod (port 443) | Self-signed (pod-level) | Not verified (no CA configured) | -| Contour → IAP pod (port 8080) | Self-signed (pod-level) | Not verified (no CA configured) | - -**Step 2 — Helm values configuration:** - -```yaml -service: - type: ClusterIP - name: iap-service - port: 443 - annotations: - # Tell Contour/Envoy to use TLS for both the main application port and the WebSocket port. - projectcontour.io/upstream-protocol.tls: "443,8080" -``` - -```yaml -ingress: - enabled: true - className: "contour" - loadBalancer: - enabled: true - host: iap.example.com - path: / - directAccess: - enabled: true - baseDomain: example.com - hostOverride: "iap-{ns}-contour" - path: / - annotations: - # Redirect HTTP to HTTPS - ingress.kubernetes.io/force-ssl-redirect: "true" - # Response timeout — set high for long-lived WebSocket connections - projectcontour.io/response-timeout: "3600s" - tls: - - hosts: - - iap.example.com - secretName: iap-tls-secret -``` - -> **Cloud environments:** On EKS, GKE, or AKS, Contour's Envoy `LoadBalancer` service is automatically assigned an external IP by the cloud provider. No additional configuration is needed. - -> **Bare-metal environments:** Without a cloud provider, the `LoadBalancer` service will remain in `` state. Install [MetalLB](https://metallb.universe.tf/) to assign external IPs, or consult your cluster administrator for how external traffic is routed to the cluster. - -> **WebSocket support:** Contour supports WebSockets natively. No annotation is required. The `projectcontour.io/response-timeout` annotation controls the idle timeout for long-lived connections including WebSocket. - ---- - ### Backend SSL Behavior by Controller IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every ingress controller must re-encrypt the backend connection it terminates TLS from the client and then reconnects to the IAP pod over HTTPS. How each controller handles this, and how granular that configuration is, differs significantly. @@ -335,7 +260,6 @@ IAP pods terminate TLS internally at port 3443 (self-signed certificates). Every | **ALB** | `alb.ingress.kubernetes.io/backend-protocol: HTTPS` annotation | Per-Ingress | | **HAProxy** | `haproxy.org/server-ssl: "true"` annotation | Per-Ingress object (applies to all backends in the Ingress) | | **Traefik** | Global `--serversTransport.insecureSkipVerify=true` startup flag | Global (all backends) | -| **Contour** | `projectcontour.io/upstream-protocol.tls: ""` on the Service | Per-Service port | #### WebSocket (IAG5/Gateway Manager) Backend SSL @@ -357,7 +281,6 @@ Both backends require backend SSL re-encryption. All supported controllers handl | **ALB** | AWS Native | Annotation | Per-Ingress | At load balancer | Supported natively | Native | Target group level | Annotations | `target-type: ip` | None | AWS EKS | | **HAProxy** | Self-hosted | Annotation | Per-Ingress object | At ingress (re-encrypt) | Supported natively | Native (tunnel timeout annotation) | Annotation (cookie) | Annotations | Default | None | Bare-metal / on-prem | | **Traefik** | Self-hosted | Global flag | Global (all backends) | At ingress (re-encrypt) | Supported natively | Native | Middleware (sticky sessions) | Passive (via response codes) | Default | ServersTransport CRD | Bare-metal / on-prem | -| **Contour** | Self-hosted | Service annotation | Per-Service port | At ingress (re-encrypt) | Supported natively | Native (response-timeout annotation) | HTTPProxy CRD only | Passive (Envoy) | Default | None | Bare-metal / on-prem | ## Direct Access