dapr / components-contrib

Community driven, reusable components for distributed apps
Apache License 2.0
548 stars 480 forks source link

Unable to retrieve a vault secret for kafka pub/sub when the secret contains other key-value pairs with non-string values #3500

Closed sirhc-chris closed 2 months ago

sirhc-chris commented 3 months ago

Expected Behavior

When using pubsub.kafka with authType mtls, you should be able to retrieve a value (e.g. clientKey) from secretstores.hashicorp.vault where the secret contains other key-value pairs with non-string values.

Actual Behavior

When using pubsub.kafka with authType mtls and attempting to retrieve a secret (e.g. clientKey) from secretstores.hashicorp.vault, you receive the following error when the secret contains other key-value pairs that have non-string values:

Error getting secret: couldn't decode response body: json: cannot unmarshal array into Go struct field .data.data of type string

Steps to Reproduce the Problem

├───bin
│       daprd.exe
│
└───components
        pubsub-kafka.yaml
        secretstores-hashicorp-vault.yaml
$ cat .\components\pubsub-kafka.yaml

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: pubsub-test
spec:
  type: pubsub.kafka
  version: "v1"
  metadata:
  - name: brokers
    value: "localhost:9094"
  - name: authType
    value: mtls
  - name: skipVerify
    value: "false"
  - name: clientCert
    value: foo
  - name: clientKey
    secretKeyRef:
     name: test-secret-1
     key: bar
auth:
  secretStore: vault-secretstore
$ cat .\components\secretstores-hashicorp-vault.yaml

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: vault-secretstore
spec:
  type: secretstores.hashicorp.vault
  version: v1
  metadata:
  - name: vaultAddr
    value: http://localhost:8200
  - name: vaultToken
    value : "dev-token"
  - name: vaultKVUsePrefix
    value: false
  - name: enginePath
    value: "secret"

Launch a local vault instance:

$ docker run --cap-add=IPC_LOCK -e VAULT_DEV_ROOT_TOKEN_ID=dev-token -p 8200:8200 hashicorp/vault:1.15.5

Create a secret containing a non-string value:

$ curl --header "X-Vault-Token: dev-token" --header "Content-Type: application/json" --request POST --data '{"data": {"bar": "secret-value", "baz": true}}' http://127.0.0.1:8200/v1/secret/data/test-secret-1

Run dapr and observe the json decoding error:

$ bin\daprd.exe -app-id dapr-test --log-level debug --resources-path .\components\  
...
time="2024-08-02T16:01:59.0573513+01:00" level=error msg="Error getting secret: couldn't decode response body: json: cannot unmarshal bool into Go struct field .data.data of type string" app_id=dapr-test instance=localhost scope=dapr.runtime.processor.secret type=log ver=1.13.2
...

Full log excerpt:

$ bin\daprd.exe -app-id dapr-test --log-level debug --resources-path .\components\                                                                       
time="2024-08-02T16:01:58.9846063+01:00" level=info msg="Starting Dapr Runtime -- version 1.13.2 -- commit f09b193d8ac62bef6c0fd5452a00d2a49cd0d134" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:58.9846063+01:00" level=info msg="Log level set to: debug" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:58.9846063+01:00" level=warning msg="mTLS is disabled. Skipping certificate request and tls validation" app_id=dapr-test instance=localhost scope=dapr.runtime.security type=log ver=1.13.2
time="2024-08-02T16:01:58.9971218+01:00" level=info msg="loading default configuration" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:58.998116+01:00" level=warning msg="The default value for 'spec.metric.http.increasedCardinality' will change to 'false' in Dapr 1.14" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0003079+01:00" level=debug msg="Found 0 resiliency configurations in resources path" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0008822+01:00" level=debug msg="Hot reloading disabled" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0008822+01:00" level=info msg="standalone mode configured" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0008822+01:00" level=info msg="app id: dapr-test" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0008822+01:00" level=info msg="metrics server started on :9090/" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0018494+01:00" level=info msg="Dapr trace sampler initialized: DaprTraceSampler(P=0.000100)" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0398393+01:00" level=info msg="local service entry announced: dapr-test -> 10.0.0.1:47424" app_id=dapr-test component="nr (mdns/v1)" instance=localhost scope=dapr.contrib type=log ver=1.13.2
time="2024-08-02T16:01:59.0411349+01:00" level=info msg="Initialized name resolution to mdns" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0419646+01:00" level=debug msg="the current OS does not support pluggable components feature, skipping initialization" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0419646+01:00" level=info msg="Loading components…" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0445896+01:00" level=debug msg="Found component: vault-secretstore (secretstores.hashicorp.vault/v1)" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0465879+01:00" level=debug msg="Found component: pubsub-test (pubsub.kafka/v1)" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0465879+01:00" level=debug msg="Loading component: vault-secretstore (secretstores.hashicorp.vault/v1)" app_id=dapr-test instance=localhost scope=dapr.runtime.processor type=log ver=1.13.2
time="2024-08-02T16:01:59.0475858+01:00" level=info msg="Component loaded: vault-secretstore (secretstores.hashicorp.vault/v1)" app_id=dapr-test instance=localhost scope=dapr.runtime.processor type=log ver=1.13.2
time="2024-08-02T16:01:59.0475858+01:00" level=debug msg="Loading component: pubsub-test (pubsub.kafka/v1)" app_id=dapr-test instance=localhost scope=dapr.runtime.processor type=log ver=1.13.2
time="2024-08-02T16:01:59.0475858+01:00" level=info msg="Waiting for all outstanding components to be processed…" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0573513+01:00" level=error msg="Error getting secret: couldn't decode response body: json: cannot unmarshal bool into Go struct field .data.data of type string" app_id=dapr-test instance=localhost scope=dapr.runtime.processor.secret type=log ver=1.13.2
time="2024-08-02T16:01:59.0578672+01:00" level=debug msg="ConsumerGroup='dapr-test', ClientID='', saslMechanism=''" app_id=dapr-test component="pubsub-test (pubsub.kafka/v1)" instance=localhost scope=dapr.contrib type=log ver=1.13.2
time="2024-08-02T16:01:59.0578672+01:00" level=debug msg="Found brokers: [localhost:9094]" app_id=dapr-test component="pubsub-test (pubsub.kafka/v1)" instance=localhost scope=dapr.contrib type=log ver=1.13.2
time="2024-08-02T16:01:59.0584304+01:00" level=error msg="Failed to init component pubsub-test (pubsub.kafka/v1): [INIT_COMPONENT_FAILURE]: initialization error occurred for pubsub-test (pubsub.kafka/v1): kafka error: invalid client certificate" app_id=dapr-test instance=localhost scope=dapr.runtime.processor type=log ver=1.13.2
time="2024-08-02T16:01:59.0584853+01:00" level=warning msg="Error processing component, daprd will exit gracefully" app_id=dapr-test instance=localhost scope=dapr.runtime.processor type=log ver=1.13.2
time="2024-08-02T16:01:59.0584853+01:00" level=info msg="All outstanding components processed" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0589989+01:00" level=info msg="Loading endpoints…" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0601314+01:00" level=info msg="Waiting for all outstanding http endpoints to be processed…" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0601314+01:00" level=info msg="All outstanding http endpoints processed" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0606943+01:00" level=debug msg="Refreshing channels" app_id=dapr-test instance=localhost scope=dapr.runtime.channels type=log ver=1.13.2
time="2024-08-02T16:01:59.0610393+01:00" level=warning msg="App channel is not initialized. Did you configure an app-port?" app_id=dapr-test instance=localhost scope=dapr.runtime.channels type=log ver=1.13.2
time="2024-08-02T16:01:59.0621547+01:00" level=info msg="gRPC server listening on TCP address: :50001" app_id=dapr-test instance=localhost scope=dapr.runtime.grpc.api type=log ver=1.13.2
time="2024-08-02T16:01:59.0627153+01:00" level=info msg="Enabled gRPC tracing middleware" app_id=dapr-test instance=localhost scope=dapr.runtime.grpc.api type=log ver=1.13.2
time="2024-08-02T16:01:59.0627153+01:00" level=info msg="Enabled gRPC metrics middleware" app_id=dapr-test instance=localhost scope=dapr.runtime.grpc.api type=log ver=1.13.2
time="2024-08-02T16:01:59.0627153+01:00" level=info msg="Registering workflow engine for gRPC endpoint: [::]:50001" app_id=dapr-test instance=localhost scope=dapr.runtime.grpc.api type=log ver=1.13.2
time="2024-08-02T16:01:59.0632563+01:00" level=info msg="API gRPC server is running on port 50001" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0633765+01:00" level=info msg="Enabled max body size HTTP middleware with size 4 MB" app_id=dapr-test instance=localhost scope=dapr.runtime.http type=log ver=1.13.2
time="2024-08-02T16:01:59.0633765+01:00" level=info msg="Enabled tracing HTTP middleware" app_id=dapr-test instance=localhost scope=dapr.runtime.http type=log ver=1.13.2
time="2024-08-02T16:01:59.0638958+01:00" level=info msg="Enabled metrics HTTP middleware" app_id=dapr-test instance=localhost scope=dapr.runtime.http type=log ver=1.13.2
time="2024-08-02T16:01:59.0645198+01:00" level=info msg="HTTP server listening on TCP address: :3500" app_id=dapr-test instance=localhost scope=dapr.runtime.http type=log ver=1.13.2
time="2024-08-02T16:01:59.065038+01:00" level=info msg="HTTP server is running on port 3500" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.065038+01:00" level=info msg="The request body size parameter is: 4" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0657881+01:00" level=info msg="gRPC server listening on TCP address: :47424" app_id=dapr-test instance=localhost scope=dapr.runtime.grpc.internal type=log ver=1.13.2
time="2024-08-02T16:01:59.0663047+01:00" level=info msg="Enabled gRPC tracing middleware" app_id=dapr-test instance=localhost scope=dapr.runtime.grpc.internal type=log ver=1.13.2
time="2024-08-02T16:01:59.0669212+01:00" level=info msg="Enabled gRPC metrics middleware" app_id=dapr-test instance=localhost scope=dapr.runtime.grpc.internal type=log ver=1.13.2
time="2024-08-02T16:01:59.0669212+01:00" level=info msg="Internal gRPC server is running on port 47424" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0674387+01:00" level=info msg="Configuring workflow engine with actors backend" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0674387+01:00" level=info msg="Registering component for dapr workflow engine..." app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0679968+01:00" level=info msg="Initializing Dapr workflow component" app_id=dapr-test component="dapr (workflow.dapr/v1)" instance=localhost scope=dapr.contrib type=log ver=1.13.2
time="2024-08-02T16:01:59.0679968+01:00" level=info msg="Workflow engine initialized." app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0679968+01:00" level=warning msg="failed to read from bindings: app channel not initialized " app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0686282+01:00" level=info msg="dapr initialized. Status: Running. Init Elapsed 67ms" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0686282+01:00" level=info msg="Dapr is shutting down" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0691407+01:00" level=info msg="Shutting down component vault-secretstore (secretstores.hashicorp.vault/v1)" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0691407+01:00" level=info msg="Dapr runtime stopped" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0691407+01:00" level=info msg="Closing HTTP server [::]:3500…" app_id=dapr-test instance=localhost scope=dapr.runtime.http type=log ver=1.13.2
time="2024-08-02T16:01:59.0691407+01:00" level=info msg="Shutting down workflow engine" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2
time="2024-08-02T16:01:59.0686282+01:00" level=debug msg="Graceful shutdown timeout: 5s" app_id=dapr-test instance=localhost scope=dapr.kit.concurrency type=log ver=1.13.2
time="2024-08-02T16:01:59.0691407+01:00" level=debug msg="stopping cache refreshes" app_id=dapr-test component="nr (mdns/v1)" instance=localhost scope=dapr.contrib type=log ver=1.13.2
time="2024-08-02T16:01:59.0691407+01:00" level=debug msg="received done signal, shutting down…" app_id=dapr-test component="nr (mdns/v1)" instance=localhost scope=dapr.contrib type=log ver=1.13.2
time="2024-08-02T16:01:59.0709215+01:00" level=info msg="stopping mDNS server for app id: dapr-test" app_id=dapr-test component="nr (mdns/v1)" instance=localhost scope=dapr.contrib type=log ver=1.13.2
time="2024-08-02T16:01:59.0736144+01:00" level=fatal msg="Fatal error from runtime: process component pubsub-test error: [INIT_COMPONENT_FAILURE]: initialization error occurred for pubsub-test (pubsub.kafka/v1): [INIT_COMPONENT_FAILURE]: initialization error occurred for pubsub-test (pubsub.kafka/v1): kafka error: invalid client certificate" app_id=dapr-test instance=localhost scope=dapr.runtime type=log ver=1.13.2

If the secret only contains key-value pairs with string values, the json body is successfully decoded. For example:

Create a secret containing only string values:

$ curl --header "X-Vault-Token: dev-token" --header "Content-Type: application/json" --request POST --data '{"data": {"bar": "secret-value", "baz": "string"}}' http://127.0.0.1:8200/v1/secret/data/test-secret-2

And reference it in the pubsub.kafka spec:

$ cat .\components\pubsub-kafka.yaml

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: pubsub-test
spec:
  type: pubsub.kafka
  version: "v1"
  metadata:
  - name: brokers
    value: "localhost:9094"
  - name: authType
    value: mtls
  - name: skipVerify
    value: "false"
  - name: clientCert
    value: foo
  - name: clientKey
    secretKeyRef:
     name: test-secret-2
     key: bar
auth:
  secretStore: vault-secretstore

Run dapr and note the json body is successfully decoded:

$ bin\daprd.exe -app-id dapr-test --log-level debug --resources-path .\components\  

(It will still fail, as the secret isn't a valid certificate)

...
time="2024-08-02T16:08:21.0640412+01:00" level=error msg="Failed to init component pubsub-test (pubsub.kafka/v1): [INIT_COMPONENT_FAILURE]: initialization error occurred for pubsub-test (pubsub.kafka/v1): kafka error: invalid client certificate" app_id=dapr-test instance=localhost scope=dapr.runtime.processor type=log ver=1.13.
...
github-actions[bot] commented 2 months ago

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in the next 7 days unless it is tagged (pinned, good first issue, help wanted or triaged/resolved) or other activity occurs. Thank you for your contributions.

github-actions[bot] commented 2 months ago

This issue has been automatically closed because it has not had activity in the last 37 days. If this issue is still valid, please ping a maintainer and ask them to label it as pinned, good first issue, help wanted or triaged/resolved. Thank you for your contributions.