diff --git a/deploy/ccm/envoy-config-rest-custom-proxy.yaml b/deploy/ccm/envoy-config-collector-custom-http-proxy.yaml similarity index 93% rename from deploy/ccm/envoy-config-rest-custom-proxy.yaml rename to deploy/ccm/envoy-config-collector-custom-http-proxy.yaml index d7ca567ce..926d5bee1 100644 --- a/deploy/ccm/envoy-config-rest-custom-proxy.yaml +++ b/deploy/ccm/envoy-config-collector-custom-http-proxy.yaml @@ -11,7 +11,7 @@ static_resources: - name: listener_cloud_support address: socket_address: - address: 0.0.0.0 + address: 127.0.0.1 port_value: REST_CLOUD_SUPPORT_PORT filter_chains: - filters: @@ -42,9 +42,15 @@ static_resources: - header: key: "appliance-id" value: APPLIANCE_ID + - header: + key: "component-sn" + value: COMPONENT_SN - header: key: "product-version" value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" route: host_rewrite_literal: REST_PROXY_URL cluster: cluster_cloud_support @@ -91,9 +97,15 @@ static_resources: - header: key: "appliance-id" value: APPLIANCE_ID + - header: + key: "component-sn" + value: COMPONENT_SN - header: key: "product-version" value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" clusters: - name: cluster_cloud_support type: STRICT_DNS diff --git a/deploy/ccm/envoy-config-collector-custom-https-proxy.yaml b/deploy/ccm/envoy-config-collector-custom-https-proxy.yaml new file mode 100644 index 000000000..965f8e3fd --- /dev/null +++ b/deploy/ccm/envoy-config-collector-custom-https-proxy.yaml @@ -0,0 +1,191 @@ +admin: + address: + socket_address: + address: 127.0.0.1 + port_value: 9901 +node: + id: "id_rest" + cluster: "cluster_rest" +static_resources: + listeners: + - name: listener_cloud_support + address: + socket_address: + address: 127.0.0.1 + port_value: REST_CLOUD_SUPPORT_PORT + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: + prefix: "/" + request_headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: APPLIANCE_ID + - header: + key: "component-sn" + value: COMPONENT_SN + - header: + key: "product-version" + value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" + route: + host_rewrite_literal: REST_PROXY_URL + cluster: cluster_cloud_support + - name: listener_cloud_support_tcp_proxy + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: CLOUD_SUPPORT_TCP_PROXY_PORT + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_tcp_proxy + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_cloud_support_tcp_proxy + - name: listener_customer_proxy_envoy_internal_redirect + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: CLOUD_SUPPORT_ENVOY_INTERNAL_REDIRECT_PORT + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_customer_proxy_envoy_internal_redirect + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_customer_proxy + tunneling_config: + hostname: REST_PROXY_URL:443 + headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: APPLIANCE_ID + - header: + key: "component-sn" + value: COMPONENT_SN + - header: + key: "product-version" + value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" + clusters: + - name: cluster_cloud_support + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_cloud_support + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: CLOUD_SUPPORT_ENVOY_INTERNAL_REDIRECT_PORT + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificate_sds_secret_configs: + name: tls_sds + sds_config: + path: /etc/envoy/tls_certificate_sds_secret.yaml + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: REST_PROXY_URL + - name: cluster_cloud_support_tcp_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_cloud_support_tcp_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: CLOUD_SUPPORT_ENVOY_INTERNAL_REDIRECT_PORT + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificate_sds_secret_configs: + name: tls_sds + sds_config: + path: /etc/envoy/tls_certificate_sds_secret.yaml + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: REST_PROXY_URL + - name: cluster_customer_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + # This ensures HTTP/1.1 CONNECT is used for establishing the tunnel. + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http_protocol_options: {} + load_assignment: + cluster_name: cluster_customer_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: CUSTOM_PROXY_ADDRESS + port_value: CUSTOM_PROXY_PORT + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: CUSTOM_PROXY_ADDRESS \ No newline at end of file diff --git a/deploy/ccm/envoy-config-register-custom-proxy.yaml b/deploy/ccm/envoy-config-register-custom-http-proxy.yaml similarity index 96% rename from deploy/ccm/envoy-config-register-custom-proxy.yaml rename to deploy/ccm/envoy-config-register-custom-http-proxy.yaml index 49dc9fcd4..b839a3881 100644 --- a/deploy/ccm/envoy-config-register-custom-proxy.yaml +++ b/deploy/ccm/envoy-config-register-custom-http-proxy.yaml @@ -48,6 +48,9 @@ static_resources: - header: key: "product-version" value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" route: host_rewrite_literal: REGISTER_PROXY_URL cluster: cluster_register_cloud_support @@ -100,6 +103,9 @@ static_resources: - header: key: "product-version" value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" clusters: - name: cluster_register_cloud_support type: STRICT_DNS diff --git a/deploy/ccm/envoy-config-register-custom-https-proxy.yaml b/deploy/ccm/envoy-config-register-custom-https-proxy.yaml new file mode 100644 index 000000000..005b2a4a9 --- /dev/null +++ b/deploy/ccm/envoy-config-register-custom-https-proxy.yaml @@ -0,0 +1,189 @@ +admin: + address: + socket_address: + address: 127.0.0.1 + port_value: 9901 +node: + id: "id_register" + cluster: "cluster_register" +static_resources: + listeners: + - name: listener_register_cloud_support + address: + socket_address: + address: 127.0.0.1 + port_value: REGISTER_CLOUD_SUPPORT_PORT + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: + prefix: "/" + request_headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: APPLIANCE_ID + - header: + key: "component-sn" + value: COMPONENT_SN + - header: + key: "product-version" + value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" + route: + host_rewrite_literal: REGISTER_PROXY_URL + cluster: cluster_register_cloud_support + - name: listener_register_cloud_support_tcp_proxy + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: CLOUD_SUPPORT_TCP_PROXY_PORT + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_register_tcp_proxy + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_register_cloud_support_tcp_proxy + - name: listener_register_customer_proxy_envoy_internal_redirect + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: CLOUD_SUPPORT_ENVOY_INTERNAL_REDIRECT_PORT + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_register_customer_proxy_envoy_internal_redirect + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_customer_proxy + tunneling_config: + hostname: REGISTER_PROXY_URL:443 + headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: APPLIANCE_ID + - header: + key: "component-sn" + value: COMPONENT_SN + - header: + key: "product-version" + value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" + clusters: + - name: cluster_register_cloud_support + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_register_cloud_support + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: CLOUD_SUPPORT_ENVOY_INTERNAL_REDIRECT_PORT + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificates: + - certificate_chain: + private_key: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: REGISTER_PROXY_URL + - name: cluster_register_cloud_support_tcp_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_register_cloud_support_tcp_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: CLOUD_SUPPORT_ENVOY_INTERNAL_REDIRECT_PORT + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificates: + - certificate_chain: + private_key: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: REGISTER_PROXY_URL + - name: cluster_customer_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + # This ensures HTTP/1.1 CONNECT is used for establishing the tunnel. + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http_protocol_options: {} + load_assignment: + cluster_name: cluster_customer_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: CUSTOM_PROXY_ADDRESS + port_value: CUSTOM_PROXY_PORT + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: CUSTOM_PROXY_ADDRESS \ No newline at end of file diff --git a/deploy/ccm/envoy-config-collector-custom-proxy.yaml b/deploy/ccm/envoy-config-rest-custom-http-proxy.yaml similarity index 97% rename from deploy/ccm/envoy-config-collector-custom-proxy.yaml rename to deploy/ccm/envoy-config-rest-custom-http-proxy.yaml index a39c02e42..78401a404 100644 --- a/deploy/ccm/envoy-config-collector-custom-proxy.yaml +++ b/deploy/ccm/envoy-config-rest-custom-http-proxy.yaml @@ -11,7 +11,7 @@ static_resources: - name: listener_cloud_support address: socket_address: - address: 127.0.0.1 + address: 0.0.0.0 port_value: REST_CLOUD_SUPPORT_PORT filter_chains: - filters: @@ -42,12 +42,12 @@ static_resources: - header: key: "appliance-id" value: APPLIANCE_ID - - header: - key: "component-sn" - value: COMPONENT_SN - header: key: "product-version" value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" route: host_rewrite_literal: REST_PROXY_URL cluster: cluster_cloud_support @@ -94,12 +94,12 @@ static_resources: - header: key: "appliance-id" value: APPLIANCE_ID - - header: - key: "component-sn" - value: COMPONENT_SN - header: key: "product-version" value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" clusters: - name: cluster_cloud_support type: STRICT_DNS diff --git a/deploy/ccm/envoy-config-rest-custom-https-proxy.yaml b/deploy/ccm/envoy-config-rest-custom-https-proxy.yaml new file mode 100644 index 000000000..59d5b5722 --- /dev/null +++ b/deploy/ccm/envoy-config-rest-custom-https-proxy.yaml @@ -0,0 +1,185 @@ +admin: + address: + socket_address: + address: 127.0.0.1 + port_value: 9901 +node: + id: "id_rest" + cluster: "cluster_rest" +static_resources: + listeners: + - name: listener_cloud_support + address: + socket_address: + address: 0.0.0.0 + port_value: REST_CLOUD_SUPPORT_PORT + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: + prefix: "/" + request_headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: APPLIANCE_ID + - header: + key: "product-version" + value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" + route: + host_rewrite_literal: REST_PROXY_URL + cluster: cluster_cloud_support + - name: listener_cloud_support_tcp_proxy + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: CLOUD_SUPPORT_TCP_PROXY_PORT + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_tcp_proxy + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_cloud_support_tcp_proxy + - name: listener_customer_proxy_envoy_internal_redirect + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: CLOUD_SUPPORT_ENVOY_INTERNAL_REDIRECT_PORT + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_customer_proxy_envoy_internal_redirect + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_customer_proxy + tunneling_config: + hostname: REST_PROXY_URL:443 + headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: APPLIANCE_ID + - header: + key: "product-version" + value: PRODUCT_VERSION + - header: + key: "proxy-authorization" + value: "BASIC_AUTH" + clusters: + - name: cluster_cloud_support + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_cloud_support + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: CLOUD_SUPPORT_ENVOY_INTERNAL_REDIRECT_PORT + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificate_sds_secret_configs: + name: tls_sds + sds_config: + path: /etc/envoy/tls_certificate_sds_secret.yaml + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: REST_PROXY_URL + - name: cluster_cloud_support_tcp_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_cloud_support_tcp_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: CLOUD_SUPPORT_ENVOY_INTERNAL_REDIRECT_PORT + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificate_sds_secret_configs: + name: tls_sds + sds_config: + path: /etc/envoy/tls_certificate_sds_secret.yaml + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: REST_PROXY_URL + - name: cluster_customer_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + # This ensures HTTP/1.1 CONNECT is used for establishing the tunnel. + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http_protocol_options: {} + load_assignment: + cluster_name: cluster_customer_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: CUSTOM_PROXY_ADDRESS + port_value: CUSTOM_PROXY_PORT + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: CUSTOM_PROXY_ADDRESS \ No newline at end of file diff --git a/drivers/storage/portworx/component/telemetry.go b/drivers/storage/portworx/component/telemetry.go index 86e2ff707..128a2312e 100644 --- a/drivers/storage/portworx/component/telemetry.go +++ b/drivers/storage/portworx/component/telemetry.go @@ -2,6 +2,7 @@ package component import ( "context" + cryptoTls "crypto/tls" "fmt" "io" "net/http" @@ -63,20 +64,24 @@ const ( // DeploymentNameTelemetryCollectorV2 is name of telemetry metrics collector DeploymentNameTelemetryCollectorV2 = "px-telemetry-metrics-collector" - roleFileNameTelemetry = "px-telemetry-role.yaml" - roleBindingFileNameTelemetry = "px-telemetry-role-binding.yaml" - configFileNameTelemetryRegister = "config_properties_px.yaml" - configFileNameTelemetryRegisterProxy = "envoy-config-register.yaml" - configFileNameTelemetryRegisterCustomProxy = "envoy-config-register-custom-proxy.yaml" - configFileNameTelemetryPhonehome = "ccm.properties" - configFileNameTelemetryPhonehomeProxy = "envoy-config-rest.yaml" - configFileNameTelemetryRestCustomProxy = "envoy-config-rest-custom-proxy.yaml" - configFileNameTelemetryCollectorProxy = "envoy-config-collector.yaml" - configFileNameTelemetryCollectorCustomProxy = "envoy-config-collector-custom-proxy.yaml" - configFileNameTelemetryTLSCertificate = "tls_certificate_sds_secret.yaml" - deploymentFileNameTelemetryRegistration = "registration-service.yaml" - deploymentFileNameTelemetryCollectorV2 = "metrics-collector-deployment.yaml" - daemonsetFileNameTelemetryPhonehome = "phonehome-cluster.yaml" + roleFileNameTelemetry = "px-telemetry-role.yaml" + roleBindingFileNameTelemetry = "px-telemetry-role-binding.yaml" + configFileNameTelemetryRegister = "config_properties_px.yaml" + configFileNameTelemetryRegisterProxy = "envoy-config-register.yaml" + configFileNameTelemetryRegisterCustomHttpProxy = "envoy-config-register-custom-http-proxy.yaml" + configFileNameTelemetryRegisterCustomHttpsProxy = "envoy-config-register-custom-https-proxy.yaml" + configFileNameTelemetryPhonehome = "ccm.properties" + configFileNameTelemetryPhonehomeProxy = "envoy-config-rest.yaml" + configFileNameTelemetryPhonehomeCustomHttpProxy = "envoy-config-rest-custom-http-proxy.yaml" + configFileNameTelemetryPhonehomeCustomHttpsProxy = "envoy-config-rest-custom-https-proxy.yaml" + configFileNameTelemetryCollectorProxy = "envoy-config-collector.yaml" + configFileNameTelemetryCollectorCustomHttpProxy = "envoy-config-collector-custom-http-proxy.yaml" + configFileNameTelemetryCollectorCustomHttpsProxy = "envoy-config-collector-custom-https-proxy.yaml" + configFileNameTelemetryTLSCertificate = "tls_certificate_sds_secret.yaml" + configFileNameTelemetryCustomProxyTLS = "envoy-config-custom-proxy-tls.yaml" + deploymentFileNameTelemetryRegistration = "registration-service.yaml" + deploymentFileNameTelemetryCollectorV2 = "metrics-collector-deployment.yaml" + daemonsetFileNameTelemetryPhonehome = "phonehome-cluster.yaml" configParameterApplianceID = "APPLIANCE_ID" configParameterComponentSN = "COMPONENT_SN" @@ -86,6 +91,7 @@ const ( configParameterCertSecretNamespace = "CERT_SECRET_NAMESPACE" configParameterCustomProxyAddress = "CUSTOM_PROXY_ADDRESS" configParameterCustomProxyPort = "CUSTOM_PROXY_PORT" + configParameterCustomProxyBasicAuth = "BASIC_AUTH" configParameterPortworxPort = "PORTWORX_PORT" configParameterRegisterCloudSupportPort = "REGISTER_CLOUD_SUPPORT_PORT" configParameterRestCloudSupportPort = "REST_CLOUD_SUPPORT_PORT" @@ -603,16 +609,22 @@ func (t *telemetry) createCCMGoConfigMapRegisterProxy( _, proxy := pxutil.GetPxProxyEnvVarValue(cluster) if proxy != "" && t.usePxProxy { - address, port, err := pxutil.SplitPxProxyHostPort(proxy) + host, port, authHeader, err := pxutil.ParsePxProxyURL(proxy) if err != nil { logrus.Errorf("failed to get custom proxy address and port from proxy %s: %v", proxy, err) return k8sutil.DeleteConfigMap(t.k8sClient, ConfigMapNameTelemetryRegisterProxy, cluster.Namespace, *ownerRef) } - configFileName = configFileNameTelemetryRegisterCustomProxy replaceMap[configParameterCloudSupportTCPProxyPort] = fmt.Sprint(tcpProxyPort) replaceMap[configParameterCloudSupportEnvoyInternalRedirectPort] = fmt.Sprint(envoyRedirectPort) - replaceMap[configParameterCustomProxyAddress] = address + replaceMap[configParameterCustomProxyAddress] = host replaceMap[configParameterCustomProxyPort] = port + replaceMap[configParameterCustomProxyBasicAuth] = authHeader + + if authHeader == "" { + configFileName = configFileNameTelemetryRegisterCustomHttpProxy + } else { + configFileName = configFileNameTelemetryRegisterCustomHttpsProxy + } } config, err := readConfigMapDataFromFile(configFileName, replaceMap) @@ -652,16 +664,23 @@ func (t *telemetry) createCCMGoConfigMapTelemetryPhonehomeProxy( _, proxy := pxutil.GetPxProxyEnvVarValue(cluster) if proxy != "" && t.usePxProxy { - address, port, err := pxutil.SplitPxProxyHostPort(proxy) + host, port, authHeader, err := pxutil.ParsePxProxyURL(proxy) if err != nil { logrus.Errorf("failed to get custom proxy address and port from %s: %v", proxy, err) return k8sutil.DeleteConfigMap(t.k8sClient, ConfigMapNameTelemetryPhonehomeProxy, cluster.Namespace, *ownerRef) } - configFileName = configFileNameTelemetryRestCustomProxy + replaceMap[configParameterCloudSupportTCPProxyPort] = fmt.Sprint(tcpProxyPort) replaceMap[configParameterCloudSupportEnvoyInternalRedirectPort] = fmt.Sprint(envoyRedirectPort) - replaceMap[configParameterCustomProxyAddress] = address + replaceMap[configParameterCustomProxyAddress] = host replaceMap[configParameterCustomProxyPort] = port + replaceMap[configParameterCustomProxyBasicAuth] = authHeader + + if authHeader == "" { + configFileName = configFileNameTelemetryPhonehomeCustomHttpProxy + } else { + configFileName = configFileNameTelemetryPhonehomeCustomHttpsProxy + } } config, err := readConfigMapDataFromFile(configFileName, replaceMap) @@ -703,16 +722,23 @@ func (t *telemetry) createCCMGoConfigMapCollectorProxyV2( _, proxy := pxutil.GetPxProxyEnvVarValue(cluster) if proxy != "" && t.usePxProxy { - address, port, err := pxutil.SplitPxProxyHostPort(proxy) + host, port, authHeader, err := pxutil.ParsePxProxyURL(proxy) if err != nil { logrus.Errorf("failed to get custom proxy address and port from %s: %v", proxy, err) return k8sutil.DeleteConfigMap(t.k8sClient, ConfigMapNameTelemetryCollectorProxyV2, cluster.Namespace, *ownerRef) } - configFileName = configFileNameTelemetryCollectorCustomProxy + replaceMap[configParameterCloudSupportTCPProxyPort] = fmt.Sprint(tcpProxyPort) replaceMap[configParameterCloudSupportEnvoyInternalRedirectPort] = fmt.Sprint(envoyRedirectPort) - replaceMap[configParameterCustomProxyAddress] = address + replaceMap[configParameterCustomProxyAddress] = host replaceMap[configParameterCustomProxyPort] = port + replaceMap[configParameterCustomProxyBasicAuth] = authHeader + + if authHeader == "" { + configFileName = configFileNameTelemetryCollectorCustomHttpProxy + } else { + configFileName = configFileNameTelemetryCollectorCustomHttpsProxy + } } config, err := readConfigMapDataFromFile(configFileName, replaceMap) @@ -1009,7 +1035,7 @@ func getArcusRegisterProxyURL(cluster *corev1.StorageCluster) string { // return false after failing 5 times in a row func CanAccessArcusRegisterEndpoint( cluster *corev1.StorageCluster, - httpProxy string, + proxy string, ) bool { endpoint := getArcusRegisterProxyURL(cluster) logrus.Debugf("checking whether telemetry registration endpoint %s is accessible on cluster %s", @@ -1028,17 +1054,24 @@ func CanAccessArcusRegisterEndpoint( }, } client := &http.Client{} - if httpProxy != "" { - if !strings.HasPrefix(strings.ToLower(httpProxy), "http://") { - httpProxy = "http://" + httpProxy + if proxy != "" { + if strings.Contains(strings.ToLower(proxy), "@") { + if !strings.HasPrefix(strings.ToLower(proxy), "https://") { + proxy = "https://" + proxy + } + } else { + if !strings.HasPrefix(strings.ToLower(proxy), "http://") { + proxy = "http://" + proxy + } } - proxyURL, err := url.Parse(httpProxy) + proxyURL, err := url.Parse(proxy) if err != nil { - logrus.WithError(err).Errorf("failed to parse http proxy %s for checking Pure1 connectivity", httpProxy) + logrus.WithError(err).Errorf("failed to parse http proxy %s for checking Pure1 connectivity", proxy) return false } client.Transport = &http.Transport{ - Proxy: http.ProxyURL(proxyURL), + Proxy: http.ProxyURL(proxyURL), + TLSClientConfig: &cryptoTls.Config{InsecureSkipVerify: true}, } } for i := 1; i <= arcusPingRetry; i++ { diff --git a/drivers/storage/portworx/components_test.go b/drivers/storage/portworx/components_test.go index 72d6176cd..ec15495c5 100644 --- a/drivers/storage/portworx/components_test.go +++ b/drivers/storage/portworx/components_test.go @@ -12847,7 +12847,7 @@ func TestValidateTelemetryEnabled(t *testing.T) { require.Nil(t, cluster.Spec.Monitoring) require.Len(t, recorder.Events, 0) - // TestCase: telemetry should be disabled if using secure proxy on ccm-go + // TestCase: telemetry should be disabled if using secure proxy but with invalid http proxy format cluster.Spec.Image = "portworx/oci-monitor:2.12.0" cluster.Spec.Monitoring = &corev1.MonitoringSpec{ Telemetry: &corev1.TelemetrySpec{ @@ -12865,7 +12865,7 @@ func TestValidateTelemetryEnabled(t *testing.T) { require.False(t, cluster.Spec.Monitoring.Telemetry.Enabled) require.Len(t, recorder.Events, 1) require.Contains(t, <-recorder.Events, - fmt.Sprintf("%v %v telemetry will be disabled: telemetry is not supported with secure proxy", + fmt.Sprintf("%v %v telemetry will be disabled: telemetry is not supported with proxy in a format of", v1.EventTypeWarning, util.TelemetryDisabledReason)) // TestCase: telemetry should be disabled if using invalid http proxy format @@ -13311,7 +13311,7 @@ func TestTelemetryCCMGoUpgrade(t *testing.T) { validateCCMGoComponents() } -func TestTelemetryCCMGoProxy(t *testing.T) { +func TestTelemetryCCMGoHTTPProxy(t *testing.T) { coreops.SetInstance(coreops.New(fakek8sclient.NewSimpleClientset())) reregisterComponents() k8sClient := testutil.FakeK8sClient() @@ -13402,7 +13402,7 @@ func TestTelemetryCCMGoProxy(t *testing.T) { err = driver.PreInstall(cluster) require.NoError(t, err) - expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoRegisterProxyConfigMap_proxy.yaml") + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoRegisterProxyConfigMap_httpproxy.yaml") configMap = &v1.ConfigMap{} err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryRegisterProxy, cluster.Namespace) require.NoError(t, err) @@ -13412,7 +13412,7 @@ func TestTelemetryCCMGoProxy(t *testing.T) { require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) require.Equal(t, expectedConfigMap.Data, configMap.Data) - expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoPhonehomeProxyConfigMap_proxy.yaml") + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoPhonehomeProxyConfigMap_httpproxy.yaml") configMap = &v1.ConfigMap{} err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryPhonehomeProxy, cluster.Namespace) require.NoError(t, err) @@ -13422,7 +13422,7 @@ func TestTelemetryCCMGoProxy(t *testing.T) { require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) require.Equal(t, expectedConfigMap.Data, configMap.Data) - expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoCollectorProxyConfigMap_proxy.yaml") + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoCollectorProxyConfigMap_httpproxy.yaml") configMap = &v1.ConfigMap{} err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryCollectorProxyV2, cluster.Namespace) require.NoError(t, err) @@ -13654,6 +13654,181 @@ func TestTelemetryMetricsCollectorDisabledByDefault(t *testing.T) { require.True(t, errors.IsNotFound(err)) } +func TestTelemetryCCMGoHTTPSProxy(t *testing.T) { + coreops.SetInstance(coreops.New(fakek8sclient.NewSimpleClientset())) + reregisterComponents() + k8sClient := testutil.FakeK8sClient() + driver := portworx{} + err := driver.Init(k8sClient, runtime.NewScheme(), record.NewFakeRecorder(0)) + require.NoError(t, err) + startPort := uint32(10001) + + cluster := &corev1.StorageCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "px-cluster", + Namespace: "kube-test", + }, + Spec: corev1.StorageClusterSpec{ + Image: "portworx/oci-monitor:2.12.0", + Monitoring: &corev1.MonitoringSpec{ + Telemetry: &corev1.TelemetrySpec{ + Enabled: true, + }, + }, + StartPort: &startPort, + }, + Status: corev1.StorageClusterStatus{ + ClusterUID: "test-clusteruid", + }, + } + createTelemetrySecret(t, k8sClient, cluster.Namespace) + + // PWX-27401 reconcile collector to validate specs + err = k8sClient.Create( + context.TODO(), + &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: component.DeploymentNameTelemetryCollectorV2, + Namespace: cluster.Namespace, + }, + }, + &client.CreateOptions{}, + ) + require.NoError(t, err) + + err = driver.SetDefaultsOnStorageCluster(cluster) + require.NoError(t, err) + + // TestCase: no px proxy specified + err = driver.PreInstall(cluster) + require.NoError(t, err) + + // Validate component proxy config map content + expectedConfigMap := testutil.GetExpectedConfigMap(t, "ccmGoRegisterProxyConfigMap.yaml") + configMap := &v1.ConfigMap{} + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryRegisterProxy, cluster.Namespace) + require.NoError(t, err) + require.Equal(t, expectedConfigMap.Name, configMap.Name) + require.Equal(t, expectedConfigMap.Namespace, configMap.Namespace) + require.Len(t, configMap.OwnerReferences, 1) + require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) + require.Equal(t, expectedConfigMap.Data, configMap.Data) + + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoPhonehomeProxyConfigMap.yaml") + configMap = &v1.ConfigMap{} + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryPhonehomeProxy, cluster.Namespace) + require.NoError(t, err) + require.Equal(t, expectedConfigMap.Name, configMap.Name) + require.Equal(t, expectedConfigMap.Namespace, configMap.Namespace) + require.Len(t, configMap.OwnerReferences, 1) + require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) + require.Equal(t, expectedConfigMap.Data, configMap.Data) + + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoCollectorProxyConfigMap.yaml") + configMap = &v1.ConfigMap{} + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryCollectorProxyV2, cluster.Namespace) + require.NoError(t, err) + require.Equal(t, expectedConfigMap.Name, configMap.Name) + require.Equal(t, expectedConfigMap.Namespace, configMap.Namespace) + require.Len(t, configMap.OwnerReferences, 1) + require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) + require.Equal(t, expectedConfigMap.Data, configMap.Data) + + // Add PX_HTTPS_PROXY environment variable and config maps should be updated + cluster.Spec.Env = []v1.EnvVar{ + { + Name: pxutil.EnvKeyPortworxHTTPSProxy, + Value: "https://user:password@hostname:1234", + }, + } + + err = driver.PreInstall(cluster) + require.NoError(t, err) + + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoRegisterProxyConfigMap_httpsproxy.yaml") + configMap = &v1.ConfigMap{} + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryRegisterProxy, cluster.Namespace) + require.NoError(t, err) + require.Equal(t, expectedConfigMap.Name, configMap.Name) + require.Equal(t, expectedConfigMap.Namespace, configMap.Namespace) + require.Len(t, configMap.OwnerReferences, 1) + require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) + require.Equal(t, expectedConfigMap.Data, configMap.Data) + + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoPhonehomeProxyConfigMap_httpsproxy.yaml") + configMap = &v1.ConfigMap{} + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryPhonehomeProxy, cluster.Namespace) + require.NoError(t, err) + require.Equal(t, expectedConfigMap.Name, configMap.Name) + require.Equal(t, expectedConfigMap.Namespace, configMap.Namespace) + require.Len(t, configMap.OwnerReferences, 1) + require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) + require.Equal(t, expectedConfigMap.Data, configMap.Data) + + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoCollectorProxyConfigMap_httpsproxy.yaml") + configMap = &v1.ConfigMap{} + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryCollectorProxyV2, cluster.Namespace) + require.NoError(t, err) + require.Equal(t, expectedConfigMap.Name, configMap.Name) + require.Equal(t, expectedConfigMap.Namespace, configMap.Namespace) + require.Len(t, configMap.OwnerReferences, 1) + require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) + require.Equal(t, expectedConfigMap.Data, configMap.Data) + + // Remove PX_HTTPS_PROXY environment variable and config maps should be updated + cluster.Spec.Env = []v1.EnvVar{} + + err = driver.PreInstall(cluster) + require.NoError(t, err) + + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoRegisterProxyConfigMap.yaml") + configMap = &v1.ConfigMap{} + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryRegisterProxy, cluster.Namespace) + require.NoError(t, err) + require.Equal(t, expectedConfigMap.Name, configMap.Name) + require.Equal(t, expectedConfigMap.Namespace, configMap.Namespace) + require.Len(t, configMap.OwnerReferences, 1) + require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) + require.Equal(t, expectedConfigMap.Data, configMap.Data) + + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoPhonehomeProxyConfigMap.yaml") + configMap = &v1.ConfigMap{} + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryPhonehomeProxy, cluster.Namespace) + require.NoError(t, err) + require.Equal(t, expectedConfigMap.Name, configMap.Name) + require.Equal(t, expectedConfigMap.Namespace, configMap.Namespace) + require.Len(t, configMap.OwnerReferences, 1) + require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) + require.Equal(t, expectedConfigMap.Data, configMap.Data) + + expectedConfigMap = testutil.GetExpectedConfigMap(t, "ccmGoCollectorProxyConfigMap.yaml") + configMap = &v1.ConfigMap{} + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryCollectorProxyV2, cluster.Namespace) + require.NoError(t, err) + require.Equal(t, expectedConfigMap.Name, configMap.Name) + require.Equal(t, expectedConfigMap.Namespace, configMap.Namespace) + require.Len(t, configMap.OwnerReferences, 1) + require.Equal(t, cluster.Name, configMap.OwnerReferences[0].Name) + require.Equal(t, expectedConfigMap.Data, configMap.Data) + + // When using invalid proxy format configmaps will be deleted + cluster.Spec.Env = []v1.EnvVar{ + { + Name: pxutil.EnvKeyPortworxHTTPSProxy, + Value: "https://user:password@hostnameonly", + }, + } + + err = driver.PreInstall(cluster) + require.NoError(t, err) + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryRegisterProxy, cluster.Namespace) + require.True(t, errors.IsNotFound(err)) + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryPhonehomeProxy, cluster.Namespace) + require.True(t, errors.IsNotFound(err)) + err = testutil.Get(k8sClient, configMap, component.ConfigMapNameTelemetryCollectorProxyV2, cluster.Namespace) + require.True(t, errors.IsNotFound(err)) +} + func TestTelemetrySecretDeletion(t *testing.T) { coreops.SetInstance(coreops.New(fakek8sclient.NewSimpleClientset())) reregisterComponents() diff --git a/drivers/storage/portworx/portworx.go b/drivers/storage/portworx/portworx.go index 418c2d12d..3c969b6fb 100644 --- a/drivers/storage/portworx/portworx.go +++ b/drivers/storage/portworx/portworx.go @@ -1127,10 +1127,9 @@ func setDefaultAutopilotProviders( // setTelemetryDefaults validates and sets telemetry values // Telemetry will be disabled if: // 1. It's disabled explicitly -// 2. HTTPS proxy is configured -// 3. HTTP proxy url is not in a format of hostname:port -// 4. PX version incompatible -// 5. Cannot ping Arcus endpoint when first time enabled (telemetry cert is not created yet) +// 2. HTTP/HTTPS proxy url is not in a format of hostname:port +// 3. PX version incompatible +// 4. Cannot ping Arcus endpoint when first time enabled (telemetry cert is not created yet) // Otherwise it will be enabled by default func (p *portworx) setTelemetryDefaults( toUpdate *corev1.StorageCluster, @@ -1153,15 +1152,11 @@ func (p *portworx) setTelemetryDefaults( } else if !pxutil.IsCCMGoSupported(pxVersion) { // CCM Java case, PX version is between 2.8 and 2.12, don't set any default values return nil - } else if proxyType == pxutil.EnvKeyPortworxHTTPProxy { - // CCM Go is supported, but HTTP proxy cannot be split into host and port - if _, _, proxyFormatErr := pxutil.SplitPxProxyHostPort(proxy); proxyFormatErr != nil { + } else if proxyType == pxutil.EnvKeyPortworxHTTPProxy || proxyType == pxutil.EnvKeyPortworxHTTPSProxy { + // CCM Go is supported, but HTTP/HTTPS proxy cannot be split into host and port + if _, _, _, proxyFormatErr := pxutil.ParsePxProxyURL(proxy); proxyFormatErr != nil { err = fmt.Errorf("telemetry is not supported with proxy in a format of: %s", proxy) } - } else if proxyType == pxutil.EnvKeyPortworxHTTPSProxy { - // CCM Go is not supported with https proxy - // TODO: remove when HTTPS proxy is supported - err = fmt.Errorf("telemetry is not supported with secure proxy: %s", proxy) } if toUpdate.Spec.Monitoring == nil { toUpdate.Spec.Monitoring = &corev1.MonitoringSpec{} diff --git a/drivers/storage/portworx/testspec/ccmGoCollectorProxyConfigMap_proxy.yaml b/drivers/storage/portworx/testspec/ccmGoCollectorProxyConfigMap_httpproxy.yaml similarity index 97% rename from drivers/storage/portworx/testspec/ccmGoCollectorProxyConfigMap_proxy.yaml rename to drivers/storage/portworx/testspec/ccmGoCollectorProxyConfigMap_httpproxy.yaml index f9ede32d2..87609a47c 100644 --- a/drivers/storage/portworx/testspec/ccmGoCollectorProxyConfigMap_proxy.yaml +++ b/drivers/storage/portworx/testspec/ccmGoCollectorProxyConfigMap_httpproxy.yaml @@ -60,6 +60,9 @@ data: - header: key: "product-version" value: 2.12.0 + - header: + key: "proxy-authorization" + value: "" route: host_rewrite_literal: rest.cloud-support.purestorage.com cluster: cluster_cloud_support @@ -112,6 +115,9 @@ data: - header: key: "product-version" value: 2.12.0 + - header: + key: "proxy-authorization" + value: "" clusters: - name: cluster_cloud_support type: STRICT_DNS diff --git a/drivers/storage/portworx/testspec/ccmGoCollectorProxyConfigMap_httpsproxy.yaml b/drivers/storage/portworx/testspec/ccmGoCollectorProxyConfigMap_httpsproxy.yaml new file mode 100644 index 000000000..135d6d78e --- /dev/null +++ b/drivers/storage/portworx/testspec/ccmGoCollectorProxyConfigMap_httpsproxy.yaml @@ -0,0 +1,203 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: px-telemetry-collector-proxy + namespace: kube-test + ownerReferences: + - apiVersion: core.libopenstorage.org/v1 + blockOwnerDeletion: true + controller: true + kind: StorageCluster +data: + envoy-config.yaml: |- + admin: + address: + socket_address: + address: 127.0.0.1 + port_value: 9901 + node: + id: "id_rest" + cluster: "cluster_rest" + static_resources: + listeners: + - name: listener_cloud_support + address: + socket_address: + address: 127.0.0.1 + port_value: 11000 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: + prefix: "/" + request_headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: test-clusteruid + - header: + key: "component-sn" + value: portworx-metrics-node + - header: + key: "product-version" + value: 2.12.0 + - header: + key: "proxy-authorization" + value: "Basic dXNlcjpwYXNzd29yZA==" + route: + host_rewrite_literal: rest.cloud-support.purestorage.com + cluster: cluster_cloud_support + - name: listener_cloud_support_tcp_proxy + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: 11002 + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_tcp_proxy + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_cloud_support_tcp_proxy + - name: listener_customer_proxy_envoy_internal_redirect + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: 11004 + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_customer_proxy_envoy_internal_redirect + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_customer_proxy + tunneling_config: + hostname: rest.cloud-support.purestorage.com:443 + headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: test-clusteruid + - header: + key: "component-sn" + value: portworx-metrics-node + - header: + key: "product-version" + value: 2.12.0 + - header: + key: "proxy-authorization" + value: "Basic dXNlcjpwYXNzd29yZA==" + clusters: + - name: cluster_cloud_support + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_cloud_support + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: 11004 + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificate_sds_secret_configs: + name: tls_sds + sds_config: + path: /etc/envoy/tls_certificate_sds_secret.yaml + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: rest.cloud-support.purestorage.com + - name: cluster_cloud_support_tcp_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_cloud_support_tcp_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: 11004 + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificate_sds_secret_configs: + name: tls_sds + sds_config: + path: /etc/envoy/tls_certificate_sds_secret.yaml + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: rest.cloud-support.purestorage.com + - name: cluster_customer_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + # This ensures HTTP/1.1 CONNECT is used for establishing the tunnel. + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http_protocol_options: {} + load_assignment: + cluster_name: cluster_customer_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: hostname + port_value: 1234 + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: hostname diff --git a/drivers/storage/portworx/testspec/ccmGoPhonehomeProxyConfigMap_proxy.yaml b/drivers/storage/portworx/testspec/ccmGoPhonehomeProxyConfigMap_httpproxy.yaml similarity index 96% rename from drivers/storage/portworx/testspec/ccmGoPhonehomeProxyConfigMap_proxy.yaml rename to drivers/storage/portworx/testspec/ccmGoPhonehomeProxyConfigMap_httpproxy.yaml index f1f9e6398..af81c00fc 100644 --- a/drivers/storage/portworx/testspec/ccmGoPhonehomeProxyConfigMap_proxy.yaml +++ b/drivers/storage/portworx/testspec/ccmGoPhonehomeProxyConfigMap_httpproxy.yaml @@ -57,6 +57,9 @@ data: - header: key: "product-version" value: 2.12.0 + - header: + key: "proxy-authorization" + value: "" route: host_rewrite_literal: rest.cloud-support.purestorage.com cluster: cluster_cloud_support @@ -106,6 +109,9 @@ data: - header: key: "product-version" value: 2.12.0 + - header: + key: "proxy-authorization" + value: "" clusters: - name: cluster_cloud_support type: STRICT_DNS diff --git a/drivers/storage/portworx/testspec/ccmGoPhonehomeProxyConfigMap_httpsproxy.yaml b/drivers/storage/portworx/testspec/ccmGoPhonehomeProxyConfigMap_httpsproxy.yaml new file mode 100644 index 000000000..3487e5f1f --- /dev/null +++ b/drivers/storage/portworx/testspec/ccmGoPhonehomeProxyConfigMap_httpsproxy.yaml @@ -0,0 +1,197 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: px-telemetry-phonehome-proxy + namespace: kube-test + ownerReferences: + - apiVersion: core.libopenstorage.org/v1 + blockOwnerDeletion: true + controller: true + kind: StorageCluster +data: + envoy-config-rest.yaml: |- + admin: + address: + socket_address: + address: 127.0.0.1 + port_value: 9901 + node: + id: "id_rest" + cluster: "cluster_rest" + static_resources: + listeners: + - name: listener_cloud_support + address: + socket_address: + address: 0.0.0.0 + port_value: 13002 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: + prefix: "/" + request_headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: test-clusteruid + - header: + key: "product-version" + value: 2.12.0 + - header: + key: "proxy-authorization" + value: "Basic dXNlcjpwYXNzd29yZA==" + route: + host_rewrite_literal: rest.cloud-support.purestorage.com + cluster: cluster_cloud_support + - name: listener_cloud_support_tcp_proxy + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: 13004 + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_tcp_proxy + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_cloud_support_tcp_proxy + - name: listener_customer_proxy_envoy_internal_redirect + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: 13006 + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_customer_proxy_envoy_internal_redirect + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_customer_proxy + tunneling_config: + hostname: rest.cloud-support.purestorage.com:443 + headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: test-clusteruid + - header: + key: "product-version" + value: 2.12.0 + - header: + key: "proxy-authorization" + value: "Basic dXNlcjpwYXNzd29yZA==" + clusters: + - name: cluster_cloud_support + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_cloud_support + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: 13006 + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificate_sds_secret_configs: + name: tls_sds + sds_config: + path: /etc/envoy/tls_certificate_sds_secret.yaml + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: rest.cloud-support.purestorage.com + - name: cluster_cloud_support_tcp_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_cloud_support_tcp_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: 13006 + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificate_sds_secret_configs: + name: tls_sds + sds_config: + path: /etc/envoy/tls_certificate_sds_secret.yaml + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: rest.cloud-support.purestorage.com + - name: cluster_customer_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + # This ensures HTTP/1.1 CONNECT is used for establishing the tunnel. + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http_protocol_options: {} + load_assignment: + cluster_name: cluster_customer_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: hostname + port_value: 1234 + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: hostname diff --git a/drivers/storage/portworx/testspec/ccmGoRegisterProxyConfigMap_proxy.yaml b/drivers/storage/portworx/testspec/ccmGoRegisterProxyConfigMap_httpproxy.yaml similarity index 97% rename from drivers/storage/portworx/testspec/ccmGoRegisterProxyConfigMap_proxy.yaml rename to drivers/storage/portworx/testspec/ccmGoRegisterProxyConfigMap_httpproxy.yaml index 537324f93..2966f436e 100644 --- a/drivers/storage/portworx/testspec/ccmGoRegisterProxyConfigMap_proxy.yaml +++ b/drivers/storage/portworx/testspec/ccmGoRegisterProxyConfigMap_httpproxy.yaml @@ -60,6 +60,9 @@ data: - header: key: "product-version" value: 2.12.0 + - header: + key: "proxy-authorization" + value: "" route: host_rewrite_literal: register.cloud-support.purestorage.com cluster: cluster_register_cloud_support @@ -112,6 +115,9 @@ data: - header: key: "product-version" value: 2.12.0 + - header: + key: "proxy-authorization" + value: "" clusters: - name: cluster_register_cloud_support type: STRICT_DNS diff --git a/drivers/storage/portworx/testspec/ccmGoRegisterProxyConfigMap_httpsproxy.yaml b/drivers/storage/portworx/testspec/ccmGoRegisterProxyConfigMap_httpsproxy.yaml new file mode 100644 index 000000000..48fb18d3b --- /dev/null +++ b/drivers/storage/portworx/testspec/ccmGoRegisterProxyConfigMap_httpsproxy.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: px-telemetry-register-proxy + namespace: kube-test + ownerReferences: + - apiVersion: core.libopenstorage.org/v1 + blockOwnerDeletion: true + controller: true + kind: StorageCluster +data: + envoy-config-register.yaml: |- + admin: + address: + socket_address: + address: 127.0.0.1 + port_value: 9901 + node: + id: "id_register" + cluster: "cluster_register" + static_resources: + listeners: + - name: listener_register_cloud_support + address: + socket_address: + address: 127.0.0.1 + port_value: 13001 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: ["*"] + routes: + - match: + prefix: "/" + request_headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: test-clusteruid + - header: + key: "component-sn" + value: px-cluster + - header: + key: "product-version" + value: 2.12.0 + - header: + key: "proxy-authorization" + value: "Basic dXNlcjpwYXNzd29yZA==" + route: + host_rewrite_literal: register.cloud-support.purestorage.com + cluster: cluster_register_cloud_support + - name: listener_register_cloud_support_tcp_proxy + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: 13003 + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_register_tcp_proxy + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_register_cloud_support_tcp_proxy + - name: listener_register_customer_proxy_envoy_internal_redirect + address: + socket_address: + protocol: TCP + address: 127.0.0.1 + port_value: 13005 + filter_chains: + - filters: + - name: envoy.filters.network.tcp_proxy + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + stat_prefix: ingress_register_customer_proxy_envoy_internal_redirect + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + cluster: cluster_customer_proxy + tunneling_config: + hostname: register.cloud-support.purestorage.com:443 + headers_to_add: + - header: + key: "product-name" + value: "portworx" + - header: + key: "appliance-id" + value: test-clusteruid + - header: + key: "component-sn" + value: px-cluster + - header: + key: "product-version" + value: 2.12.0 + - header: + key: "proxy-authorization" + value: "Basic dXNlcjpwYXNzd29yZA==" + clusters: + - name: cluster_register_cloud_support + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_register_cloud_support + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: 13005 + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificates: + - certificate_chain: + private_key: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: register.cloud-support.purestorage.com + - name: cluster_register_cloud_support_tcp_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: cluster_register_cloud_support_tcp_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: localhost + port_value: 13005 + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_certificates: + - certificate_chain: + private_key: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt + match_typed_subject_alt_names: + - san_type: DNS + matcher: + exact: register.cloud-support.purestorage.com + - name: cluster_customer_proxy + type: STRICT_DNS + dns_lookup_family: V4_ONLY + lb_policy: ROUND_ROBIN + # This ensures HTTP/1.1 CONNECT is used for establishing the tunnel. + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http_protocol_options: {} + load_assignment: + cluster_name: cluster_customer_proxy + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: hostname + port_value: 1234 + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: hostname diff --git a/drivers/storage/portworx/util/util.go b/drivers/storage/portworx/util/util.go index e758e63ed..957cd943e 100644 --- a/drivers/storage/portworx/util/util.go +++ b/drivers/storage/portworx/util/util.go @@ -8,6 +8,7 @@ import ( "fmt" "math" "net" + "net/url" "os" "regexp" "strconv" @@ -234,6 +235,10 @@ const ( // TelemetryCertName is name of the telemetry cert. TelemetryCertName = "pure-telemetry-certs" + // HttpProtocolPrefix is the prefix for HTTP protocol + HttpProtocolPrefix = "http://" + // HttpsProtocolPrefix is the prefix for HTTPS protocol + HttpsProtocolPrefix = "https://" ) var ( @@ -651,17 +656,39 @@ func GetPxProxyEnvVarValue(cluster *corev1.StorageCluster) (string, string) { return "", "" } -// SplitPxProxyHostPort trims protocol prefix then splits the proxy address of the form "host:port" -func SplitPxProxyHostPort(proxy string) (string, string, error) { - proxy = strings.TrimPrefix(proxy, "http://") - proxy = strings.TrimPrefix(proxy, "https://") - address, port, err := net.SplitHostPort(proxy) - if err != nil { - return "", "", err - } else if address == "" || port == "" { - return "", "", fmt.Errorf("failed to split px proxy address %s", proxy) +var ( + authHeader string +) + +// ParsePxProxy trims protocol prefix then splits the proxy address of the form "host:port" with possible basic authentication credential +func ParsePxProxyURL(proxy string) (string, string, string, error) { + if strings.HasPrefix(proxy, HttpsProtocolPrefix) && strings.Contains(proxy, "@") { + proxyUrl, err := url.Parse(proxy) + if err != nil { + return "", "", "", fmt.Errorf("failed to parse px proxy url %s", proxy) + } + username := proxyUrl.User.Username() + password, _ := proxyUrl.User.Password() + encodedAuth := base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) + authHeader = fmt.Sprintf("Basic %s", encodedAuth) + host, port, err := net.SplitHostPort(proxyUrl.Host) + if err != nil { + return "", "", "", err + } else if host == "" || port == "" || encodedAuth == "" { + return "", "", "", fmt.Errorf("failed to split px proxy to get host and port %s", proxy) + } + return host, port, authHeader, nil + } else { + proxy = strings.TrimPrefix(proxy, HttpProtocolPrefix) + proxy = strings.TrimPrefix(proxy, HttpsProtocolPrefix) // treat https proxy as http proxy if no credential provided + host, port, err := net.SplitHostPort(proxy) + if err != nil { + return "", "", "", err + } else if host == "" || port == "" { + return "", "", "", fmt.Errorf("failed to split px proxy to get host and port %s", proxy) + } + return host, port, authHeader, nil } - return address, port, nil } // GetValueFromEnvVar returns the value of v1.EnvVar Value or ValueFrom diff --git a/drivers/storage/portworx/util/util_test.go b/drivers/storage/portworx/util/util_test.go index f4a9489d8..282544b00 100644 --- a/drivers/storage/portworx/util/util_test.go +++ b/drivers/storage/portworx/util/util_test.go @@ -77,45 +77,68 @@ func TestGetServiceTypeFromAnnotation(t *testing.T) { require.Equal(t, v1.ServiceType(""), ServiceType(cluster, "other-services")) } -func TestSplitPxProxyHostPort(t *testing.T) { +func TestParsePxProxyURL(t *testing.T) { // Valid cases - address, port, err := SplitPxProxyHostPort("http.proxy.address:1234") + host, port, authHeader, err := ParsePxProxyURL("http.proxy.address:1234") require.NoError(t, err) - require.Equal(t, "http.proxy.address", address) + require.Equal(t, "http.proxy.address", host) require.Equal(t, "1234", port) + require.Equal(t, "", authHeader) - address, port, err = SplitPxProxyHostPort("http://http.proxy.address:1234") + host, port, authHeader, err = ParsePxProxyURL("http://http.proxy.address:1234") require.NoError(t, err) - require.Equal(t, "http.proxy.address", address) + require.Equal(t, "http.proxy.address", host) require.Equal(t, "1234", port) + require.Equal(t, "", authHeader) - address, port, err = SplitPxProxyHostPort("1.2.3.4:1234") + host, port, authHeader, err = ParsePxProxyURL("https://http.proxy.address:1234") require.NoError(t, err) - require.Equal(t, "1.2.3.4", address) + require.Equal(t, "http.proxy.address", host) require.Equal(t, "1234", port) + require.Equal(t, "", authHeader) - address, port, err = SplitPxProxyHostPort("[1:2:3:4:5:6:7:8]:1234") + host, port, authHeader, err = ParsePxProxyURL("1.2.3.4:1234") require.NoError(t, err) - require.Equal(t, "1:2:3:4:5:6:7:8", address) + require.Equal(t, "1.2.3.4", host) require.Equal(t, "1234", port) + require.Equal(t, "", authHeader) + + host, port, authHeader, err = ParsePxProxyURL("[1:2:3:4:5:6:7:8]:1234") + require.NoError(t, err) + require.Equal(t, "1:2:3:4:5:6:7:8", host) + require.Equal(t, "1234", port) + require.Equal(t, "", authHeader) + + // The only valid format for HTTPS proxy + host, port, authHeader, err = ParsePxProxyURL("https://user:password@http.proxy.address:1234") + require.NoError(t, err) + require.Equal(t, "http.proxy.address", host) + require.Equal(t, "1234", port) + require.Equal(t, "Basic dXNlcjpwYXNzd29yZA==", authHeader) // Invalid cases - _, _, err = SplitPxProxyHostPort("") + _, _, _, err = ParsePxProxyURL("") + require.Error(t, err) + + _, _, _, err = ParsePxProxyURL("http://address") + require.Error(t, err) + + _, _, _, err = ParsePxProxyURL("address:") require.Error(t, err) - _, _, err = SplitPxProxyHostPort("http://address") + _, _, _, err = ParsePxProxyURL("1:2:3:4:5:6:7:8") require.Error(t, err) - _, _, err = SplitPxProxyHostPort("address:") + _, _, _, err = ParsePxProxyURL(":1234") require.Error(t, err) - _, _, err = SplitPxProxyHostPort("1:2:3:4:5:6:7:8") + _, _, _, err = ParsePxProxyURL("user:password@http.proxy.address:1234") require.Error(t, err) - _, _, err = SplitPxProxyHostPort(":1234") + _, _, _, err = ParsePxProxyURL("https://user:password@address") require.Error(t, err) - _, _, err = SplitPxProxyHostPort("user:password@host:1234") + _, _, _, err = ParsePxProxyURL("https://user:password@:1234") require.Error(t, err) }