Zaid-Ajaj/Npgsql.FSharp

Ability to hook in secret fetching?

njlr opened this issue · 1 comments

njlr commented

I was wondering if there is support in the library for fetching secrets (e.g. from AWS Secrets Manager) as part of the connection procedure. This is important because it allows for secret rotation without restarting a service.

The flow is something like this:

let creatConnectionUsingSecretsManager () =
  let rec loop connectionData = 
    async {
      // Build the connection string
      let connectionString =
        Sql.host "localhost"
        |> Sql.database connectionData.Database
        |> Sql.username connectionData.Username
        |> Sql.password connectionData.Password
        |> Sql.port connectionData.Port
        |> Sql.formatConnectionString

      // Verify the connection works
      try
        use connection =
          connectionString
          |> Sql.connect
          |> Sql.createConnection

        connection.Open()

        return connection
      with exn ->
        // Has the connection data changed?
        let! nextConnectionData = fetchConnectionDataFromSecretsManager

        if connectionData = nextConnectionData then
          // No, something else must have gone wrong
          return raise exn
        else
          // Yes, try again with the new data
          return! loop nextConnectionData
    }

  async {
    // Fetch the connection settings from the secrets manager
    let! connectionData = fetchConnectionDataFromSecretsManager

    return! loop connectionData
  }

Ideally this flow could be somehow injected into the SqlProps.

Is this possible?

Perhaps it could go here?

    type ExecutionTarget =
        | ConnectionString of string
        | Connection of NpgsqlConnection
        | Empty
        // Addition
        | ConnectionBuilder of (SqlProps -> Async<Connection>)

Happy to send a PR if not supported.

Hi there @njlr this is an interesting use case. Since you have found a workaround to rotating credentials with the existing API, the most I think we can do on the library side of things is to add a documentation page about it. I don't think baking in ConnectionBuilder of (SqlProps -> Async<Connection>) is generic enough for the library