Skip to content

[IDENTITY-7450] Support Global Key - Store & Use#3377

Open
Taohao Wang (taohaowang) wants to merge 3 commits into
mainfrom
cli-global-api-key-store-use
Open

[IDENTITY-7450] Support Global Key - Store & Use#3377
Taohao Wang (taohaowang) wants to merge 3 commits into
mainfrom
cli-global-api-key-store-use

Conversation

@taohaowang
Copy link
Copy Markdown
Contributor

@taohaowang Taohao Wang (taohaowang) commented Jun 1, 2026

Release Notes

Breaking Changes

  • PLACEHOLDER

New Features

  • confluent api-key create, store, and use now support org-scoped Global API keys. Global keys are stored locally (separate from cluster-scoped keys) and can be selected as the active key with confluent api-key use <key>.
  • confluent kafka topic produce/consume and confluent kafka client-config create now fall back to the active Global API key when the target cluster has no cluster-scoped API key configured. (?)

Bug Fixes

  • PLACEHOLDER

Checklist

  • I have successfully built and used a custom CLI binary, without linter issues from this PR.
  • I have clearly specified in the What section below whether this PR applies to Confluent Cloud, Confluent Platform, or both.
  • I have verified this PR in Confluent Cloud pre-prod or production environment, if applicable.
  • I have verified this PR in Confluent Platform on-premises environment, if applicable.
  • I have attached manual CLI verification results or screenshots in the Test & Review section below.
  • I have added appropriate CLI integration or unit tests for any new or updated commands and functionality.
  • I confirm that this PR introduces no breaking changes or backward compatibility issues.
  • I have indicated the potential customer impact if something goes wrong in the Blast Radius section below.
  • I have put checkmarks below confirming that the feature associated with this PR is enabled in:
    • Confluent Cloud prod
    • Confluent Cloud stag
    • Confluent Platform
    • Check this box if the feature is enabled for certain organizations only

What

Blast Radius

References

https://confluentinc.atlassian.net/browse/IDENTITY-7450

Test & Review

Copilot AI review requested due to automatic review settings June 1, 2026 16:07
@taohaowang Taohao Wang (taohaowang) requested a review from a team as a code owner June 1, 2026 16:07
@confluent-cla-assistant
Copy link
Copy Markdown

🎉 All Contributor License Agreements have been signed. Ready to merge.
Please push an empty commit if you would like to re-run the checks to verify CLA status for all contributors.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds first-class support for org-scoped “Global” API keys in the CLI’s local state so they can be stored, selected via confluent api-key use, and used as a fallback for Kafka client operations when no cluster-scoped key is configured.

Changes:

  • Extend config.Context to persist Global API key pairs and an “active” Global key, including validation and secret encrypt/decrypt helpers.
  • Update Kafka produce/consume + client config generation to resolve credentials via a new Context.ResolveKafkaAPIKey() (cluster-scoped preferred, Global fallback).
  • Update api-key create, api-key store, and api-key use to detect/store/use Global API keys and persist the active Global selection.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pkg/keystore/keystore.go Deletes Global keys on DeleteAPIKey; adds Global key store/has helpers.
pkg/config/context.go Adds Global API key storage to context, validation, encryption helpers, and Kafka credential resolution logic.
pkg/config/context_test.go Adds unit tests for Global API key storage and Kafka credential resolution behavior.
pkg/config/config_test.go Initializes GlobalAPIKeys in test contexts to match new context shape.
internal/kafka/confluent_kafka.go Threads *config.Context into producer/consumer creation to support Global credential resolution.
internal/kafka/confluent_kafka_configs.go Builds Kafka config using Context.ResolveKafkaAPIKey() instead of cluster-only fields.
internal/kafka/command_topic.go Allows Kafka topic produce/consume to proceed without cluster-scoped key if an active Global key exists.
internal/kafka/command_topic_produce.go Passes context into producer creation and API key validation helper.
internal/kafka/command_topic_consume.go Passes context into consumer creation and API key validation helper.
internal/kafka/command_clientconfig_create.go Uses resolved credentials (cluster/global) when templating client configs and validating creds.
internal/api-key/command_use.go Supports api-key use selecting a stored Global key when --resource isn’t set.
internal/api-key/command_store.go Detects Global keys (via --resource global or server Kind) and stores them in the Global keystore.
internal/api-key/command_create.go Stores Global key secrets locally on creation and supports --use activating the Global key.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/config/context.go
Comment on lines +593 to +599
func (c *Context) StoreGlobalAPIKey(pair *APIKeyPair) error {
if c.GlobalAPIKeys == nil {
c.GlobalAPIKeys = map[string]*APIKeyPair{}
}
c.GlobalAPIKeys[pair.Key] = pair
return c.EncryptGlobalAPIKeys()
}
Comment thread pkg/config/context.go
Comment on lines +639 to +655
func (c *Context) ResolveKafkaAPIKey(kcc *KafkaClusterConfig) (string, string, error) {
if kcc != nil && kcc.APIKey != "" {
if pair, ok := kcc.APIKeys[kcc.APIKey]; ok {
if err := pair.DecryptSecret(); err != nil {
return "", "", err
}
return pair.Key, pair.Secret, nil
}
}
if pair := c.GetActiveGlobalAPIKeyPair(); pair != nil {
if err := pair.DecryptSecret(); err != nil {
return "", "", err
}
return pair.Key, pair.Secret, nil
}
return "", "", nil
}
Comment thread pkg/config/context.go
Comment on lines +593 to +599
func (c *Context) StoreGlobalAPIKey(pair *APIKeyPair) error {
if c.GlobalAPIKeys == nil {
c.GlobalAPIKeys = map[string]*APIKeyPair{}
}
c.GlobalAPIKeys[pair.Key] = pair
return c.EncryptGlobalAPIKeys()
}
Comment thread pkg/config/context.go
Comment on lines +639 to +655
func (c *Context) ResolveKafkaAPIKey(kcc *KafkaClusterConfig) (string, string, error) {
if kcc != nil && kcc.APIKey != "" {
if pair, ok := kcc.APIKeys[kcc.APIKey]; ok {
if err := pair.DecryptSecret(); err != nil {
return "", "", err
}
return pair.Key, pair.Secret, nil
}
}
if pair := c.GetActiveGlobalAPIKeyPair(); pair != nil {
if err := pair.DecryptSecret(); err != nil {
return "", "", err
}
return pair.Key, pair.Secret, nil
}
return "", "", nil
}
@sonarqube-confluent
Copy link
Copy Markdown

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.

2 participants