dotnet-sdk: New gRPC DaprClient fails for Secret API requests if mTLS is enabled

Expected Behavior

DaprClient should work with mTLS enabled.

Actual Behavior

clients created through the builder:

var client = new DaprClientBuilder().Build();

Fail to get secrets through calling client.GetSecretAsync when Dapr mTLS is enabled.

Steps to Reproduce the Problem

Deploy the following yaml to K8s:

---
# Create a Kubernetes Secret
apiVersion: v1
kind: Secret
metadata:
  name: super-secret
  namespace: default
type: Opaque
data:
  super-secret: eW91ciBzdXBlciBzZWNyZXQK

---
# If RBAC is enabled in K8s, give the default SA access to secrets in the default namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: dapr-secret-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: secret-reader
subjects:
  - kind: ServiceAccount
    name: default
    namespace: default

Create and deploy an ASP.NET Core application which implements the following call:

var secrets = await client.GetSecretAsync("kubernetes", "super-secret", new Dictionary<string, string>() { { "namespace", "default" } });

The call will fail with mTLS enabled.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 23 (23 by maintainers)

Most upvoted comments

@cmendible I have published new package version 0.5.0-preview02 witht he changes.

@cmendible Please see this PR https://github.com/dapr/dotnet-sdk/pull/263 It will be cherry-picked into 0.5.0 branch to release a new nuget package to see if it works for you. There is an internal method on DaprClientBuilder, its UseGrpcChannelOptions(). I am thinking of making it public to allow for more configurable brhavior form users in future, any feedback around it? The change will be reverted from master branch for 0.6.0 when the issue is fixed in Dapr runtime.

This is what is working for me using the client provide by gRPC:

using (var httpClientHandler = new HttpClientHandler())
{
	httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>
	{
		return true;
	};
	using (var httpClient = new HttpClient(httpClientHandler))
	{
		var channel = GrpcChannel.ForAddress("https://127.0.0.1:50001", new GrpcChannelOptions()
		{
			HttpClient = httpClient
		});
		var dapr = new Dapr.Client.Autogen.Grpc.Dapr.DaprClient(channel);
		var envelope = new Dapr.Client.Autogen.Grpc.GetSecretEnvelope()
		{
			Key = "super-secret",
			StoreName = "kubernetes"
		};
		envelope.Metadata.Add("namespace", "default");
		var secreValue = dapr.GetSecret(envelope).Data["super-secret"];

		context.Response.ContentType = "application/json";
		await JsonSerializer.SerializeAsync(context.Response.Body, secreValue);
	}
}

The current implementation does no allow me to setup such as configuration.

Thanks for sharing it @cmendible I will look into whats the best option to enable it temporarily until 0.6.0 when the linked runtime issue will be fixed to hanlde this. Till then the code has to be different when running with & without mTLS.

It’s a side effect of it yes, which is a side effect of how gRPC behaves when you apply a “verify only if cert is given to you”.

Maybe it is time to separate it. I’ll create an issue for it for 0.6.0.

Great, thanks @yaron2 !, users wont have to create grpc connection conditionally.

@cmendible It will be fixed in the runtime for 0.6.0, how do you want to handle it for 0.5.0 in the meantime so that same code runs locally on dev box and in k8s with mTLS. I am open to releasing a nuget package with the fix so that things continue to work on 0.5.0

It’s a side effect of it yes, which is a side effect of how gRPC behaves when you apply a “verify only if cert is given to you”.

Maybe it is time to separate it. I’ll create an issue for it for 0.6.0.