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

Decouple from Rails secrets #4

Merged
merged 9 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
- Add rubocop gems: factory_bot, infinum, rake, rspec_rails
- Fix RuboCop offenses
- Add build GHA workflow
- Remove dependency on Rails secrets and enable clients to choose how to manage secret parameters

## [2.0.0] - 2024-03-12

Expand Down
36 changes: 10 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ InfinumAzure Engine is gem for resource authentication with Infinum Azure AD ser
- [Dependencies](#dependencies)
- [Configuration](#configuration)
* [InfinumAzure](#infinumazure)
* [Secrets](#secrets)
- [Usage](#usage)

## Installation
Expand Down Expand Up @@ -39,7 +38,6 @@ Or install it yourself as:
# config/initializers/infinum_azure.rb

InfinumAzure.configure do |config|
config.service_name = 'Revisor'
config.resource_name = 'User'
config.resource_attributes = [:uid, :email, :first_name, :last_name, :avatar_url,
:deactivated_at, :provider_groups, :employee]
Expand All @@ -49,12 +47,20 @@ InfinumAzure.configure do |config|
record.update_attribute(:provider, 'infinum_azure')
record.update_attribute(:uid, resource['uid'])
}
config.client_id = 'client-id'
config.client_secret = 'client-secret'
config.domain = 'https://login.b2c.com'
config.tenant = 'tenant'
config.users_auth_url = 'https://example.com'
end
```

Configuration options:
* service_name(mandatory) - name of application
* client_id(mandatory) - client ID
* client_secret(mandatory) - client secret
* domain(mandatory) - Identity service domain
* resource_name(mandatory) - name of resource on whom authentication is being done
* tenant(mandatory) - Tenant id
* resource_attributes(optional) - attributes that will be permitted once the webhook controller receives the params from InfinumAzure
* user_migration_scope(optional) - a block that will be used to get the initial collection of resources (if blank, default is written above)
* user_migration_operation(optional) - a block that will be called for each resource from the above collection if a matching resource on InfinumAzure is found. The resource is a Hash containing the following properties:
Expand All @@ -65,29 +71,7 @@ Configuration options:
* `avatar_url` - string || null
* `groups` - string || null -> a comma separated list; if "employees" is present, the user is an employee
* `deactivated` - boolean

### Secrets

Secrets should be kept in `config/secrets.yml` file.

Required ones are:

```ruby
# config/secrets.yml

infinum_azure:
client_id: 'client_id_from_InfinumAzure'
client_secret: 'client_secret_from_InfinumAzure'
domain: 'https://login.b2c.com'
tenant: 'InfinumAzure_tenant'
```

Optional ones are:

```ruby
infinum_azure:
users_auth_url: 'InfinumAzure_users_auth_url_with_api_code' # required only if infinum_azure:migrate_users rake task is used
```
* users_auth_url(optional)

## Usage

Expand Down
3 changes: 2 additions & 1 deletion app/controllers/infinum_azure/api/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ class BaseController < ApplicationController
protect_from_forgery with: :null_session
respond_to :json

delegate :resource_name, :resource_class, to: InfinumAzure
delegate :resource_name, to: 'InfinumAzure.config'
delegate :resource_class, to: InfinumAzure
end
end
end
2 changes: 1 addition & 1 deletion app/controllers/infinum_azure/api/webhooks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def resource

def user_params
normalized_azure_params
.slice(*InfinumAzure.resource_attributes)
.slice(*InfinumAzure.config.resource_attributes)
.merge(provider: InfinumAzure.provider)
end

Expand Down
7 changes: 0 additions & 7 deletions config/initializers/devise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,4 @@
config.email_regexp = /\A[^@\s]+@[^@\s]+\z/

config.sign_out_via = :get

# ==> OmniAuth
config.omniauth :infinum_azure, InfinumAzure.client_id, InfinumAzure.client_secret,
client_options: {
domain: InfinumAzure.domain,
tenant: InfinumAzure.tenant
}
end
6 changes: 3 additions & 3 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# frozen_string_literal: true

Rails.application.routes.draw do
get "/#{InfinumAzure.resource_name.pluralize.underscore}/auth/infinum_azure/logout",
get "/#{InfinumAzure.config.resource_name.pluralize.underscore}/auth/infinum_azure/logout",
to: 'infinum_azure/resources#passthru',
as: :infinum_azure_logout
get "/#{InfinumAzure.resource_name.pluralize.underscore}/auth/logout",
get "/#{InfinumAzure.config.resource_name.pluralize.underscore}/auth/logout",
to: 'infinum_azure/resources#destroy',
as: :logout

devise_for InfinumAzure.resource_name.pluralize.underscore, controllers: {
devise_for InfinumAzure.config.resource_name.pluralize.underscore, controllers: {
omniauth_callbacks: 'infinum_azure/resources/omniauth_callbacks'
}

Expand Down
37 changes: 2 additions & 35 deletions lib/infinum_azure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
require 'omniauth/infinum_azure'
require 'infinum_azure/version'
require 'infinum_azure/engine'
require 'infinum_azure/defaults'
require 'infinum_azure/config'
require 'devise'

Expand All @@ -14,51 +13,19 @@ class << self
def configure
yield config if block_given?

ensure_all_attributes_present!
config.validate!
end

def config
@config ||= Config.new
end

def ensure_all_attributes_present!
Defaults.all_attribute_names.each do |attribute|
raise Error, "InfinumAzure attribute '@#{attribute}' not set" if config.public_send(attribute).blank?
end
end

delegate(*Defaults.all_attribute_names, to: :config)

def provider
to_s.underscore
end

def resource_class
resource_name.constantize
end

def client_id
dig_secret(:client_id)
end

def client_secret
dig_secret(:client_secret)
end

def domain
dig_secret(:domain)
end

def tenant
dig_secret(:tenant)
end

def users_auth_url
dig_secret(:users_auth_url)
end

def dig_secret(key)
Rails.application.secrets.dig(:infinum_azure, key)
config.resource_name.constantize
end
end
end
35 changes: 31 additions & 4 deletions lib/infinum_azure/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,38 @@

module InfinumAzure
class Config
Defaults.all_attributes.each do |attr, value|
attr_writer attr
PROVIDER_INFINUM_ID = 'infinum_id'
PROVIDER_INFINUM_AZURE = 'infinum_azure'
UID = 'uid'
DEFAULT_RESOURCE_ATTRIBUTES = [
:uid, :email, :first_name, :last_name, :avatar_url, :deactivated_at, :provider_groups, :employee
].freeze

define_method(attr) do
instance_variable_set(:"@#{attr}", instance_variable_get(:"@#{attr}") || value)
attr_accessor :resource_name
attr_accessor :resource_attributes
attr_accessor :user_migration_scope
attr_accessor :user_migration_operation
attr_accessor :client_id
attr_accessor :client_secret
attr_accessor :domain
attr_accessor :tenant
attr_accessor :users_auth_url

def initialize
self.resource_attributes = DEFAULT_RESOURCE_ATTRIBUTES
self.user_migration_scope = -> { InfinumAzure.resource_class.where(provider: PROVIDER_INFINUM_ID) }
self.user_migration_operation = lambda { |record, resource|
record.update_columns( # rubocop:disable Rails/SkipsModelValidations
provider: PROVIDER_INFINUM_AZURE,
uid: resource[UID]
)
}
end

def validate!
[:resource_name, :resource_attributes, :user_migration_scope, :user_migration_operation, :client_id,
:client_secret, :domain, :tenant].each do |attribute|
raise InfinumAzure::Error, "InfinumAzure attribute '@#{attribute}' not set" if public_send(attribute).blank?
end
end
end
Expand Down
28 changes: 0 additions & 28 deletions lib/infinum_azure/defaults.rb

This file was deleted.

13 changes: 13 additions & 0 deletions lib/infinum_azure/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,18 @@ class Engine < ::Rails::Engine
if defined?(FactoryBotRails)
config.factory_bot.definition_file_paths += [File.expand_path('../../spec/factories', __dir__)]
end

initializer 'infinum_azure.devise_omniauth', before: 'devise.omniauth' do
Devise.setup do |config|
# ==> OmniAuth
config.omniauth :infinum_azure,
InfinumAzure.config.client_id,
InfinumAzure.config.client_secret,
client_options: {
domain: InfinumAzure.config.domain,
tenant: InfinumAzure.config.tenant
}
end
end
end
end
2 changes: 1 addition & 1 deletion lib/tasks/infinum_azure/users/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
module InfinumAzure
module Users
class Request
URL = InfinumAzure.users_auth_url
URL = InfinumAzure.config.users_auth_url

def self.execute
raise 'infinum_azure_users_auth_url secret required for this rake task' if URL.blank?
Expand Down
Loading