- Author(s): Artur Souza (@artursouza), Josh van Leeuwen (@JoshVanL)
- State: Ready for Implementation
- Updated: 05/08/2024
This is a design proposal to support remote or shared Dapr APIs.
This will allow applications to talk to a remote or shared sidecar, without having to rely on localhost sidecar running per app instance. It means the communication will likely require TLS communication.
- Applications to communicate to Dapr APIs without a local sidecar.
- Dapr users can talk to a remote Dapr API without using CLI or any other tool, by just running the application with environment variables.
- System administrators don't need to have different configurations per application based on programming language, meaning the same environment variables will work with every SDK - exception is when SDK only supports HTTP or GRPC, but sysadmin can simply always setup environment variables for both protocols to guarantee consistency.
- Inconsistency on setting up Dapr's sidecar endpoint on each SDK.
- Not every SDK support a secure endpoint.
Formalizing the proposal here from this issue.
- What is in scope for this proposal?
- SDKs to support a consistent pair of environment variables to setup Dapr API
- SDKs to support TLS endpoints for Dapr API
- What is deliberately not in scope?
- SSL certificate pinning
- Have consistency of other environment variables for SDK (
DAPR_HOST
,DAPR_SIDECAR_IP
, etc) - Have consistency of how Dapr client is instanciated on each SDK
- What alternatives have been considered, and why do they not solve the problem?
- Leave every SDK as-is:
- Not every SDK offers an environment variable to configure Dapr endpoint, forcing configuration in code
- Environment variables per SDK, forcing sysadmin to know about each application's language use
- Not every SDK supports TLS endpoint
- Add TLS support only, giving each SDK room to decide on how to expose it to the user
- Not every SDK offers an environment variable to configure Dapr endpoint, forcing configuration in code
- Environment variables per SDK, forcing sysadmin to know about each application's language use
- Are there any trade-offs being made? (space for time, for example)
- Leaving existing environment variables for host and port as-is per SDK, but driving consistency on this new way.
- Not changing Dapr's DAPR_HOST (or equivalent), DAPR_HTTP_PORT and DAPR_GRPC_PORT.
- What advantages / disadvantages does this proposal have? Pros:
- Bring consistency in Dapr API endpoint configuration cross SDKs
- Add support for TLS endpoint
Cons:
- Does not address existing inconsistencies in client instantiation and env variables
- Needs to define a priority between new env variables and old ones
DAPR_GRPC_ENDPOINT
defines entire endpoint for gRPC, not just host:dapr-grpc.mycompany.com
. No port in the URL defaults to 443.DAPR_HTTP_ENDPOINT
defines entire endpoint for HTTP, not just host:https://dapr-http.mycompany.com
- Port is parsed from the hostport string (
dapr.mycompany.com:8080
) or via the default port of the protocol used in the URL (80 forplaintext
and 443 forTLS
) DAPR_GRPC_ENDPOINT
andDAPR_HTTP_ENDPOINT
can be set at the same time since some SDKs (Java, as of now) supports both protocols at the same time and app can pick which one to use.DAPR_HTTP_ENDPOINT
must be parsed and the protocol will be used by SDK to determine if communication is over TLS (if not done automatically). In summary,https
means secure channel.DAPR_GRPC_ENDPOINT
must be parsed and the query parameter will be used to determine whether the endpoint uses TLS. In summary,?tls=true
means to use TLS. An empty query parameter defaults TLS to false. SDKs should error on unrecognised or invalid query parameters.DAPR_GRPC_ENDPOINT
andDAPR_HTTP_ENDPOINT
have priority over existingDAPR_HOST
andDAPR_HTTP_PORT
orDAPR_GRPC_PORT
environment variables. Application's hardcoded values passed via constructor takes priority over any environment variable. In summary, this is the priority list (highest on top):- Values passed via constructor or builder method.
- Properties or any other language specific configuration framework.
DAPR_GRPC_ENDPOINT
andDAPR_HTTP_ENDPOINT
- Existing
DAPR_HOST
(or equivalent, defaulting to127.0.0.1
) +DAPR_HTTP_PORT
orDAPR_GRPC_PORT
DAPR_GRPC_ENDPOINT
host port parsing example:
myhost => port=443 tls=false resolver=dns
myhost?tls=false => port=443 tls=false resolver=dns
myhost:443 => port=443 tls=false resolver=dns
myhost:1003 => port=1003 tls=false resolver=dns
myhost:1003?tls=true => port=1003 tls=true resolver=dns
dns://myhost:1003?tls=true => port=1003 tls=true resolver=dns
unix://my.sock => port=<no concept of port> tls=false resolver=unix
unix://my.sock?tls=true => port=<no concept of port> tls=true resolver=unix
http://myhost => port=80 tls=false resolver=dns
https://myhost => port=443 tls=true resolver=dns
-
Compatability guarantees This feature should allow localhost definition too
http://127.0.0.1:3500
, for example. -
This feature should continue to allow using other resolvers other than DNS (e.g.
unix://
). -
Deprecation / co-existence with existing functionality This feature takes priority over existing (inconsistent) environment variables from each SDK. If app provides a hardcoded value for Dapr endpoint (via constructor, for example), it takes priority. Use of existing
DAPR_API_TOKEN
environment variables is highly encouraged for remote API but not required. -
SDKs will continue to accept the old behaviour of DAPR_GRPC_ENPOINT
with the scheme value
httpsto signal to use TLS. Where a value contains both the
httpsscheme and
?tls=false` query, SDKs will error and refuse to connect. -
Feature flags N/A
How will success be measured?
-
Performance targets N/A
-
Compabitility requirements Same environment variables work with any SDK - except if protocol is not supported by given SDK.
-
Metrics N/A
What changes or actions are required to make this proposal complete?
- SDK changes
- Add support for new environment variable
- Add integration testing on each SDK when possible
- Documentation
URL | Endpoint string to pass to grpc client | Hostname | Port | TLS | Error |
---|---|---|---|---|---|
:5000 | dns:localhost:5000 | localhost | 5000 | FALSE | |
:5000?tls=false | dns:localhost:5000 | localhost | 5000 | FALSE | |
:5000?tls=true | dns:localhost:5000 | localhost | 5000 | TRUE | |
myhost | dns:myhost:443 | myhost | 443 | FALSE | |
myhost?tls=false | dns:myhost:443 | myhost | 443 | FALSE | |
myhost?tls=true | dns:myhost:443 | myhost | 443 | TRUE | |
myhost:443 | dns:myhost:443 | myhost | 443 | FALSE | |
myhost:443?tls=false | dns:myhost:443 | myhost | 443 | FALSE | |
myhost:443?tls=true | dns:myhost:443 | myhost | 443 | TRUE | |
http://myhost | dns:myhost:80 | myhost | 80 | FALSE | |
http://myhost?tls=false | the tls query parameter is not supported for http(s) endpoints: 'tls=false' | ||||
http://myhost?tls=true | the tls query parameter is not supported for http(s) endpoints: 'tls=true' | ||||
http://myhost:443 | dns:myhost:443 | myhost | 443 | FALSE | |
http://myhost:443?tls=false | the tls query parameter is not supported for http(s) endpoints: 'tls=false' | ||||
http://myhost:443?tls=true | the tls query parameter is not supported for http(s) endpoints: 'tls=true' | ||||
http://myhost:5000 | dns:myhost:5000 | myhost | 5000 | FALSE | |
http://myhost:5000?tls=false | the tls query parameter is not supported for http(s) endpoints: 'tls=false' | ||||
http://myhost:5000?tls=true | the tls query parameter is not supported for http(s) endpoints: 'tls=true' | ||||
https://myhost:443 | dns:myhost:443 | myhost | 443 | TRUE | |
https://myhost:443?tls=false | the tls query parameter is not supported for http(s) endpoints: 'tls=false' | ||||
https://myhost:443?tls=true | the tls query parameter is not supported for http(s) endpoints: 'tls=true' | ||||
dns:myhost | dns:myhost:443 | myhost | 443 | FALSE | |
dns:myhost?tls=false | dns:myhost:443 | myhost | 443 | FALSE | |
dns:myhost?tls=true | dns:myhost:443 | myhost | 443 | TRUE | |
dns://myauthority:53/myhost | dns://myauthority:53/myhost:443 | myhost | 443 | FALSE | |
dns://myauthority:53/myhost?tls=false | dns://myauthority:53/myhost:443 | myhost | 443 | FALSE | |
dns://myauthority:53/myhost?tls=true | dns://myauthority:53/myhost:443 | myhost | 443 | TRUE | |
dns://myhost | invalid dns authority 'myhost' in URL 'dns://myhost' | ||||
unix:my.sock | unix:my.sock | my.sock | FALSE | ||
unix:my.sock?tls=true | unix:my.sock | my.sock | TRUE | ||
unix://my.sock | unix://my.sock | my.sock | FALSE | ||
unix://my.sock?tls=true | unix://my.sock | my.sock | TRUE | ||
unix-abstract:my.sock | unix-abstract:my.sock | my.sock | FALSE | ||
unix-abstract:my.sock?tls=true | unix-abstract:my.sock | my.sock | TRUE | ||
vsock:mycid:5000 | vsock:mycid:5000 | mycid | 5000 | FALSE | |
vsock:mycid:5000?tls=true | vsock:mycid:5000 | mycid | 5000 | TRUE | |
[2001:db8:1f70::999:de8:7648:6e8] | dns:[2001:db8:1f70::999:de8:7648:6e8]:443 | [2001:db8:1f70::999:de8:7648:6e8] | 443 | FALSE | |
dns:[2001:db8:1f70::999:de8:7648:6e8]:5000 | dns:[2001:db8:1f70::999:de8:7648:6e8]:5000 | [2001:db8:1f70::999:de8:7648:6e8] | 5000 | FALSE | |
dns:[2001:db8:1f70::999:de8:7648:6e8]:5000?abc=[] | Error: query parameters are not supported for gRPC endpoints: 'abc=[]' | ||||
dns://myauthority:53/[2001:db8:1f70::999:de8:7648:6e8] | dns://myauthority:53/[2001:db8:1f70::999:de8:7648:6e8]:443 | [2001:db8:1f70::999:de8:7648:6e8] | 443 | FALSE | |
dns:[2001:db8:1f70::999:de8:7648:6e8] | dns:[2001:db8:1f70::999:de8:7648:6e8]:443 | [2001:db8:1f70::999:de8:7648:6e8] | 443 | FALSE | |
https://[2001:db8:1f70::999:de8:7648:6e8] | dns:[2001:db8:1f70::999:de8:7648:6e8]:80 | [2001:db8:1f70::999:de8:7648:6e8] | 80 | TRUE | |
https://[2001:db8:1f70::999:de8:7648:6e8]:5000 | dns:[2001:db8:1f70::999:de8:7648:6e8]:5000 | [2001:db8:1f70::999:de8:7648:6e8] | 5000 | TRUE | |
host:5000/v1/dapr | paths are not supported for gRPC endpoints: '/v1/dapr' | ||||
host:5000/?a=1 | paths are not supported for gRPC endpoints: '/' | ||||
inv-scheme://myhost | invalid scheme 'inv-scheme' in URL 'inv-scheme://myhost' | ||||
inv-scheme:myhost:5000 | invalid scheme 'inv-scheme' in URL 'inv-scheme:myhost:5000' |