Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: adds support for go-control-plane based xDS implementations #41

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

owayss
Copy link

@owayss owayss commented Mar 31, 2022

👋 This proposal adds support for OSS implementations of the xDS control plane.

Kindly let me know whether this is something you would like integrated into envoy-tools/csds-client, and what are your thoughts on this approach.

platform go

This patch adds support for a second type of platform, named go. It does so by providing utility function ConnToXDS and DialOptions to initiate gRPCs to the address specified by the flag service_uri.

authentication options for platform go

Support is added for mTLS via the introduction of the following new flags:

  -authority string
        the :authority header to use when connecting to uri
  -cacert string
        filepath to the CAs certs used to verify the server's certificate
  -cert string
        filepath to the client TLS certificate
  -key string
        filepath to the client TLS private key

The the client certificate/private key pair are included in the ClientHello message for establishing a connection over TLS.

If a certificate authority is provided via cacert, it is used to validate the server's certificate identity.

Additionally, the -authority flag allows for setting the HTTP/2 :authority header to use for SNI.

Example

$ ~/github/owayss/envoy-tools/csds-client/csds-client \
    -request_file ~/github/owayss/envoy-tools/csds-client/client/v3/test_request.yaml \
    -cert client.crt \
    -key client.key \
    -cacert ca.crt \
    -service_uri localhost:18000 \
    -platform go \
    -api_version v3 
Click to expand response output
Client ID                                          xDS stream type                Config Status                  
api-gateway                                                                       CDS   SYNCED                   
                                                                                  LDS   SYNCED                   
Detailed Config:
{
  "config": [
    {
      "node": {
        "id": "api-gateway"
      },
      "xdsConfig": [
        {
          "status": "SYNCED",
          "clusterConfig": {
            "staticClusters": [
              {
                "cluster": {
                  "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
                  "name": "service_api-gateway-stg",
                  "type": "STRICT_DNS",
                  "connectTimeout": "5s",
                  "loadAssignment": {
                    "clusterName": "service_api-gateway-stg",
                    "endpoints": [
                      {
                        "lbEndpoints": [
                          {},
                          {
                            "endpoint": {
                              "address": {
                                "socketAddress": {
                                  "address": "envoyproxy.io",
                                  "portValue": 443
                                }
                              }
                            }
                          }
                        ]
                      }
                    ]
                  },
                  "healthChecks": [
                    {
                      "timeout": "5s",
                      "interval": "5s",
                      "unhealthyThreshold": 3,
                      "healthyThreshold": 3,
                      "reuseConnection": true,
                      "httpHealthCheck": {
                        "host": "api-gateway-stg.mydomain.com",
                        "path": "/api/health",
                        "expectedStatuses": [
                          {
                            "start": "200",
                            "end": "405"
                          }
                        ]
                      },
                      "noTrafficInterval": "60s",
                      "eventLogPath": "/dev/stdout",
                      "alwaysLogHealthCheckFailures": true
                    }
                  ],
                  "dnsLookupFamily": "V4_ONLY",
                  "transportSocket": {
                    "name": "envoy.transport_sockets.tls"
                  }
                }
              }
            ]
          }
        },
        {
          "status": "SYNCED",
          "listenerConfig": {
            "staticListeners": [
              {
                "listener": {
                  "@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
                  "name": "listener_api-gateway-stg",
                  "address": {
                    "socketAddress": {
                      "address": "0.0.0.0",
                      "portValue": 4455
                    }
                  },
                  "filterChains": [
                    {
                      "filters": [
                        {
                          "name": "envoy.filters.network.http_connection_manager",
                          "typedConfig": {
                            "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
                            "statPrefix": "http",
                            "routeConfig": {
                              "name": "route_api-gateway-stg",
                              "virtualHosts": [
                                {
                                  "name": "route_api-gateway-stg",
                                  "domains": [
                                    "*"
                                  ],
                                  "routes": [
                                    {
                                      "match": {
                                        "path": "/__envoy__/status"
                                      },
                                      "directResponse": {
                                        "status": 200,
                                        "body": {
                                          "inlineString": "OK"
                                        }
                                      }
                                    },
                                    {
                                      "match": {
                                        "prefix": "/"
                                      },
                                      "route": {
                                        "cluster": "service_api-gateway-stg",
                                        "hostRewriteLiteral": "api-gateway-stg.mydomain.com"
                                      }
                                    }
                                  ]
                                }
                              ]
                            },
                            "httpFilters": [
                              {
                                "name": "envoy.filters.http.router"
                              }
                            ],
                            "accessLog": [
                              {
                                "name": "envoy.access_loggers.file",
                                "typedConfig": {
                                  "@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog",
                                  "path": "/dev/stdout",
                                  "logFormat": {
                                    "jsonFormat": {
                                      "bytes_received": "%BYTES_RECEIVED%",
                                      "bytes_sent": "%BYTES_SENT%",
                                      "downstream_local_address": "%DOWNSTREAM_LOCAL_ADDRESS%",
                                      "downstream_local_uri_san": "%DOWNSTREAM_LOCAL_URI_SAN%",
                                      "downstream_peer_uri_san": "%DOWNSTREAM_PEER_URI_SAN%",
                                      "downstream_remote_address": "%DOWNSTREAM_REMOTE_ADDRESS%",
                                      "duration": "%DURATION%",
                                      "envoy_upstream_service_time": "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%",
                                      "epoch_micro": "%START_TIME(%s.%6f)%",
                                      "jwt_aud": "%DYNAMIC_METADATA(envoy.filters.http.jwt_authn\\:config)%",
                                      "protocol": "%PROTOCOL%",
                                      "req_authority": "%REQ(:AUTHORITY)%",
                                      "req_envoy_original_path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%",
                                      "req_path": "%REQ(:PATH)%",
                                      "req_user_agent": "%REQ(USER-AGENT)%",
                                      "req_x_request_id": "%REQ(X-REQUEST-ID)%",
                                      "req_xff": "%REQ(X-FORWARDED-FOR)%",
                                      "request_method": "%REQ(:METHOD)%",
                                      "response_code": "%RESPONSE_CODE%",
                                      "response_duration": "%RESPONSE_DURATION%",
                                      "response_flags": "%RESPONSE_FLAGS%",
                                      "response_tx_duration": "%RESPONSE_TX_DURATION%",
                                      "start_time": "%START_TIME(%Y/%m/%d %H:%M:%S)%",
                                      "upstream_cluster": "%UPSTREAM_CLUSTER%",
                                      "upstream_host": "%UPSTREAM_HOST%",
                                      "upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%",
                                      "upstream_transport_failure_reason": "%UPSTREAM_TRANSPORT_FAILURE_REASON%"
                                    }
                                  }
                                }
                              }
                            ]
                          }
                        }
                      ]
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  ]
}

Testing coverage

The patch does not include any additional tests. The various test functions in the client/v2 and client/v3 seem to cover the existing utility functions (for parsing and printing out detailed responses) with golden JSON data files.

The part that I think would benefit from a unit test is the DialOptions functions that configures the HTTP/2 connection depending on the provided command-line flags for authentication.


Best,
Owayss.

@owayss owayss marked this pull request as ready for review March 31, 2022 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant