Skip to content

Added Support for providing configuration option for supplying password function #157

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

Merged
merged 5 commits into from
Oct 10, 2023

Conversation

bhosale
Copy link
Contributor

@bhosale bhosale commented Oct 7, 2023

Motivation:
Currently r2dbc-mysql does not support IAM based Authentication for authenticating with AWS Aurora RDS database. The way IAM based authentication works is requesting token from AWS RDS for that hostname and username (which is same as AWS IAM Role name). These tokens are valid for 15 minutes, cannot reuse same token after 15 minutes.
By adding configuration option for supplying password function, whenever a new connection is made then password is retrieved using supplier function each time.

Modification:
Modified MySqlConnectionFactoryProvider - Added new configurable option.
Option<Supplier<Mono<String>>> PASSWORD_SUPPLIER = Option.valueOf("passwordSupplier");
Modified MySqlConnectionConfiguration - Added the new configuration for Password Supplier function.
Supplier<Mono<String>> passwordSupplier;
Modified MySqlConnectionFactory - Retrieves Password Supplier function from configuration, and then retrieves password each time connection factory is created.

Result:
Users can provide a supplier function using PASSWORD_SUPPLIER option. This function will be used for retrieving password/token each time.

public ConnectionFactory writeConnectionFactory(final RdsTokenGenerator rdsTokenGenerator) {
        return ConnectionFactories.get(ConnectionFactoryOptions.builder()
            .option(ConnectionFactoryOptions.DRIVER, "mysql")
            .option(ConnectionFactoryOptions.HOST, "Hostname of AWS Aurora DB instance")
            .option(ConnectionFactoryOptions.PORT, 3306)
            .option(ConnectionFactoryOptions.USER, "IAM ROLE Having access to RDS")
            .option(MySqlConnectionFactoryProvider.PASSWORD_SUPPLIER, rdsTokenGenerator::generateAuthenticationToken)
            .build());
    }

Example of RdsTokenGenerator

public class RdsTokenGenerator {
    public Mono<String> generateAuthenticationToken() {
        return Mono.fromCallable(() -> RdsUtilities.builder()
            .credentialsProvider(DefaultCredentialsProvider.create())
            .region(Region.US_EAST_1)
            .build();
            .generateAuthenticationToken((builder) ->
                builder
                    .hostname(hostname)
                    .port(port)
                    .username(user)
            ))
            .flatMap(token -> LOGGER.info("Retrieved token from RdsUtilities")
                .then(Mono.just(token)))
            .subscribeOn(Schedulers.boundedElastic());
    }

}

@bhosale bhosale changed the title Added Support for providing configuration option for supplying password Added Support for providing configuration option for supplying password function Oct 7, 2023
@jchrys jchrys self-requested a review October 8, 2023 18:03
@jchrys
Copy link
Collaborator

jchrys commented Oct 8, 2023

Hello, @bhosale thank you so much for your efforts in supporting this.

I believe we could utilize Supplier<String> instead of Supplier<Mono<String>> to avoid imposing the adoption of Reactor and simplify the interface. WDYT?

Additionally, could you please write a test case for this change?

@jchrys jchrys requested a review from mobidick1969 October 8, 2023 18:24
@jchrys jchrys added the enhancement New feature or request label Oct 8, 2023
@jchrys
Copy link
Collaborator

jchrys commented Oct 8, 2023

PTAL @JohnNiang @mobidick1969

@bhosale
Copy link
Contributor Author

bhosale commented Oct 8, 2023

Thanks @jchrys for reviewing and providing feedback on the pull request. I have added couple of unit test cases.

As I understand the connection is established each time an SQL statement is executed, if we use just Supplier<String> instead of Supplier<Mono<String>>, there's a potential risk that the supplier function might involve blocking operations, which could have adverse consequences.

@jchrys
Copy link
Collaborator

jchrys commented Oct 9, 2023

Establishing a connection involves multiple round-trip operations, which is why many of our users choose to pool connections using r2dbc-pool or similar solutions (and we highly recommend it).

I understand your point. I believe it would be more suitable to expose org.reactivestreams.Publisher<String> instead of Supplier<Mono<String>>. This way, we provide a more general interface that accommodates users who may use RxJava, Reactor, or other reactive libraries

