envoy-mobile icon indicating copy to clipboard operation
envoy-mobile copied to clipboard

Extend Envoy cert validator to use platform provided APIs

Open danzh2010 opened this issue 2 years ago • 7 comments

Cert validator is extendable in upstream Envoy. As platforms such as Android and iOS provide their own cert validation APIs, E-M should use these platform provided APIs instead of, as the default cert validator does in upstream Envoy, calling into boring SSL on its own. The plan for Android is documented in https://github.com/envoyproxy/envoy-mobile/issues/1575. As we are designing the Android implementation with External::Api, which can be used for iOS extension in the future, we need to decide how to config the non-Android platform to still use the upstream Envoy's default cert validator in the transition period.

The Android config would look like:

transport_socket:
    name: envoy.transport_sockets.tls
    typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
      common_tls_context:
        # omit trusted_ca and ca_certificate_provider_instance
        ...
        custom_validator_config:
           name: "envoy_mobile.cert_validator.platform_bridge_cert_validator"
           typed_config:
             "@type": type.googleapis.com/envoymobile.extensions.transport_socket.cert_validator.v3.PlatformBridgeCertValidator
             platform_name: ${platform_specific_key}

with an Android specific ${platform_specific_key}.

For other platforms, before they switch to use the platform provided cert validator, they should be able to use the current transport socket config with trusted_ca or ca_certificate_provider_instance and without custom_validator_config. So their config looks like a)

transport_socket:
    name: envoy.transport_sockets.tls
    typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
      common_tls_context:
        trusted_ca: ${ca_config}
        ...

To do so, the config pipeline need to generate transport socket config differently for Android and non-Andoid platforms.

b) The other option is to use the same custom_validator_config with a different ${platform_specific_key}, so their config pipeline will be the same. But as they haven't switched to using the platform provided APIs, their platform code should call into Envoy default cert validator.

We can gather thoughts here about which direction to take. IMO if a) is feasible, we should avoid b) as it causes extra layer of indirection from native code to platform and then back to native and the indirection will only be used in transition period.

danzh2010 avatar Apr 04 '22 15:04 danzh2010

@mattklein123 @ggreenway @goaway @RyanTheOptimist @alyssawilk

danzh2010 avatar Apr 04 '22 15:04 danzh2010

What is platform_name? Is it something like android? If so, isn't that known at compile-time, and unneeded in the config?

ggreenway avatar Apr 05 '22 15:04 ggreenway

I'm guessing platform_name is the runtime key needed to look up the API bindings?

If it is, that's great, but maybe the name is a bit misleading. If not, we do need a key that the EngineBuilder can write into config for that.

To elaborate, for these bridged extensions with platform implementations, the API calls are mapped to function pointers which have per-platform definitions mapping them to actual platform calls. The Envoy internals are agnostic of the platform, so these connections are made at runtime during Engine configuration, and the mapped API is assigned a lookup key. During initialization, the Engine creates the call paths, registers the runtime API under the key, and then writes the key into config so the extension can retrieve it by name.

goaway avatar Apr 06 '22 09:04 goaway

I'm not a huge fan of the idea of a configuration bit that must be provided, and that there's only one correct value for on a given platform. That just screams "compile-time constant" to me. But I may not be understanding all the details; if so, ignore me and proceed.

ggreenway avatar Apr 06 '22 17:04 ggreenway

I'm guessing platform_name is the runtime key needed to look up the API bindings?

Yes, it is the key used to register the runtime API.

danzh2010 avatar Apr 07 '22 14:04 danzh2010

I'm not a huge fan of the idea of a configuration bit that must be provided, and that there's only one correct value for on a given platform. That just screams "compile-time constant" to me.

That's a good point! In https://github.com/envoyproxy/envoy-mobile/pull/2525, I removed platform_name from the config, but just hard-coded the platform registry key for Android.

danzh2010 avatar Sep 06 '22 20:09 danzh2010

For this use case, I think hardcoding is fine, especially given that there will only ever be one implementation in use per Envoy Engine. The name can just be baked into the registration of the API on the EM side.

goaway avatar Sep 07 '22 09:09 goaway

Platform cert validators are now available for iOS and Android.

jpsim avatar Dec 08 '22 21:12 jpsim