-
Notifications
You must be signed in to change notification settings - Fork 9
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
Skip 004 - Cloud Identity and Access Management #9
Draft
devigned
wants to merge
1
commit into
spinkube:main
Choose a base branch
from
devigned:004
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
# SKIP 004 - Cloud Identity and Access Management | ||
|
||
Summary: Many cloud Kubernetes services offer OIDC integration for authentication and authorization. This SKIP proposes to provide an opinionated way to manage IAM for SpinApps using workload identity and OIDC. | ||
|
||
Owner: [email protected] (David Justice) | ||
|
||
Impacted Projects: | ||
|
||
- [x] spin-operator | ||
- [ ] `spin kube` plugin | ||
- [ ] runtime-class-manager | ||
- [ ] containerd-shim-spin | ||
- [ ] Governance | ||
- [ ] Creates a new project | ||
|
||
Created: July 25th, 2024 | ||
|
||
Updated: N/A | ||
|
||
## Background | ||
|
||
A Spin application is likely to use cloud services to peform tasks such as storing data, fetching runtime configuration variables, and other related tasks. These services often require IAM permissions to access. The current method of authentication is to load secrets into the runtime configuration for authentication to services. This is not ideal because it requires the developer to manage the secrets and the secrets are not rotated automatically. | ||
|
||
## Proposal | ||
|
||
Each SpinApp should be able to have a cloud identity associated with it granting access to the cloud resources it requires. This identity should be managed by the Spin operator and should be associated with the workload identity of the application. The workload identity should be associated with an OIDC provider, which can be used to authenticate to cloud services. The Spin operator should be able to reconcile the necessary cloud and cluster resources to enable this. | ||
|
||
Multiple cloud providers support Kubernetes service account OIDC integration. For example: | ||
- [Google Cloud](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) | ||
- [AWS](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) | ||
- [Azure](https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview) | ||
|
||
### SpinApp Resource Structure | ||
#### SpinApp with Azure Workload Identity using Key Vault and CosmosDB | ||
The yaml below shows an example of a SpinApp resource that uses Azure Workload Identity to authenticate to Azure Key Vault and CosmosDB. The `workloadIdentity` field is used to enable workload identity and specify the providers and service account to use. The `providers` field is used to specify the cloud providers that the workload identity will use. The `variableProviders` field is used to specify the variable providers that the workload identity will use. The `keyValueProviders` field is used to specify the key value providers that the workload identity will use. The `serviceAccount` field is used to specify the service account that the operator should create and associate to the workload. | ||
|
||
```yaml | ||
apiVersion: core.spinoperator.dev/v1alpha1 | ||
kind: SpinApp | ||
metadata: | ||
name: wid-spinapp | ||
spec: | ||
image: "ghcr.io/spinkube/containerd-shim-spin/examples/spin-rust-hello:v0.13.0" | ||
replicas: 1 | ||
executor: containerd-shim-spin | ||
workloadIdentity: | ||
enabled: true | ||
providers: | ||
azure: | ||
tenantId: "9b9924f3-596a-4b18-a251-3de9eeef2bbc" | ||
variableProviders: | ||
- type: keyvault | ||
uri: "https://my-keyvault.vault.azure.net/" | ||
keyValueProviders: | ||
- type: cosmosdb | ||
account: "my-cosmosdb" | ||
database: "my-database" | ||
container: "my-container" | ||
serviceAccount: "my-service-account" | ||
``` | ||
|
||
In this case the operator would be responsible for provisioning the following Azure resources, a user-assigned managed identity in Azure, an Azure Federated Identity Credential using the cluster's OIDC issurer URL, a CosmosDB SQL role assignment for read/write to the collection, and the Key Vault access policy to read secrets. Once those Azure resources have been created, then the operator should reconcile the service account and the SpinApp deployment. | ||
|
||
The operator would then need to create the following Kubernetes resources (some details omitted for brevity): | ||
```yaml | ||
apiVersion: v1 | ||
kind: ServiceAccount | ||
metadata: | ||
annotations: | ||
"azure.workload.identity/client-id": "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY" # The client ID of the user-assigned managed identity | ||
name: "my-service-account" | ||
--- | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: wid-spinapp | ||
spec: | ||
template: | ||
metadata: | ||
labels: | ||
"azure.workload.identity/use": "true" | ||
spec: | ||
containers: | ||
- name: wid-spinapp | ||
image: "ghcr.io/spinkube/containerd-shim-spin/examples/spin-rust-hello:v0.13.0" | ||
``` | ||
|
||
#### SpinApp with Azure Workload Identity using an Existing Identity | ||
The yaml below shows an example of a SpinApp resource that uses Azure Workload Identity using a pre-existing identity. This is useful for when the operator is not able to create identities. For example, if a company does not allow the operator rights to create identities, and identities must be created via a security team. | ||
|
||
In this case, the operator would not try to create the identity, but would instead use the existing identity and reconcele the service account and decorate the deployment with the necessary annotations and service account name. | ||
|
||
```yaml | ||
apiVersion: core.spinoperator.dev/v1alpha1 | ||
kind: SpinApp | ||
metadata: | ||
name: wid-spinapp | ||
spec: | ||
image: "ghcr.io/spinkube/containerd-shim-spin/examples/spin-rust-hello:v0.13.0" | ||
replicas: 1 | ||
executor: containerd-shim-spin | ||
workloadIdentity: | ||
enabled: true | ||
providers: | ||
azure: | ||
tenantID: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" | ||
clientID: "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY" # The client ID of the user-assigned managed identity | ||
serviceAccount: "my-service-account" | ||
``` | ||
|
||
The operator would then need to create the following resources (some details omitted for brevity): | ||
```yaml | ||
apiVersion: v1 | ||
kind: ServiceAccount | ||
metadata: | ||
annotations: | ||
"azure.workload.identity/client-id": "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY" | ||
name: "my-service-account" | ||
--- | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: wid-spinapp | ||
spec: | ||
template: | ||
metadata: | ||
labels: | ||
"azure.workload.identity/use": "true" | ||
spec: | ||
containers: | ||
- name: wid-spinapp | ||
image: "ghcr.io/spinkube/containerd-shim-spin/examples/spin-rust-hello:v0.13.0" | ||
``` | ||
|
||
#### SpinApp with Google Cloud Workload Identity | ||
TODO(DJ) | ||
|
||
#### SpinApp with AWS Workload Identity | ||
TODO(DJ) | ||
|
||
## Alternatives Considered | ||
|
||
I believe the alternative is to continue using the runtime configuration model where secrets can be stored in a secure vault. There will still need to be an initial secret to access the vault, which isn't ideal, but it is a common pattern. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Does the user need the ability to enable/disable workload identity within the manifest? I'm wondering if the presence of
providers
,serviceAccount
, or other fields not beingnil
is enough to consider that the user is opting into workload identity or not.If this is the wrong place to debate the schema of the
workloadIdentity
object, let me know. :)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.
You, sir, have come to the right place. Step on up to debate the schema!!
I'm indifferent about the
enabled
field. Truth be told, I deleted 1 less time than I typed it. I believe that having a provider and service account defined may be adequate to determine the behavior is enabled.