-
Notifications
You must be signed in to change notification settings - Fork 375
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
I want to import existing KMS keys instead of creating new ones #1740
Comments
I feel like 2. is better for handling cases where the same KMS key is shared by multiple resources or when multiple Aliases point to the same key. |
Crossplane does not currently have enough maintainers to address every issue and pull request. This issue has been automatically marked as |
/fresh |
Is this issue about Regarding the import of existing KMS keys as a new |
Yes, that's correct.
Who should perform this late initialization? The provider itself, right? Keep in mind we're using a selector, not an ID directly to reference the Key, because the key might not exist yet. The Assuming the provider should populate
Ok, but that doesn't seem to play very well with GitOps. If that's something we're aiming for here, I think this needs addressing. Picture this use case, where the actor is the developer team, using the composition provided by the platform team:
This leads to the Provider creating a new KMS key, which is unwanted and leaks money. In order to fix this, according to what you're saying, the KMS Key resource should be recreated with an annotation to inform the ID of the existing Key, but how could this be achieved, given that:
|
This is, unfortunately, the way AWS works with KMS keys: You either provide the ID of an existing key or you get a new one with a random ID assigned. It works the same for other AWS APIs, such as VPCs and subnets. Its not very nice indeed. I don't think there is anything we can do in the provider to work around this effeciently. The provider is, by design, only a simple delegate that mirrors the AWS API into K8s. However, I think you can solve your problem on a higher level by moving key and DBCluster into two separate compositions / XRDs. Since the lifetime of your key seems to not be coupled to that of your DB (hence the orphan deletion) it makes sense to do that anyways. This approach would also comply to the GitOps workflow. Does this help you? |
Thank you @MisterMX, I understand the desire to keep things simple here at the provider level. There are other places where this exact mirroring architecture combined with the (also by design) simplicity of Crossplane compositions that caused us some annoyances, such as arrays which would more naturally be defined as maps (eg tags). Hopefully composition functions will assist with this, but that comes with its own trade-offs, maintainability and availability concerns for us. We really want to keep things at a single "package", that provides and manages everything necessary for a Database. I don't think it would be good from an UX perspective to make users first provision the KMS, and only then provision the DBCluster (as I believe would be necessary if we split it all into 2 separate compositions). We will probably want to fix this some other way, but keep this suggestion close to heart. Maybe some cleanup recurring job, idk. |
For anyone having to deal with this, we were able to import an existing Key, by using the The observe composition is something like this: apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
labels:
crossplane.io/xrd: xgetkmss.foo
provider: default.getkms.foo
name: xgetkms.foo
spec:
compositeTypeRef:
apiVersion: foo/v1alpha1
kind: XGetKMS
resources:
- name: observeKmsAlias
base:
apiVersion: kms.aws.upbound.io/v1beta1
kind: Alias
spec:
deletionPolicy: Orphan
forProvider:
region: my-region
managementPolicies:
- 'Observe'
readinessChecks:
- type: None
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.myAlias
toFieldPath: metadata.annotations[crossplane.io/external-name]
- type: ToCompositeFieldPath
fromFieldPath: status.conditions[0].status
toFieldPath: status.kmsKeyId
transforms:
- type: match
match:
patterns:
- type: literal
literal: "False"
result: ""
fallbackTo: Input
- type: ToCompositeFieldPath
fromFieldPath: status.atProvider.targetKeyId
toFieldPath: status.kmsKeyId then, on the KMS Key resources, the patch would be like: - type: FromCompositeFieldPath
fromFieldPath: status.kmsKeyId
toFieldPath: metadata.annotations[crossplane.io/external-name]
policy:
fromFieldPath: Required |
What problem are you facing?
We have a composition that manages RDS Aurora clusters. In it, besides the DBCluster, we manage a KMS key. This key is used to encrypt the DB's data.
On creation, this works great. The Key is created and correctly associated with the DBCluster.
We always set the the Key's
.spec.deletionPolicy
to beOrphan
, because we want previous snapshots taken with that Key to continue to be available long after the RDS is gone.However, if
.spec.deletionPolicy
of the DBCluster is set toOrphan
and we delete the claim from Kubernetes, then re-create it, the DBCluster gets imported (as expected). What's not so expected, is that another Key is created. The DBCluster continues to use the previous Key, so this new Key isn't being used at all.From the research I performed, it's impossible to change the KMS of a DBCluster.
Additionally, I'm guessing the existing key isn't imported because its identifier is random, meaning the provider has no way of finding the existing key in order to import it.
These lingering additional keys are a problem, since "Each AWS KMS key that you create in AWS KMS costs $1/month (prorated hourly)", not to mention that cloud organization becomes kind of a mess.
How could Crossplane help solve your problem?
I'm thinking of two approaches:
.spec.forProvider
. It should check if the resource already has a Key bound to it, and import that key if does. If there is no bound key, it should be created.Looking forward to hearing alternatives, as to be honest I think both of these sound pretty complex. It would be much easier if we could just search for the Key using a name instead of a non-deterministic string/ID.
The text was updated successfully, but these errors were encountered: