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

Update gem dependencies #7

Merged
merged 21 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/pr-verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Run Tests

on:
pull_request:
branches:
- main

jobs:
# Test on code-dot-org Ruby version
test_3_0_5:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.0.5
bundler-cache: true

- name: Install gems
run: bundle install

- name: Run tests
run: bundle exec rake test

#Test on latest Ruby
test_3_3:
cat5inthecradle marked this conversation as resolved.
Show resolved Hide resolved
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.3
bundler-cache: true

- name: Install gems
run: bundle install

- name: Run tests
run: bundle exec rake test
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.0.5
8 changes: 8 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM ruby:3.0.5
cat5inthecradle marked this conversation as resolved.
Show resolved Hide resolved

WORKDIR /app

# Copy bare minimum files to install gems
COPY Gemfile aws-google.gemspec /app/
COPY lib /app/lib
RUN bundle install
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ Or install it yourself as:
Visit the [Google API Console](https://console.developers.google.com/) to create/obtain [OAuth 2.0 Client ID credentials](https://support.google.com/cloud/answer/6158849) (client ID and client secret) for an application in your Google account.

### Create an AWS IAM Role
Create an AWS IAM Role with the desired IAM policies attached, and a ['trust policy'](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#term_trust-policy) ([`AssumeRolePolicyDocument`](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateRole.html)) allowing the [`sts:AssumeRoleWithWebIdentity`](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html) action with [Web Identity Federation condition keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html#condition-keys-wif) authorizing
Create an AWS IAM Role with the desired IAM policies attached, and a ['trust policy'][1] ([`AssumeRolePolicyDocument`][2]) allowing the [`sts:AssumeRoleWithWebIdentity`][3] action with [Web Identity Federation condition keys][4] authorizing
your Google Client ID (`accounts.google.com:aud`) and a specific set of Google Account IDs (`accounts.google.com:sub`):

[1]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#term_trust-policy "IAM Trust Policy"
[2]: https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateRole.html "Create Role API"
[3]: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html "Assume Role With Identity API"
[4]: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html#condition-keys-wif "IAM Condition Keys"

```json
{
"Version": "2012-10-17",
Expand All @@ -53,6 +58,7 @@ your Google Client ID (`accounts.google.com:aud`) and a specific set of Google A

### Method 1: `Aws::Google`
In your Ruby code, construct an `Aws::Google` object by passing the AWS `role_arn`, Google `client_id` and `client_secret`, either as constructor arguments or via the `Aws::Google.config` global defaults:

```ruby
require 'aws/google'

Expand Down Expand Up @@ -87,9 +93,22 @@ The extra `credential_process` config line tells AWS to [Source Credentials with

## 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.
Prerequisites:

* Ruby 3.0.5

You can have Ruby installed locally, or use Docker and mount this repository into a Ruby container. By using Docker you can avoid conflicts with differing Ruby versions or other installed gems. To run and 'bash' into a Ruby container, install Docker and run the following. See [docker-compose.yml](docker-compose.yml) for details.

```
docker compose build
docker compose run ruby
```

With either option, 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.

To install this gem onto your local machine, run `bundle exec rake install`.

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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).

## Contributing

Expand Down
21 changes: 11 additions & 10 deletions aws-google.gemspec
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
lib = File.expand_path('../lib', __FILE__)
lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'aws/google/version'

Gem::Specification.new do |spec|
spec.required_ruby_version = '>= 3.0.5'
spec.name = 'aws-google'
spec.version = Aws::Google::VERSION
spec.authors = ['Will Jordan']
Expand All @@ -21,14 +22,14 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ['lib']

spec.add_dependency 'aws-sdk-core', '~> 3.130'
spec.add_dependency 'google-apis-core'
spec.add_dependency 'launchy', '~> 2'
spec.add_dependency 'aws-sdk-core', '~> 3.211.0'
spec.add_dependency 'google-apis-core', '~> 0.15.1'
spec.add_dependency 'launchy', '~> 3.0.1'

spec.add_development_dependency 'activesupport', '~> 5'
spec.add_development_dependency 'minitest', '~> 5.14.2'
spec.add_development_dependency 'mocha', '~> 1.5'
spec.add_development_dependency 'rake', '~> 12'
spec.add_development_dependency 'timecop', '~> 0.8'
spec.add_development_dependency 'webmock', '~> 3.3'
spec.add_development_dependency 'activesupport', '~> 6.1.7.8'
spec.add_development_dependency 'minitest', '~> 5.25.1'
spec.add_development_dependency 'mocha', '~> 2.4.5'
spec.add_development_dependency 'rake', '~> 13.2.1'
spec.add_development_dependency 'timecop', '~> 0.9.10'
spec.add_development_dependency 'webmock', '3.24.0'
end
8 changes: 8 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: '3'
services:
ruby:
build: .
volumes:
- .:/app
working_dir: /app
command: bash
27 changes: 18 additions & 9 deletions lib/aws/google/cached_credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,31 @@ def initialize(options = {})
end

def refresh_if_near_expiration
if near_expiration?(SYNC_EXPIRATION_LENGTH)
@mutex.synchronize do
if near_expiration?(SYNC_EXPIRATION_LENGTH)
refresh
write_credentials
end
return unless near_expiration?(SYNC_EXPIRATION_LENGTH)

@mutex.synchronize do
if near_expiration?(SYNC_EXPIRATION_LENGTH)
refresh
write_credentials
end
end
end

# Write credentials and expiration to AWS credentials file.
def write_credentials
# AWS CLI is needed because writing AWS credentials is not supported by the AWS Ruby SDK.
# Ensure the AWS CLI is available before attempting to write credentials.
return unless system('which aws >/dev/null 2>&1')
Aws::SharedCredentials::KEY_MAP.transform_values(&@credentials.method(:send)).
merge(expiration: @expiration).each do |key, value|

# Manually map the credentials to the keys used by AWS CLI
credentials_map = {
'aws_access_key_id' => @credentials.access_key_id,
'aws_secret_access_key' => @credentials.secret_access_key,
'aws_session_token' => @credentials.session_token,
'expiration' => @expiration
}

# Use the AWS CLI to set the credentials in the session profile
credentials_map.each do |key, value|
system("aws configure set #{key} #{value} --profile #{@session_profile}")

Choose a reason for hiding this comment

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

Not an issue with your current code changes, just a vulnerability in general. This putting secrets on CLI arguments allows other people to sniff the creds with a simple ps auxw. This is a recommendation by ChatGPT for an alternate (untested). Should I add this as a separate PR?

require 'aws-sdk-core'

def write_credentials
  shared_credentials = Aws::SharedCredentials.new(profile_name: @session_profile)
  shared_credentials.load
  shared_credentials.update(
    access_key_id: @credentials.access_key_id,
    secret_access_key: @credentials.secret_access_key,
    session_token: @credentials.session_token,
    expiration: @expiration
  )
end

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, sounds like a good idea

end
cat5inthecradle marked this conversation as resolved.
Show resolved Hide resolved
end
Expand Down
11 changes: 6 additions & 5 deletions test/aws/google_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@
it 'refreshes expired Google auth token credentials' do
m = mock
m.stubs(:refresh!)
m.stubs(:id_token).
returns(JWT.encode({ email: 'email', exp: Time.now.to_i - 1 }, '')).
then.returns(JWT.encode({ email: 'email' }, ''))
m.stubs(:id_token)
.returns(JWT.encode({ email: 'email', exp: Time.now.to_i - 1 }, ''))
.then.returns(JWT.encode({ email: 'email' }, ''))
Google::Auth.stubs(:get_application_default).returns(m)

system.times(5)
Expand All @@ -108,6 +108,7 @@
expiration = provider.expiration
_(expiration).must_equal(provider.expiration)
Timecop.travel(1.5.hours.from_now) do
provider.refresh!
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Hamms The newer versions of aws-sdk-core do not automatically refresh when you check the expiration property, so this test no longer triggers a refresh. I've added an explicit call to refresh on our provider, so what we're testing here is the handling of expired tokens in our google.rb refresh method.

_(expiration).wont_equal(provider.expiration)
end
end
Expand All @@ -124,7 +125,7 @@
Aws::Google.any_instance.expects(:refresh).never
Aws::Google.new(config).credentials
end

it 'uses config defaults for new AWS clients' do
Aws::Google.stubs(:config).returns(config)
@oauth_default.once
Expand Down Expand Up @@ -204,7 +205,7 @@
Aws::Google.new(config).credentials
end
end

describe 'no shared config' do
before do
Aws.shared_config.fresh(
Expand Down
Loading