- 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_ENDPOINTdefines entire endpoint for gRPC, not just host:dapr-grpc.mycompany.com. No port in the URL defaults to 443.DAPR_HTTP_ENDPOINTdefines 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 forplaintextand 443 forTLS) DAPR_GRPC_ENDPOINTandDAPR_HTTP_ENDPOINTcan 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_ENDPOINTmust be parsed and the protocol will be used by SDK to determine if communication is over TLS (if not done automatically). In summary,httpsmeans secure channel.DAPR_GRPC_ENDPOINTmust be parsed and the query parameter will be used to determine whether the endpoint uses TLS. In summary,?tls=truemeans to use TLS. An empty query parameter defaults TLS to false. SDKs should error on unrecognised or invalid query parameters.DAPR_GRPC_ENDPOINTandDAPR_HTTP_ENDPOINThave priority over existingDAPR_HOSTandDAPR_HTTP_PORTorDAPR_GRPC_PORTenvironment 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_ENDPOINTandDAPR_HTTP_ENDPOINT- Existing
DAPR_HOST(or equivalent, defaulting to127.0.0.1) +DAPR_HTTP_PORTorDAPR_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_TOKENenvironment 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 valuehttpsto signal to use TLS. Where a value contains both thehttpsscheme 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' |