Skip to content
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

Dynamic credentials support for SQL components #2566

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

jfrconley
Copy link

@jfrconley jfrconley commented May 7, 2024

Currently, there is no way to change the credentials used by any of the SQL components without updating the configuration and restarting the stream. This is a problem for use cases where credentials must be rotated on a regular basis (AWS RDS IAM, CockroachDB JWT, Hashicorp Vault temporary credentials).

To resolve this, I have implemented an additional dynamic_credentials configuration block supported by all SQL components (other than deprecated ones). This property allows specifying a cache resource and a key with which to retrieve credentialing information. The value stored in this key is used to supply interpolation parameters to the dsn field, which has now been made dynamic. The cache is queried and the dsn is regenerated when a new connection is created. Init statements and files are only run once, and are not reapplied when creating a new connection. This has the advantage of working with all drivers, regardless of underlying implementation. A side effect of this approach is that idle connections with stale credentials are not proactively removed. The settings conn_max_idle and conn_max_idle_time can be used counteract this based on use case requirements.

Example:

input:
  sql_select:
    driver: postgres
    // You can use interpolation to insert properties from the retrieve cache item
    dsn: "postgres://${! username }:${! password }@localhost/testdb"
    table: test
    columns: [ "*" ]
    dynamic_credentials:
      cache: cred_cache
      cache_key: input_db_creds

cache_resources:
  - label: cred_cache
    memory:
      init_values:
        input_db_creds: '{"username": "testuser", "password": "testpass" }'  

This setup can pair well with the cached processor to refresh credentials on a regular interval.

In principle, you could use this field to template any value in the DSN including database/settings/port/hostname or really anything that doesn't require changing the driver.
However, this is not the intention since this could lead to unintended consequences as initialization options are only run once.
The name dynamic_credentials is chosen intentionally as this is the intended purpose.

@jfrconley jfrconley requested a review from Jeffail as a code owner May 7, 2024 01:19
Comment on lines +24 to +29
driveri, err := sql.Open(driverName, "")
if err != nil {
return nil, err
}
resolvedDriver := driveri.Driver()
_ = driveri.Close()
Copy link
Author

Choose a reason for hiding this comment

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

This is a bit of a hack to get the underlying driver using our driver string. The stdlib sql package specified that no connections should be created when calling open, so this should be generally safe. Tests for all current drivers are written and pass.

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.

None yet

1 participant