Skip to content

Commit

Permalink
Implement initial logic.
Browse files Browse the repository at this point in the history
  • Loading branch information
floor114 committed Jan 14, 2024
1 parent 425a1f8 commit 14a083f
Show file tree
Hide file tree
Showing 22 changed files with 842 additions and 30 deletions.
11 changes: 8 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: CI

on: pull_request
on:
push:
branches:
- main
pull_request:

jobs:
lint:
Expand All @@ -21,8 +25,9 @@ jobs:
strategy:
matrix:
ruby:
- '3.0.0'
- '3.1.0'
- '3.1.4'
- '3.2.2'
- '3.3.0'
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
Expand Down
16 changes: 16 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,19 @@ Layout/LineLength:

Style/Documentation:
Enabled: false

Naming/FileName:
Exclude:
- lib/mysql2-aws_rds_iam.rb

Metrics/MethodLength:
Max: 15
Exclude:
- test/**/**.rb

Metrics/AbcSize:
Max: 20

Metrics/ClassLength:
Exclude:
- test/**/**.rb
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1.0
3.3.0
4 changes: 3 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ gem 'bundler'
gem 'commonmarker'
gem 'minitest'
gem 'minitest-reporters'
gem 'mocha'
gem 'pry'
gem 'racc'
gem 'rake'
gem 'rubocop'
gem 'rubocop-minitest'
gem 'rubocop-rake'
gem 'timecop'
gem 'simplecov'
gem 'webrick'
gem 'yard'
20 changes: 16 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ GEM
builder (3.2.4)
coderay (1.1.3)
commonmarker (0.23.9)
docile (1.4.0)
jmespath (1.6.2)
json (2.6.3)
method_source (1.0.0)
Expand All @@ -35,18 +36,21 @@ GEM
builder
minitest (>= 5.0)
ruby-progressbar
mocha (2.0.2)
ruby2_keywords (>= 0.0.5)
mysql2 (0.5.5)
parallel (1.23.0)
parser (3.2.2.1)
ast (~> 2.4.1)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
racc (1.7.3)
rainbow (3.1.1)
rake (13.0.6)
regexp_parser (2.8.0)
rexml (3.2.5)
rubocop (1.51.0)
rubocop (1.52.0)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 3.2.0.0)
Expand All @@ -63,7 +67,13 @@ GEM
rubocop-rake (0.6.0)
rubocop (~> 1.0)
ruby-progressbar (1.13.0)
timecop (0.9.6)
ruby2_keywords (0.0.5)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.4)
unicode-display_width (2.4.2)
webrick (1.8.1)
yard (0.9.34)
Expand All @@ -78,15 +88,17 @@ DEPENDENCIES
commonmarker
minitest
minitest-reporters
mocha
mysql2-aws_rds_iam!
pry
racc
rake
rubocop
rubocop-minitest
rubocop-rake
timecop
simplecov
webrick
yard

BUNDLED WITH
2.4.13
2.5.3
116 changes: 103 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,129 @@
# Mysql2::AwsRdsIam

TODO: Delete this and the text below, and describe your gem
[![Gem](https://img.shields.io/gem/v/mysql2-aws_rds_iam)](https://rubygems.org/gems/mysql2-aws_rds_iam)
 
![CI](https://img.shields.io/github/actions/workflow/status/floor114/mysql2-aws_rds_iam/ci.yml)

Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/mysql2/aws_rds_iam`. To experiment with that code, run `bin/console` for an interactive prompt.
`Mysql2::AwsRdsIam` is an extension of [mysql2](https://github.com/brianmario/mysql2) gem that adds support of [IAM authentication](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html) when connecting to MySQL in Amazon RDS.

## Installation
`Mysql2::AwsRdsIam` is an extension of [mysql2](https://github.com/brianmario/mysql2) gem that adds support of [IAM authentication](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html) when connecting to MySQL in Amazon RDS.

This gem is a powerful tool that enables seamless connection to MySQL databases using the [mysql2](https://github.com/brianmario/mysql2) gem. It leverages the dynamic password generation feature of AWS RDS [IAM authentication](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html) for enhanced security and easy password management.

TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.

Install the gem and add to the application's Gemfile by executing:
## Installation

Install manually:

$ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
```console
$ gem install mysql2-aws_rds_iam
```

If bundler is not being used to manage dependencies, install the gem by executing:
or with Bundler:

$ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
```console
$ bundle add mysql2-aws_rds_iam
```

## Usage

TODO: Write usage instructions here
To leverage [IAM authentication](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html) for your database connections, follow these steps:

1. Enable [IAM authentication](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html) for your database through AWS
2. Add IAM credentials to your application.
3. Set up your application to generate authentication tokens.


### Application configurations

The default algorithm is `Mysql2::AwsRdsIam`'s [default authentication token generator](https://github.com/floor114/mysql2-aws_rds_iam/blob/main/lib/mysql2/aws_rds_iam/auth_token/generator.rb). Credentials and region are extracted using [aws-sdk-rds](https://github.com/aws/aws-sdk-ruby/tree/version-3/gems/aws-sdk-rds) configurations.


#### Apply msql2 patch
To connect to your MySQL database, you need to create initializer file that applies the patch:

```ruby
# config/initializers/tcc_rds_iam_auth.rb

Tcc::RdsIamAuth.apply_patch

```

#### Configure `database.yml`
New rds_iam_auth_host parameter must be added to the database.yml file:

```yaml
production:
# ...
aws_rds_iam_auth: true
```
#### Custom token generator
If the default generator doesn't meet your needs, you can create a custom one
```ruby
# config/initializers/tcc_rds_iam_auth.rb

Mysql2::AwsRdsIam.auth_token_registry.add(:custom, ->(host, port, username) { 'your custom logic' })

```

and specify it in `database.yml`

```yaml
production:
# ...
aws_rds_iam_auth: true
aws_rds_iam_auth_token_generator: custom
```
`Mysql2::AwsRdsIam.auth_token_registry` accepts two parameters:
1. Generator name. The same name should be specified in `database.yml`
2. Object that responds to `call` method and accepts 3 arguments (`host, port, username`) specified in `database.yml`.

##### Possible generator types
* Lambda
```ruby
Mysql2::AwsRdsIam.auth_token_registry.add(:custom, ->(host, port, username) { 'your custom logic' })
```
* Generator instance
```ruby
class CustomGenerator
def call(host, port, username)
GenerateMyCode
end
end
Mysql2::AwsRdsIam.auth_token_registry.add(:custom, CustomGenerator.new)
```
* Generator class
```ruby
class CustomGenerator
def self.call(host, port, username)
GenerateMyCode
end
end
Mysql2::AwsRdsIam.auth_token_registry.add(:custom, CustomGenerator)
```

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake` to run the tests and linter. You can also run `bin/console` for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/mysql2-aws_rds_iam. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/mysql2-aws_rds_iam/blob/main/CODE_OF_CONDUCT.md).
Bug reports and pull requests are welcome on GitHub at https://github.com/floor114/mysql2-aws_rds_iam. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/mysql2-aws_rds_iam/blob/main/CODE_OF_CONDUCT.md).

## License

The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).

## Code of Conduct
## Special Thanks

Everyone interacting in the Mysql2::AwsRdsIam project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/mysql2-aws_rds_iam/blob/main/CODE_OF_CONDUCT.md).
Inspired by [Andrew Haines'](https://github.com/haines) PG version [pg-aws_rds_iam](https://github.com/haines/pg-aws_rds_iam)
28 changes: 28 additions & 0 deletions bin/rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

#
# This file was generated by Bundler.
#
# The application 'rake' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)

bundle_binstub = File.expand_path('bundle', __dir__)

if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
end
end

require 'rubygems'
require 'bundler/setup'

load Gem.bin_path('rake', 'rake')
3 changes: 3 additions & 0 deletions lib/mysql2-aws_rds_iam.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

require 'mysql2/aws_rds_iam'
22 changes: 22 additions & 0 deletions lib/mysql2/aws_rds_iam.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

require 'aws-sdk-rds'
require 'mysql2'
require 'zeitwerk'

Expand All @@ -8,5 +9,26 @@

module Mysql2
module AwsRdsIam
def self.auth_token_registry
@auth_token_registry ||= AuthToken::Registry.new
end

def self.apply_patch
const = begin
Object.const_get('Mysql2::Client')
rescue StandardError
raise Errors::Mysql2ClientNotFoundError
end

begin
const.instance_method(:initialize)
rescue StandardError
raise Errors::Mysql2ClientNotFoundError
end

const.prepend(ClientExtension)
end
end

AwsRdsIam.apply_patch
end
19 changes: 19 additions & 0 deletions lib/mysql2/aws_rds_iam/auth_token/factory.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module Mysql2
module AwsRdsIam
module AuthToken
class Factory
DEFAULT_GENERATOR = :default

def self.call(generator, host, port, username)
AwsRdsIam.auth_token_registry.fetch(generator&.to_sym || DEFAULT_GENERATOR).call(
host: host,
port: port,
username: username
)
end
end
end
end
end
28 changes: 28 additions & 0 deletions lib/mysql2/aws_rds_iam/auth_token/generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

module Mysql2
module AwsRdsIam
module AuthToken
class Generator
def initialize
aws_config = Aws::RDS::Client.new.config

@generator = Aws::RDS::AuthTokenGenerator.new(credentials: aws_config.credentials)
@region = aws_config.region
end

def call(host:, port:, username:)
generator.auth_token(
region: region,
endpoint: "#{host}:#{port}",
user_name: username.to_s
)
end

private

attr_reader :generator, :region
end
end
end
end
Loading

0 comments on commit 14a083f

Please sign in to comment.