Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for secret store reference in Dapr components #7823

Merged
merged 6 commits into from
Sep 5, 2024

Conversation

SoTrx
Copy link
Contributor

@SoTrx SoTrx commented Aug 20, 2024

Description

Hey,

This PR adds support for building Dapr components with an optional reference to a Dapr secret store.

The new property is named secretStoreComponentName. This name is totally arbitrary but was chosen to try to be as clear as possible.

A secret reference can be created using a secretKeyRef object, following the same naming convention as Dapr.

Example :

resource stateStore 'Applications.Dapr/stateStores@2023-10-01-preview' = {
  name: 'statestore'
  properties: {
    environment: environment
    application: application
    resourceProvisioning: 'manual'
    type: 'state.redis'
    version: 'v1'
    metadata: {
      redisHost: {
        secretKeyRef: {
            name: 'redisHost'
            key: 'redisHost'
        }

      }
      redisPassword: ''
    }
    secretStoreComponentName: daprSecretStore.name
  }
}

Type of change

  • This pull request adds or changes features of Radius and has an approved issue (issue link required).

Fixes: #7704

@SoTrx SoTrx requested review from a team as code owners August 20, 2024 15:34
Copy link

codecov bot commented Aug 20, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 61.20%. Comparing base (dca3a27) to head (883e043).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7823      +/-   ##
==========================================
+ Coverage   61.12%   61.20%   +0.08%     
==========================================
  Files         523      523              
  Lines       27632    27683      +51     
==========================================
+ Hits        16889    16944      +55     
+ Misses       9251     9249       -2     
+ Partials     1492     1490       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@SoTrx SoTrx temporarily deployed to functional-tests August 20, 2024 17:25 — with GitHub Actions Inactive
@radius-functional-tests
Copy link

radius-functional-tests bot commented Aug 20, 2024

Radius functional test overview

🔍 Go to test action run

Name Value
Repository SoTrx/radius
Commit ref 4b23f1c
Unique ID func68cb8c7ac2
Image tag pr-func68cb8c7ac2
Click here to see the list of tools in the current test run
  • gotestsum 1.12.0
  • KinD: v0.20.0
  • Dapr: 1.12.0
  • Azure KeyVault CSI driver: 1.4.2
  • Azure Workload identity webhook: 1.3.0
  • Bicep recipe location ghcr.io/radius-project/dev/test/testrecipes/test-bicep-recipes/<name>:pr-func68cb8c7ac2
  • Terraform recipe location http://tf-module-server.radius-test-tf-module-server.svc.cluster.local/<name>.zip (in cluster)
  • applications-rp test image location: ghcr.io/radius-project/dev/applications-rp:pr-func68cb8c7ac2
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-func68cb8c7ac2
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-func68cb8c7ac2
  • deployment-engine test image location: ghcr.io/radius-project/deployment-engine:latest

Test Status

⌛ Building Radius and pushing container images for functional tests...
✅ Container images build succeeded
⌛ Publishing Bicep Recipes for functional tests...
✅ Recipe publishing succeeded
⌛ Starting corerp-cloud functional tests...
⌛ Starting datastoresrp-cloud functional tests...
⌛ Starting ucp-cloud functional tests...
✅ datastoresrp-cloud functional tests succeeded
✅ ucp-cloud functional tests succeeded
✅ corerp-cloud functional tests succeeded

@rynowak
Copy link
Contributor

rynowak commented Aug 22, 2024

Wow thanks for sending this. This is a big improvement. I'll take a look at this tomorrow.

Normally we might ask for an design document for an API change, but I think we can skip that in this case:

  • It's a very small change
  • It has an approved issue that describes the API change.
  • It's aligned with the naming and design of the existing Dapr API - which we're trying to match.

@radius-project/maintainers-radius holler if you have any concerns.

Copy link
Contributor

@ytimocin ytimocin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great addition. Thanks!

Should we add a functional test or add this to an existing functional test so that we can test it out?

Comment on lines 284 to 223
"auth": map[string]any{
"secretStore": secretStoreComponentName,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this auth generated by Dapr since we create a Dapr object with a property called secretStoreComponentName?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, the auth.secretstore property is added here if the Applications.Dapr/* contains the secretStoreComponentName property.
The auth.secretstore property comes from the Dapr component spec

Comment on lines 67 to 71
// Nested object, has to be a secret reference
case map[string]any:
if secretKeyRef, ok := value["secretKeyRef"]; ok {
yamlItem["secretKeyRef"] = secretKeyRef
} else {
return unstructured.Unstructured{}, v1.NewClientErrInvalidRequest(fmt.Sprintf("Invalid metadata value for key %s in Dapr component %s", k, componentName))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could there be a case where it is not a secret reference even if it is a nested object? Do we need to do an additional check for this case to make sure that it is a secret reference?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can see the schema of Component here: https://github.com/dapr/dapr/blob/master/charts/dapr/crds/components.yaml#L48

Note that this is the output we're generating.

The reason why I'm mention it is that it shows what the schema is in Dapr that we're trying roughly match. The allowed keys are:

  • value
  • secretKeyRef
  • envRef

envRef isn't relevant for us - it's a dev-time feature.

@rynowak
Copy link
Contributor

rynowak commented Aug 23, 2024

Hi @SoTrx - thanks for sending this PR. Looks like it works overall.

One question based on your example:

resource stateStore 'Applications.Dapr/stateStores@2023-10-01-preview' = {
  name: 'statestore'
  properties: {
    environment: environment
    application: application
    resourceProvisioning: 'manual'
    type: 'state.redis'
    version: 'v1'
    metadata: {
      redisHost: {
        secretKeyRef: {
            name: 'redisHost'
            key: 'redisHost'
        }

      }
      redisPassword: ''
    }
    secretStoreComponentName: daprSecretStore.name
  }
}

It looks like the type of metadata after your change is map from string to (string or object). This isn't ideal because we try to avoid designs where a field has an ambiguous type. Ideally this would be map from string to object in all cases. I think we probably made a mistake in the original design 😢

If I compare to the Dapr schema of Component I'd describe this as list of key-value-pairs where the key is a string and the value is an object.

Do you think it makes sense for us to change the design?

Example:

resource stateStore 'Applications.Dapr/stateStores@2023-10-01-preview' = {
  name: 'statestore'
  properties: {
    environment: environment
    application: application
    resourceProvisioning: 'manual'
    type: 'state.redis'
    version: 'v1'
    metadata: {
      redisHost: {
        secretKeyRef: {
            name: 'redisHost'
            key: 'redisHost'
        }
      }
      redisPassword: {
        value: ''
      }
    }
    secretStoreComponentName: daprSecretStore.name
  }
}

This would be a breaking change, and we'd need to update our existing code, but it's probably a better design. What do you think?

@SoTrx
Copy link
Contributor Author

SoTrx commented Aug 26, 2024

Thank you for your reviews

@rynowak
I believe your proposed change might be the best approach, as it would provide the most extensibility.

Going the other way and using strings only (with a magic prefix to reference secrets) might also seem tempting since it would be non-breaking. But this is a worse design and may lead to parsing/escaping issues or conflict with special values or even a company's own oddly defined pluggable components.

resource stateStore 'Applications.Dapr/stateStores@2023-10-01-preview' = {
  name: 'statestore'
  properties: {
    environment: environment
    application: application
    resourceProvisioning: 'manual'
    type: 'state.redis'
    version: 'v1'
    metadata: {
      redisHost: 'secretRef:://key,value'
      redisPassword: ''
    }
    secretStoreComponentName: daprSecretStore.name
  }
}

Another approach could be treating the secret as its own resource. However, aside from the added complexity, this might encourage users to attempt using secrets from multiple secret stores within a single component, which, as far as I'm aware, Dapr does not support.

So using only objects may be the best solution in my opinion.


On a related note, if the goal is to match Dapr component schema, should we also change the secretStoreComponentName property to auth.secretstore to match what Dapr [uses]((https://docs.dapr.io/operations/components/component-secrets/) ?

Something like :

resource stateStore 'Applications.Dapr/stateStores@2023-10-01-preview' = {
  name: 'statestore'
  properties: {
    environment: environment
    application: application
    resourceProvisioning: 'manual'
    type: 'state.redis'
    version: 'v1'
    metadata: {
      redisHost: {
        secretKeyRef: {
            name: 'redisHost'
            key: 'redisHost'
        }
      }
      redisPassword: {
        value: ''
      }
    }
    auth: {
      secretStore: daprSecretStore.name
    }
  }
}

I'll make some functional tests with the curent implementation first as @ytimocin suggested before going forward with the changes we decide on.

@SoTrx SoTrx force-pushed the feat_dapr-secret-store branch 3 times, most recently from 3f7c87e to a417124 Compare August 30, 2024 12:51
@SoTrx
Copy link
Contributor Author

SoTrx commented Aug 30, 2024

The current implementation follow this schema :

resource stateStore 'Applications.Dapr/stateStores@2023-10-01-preview' = {
  name: 'statestore'
  properties: {
    environment: environment
    application: application
    resourceProvisioning: 'manual'
    type: 'state.redis'
    version: 'v1'
    metadata: {
      redisHost: {
        secretKeyRef: {
            name: 'redisHost'
            key: 'redisHost'
        }
      }
      redisPassword: {
        value: ''
      }
    }
    secretStoreComponentName: daprSecretStore.name
  }
}

Should I change secretStoreComponentName to auth.secretStore as well?

Let me know if you need any further adjustments

@rynowak
Copy link
Contributor

rynowak commented Aug 30, 2024

Should I change secretStoreComponentName to auth.secretStore as well?

Let me know if you need any further adjustments

I'm on board with this 👍. I think it's good if we align to the Dapr component schema. Then it will be easy to update Radius as Dapr continues to add features.

Taking a look now! Thanks for working through this.

Copy link
Contributor

@rynowak rynowak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking awesome overall. Can you make the schema changes?

@SoTrx SoTrx force-pushed the feat_dapr-secret-store branch 3 times, most recently from 408af4a to a6799ac Compare September 4, 2024 16:35
@SoTrx SoTrx requested a review from rynowak September 4, 2024 17:03
Copy link
Contributor

@rynowak rynowak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow this looks great! Thanks @SoTrx

@radius-functional-tests
Copy link

radius-functional-tests bot commented Sep 5, 2024

Radius functional test overview

🔍 Go to test action run

Name Value
Repository SoTrx/radius
Commit ref a6799ac
Unique ID func9e97a8a57a
Image tag pr-func9e97a8a57a
Click here to see the list of tools in the current test run
  • gotestsum 1.12.0
  • KinD: v0.20.0
  • Dapr: 1.12.0
  • Azure KeyVault CSI driver: 1.4.2
  • Azure Workload identity webhook: 1.3.0
  • Bicep recipe location ghcr.io/radius-project/dev/test/testrecipes/test-bicep-recipes/<name>:pr-func9e97a8a57a
  • Terraform recipe location http://tf-module-server.radius-test-tf-module-server.svc.cluster.local/<name>.zip (in cluster)
  • applications-rp test image location: ghcr.io/radius-project/dev/applications-rp:pr-func9e97a8a57a
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-func9e97a8a57a
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-func9e97a8a57a
  • deployment-engine test image location: ghcr.io/radius-project/deployment-engine:latest

Test Status

⌛ Building Radius and pushing container images for functional tests...
✅ Container images build succeeded
⌛ Publishing Bicep Recipes for functional tests...
✅ Recipe publishing succeeded
⌛ Starting datastoresrp-cloud functional tests...
⌛ Starting corerp-cloud functional tests...
⌛ Starting ucp-cloud functional tests...
✅ datastoresrp-cloud functional tests succeeded
✅ corerp-cloud functional tests succeeded
✅ ucp-cloud functional tests succeeded

@rynowak rynowak temporarily deployed to functional-tests September 5, 2024 02:05 — with GitHub Actions Inactive
@radius-functional-tests
Copy link

radius-functional-tests bot commented Sep 5, 2024

Radius functional test overview

🔍 Go to test action run

Name Value
Repository SoTrx/radius
Commit ref b1583ad
Unique ID funcca270f866c
Image tag pr-funcca270f866c
Click here to see the list of tools in the current test run
  • gotestsum 1.12.0
  • KinD: v0.20.0
  • Dapr: 1.12.0
  • Azure KeyVault CSI driver: 1.4.2
  • Azure Workload identity webhook: 1.3.0
  • Bicep recipe location ghcr.io/radius-project/dev/test/testrecipes/test-bicep-recipes/<name>:pr-funcca270f866c
  • Terraform recipe location http://tf-module-server.radius-test-tf-module-server.svc.cluster.local/<name>.zip (in cluster)
  • applications-rp test image location: ghcr.io/radius-project/dev/applications-rp:pr-funcca270f866c
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-funcca270f866c
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-funcca270f866c
  • deployment-engine test image location: ghcr.io/radius-project/deployment-engine:latest

Test Status

⌛ Building Radius and pushing container images for functional tests...
✅ Container images build succeeded
⌛ Publishing Bicep Recipes for functional tests...
✅ Recipe publishing succeeded
⌛ Starting ucp-cloud functional tests...
⌛ Starting corerp-cloud functional tests...
⌛ Starting datastoresrp-cloud functional tests...
✅ ucp-cloud functional tests succeeded
✅ datastoresrp-cloud functional tests succeeded
✅ corerp-cloud functional tests succeeded

SoTrx and others added 5 commits September 4, 2024 22:27
BREAKING CHANGE: All Dapr components metadata are now parsed as objects instead of their previous format. All string-based values will break

Signed-off-by: SoTrx <[email protected]>
…ll Dapr components

BREAKING CHANGE: The property `secretStoreComponentName` has been replaced with `auth.secretStore`. This change requires updates to any references to the old property.
Signed-off-by: SoTrx <[email protected]>
@ytimocin ytimocin force-pushed the feat_dapr-secret-store branch from b1583ad to 883e043 Compare September 5, 2024 05:27
@radius-functional-tests
Copy link

radius-functional-tests bot commented Sep 5, 2024

Radius functional test overview

🔍 Go to test action run

Name Value
Repository SoTrx/radius
Commit ref 883e043
Unique ID func898d558925
Image tag pr-func898d558925
Click here to see the list of tools in the current test run
  • gotestsum 1.12.0
  • KinD: v0.20.0
  • Dapr: 1.12.0
  • Azure KeyVault CSI driver: 1.4.2
  • Azure Workload identity webhook: 1.3.0
  • Bicep recipe location ghcr.io/radius-project/dev/test/testrecipes/test-bicep-recipes/<name>:pr-func898d558925
  • Terraform recipe location http://tf-module-server.radius-test-tf-module-server.svc.cluster.local/<name>.zip (in cluster)
  • applications-rp test image location: ghcr.io/radius-project/dev/applications-rp:pr-func898d558925
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-func898d558925
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-func898d558925
  • deployment-engine test image location: ghcr.io/radius-project/deployment-engine:latest

Test Status

⌛ Building Radius and pushing container images for functional tests...
✅ Container images build succeeded
⌛ Publishing Bicep Recipes for functional tests...
✅ Recipe publishing succeeded
⌛ Starting corerp-cloud functional tests...
⌛ Starting datastoresrp-cloud functional tests...
⌛ Starting ucp-cloud functional tests...
✅ datastoresrp-cloud functional tests succeeded
✅ corerp-cloud functional tests succeeded
✅ ucp-cloud functional tests succeeded

@ytimocin ytimocin merged commit a1ab146 into radius-project:main Sep 5, 2024
29 checks passed
@SoTrx SoTrx deleted the feat_dapr-secret-store branch September 6, 2024 08:48
kachawla added a commit to radius-project/samples that referenced this pull request Sep 6, 2024
* Dapr Resource Schema Update

More context: radius-project/radius#7823

Signed-off-by: karishma-chawla <[email protected]>

* Update env vars schema

Related to: #1742

Signed-off-by: karishma-chawla <[email protected]>

---------

Signed-off-by: karishma-chawla <[email protected]>
Co-authored-by: karishma-chawla <[email protected]>
@kachawla
Copy link
Contributor

@SoTrx Thank you for contributing. We have updated the samples to reflect these changes. Could you please update the docs corresponding to this feature? For example, here.

@kachawla
Copy link
Contributor

kachawla commented Sep 24, 2024

Wow thanks for sending this. This is a big improvement. I'll take a look at this tomorrow.

Normally we might ask for an design document for an API change, but I think we can skip that in this case:

  • It's a very small change
  • It has an approved issue that describes the API change.
  • It's aligned with the naming and design of the existing Dapr API - which we're trying to match.

@radius-project/maintainers-radius holler if you have any concerns.

@rynowak missed this notification. I agree it's ok to skip design documents for such changes, but if a change changes an api then an overview of the updated schema, samples and doc updates should be needed regardless of the scope of change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reference secrets in components for Dapr resources
4 participants