-
Notifications
You must be signed in to change notification settings - Fork 14
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
Adding design doc for to extend the capabilities of secretStores to a global scope #38
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
# Adding support to extend the capabilities of secretStores to a global scope. | ||
|
||
* **Status**: Pending | ||
* **Author**: Vishwanath Hiremath (@vishwahiremat) | ||
|
||
## Overview | ||
|
||
Today we have Application.Core/secretStores resource to securely manage secrets for the Application. However a gap exists if user wants to create a secret before application or environment is created. To address this limitation, we need to enhance the capabilities of the existing secretStores resource. The objective is to extend its support to a global scope, enabling users to store secrets prior to the creation of the application or environment. | ||
|
||
|
||
## Terms and definitions | ||
| Term | Definition | | ||
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| Global scope | The ability of the secretStores resource to operate universally, allowing users to manage secrets independently of a particular application or environment. | | ||
| secretStores | Resource used to securely manage secrets for Environment and Application. | | ||
| Private Terraform Repository | A private Terraform repository typically refers to a version control repository that contains Terraform module code, but is not publicly accessible. | | ||
|
||
## Objectives | ||
|
||
> **Issue Reference:** https://github.com/radius-project/radius/issues/7030 | ||
|
||
### Goals | ||
|
||
- Enable support to extend the capabilities of secretStores to a global scope. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something I am curious about is whether this type should move to UCP. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we have usecases for this type in other parts of UCP then it would be better to rename/move than it would be to have two different secret types. |
||
### Non goals | ||
kachawla marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- To move secret store resource as part of UCP. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vishwahiremat Please log an issue to revisit this when you get a chance |
||
|
||
### User scenarios (optional) | ||
|
||
#### User story 1 | ||
As a operator I define and curate the set of terraform recipes that developers in my organization rely on. And these terraform modules are stored in a private module sources (e.g private git repository). I would need to securely store the credential information or use the existing secret (e.g kubernetes secret) with credential information. So it can be used while creating the env and registering recipes. | ||
|
||
```diff | ||
resource env 'Applications.Core/environments@2023-10-01-preview' = { | ||
name: 'dsrp-resources-env-recipes-context-env' | ||
location: 'global' | ||
properties: { | ||
compute: { | ||
... | ||
} | ||
providers: { | ||
... | ||
} | ||
recipeConfig: { | ||
terraform: { | ||
authentication:{ | ||
git:{ | ||
pat: { | ||
"dev.azure.com": { | ||
+ secret: secretStoreAzure.id | ||
} | ||
"github.com": { | ||
+ secret: secretStoreGithub.id | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
recipes: { | ||
'Applications.Datastores/mongoDatabases':{ | ||
default: { | ||
templateKind: 'terraform' | ||
templatePath: 'https://dev.azure.com/test-private-repo' | ||
} | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
|
||
## Design | ||
Today we use Application.Core/secretstores resource to store secrets/credentials information for an application but we cannot use it in this scenario as secretStores is application scoped and expects to have an application created before we create a secretStore. | ||
|
||
And we cannot have secretStore created for environment scope in this scenario as we are adding the secret to the environment which creates cyclic dependency between environment and secretStore resource. | ||
|
||
#### Application.Core/secretStores as a global scoped resource. | ||
We could make secretStores as a global scoped resource by removing application as a required property. | ||
|
||
```diff | ||
"SecretStoreProperties": { | ||
"type": "object", | ||
"description": "The properties of SecretStore", | ||
"properties": { | ||
"environment": { | ||
... | ||
}, | ||
"application": { | ||
... | ||
}, | ||
"provisioningState": { | ||
... | ||
}, | ||
"status": { | ||
... | ||
}, | ||
"type": { | ||
... | ||
}, | ||
"data": { | ||
"type": "object", | ||
"description": "An object to represent key-value type secrets", | ||
"additionalProperties": { | ||
"$ref": "#/definitions/SecretValueProperties" | ||
} | ||
}, | ||
"resource": { | ||
"type": "string", | ||
"description": "The resource id of external secret store." | ||
} | ||
}, | ||
"required": [ | ||
- "application", | ||
"data" | ||
] | ||
}, | ||
``` | ||
With this change we can create a secret store resource before an application or environment is created. But, if the user is creating a secretStore of kind kubernetes secret, it is deployed in application/environment namespace. But for secret resource with global scope use the `resource` property which is used to specify the secret ref of the existing secret to provide namespace and secret name details. User is expected to provide these details in `<namespace>/<secretName>` format for secretStore with global scope. | ||
|
||
```diff | ||
resource secretStore 'Applications.Core/secretStores@2023-10-01-preview' = { | ||
name: 'github' | ||
properties:{ | ||
- app: app.id | ||
+ resource: <namespace>/<secretName> | ||
kachawla marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternatively, we might be able to use UCP style resource id instead of using e.g.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the initial proposal of secretstore, we proposed using full resource id for Azure KeyVault in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's talk about the semantics of this field.
vishwahiremat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
type: 'generic' | ||
data: { | ||
'pat': { | ||
value: '<personal-access-token>' | ||
} | ||
'username': { | ||
value: '<username>' | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### API design | ||
|
||
#### Typespec changes | ||
|
||
radius/typespec/radius/v1/resources.tsp | ||
```diff | ||
+@doc("Base properties of a Global-scoped resource") | ||
+model GlobalScopedResource { | ||
+ @doc("Fully qualified resource ID for the environment that the application is linked to") | ||
+ environment?: string; | ||
|
||
+ @doc("Fully qualified resource ID for the application") | ||
+ application?: string; | ||
|
||
+ @doc("The status of the asynchronous operation.") | ||
+ @visibility("read") | ||
+ provisioningState?: ProvisioningState; | ||
|
||
+ @doc("Status of a resource.") | ||
+ @visibility("read") | ||
+ status?: ResourceStatus; | ||
+} | ||
``` | ||
|
||
typespec/Applications.Core/secretstores.tsp | ||
|
||
```diff | ||
@doc("The properties of SecretStore") | ||
model SecretStoreProperties { | ||
- ...ApplicationScopedResource; | ||
+ ...GlobalScopedResource; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since this is new type, pls describe it in detail |
||
|
||
#suppress "@azure-tools/typespec-azure-resource-manager/arm-resource-duplicate-property" | ||
@doc("The type of secret store data") | ||
type?: SecretStoreDataType = SecretStoreDataType.generic; | ||
|
||
@doc("An object to represent key-value type secrets") | ||
data: Record<SecretValueProperties>; | ||
|
||
@doc("The resource id of external secret store.") | ||
resource?: string; | ||
} | ||
``` | ||
|
||
## Alternatives considered | ||
|
||
#### Adding default a namespace for global scoped secretstore resource. | ||
Add a default namespace `global-secretStores` to store the global scoped secretStores. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or we could use |
||
|
||
```diff | ||
resource secretStore 'Applications.Core/secretStores@2023-10-01-preview' = { | ||
name: 'github' | ||
properties:{ | ||
- app: app.id | ||
type: 'generic' | ||
data: { | ||
'pat': { | ||
value: '<personal-access-token>' | ||
} | ||
'username': { | ||
value: '<username>' | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
|
||
#### Adding a new property `namespace` | ||
|
||
Add a new property `namespace` for kubernetes secret type. | ||
```diff | ||
resource secretStore 'Applications.Core/secretStores@2023-10-01-preview' = { | ||
name: 'github' | ||
properties:{ | ||
- app: app.id | ||
type: 'generic' | ||
+ namespace: <namespace> | ||
data: { | ||
'pat': { | ||
value: '<personal-access-token>' | ||
} | ||
'username': { | ||
value: '<username>' | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
for existing kubernetes secret | ||
```diff | ||
resource secretStore 'Applications.Core/secretStores@2023-10-01-preview' = { | ||
name: 'github' | ||
properties:{ | ||
- app: app.id | ||
type: 'generic' | ||
+ namespace: <namespace> | ||
+ resource: <secretName> | ||
data: { | ||
'pat': {} | ||
'username': {} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
## Test plan | ||
|
||
Unit tests: | ||
- Update and add unit tests for changes in conversions for secret store. | ||
|
||
Functional Tests: | ||
- Functional test for private repository support takes care of this scenario. | ||
|
||
## Development plan | ||
|
||
Tasks: | ||
- Adding typespec changes and conversions to secretstores resource. | ||
- Adding unit tests for conversions. | ||
- Updating secretStores frontend controller to support global scope. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does the secretstore decide what Kubernetes namespace to use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By asking the users to provide
resource
property in the format of / if secret stores is a global scoped.https://github.com/radius-project/design-notes/pull/38/files#diff-89d84238f05b572cd71ded0059391247faab67f69d3d9232b31350325b946cfaR125:~:text=%2B%20%20%20resource%3A%20%3Cnamespace%3E/%3C-,secretName,-%3E
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we're talking about the same thing. Let me try being more specific.
If I create an
Applications.Core/secretStores
resource today and I don't specify the kubernetes secret name + namespace, then it will use the namespace of the application (or environment).For the global secret case, there's no application or environment, so there's no way to look up the namespace we're going to use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From reading more of the doc, it looks like you did try to address this feedback as part of the proposal. Let's talk about it 👍