@jchrys jchrys assigned bhosale and jchrys and unassigned bhosale and jchrys Oct 9, 2023
@jchrys jchrys added this to the 1.0.5/0.9.6 milestone Oct 9, 2023
@bhosale
Copy link
Contributor Author

bhosale commented Oct 9, 2023

Agree, I am also using pool.

Publisher<String> makes sense instead of Subscriber<Mono<String>>. Updated the code with that change.

Copy link
Collaborator

@jchrys jchrys left a comment

Choose a reason for hiding this comment

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

Just a nit

Copy link
Collaborator

@jchrys jchrys left a comment

Choose a reason for hiding this comment

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

@bhosale Thanks a lot!

@jchrys jchrys merged commit 2a842e8 into asyncer-io:trunk Oct 10, 2023
jchrys pushed a commit that referenced this pull request Oct 10, 2023
…rd function (#157)

Motivation:
Currently r2dbc-mysql does not support IAM based Authentication for
authenticating with AWS Aurora RDS database. The way IAM based
authentication works is requesting token from AWS RDS for that hostname
and username (which is same as AWS IAM Role name). These tokens are
valid for 15 minutes, cannot reuse same token after 15 minutes.
By adding configuration option for supplying password function, whenever
a new connection is made then password is retrieved using supplier
function each time.

Modification:
Modified `MySqlConnectionFactoryProvider` - Added new configurable
option.
`Option<Publisher<String>> PASSWORD_SUPPLIER =
Option.valueOf("passwordSupplier");`
Modified `MySqlConnectionConfiguration` - Added the new configuration
for Password Supplier function.
`Publisher<String> passwordSupplier;`
Modified `MySqlConnectionFactory` - Retrieves Password Supplier function
from configuration, and then retrieves password each time connection
factory is created.

Result:
Users can provide a supplier function using `PASSWORD_SUPPLIER` option.
This function will be used for retrieving password/token each time.

```
public ConnectionFactory writeConnectionFactory(final RdsTokenGenerator rdsTokenGenerator) {
        return ConnectionFactories.get(ConnectionFactoryOptions.builder()
            .option(ConnectionFactoryOptions.DRIVER, "mysql")
            .option(ConnectionFactoryOptions.HOST, "Hostname of AWS Aurora DB instance")
            .option(ConnectionFactoryOptions.PORT, 3306)
            .option(ConnectionFactoryOptions.USER, "IAM ROLE Having access to RDS")
            .option(MySqlConnectionFactoryProvider.PASSWORD_SUPPLIER, rdsTokenGenerator. generateAuthenticationToken())
            .build());
    }
```

Example of `RdsTokenGenerator`
```
public class RdsTokenGenerator {
    public Mono<String> generateAuthenticationToken() {
        return Mono.fromCallable(() -> RdsUtilities.builder()
            .credentialsProvider(DefaultCredentialsProvider.create())
            .region(Region.US_EAST_1)
            .build();
            .generateAuthenticationToken((builder) ->
                builder
                    .hostname(hostname)
                    .port(port)
                    .username(user)
            ))
            .flatMap(token -> LOGGER.info("Retrieved token from RdsUtilities")
                .then(Mono.just(token)))
            .subscribeOn(Schedulers.boundedElastic());
    }

}
```
jchrys pushed a commit that referenced this pull request Oct 10, 2023
…rd function (#157)

Motivation:
Currently r2dbc-mysql does not support IAM based Authentication for
authenticating with AWS Aurora RDS database. The way IAM based
authentication works is requesting token from AWS RDS for that hostname
and username (which is same as AWS IAM Role name). These tokens are
valid for 15 minutes, cannot reuse same token after 15 minutes.
By adding configuration option for supplying password function, whenever
a new connection is made then password is retrieved using supplier
function each time.

Modification:
Modified `MySqlConnectionFactoryProvider` - Added new configurable
option.
`Option<Publisher<String>> PASSWORD_SUPPLIER =
Option.valueOf("passwordSupplier");`
Modified `MySqlConnectionConfiguration` - Added the new configuration
for Password Supplier function.
`Publisher<String> passwordSupplier;`
Modified `MySqlConnectionFactory` - Retrieves Password Supplier function
from configuration, and then retrieves password each time connection
factory is created.

Result:
Users can provide a supplier function using `PASSWORD_SUPPLIER` option.
This function will be used for retrieving password/token each time.

```
public ConnectionFactory writeConnectionFactory(final RdsTokenGenerator rdsTokenGenerator) {
        return ConnectionFactories.get(ConnectionFactoryOptions.builder()
            .option(ConnectionFactoryOptions.DRIVER, "mysql")
            .option(ConnectionFactoryOptions.HOST, "Hostname of AWS Aurora DB instance")
            .option(ConnectionFactoryOptions.PORT, 3306)
            .option(ConnectionFactoryOptions.USER, "IAM ROLE Having access to RDS")
            .option(MySqlConnectionFactoryProvider.PASSWORD_SUPPLIER, rdsTokenGenerator. generateAuthenticationToken())
            .build());
    }
```

Example of `RdsTokenGenerator`
```
public class RdsTokenGenerator {
    public Mono<String> generateAuthenticationToken() {
        return Mono.fromCallable(() -> RdsUtilities.builder()
            .credentialsProvider(DefaultCredentialsProvider.create())
            .region(Region.US_EAST_1)
            .build();
            .generateAuthenticationToken((builder) ->
                builder
                    .hostname(hostname)
                    .port(port)
                    .username(user)
            ))
            .flatMap(token -> LOGGER.info("Retrieved token from RdsUtilities")
                .then(Mono.just(token)))
            .subscribeOn(Schedulers.boundedElastic());
    }

}
```
@bhosale bhosale deleted the password-supplier branch October 10, 2023 19:20
jchrys pushed a commit that referenced this pull request Oct 12, 2023
…rd function (#157)

Motivation:
Currently r2dbc-mysql does not support IAM based Authentication for
authenticating with AWS Aurora RDS database. The way IAM based
authentication works is requesting token from AWS RDS for that hostname
and username (which is same as AWS IAM Role name). These tokens are
valid for 15 minutes, cannot reuse same token after 15 minutes.
By adding configuration option for supplying password function, whenever
a new connection is made then password is retrieved using supplier
function each time.

Modification:
Modified `MySqlConnectionFactoryProvider` - Added new configurable
option.
`Option<Publisher<String>> PASSWORD_SUPPLIER =
Option.valueOf("passwordSupplier");`
Modified `MySqlConnectionConfiguration` - Added the new configuration
for Password Supplier function.
`Publisher<String> passwordSupplier;`
Modified `MySqlConnectionFactory` - Retrieves Password Supplier function
from configuration, and then retrieves password each time connection
factory is created.

Result:
Users can provide a supplier function using `PASSWORD_SUPPLIER` option.
This function will be used for retrieving password/token each time.

```
public ConnectionFactory writeConnectionFactory(final RdsTokenGenerator rdsTokenGenerator) {
        return ConnectionFactories.get(ConnectionFactoryOptions.builder()
            .option(ConnectionFactoryOptions.DRIVER, "mysql")
            .option(ConnectionFactoryOptions.HOST, "Hostname of AWS Aurora DB instance")
            .option(ConnectionFactoryOptions.PORT, 3306)
            .option(ConnectionFactoryOptions.USER, "IAM ROLE Having access to RDS")
            .option(MySqlConnectionFactoryProvider.PASSWORD_SUPPLIER, rdsTokenGenerator. generateAuthenticationToken())
            .build());
    }
```

Example of `RdsTokenGenerator`
```
public class RdsTokenGenerator {
    public Mono<String> generateAuthenticationToken() {
        return Mono.fromCallable(() -> RdsUtilities.builder()
            .credentialsProvider(DefaultCredentialsProvider.create())
            .region(Region.US_EAST_1)
            .build();
            .generateAuthenticationToken((builder) ->
                builder
                    .hostname(hostname)
                    .port(port)
                    .username(user)
            ))
            .flatMap(token -> LOGGER.info("Retrieved token from RdsUtilities")
                .then(Mono.just(token)))
            .subscribeOn(Schedulers.boundedElastic());
    }

}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants