cnfs-iam 0.0.1.alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +75 -0
- data/Rakefile +24 -0
- data/app/controllers/concerns/is_tenant_scoped.rb +21 -0
- data/app/controllers/credentials_controller.rb +23 -0
- data/app/controllers/groups_controller.rb +4 -0
- data/app/controllers/iam/application_controller.rb +6 -0
- data/app/controllers/iam/confirmations_controller.rb +51 -0
- data/app/controllers/iam/passwords_controller.rb +56 -0
- data/app/controllers/iam/sessions_controller.rb +21 -0
- data/app/controllers/policies_controller.rb +4 -0
- data/app/controllers/public_keys_controller.rb +4 -0
- data/app/controllers/roots/sessions_controller.rb +16 -0
- data/app/controllers/roots_controller.rb +4 -0
- data/app/controllers/users/confirmations_controller.rb +21 -0
- data/app/controllers/users/passwords_controller.rb +25 -0
- data/app/controllers/users/sessions_controller.rb +19 -0
- data/app/controllers/users_controller.rb +17 -0
- data/app/mailers/account_mailer.rb +74 -0
- data/app/models/action.rb +6 -0
- data/app/models/credential.rb +47 -0
- data/app/models/group.rb +15 -0
- data/app/models/group_policy_join.rb +25 -0
- data/app/models/iam/application_record.rb +7 -0
- data/app/models/policy.rb +10 -0
- data/app/models/policy_action.rb +6 -0
- data/app/models/public_key.rb +17 -0
- data/app/models/role.rb +11 -0
- data/app/models/role_policy_join.rb +6 -0
- data/app/models/root.rb +26 -0
- data/app/models/root_credential.rb +7 -0
- data/app/models/tenant.rb +68 -0
- data/app/models/user.rb +69 -0
- data/app/models/user_credential.rb +8 -0
- data/app/models/user_group.rb +25 -0
- data/app/models/user_policy_join.rb +21 -0
- data/app/models/user_role.rb +6 -0
- data/app/operations/blackcomb_user_create.rb +49 -0
- data/app/operations/user_create.rb +53 -0
- data/app/policies/action_policy.rb +3 -0
- data/app/policies/credential_policy.rb +3 -0
- data/app/policies/group_policy.rb +3 -0
- data/app/policies/iam/application_policy.rb +6 -0
- data/app/policies/policy_policy.rb +3 -0
- data/app/policies/public_key_policy.rb +4 -0
- data/app/policies/root_policy.rb +3 -0
- data/app/policies/tenant_policy.rb +5 -0
- data/app/policies/user_policy.rb +33 -0
- data/app/resources/action_resource.rb +16 -0
- data/app/resources/credential_resource.rb +13 -0
- data/app/resources/group_resource.rb +8 -0
- data/app/resources/iam/application_resource.rb +7 -0
- data/app/resources/policy_resource.rb +9 -0
- data/app/resources/public_key_resource.rb +6 -0
- data/app/resources/root_resource.rb +14 -0
- data/app/resources/tenant_resource.rb +21 -0
- data/app/resources/user_resource.rb +25 -0
- data/app/views/layouts/mailer.html.erb +4 -0
- data/app/views/user_mailer/confirmation_instructions.html.erb +5 -0
- data/app/views/user_mailer/email_changed.html.erb +7 -0
- data/app/views/user_mailer/password_change.html.erb +3 -0
- data/app/views/user_mailer/reset_password_instructions.html.erb +106 -0
- data/app/views/user_mailer/team_welcome.html.erb +107 -0
- data/app/views/user_mailer/unlock_instructions.html.erb +7 -0
- data/config/environment.rb +0 -0
- data/config/initializers/devise.rb +311 -0
- data/config/locales/devise.en.yml +65 -0
- data/config/routes.rb +17 -0
- data/config/sidekiq.yml +5 -0
- data/config/spring.rb +3 -0
- data/db/migrate/20190101000001_create_policies.rb +11 -0
- data/db/migrate/20190101000002_create_actions.rb +13 -0
- data/db/migrate/20190101000003_create_policy_actions.rb +13 -0
- data/db/migrate/20190215214352_create_roots.rb +43 -0
- data/db/migrate/20190215214353_update_tenants.rb +10 -0
- data/db/migrate/20190215214355_create_credentials.rb +14 -0
- data/db/migrate/20190215214407_create_users.rb +50 -0
- data/db/migrate/20190215214409_create_user_credentials.rb +12 -0
- data/db/migrate/20190215214410_create_user_policy_joins.rb +12 -0
- data/db/migrate/20190215214411_create_groups.rb +11 -0
- data/db/migrate/20190215214412_create_user_groups.rb +12 -0
- data/db/migrate/20190215214413_create_group_policy_joins.rb +12 -0
- data/db/migrate/20190215214415_create_roles.rb +11 -0
- data/db/migrate/20190215214416_create_user_roles.rb +12 -0
- data/db/migrate/20190215214421_create_role_policy_joins.rb +12 -0
- data/db/migrate/20190924091536_add_display_properties_to_tenants.rb +5 -0
- data/db/migrate/20191021220135_create_public_keys.rb +10 -0
- data/db/migrate/20191120083154_add_confirmable_email_to_user.rb +9 -0
- data/db/seeds/development/tenants.seeds.rb +41 -0
- data/db/seeds/development/users.seeds.rb +67 -0
- data/lib/ros/api_token_strategy.rb +24 -0
- data/lib/ros/iam.rb +18 -0
- data/lib/ros/iam/console.rb +13 -0
- data/lib/ros/iam/engine.rb +51 -0
- data/lib/ros/iam/version.rb +7 -0
- data/lib/tasks/ros/iam_tasks.rake +51 -0
- metadata +209 -0
data/config/routes.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Ros::Iam::Engine.routes.draw do
|
4
|
+
jsonapi_resources :public_keys
|
5
|
+
devise_for :users, module: 'users', defaults: { format: :json }
|
6
|
+
devise_for :roots, module: 'roots', defaults: { format: :json }
|
7
|
+
|
8
|
+
jsonapi_resources :credentials
|
9
|
+
jsonapi_resources :groups
|
10
|
+
jsonapi_resources :policies
|
11
|
+
jsonapi_resources :roots
|
12
|
+
jsonapi_resources :users
|
13
|
+
|
14
|
+
# TODO: temporary route until we support registering callbacks to allow
|
15
|
+
# a root owner account to create a tenant
|
16
|
+
post '/blackcomb_credentials', to: 'credentials#blackcomb'
|
17
|
+
end
|
data/config/sidekiq.yml
ADDED
data/config/spring.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateActions < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
create_table :actions do |t|
|
6
|
+
t.string :name, null: false, index: { unique: true }
|
7
|
+
t.string :type, null: false
|
8
|
+
t.string :resource
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreatePolicyActions < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
create_table :policy_actions do |t|
|
6
|
+
t.references :policy, foreign_key: true
|
7
|
+
t.references :action, foreign_key: true
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
add_index :policy_actions, %i[policy_id action_id], unique: true
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateRoots < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
create_table :roots do |t|
|
6
|
+
t.boolean :api, null: false, default: false
|
7
|
+
t.string :time_zone, null: false, default: 'UTC'
|
8
|
+
|
9
|
+
## Database authenticatable
|
10
|
+
t.string :email, null: false, default: '', index: { unique: true }
|
11
|
+
t.string :encrypted_password, null: false, default: ''
|
12
|
+
|
13
|
+
## Recoverable
|
14
|
+
t.string :reset_password_token, index: { unique: true }
|
15
|
+
t.datetime :reset_password_sent_at
|
16
|
+
|
17
|
+
## Rememberable
|
18
|
+
t.datetime :remember_created_at
|
19
|
+
|
20
|
+
## Trackable
|
21
|
+
# t.integer :sign_in_count, default: 0, null: false
|
22
|
+
# t.datetime :current_sign_in_at
|
23
|
+
# t.datetime :last_sign_in_at
|
24
|
+
# t.string :current_sign_in_ip
|
25
|
+
# t.string :last_sign_in_ip
|
26
|
+
|
27
|
+
## Confirmable
|
28
|
+
# t.string :confirmation_token
|
29
|
+
# t.datetime :confirmed_at
|
30
|
+
# t.datetime :confirmation_sent_at
|
31
|
+
# t.string :unconfirmed_email # Only if using reconfirmable
|
32
|
+
|
33
|
+
## Lockable
|
34
|
+
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
|
35
|
+
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
36
|
+
# t.datetime :locked_at
|
37
|
+
|
38
|
+
t.timestamps null: false
|
39
|
+
end
|
40
|
+
# add_index :users, :confirmation_token, unique: true
|
41
|
+
# add_index :users, :unlock_token, unique: true
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UpdateTenants < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
add_reference :tenants, :root, null: false, foreign_key: true, index: { unique: true }
|
6
|
+
add_column :tenants, :alias, :string, null: true, index: { unique: true }
|
7
|
+
add_column :tenants, :name, :string
|
8
|
+
add_column :tenants, :state, :string
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateCredentials < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
create_table :credentials do |t|
|
6
|
+
t.references :owner, polymorphic: true
|
7
|
+
t.string :access_key_id, length: 20, index: { unique: true }
|
8
|
+
t.string :secret_access_key_digest
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
# add_index :credentials, :access_key_id, unique: true
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateUsers < ActiveRecord::Migration[6.0]
|
4
|
+
# rubocop:disable Metrics/MethodLength
|
5
|
+
def change
|
6
|
+
create_table :users do |t|
|
7
|
+
t.boolean :console, null: false, default: false, comment: 'Allow console access when true'
|
8
|
+
t.boolean :api, null: false, default: false, comment: 'Allow API access when true'
|
9
|
+
t.string :time_zone, null: false, default: 'UTC', comment: 'Adjust timestamps to this time zone'
|
10
|
+
t.jsonb :attached_policies, null: false, default: {}
|
11
|
+
t.jsonb :attached_actions, null: false, default: {}
|
12
|
+
t.jsonb :properties, null: false, default: {}, comment: 'Custom properties of the user'
|
13
|
+
t.jsonb :display_properties, null: false, default: {}, comment: 'Custom display properties of the user'
|
14
|
+
|
15
|
+
## Database authenticatable
|
16
|
+
t.string :username, null: false, index: { unique: true }
|
17
|
+
t.string :encrypted_password, null: false, default: '', comment: 'Required if console is true'
|
18
|
+
|
19
|
+
## Recoverable
|
20
|
+
t.string :reset_password_token, index: { unique: true }
|
21
|
+
t.datetime :reset_password_sent_at
|
22
|
+
|
23
|
+
## Rememberable
|
24
|
+
t.datetime :remember_created_at
|
25
|
+
|
26
|
+
## Trackable
|
27
|
+
# t.integer :sign_in_count, default: 0, null: false
|
28
|
+
# t.datetime :current_sign_in_at
|
29
|
+
# t.datetime :last_sign_in_at
|
30
|
+
# t.string :current_sign_in_ip
|
31
|
+
# t.string :last_sign_in_ip
|
32
|
+
|
33
|
+
## Confirmable
|
34
|
+
# t.string :confirmation_token
|
35
|
+
# t.datetime :confirmed_at
|
36
|
+
# t.datetime :confirmation_sent_at
|
37
|
+
# t.string :unconfirmed_email # Only if using reconfirmable
|
38
|
+
|
39
|
+
## Lockable
|
40
|
+
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
|
41
|
+
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
42
|
+
# t.datetime :locked_at
|
43
|
+
|
44
|
+
t.timestamps null: false
|
45
|
+
end
|
46
|
+
# add_index :users, :confirmation_token, unique: true
|
47
|
+
# add_index :users, :unlock_token, unique: true
|
48
|
+
end
|
49
|
+
# rubocop:enable Metrics/MethodLength
|
50
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateUserCredentials < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
create_table :user_credentials do |t|
|
6
|
+
t.references :user, foreign_key: true
|
7
|
+
t.integer :credential_id, foreign_key: true, index: { unique: true }
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateUserPolicyJoins < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
create_table :user_policy_joins do |t|
|
6
|
+
t.references :user, foreign_key: true
|
7
|
+
t.references :policy, foreign_key: true
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateGroupPolicyJoins < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
create_table :group_policy_joins do |t|
|
6
|
+
t.references :group, foreign_key: true
|
7
|
+
t.references :policy, foreign_key: true
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateRolePolicyJoins < ActiveRecord::Migration[6.0]
|
4
|
+
def change
|
5
|
+
create_table :role_policy_joins do |t|
|
6
|
+
t.references :role, foreign_key: true
|
7
|
+
t.references :policy, foreign_key: true
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class AddConfirmableEmailToUser < ActiveRecord::Migration[6.0]
|
2
|
+
def change
|
3
|
+
add_column :users, :email, :string
|
4
|
+
add_column :users, :confirmation_token, :string
|
5
|
+
add_column :users, :confirmed_at, :datetime
|
6
|
+
add_column :users, :confirmation_sent_at, :datetime
|
7
|
+
add_column :users, :unconfirmed_email, :string
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# NOTE: Disabling event logging
|
4
|
+
logging_mem = Settings.event_logging.enabled
|
5
|
+
Settings.event_logging.enabled = false
|
6
|
+
# if 'platform owner' account does not exist then create it and initialize credentials file
|
7
|
+
initialize = Root.find_by(email: 'root@platform.com').nil?
|
8
|
+
|
9
|
+
create_list = if initialize
|
10
|
+
[
|
11
|
+
{ email: 'root@platform.com', password: 'asdfjkl;', api: true, alias: 'owner' },
|
12
|
+
{ email: 'root@generic.com', password: 'asdfjkl;', alias: 'generic' },
|
13
|
+
{ email: 'root@banking.com', password: 'asdfjkl;', alias: 'banking' },
|
14
|
+
{ email: 'root@telco.com', password: 'asdfjkl;', alias: 'telco' },
|
15
|
+
{ email: 'root@insurance.com', password: 'asdfjkl;', alias: 'insurance' },
|
16
|
+
{ email: 'root@retail.com', password: 'asdfjkl;', alias: 'retail' }
|
17
|
+
]
|
18
|
+
else
|
19
|
+
# TODO: We don't need it anymore
|
20
|
+
# id = Root.last.id
|
21
|
+
# create_list = [
|
22
|
+
# { email: "root@client#{id + 1}.com", password: 'asdfjkl;' },
|
23
|
+
# { email: "root@client#{id + 2}.com", password: 'asdfjkl;' }
|
24
|
+
# ]
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
owner_root = Root.create!(email: 'root@owner.com', password: 'asdfjkl;')
|
28
|
+
Tenant.create(schema_name: 'public', name: 'Account 1', alias: 'root', root: owner_root)
|
29
|
+
|
30
|
+
@created_list = []
|
31
|
+
create_list.each do |account|
|
32
|
+
tenant_alias = account.delete(:alias)
|
33
|
+
Root.create!(account).tap do |root|
|
34
|
+
root.create_tenant(schema_name: Tenant.account_id_to_schema(root.id.to_s * 9)[0..10],
|
35
|
+
name: "Account #{root.id}", state: :active, alias: tenant_alias)
|
36
|
+
credential = Credential.create(owner: root)
|
37
|
+
@created_list.append(type: 'root', owner: root, tenant: root.tenant, credential: credential,
|
38
|
+
secret: credential.secret_access_key)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
Settings.event_logging.enabled = logging_mem
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# ubocop:disable Metrics/BlockLength
|
4
|
+
after 'development:tenants' do
|
5
|
+
Tenant.all.each do |tenant|
|
6
|
+
next if tenant.id.eql? 1
|
7
|
+
|
8
|
+
tenant.switch do
|
9
|
+
if Policy.count.zero?
|
10
|
+
# Add IAM Policies
|
11
|
+
Policy.create(name: 'AdministratorAccess')
|
12
|
+
Policy.create(name: 'IamUserFullAccess')
|
13
|
+
Policy.create(name: 'IamUserReadOnlyAccess')
|
14
|
+
end
|
15
|
+
next if User.count.positive?
|
16
|
+
|
17
|
+
user = User.create(username: 'Admin',
|
18
|
+
console: true,
|
19
|
+
api: true,
|
20
|
+
time_zone: 'Asia/Singapore',
|
21
|
+
email: 'admin@example.com',
|
22
|
+
confirmed_at: DateTime.now,
|
23
|
+
password: 'asdfjkl;')
|
24
|
+
User.create(username: 'Microsite',
|
25
|
+
console: false,
|
26
|
+
api: true,
|
27
|
+
time_zone: 'Asia/Singapore',
|
28
|
+
email: 'microsite@example.com',
|
29
|
+
confirmed_at: DateTime.now)
|
30
|
+
# user.locale: 'en-US'
|
31
|
+
credential = user.credentials.create
|
32
|
+
@created_list.append(type: 'user',
|
33
|
+
owner: user,
|
34
|
+
tenant: tenant,
|
35
|
+
credential: credential,
|
36
|
+
secret: credential.secret_access_key)
|
37
|
+
|
38
|
+
# Create a Group
|
39
|
+
group_admin = Group.create(name: 'Admin')
|
40
|
+
|
41
|
+
# Attach the Admin Policy to the Group
|
42
|
+
group_admin.policies << Policy.first
|
43
|
+
|
44
|
+
# Assign the first User to the Admin Group
|
45
|
+
group_admin.users << User.first
|
46
|
+
|
47
|
+
# NOTE: create remainign groups
|
48
|
+
Group.create(name: 'Creator')
|
49
|
+
Group.create(name: 'Customer Support')
|
50
|
+
Group.create(name: 'Manager')
|
51
|
+
Group.create(name: 'Viewer')
|
52
|
+
|
53
|
+
# Role.create(name: 'PerxServiceRoleForIAM')
|
54
|
+
# Role.create(name: 'PerxUserReadOnlyAccess')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Append newly created credentials to credentials.json in the tmp directory
|
59
|
+
FileUtils.mkdir_p(Ros.host_tmp_dir)
|
60
|
+
File.open("#{Ros.host_tmp_dir}/credentials.json", 'w') do |f|
|
61
|
+
f.puts(@created_list.to_json)
|
62
|
+
end
|
63
|
+
# Output the contents so that it can be captured by the helm log file when deployed into kubernetes
|
64
|
+
STDOUT.puts 'Credentials are next:'
|
65
|
+
STDOUT.puts File.read("#{Ros.host_tmp_dir}/credentials.json")
|
66
|
+
end
|
67
|
+
# ubocop:enable Metrics/BlockLength
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ros
|
4
|
+
# NOTE: Overrides methods in ros-core gem
|
5
|
+
class ApiTokenStrategy
|
6
|
+
def authenticate_basic
|
7
|
+
credential = if access_key[:owner_type].eql?('Root')
|
8
|
+
Apartment::Tenant.switch('public') { Credential.find_by(access_key_id: access_key_id) }
|
9
|
+
else
|
10
|
+
Credential.find_by(access_key_id: access_key_id)
|
11
|
+
end
|
12
|
+
return unless credential
|
13
|
+
|
14
|
+
credential.authenticate_secret_access_key(secret_access_key).try(:owner)
|
15
|
+
end
|
16
|
+
|
17
|
+
def authenticate_bearer
|
18
|
+
return unless (urn = Urn.from_jwt(token))
|
19
|
+
return unless urn.model_name.in? %w[Root User]
|
20
|
+
|
21
|
+
urn.instance
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|