Skip to content

Conversation

strantalis
Copy link
Member

@strantalis strantalis commented Oct 14, 2025

Proposed Changes

  • Add Secret type with redaction and safe JSON/log masking
  • Support inline secret directives: env:NAME, file:/path, literal:VALUE
  • Add BindServiceConfig helper with mapstructure decode hooks + validation
  • Implement file-based and env-based secret resolution (lazy/eager)
  • Integrate KAS: use Secret for root_key and BindServiceConfig
  • Improve env handling during reload to surface env-only keys
  • Add unit tests for Secret, BindServiceConfig, and inline decode forms
  • Update docs: “Secrets In Config” with examples and guidance
  • Remove temporary debug logs and experimental nested secret usage in KAS

DX

  • Plain strings are literals by default; use literal: to disambiguate values starting with env:/file:
  • Example:
    • services.kas.root_key: "env:OPENTDF_SERVICES_KAS_ROOT_KEY"
    • services.kas.preview.key_management: true

Checklist

  • I have added or updated unit tests
  • I have added or updated integration tests (if appropriate)
  • I have added or updated documentation

Testing Instructions

@github-actions github-actions bot added comp:kas Key Access Server docs Documentation size/l labels Oct 14, 2025
@strantalis strantalis changed the title feat(service/config): introduce typed Secret with inline env/file/literal, BindServiceConfig; integrate in KAS feat(core): introduce typed Secret with inline env/file/literal, BindServiceConfig; integrate in KAS Oct 14, 2025
@strantalis
Copy link
Member Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a Secret type with support for inline environment variables, file paths, and literal values, enhancing configuration security. It also adds a BindServiceConfig helper for simplified configuration binding and validation. The changes integrate these features into the KAS, improving environment handling and adding unit tests and documentation. The review focuses on correctness and potential issues in the new code.

@strantalis
Copy link
Member Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a robust Secret type for managing sensitive configuration values, along with a BindServiceConfig helper to streamline decoding and validation. The integration into KAS to handle the root_key is a great use case. The changes are well-structured and include thorough testing, which is excellent.

My review includes a few suggestions to enhance the implementation:

  • Improving the heuristic for redacting secrets in debug logs to prevent potential leaks.
  • Clarifying the documentation for structured secret configuration.
  • Minor improvements to error messages and code consistency for better maintainability.

@strantalis strantalis marked this pull request as ready for review October 15, 2025 17:41
@strantalis strantalis requested review from a team as code owners October 15, 2025 17:41
…eral, BindServiceConfig; integrate in KAS

  - Add Secret type with redaction and safe JSON/log masking
  - Support inline secret directives: env:NAME, file:/path, literal:VALUE
  - Add BindServiceConfig helper with mapstructure decode hooks + validation
  - Implement file-based and env-based secret resolution (lazy/eager)
  - Integrate KAS: use Secret for root_key and BindServiceConfig
  - Improve env handling during reload to surface env-only keys
  - Add unit tests for Secret, BindServiceConfig, and inline decode forms
  - Update docs: “Secrets In Config” with examples and guidance
  - Remove temporary debug logs and experimental nested secret usage in KAS

  DX

  - Plain strings are literals by default; use literal: to disambiguate values starting with env:/file:
  - Example:
      - services.kas.root_key: "env:OPENTDF_SERVICES_KAS_ROOT_KEY"
      - services.kas.preview.key_management: true
Copy link
Member

@dmihalcik-virtru dmihalcik-virtru left a comment

Choose a reason for hiding this comment

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

Can you avoid breaking compatibility with downstream users? Maybe print out a warning if the old root_key field is set, and use a new name (suggestion: envelope_key) from now on.

RSACertID string `mapstructure:"rsacertid" json:"rsacertid"`

RootKey string `mapstructure:"root_key" json:"root_key"`
RootKey config.Secret `mapstructure:"root_key" json:"root_key"`
Copy link
Member

Choose a reason for hiding this comment

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

Even changes to 'experimental' features shouldn't break builds downstream. Deprecate instead of removing to avoid blocking the next release of downstream integrations.

Suggested change
RootKey config.Secret `mapstructure:"root_key" json:"root_key"`
// Deprecated: Use EnvelopeKey
RootKey string `mapstructure:"root_key" json:"root_key"`
EnvelopeKey config.Secret `mapstructure:"envelope_key" json:"envelope_key"`

Copy link
Member Author

Choose a reason for hiding this comment

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

There shouldn't be downstream impact. This should still support a string literal in yaml without any prefix.


// If an environment loader is present, configure orderedViper to read env directly.
for _, loader := range c.loaders {
if loader.Name() == LoaderNameEnvironmentValue {
Copy link
Contributor

Choose a reason for hiding this comment

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

The env loader should already do this. And it should be configured by the consumer of the library.

Comment on lines +66 to +70
// Discover environment variables with the configured prefix and convert them to dotted keys
// Example: OPENTDF_SERVICES_KAS_ROOT_KEY -> services.kas.root_key
// Note: Viper treats keys case-insensitively; we normalize to lower-case dotted form here
prefix := l.envPrefix + "_"
for _, env := range os.Environ() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This bit looks like what Viper should be doing already. If it is adding additional keys we should cache those keys and values so they can be returned by Get, otherwise we might hit this: https://github.com/opentdf/platform/blob/main/service/pkg/config/config.go#L219-L229

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:kas Key Access Server docs Documentation size/l

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants