Summary
The litellm_key resource accepts an optional key input field (declared WriteOnly: true, added in v0.2.0) that is intended to let users supply a pre-determined key value to /key/generate. However, the supplied value is silently ignored — mapResourceDataToKey never reads the key field, so Key.Key is always empty when CreateKey is called. LiteLLM then generates its own key, which never matches the value the caller provided.
Root Cause
d.Get("key") always returns "" for write-only attributes — this is intentional SDK behaviour: the Terraform Plugin SDK v2 clears write-only fields from ResourceData after plan to prevent state persistence. The correct approach is d.GetRawConfig().GetAttr("key"), which reads the value from the raw plan config before it is cleared.
mapResourceDataToKey in resource_key.go (line 204) reads every other field from ResourceData but has no handling for key:
// resource_key.go line 204 — key field is never read
func mapResourceDataToKey(d *schema.ResourceData, key *Key) {
key.Models = expandStringList(d.Get("models").([]interface{}))
key.UserID = d.Get("user_id").(string)
key.TeamID = d.Get("team_id").(string)
// ... all other fields ...
// "key" is never set on key.Key
}
Additionally, resourceKeyCreate calls d.Set("key", createdKey.Key) before resourceKeyRead, which immediately overwrites it with nil (SDK clears write-only fields on Read):
// resource_key.go line 155 — key is overwritten to nil by resourceKeyRead
d.Set("key", createdKey.Key)
return resourceKeyRead(ctx, d, m) // clears write-only → key lost
Proposed Fix
Two changes in resource_key.go:
1. Read the supplied key via GetRawConfig in mapResourceDataToKey:
func mapResourceDataToKey(d *schema.ResourceData, key *Key) {
if rawKey := d.GetRawConfig().GetAttr("key"); rawKey.IsKnown() && !rawKey.IsNull() {
key.Key = rawKey.AsString()
}
key.Models = expandStringList(d.Get("models").([]interface{}))
// ...
}
2. Re-set the write-only value after resourceKeyRead in resourceKeyCreate:
// Before:
d.Set("key", createdKey.Key)
return resourceKeyRead(ctx, d, m)
// After:
diags := resourceKeyRead(ctx, d, m)
d.Set("key", createdKey.Key)
return diags
Reproduction
resource "random_password" "vkey" {
length = 22
special = false
}
resource "litellm_key" "team" {
key = "sk-${random_password.vkey.result}"
team_id = litellm_team.team.id
key_alias = "my-team-vkey"
duration = "90d"
}
After terraform apply, the key registered in LiteLLM does not match "sk-${random_password.vkey.result}" — LiteLLM generated its own key and the supplied value was dropped.
Why This Matters
Without this fix it is impossible to use litellm_key in combination with aws_ssm_parameter (or any other resource) to deliver the key value to consumers — the key output is write-only and cannot be referenced, and the supplied input is silently ignored, leaving no way to retrieve the actual key value from Terraform.
Environment
- Provider:
BerriAI/litellm v0.2.1
- Terraform: >= 1.11
- LiteLLM: OSS (non-Enterprise)
Summary
The
litellm_keyresource accepts an optionalkeyinput field (declaredWriteOnly: true, added in v0.2.0) that is intended to let users supply a pre-determined key value to/key/generate. However, the supplied value is silently ignored —mapResourceDataToKeynever reads thekeyfield, soKey.Keyis always empty whenCreateKeyis called. LiteLLM then generates its own key, which never matches the value the caller provided.Root Cause
d.Get("key")always returns""for write-only attributes — this is intentional SDK behaviour: the Terraform Plugin SDK v2 clears write-only fields fromResourceDataafter plan to prevent state persistence. The correct approach isd.GetRawConfig().GetAttr("key"), which reads the value from the raw plan config before it is cleared.mapResourceDataToKeyinresource_key.go(line 204) reads every other field fromResourceDatabut has no handling forkey:Additionally,
resourceKeyCreatecallsd.Set("key", createdKey.Key)beforeresourceKeyRead, which immediately overwrites it withnil(SDK clears write-only fields on Read):Proposed Fix
Two changes in
resource_key.go:1. Read the supplied key via
GetRawConfiginmapResourceDataToKey:2. Re-set the write-only value after
resourceKeyReadinresourceKeyCreate:Reproduction
After
terraform apply, the key registered in LiteLLM does not match"sk-${random_password.vkey.result}"— LiteLLM generated its own key and the supplied value was dropped.Why This Matters
Without this fix it is impossible to use
litellm_keyin combination withaws_ssm_parameter(or any other resource) to deliver the key value to consumers — thekeyoutput is write-only and cannot be referenced, and the supplied input is silently ignored, leaving no way to retrieve the actual key value from Terraform.Environment
BerriAI/litellmv0.2.1