ccli 0.1.0

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.
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Error < StandardError
4
+ end
5
+
6
+ class SessionMissingError < Error
7
+ end
8
+
9
+ class UnauthorizedError < Error
10
+ end
11
+
12
+ class ForbiddenError < Error
13
+ end
14
+
15
+ class OpenshiftClientMissingError < Error
16
+ end
17
+
18
+ class OpenshiftClientNotLoggedInError < Error
19
+ end
20
+
21
+ class KubernetesClientMissingError < Error
22
+ end
23
+
24
+ class KubernetesClientNotLoggedInError < Error
25
+ end
26
+
27
+ class OpenshiftSecretNotFoundError < Error
28
+ end
29
+
30
+ class NoFolderSelectedError < Error
31
+ end
32
+
33
+ class CryptopusAccountNotFoundError < Error
34
+ end
35
+
36
+ class TeamNotFoundError < Error
37
+ end
38
+
39
+ class FolderNotFoundError < Error
40
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Account
4
+ attr_reader :id, :accountname, :username, :password, :type, :ose_secret
5
+ attr_accessor :folder
6
+
7
+ def initialize(accountname: nil, username: nil, password: nil,
8
+ ose_secret: nil, type: nil, id: nil)
9
+ @id = id
10
+ @accountname = accountname
11
+ @username = username
12
+ @password = password
13
+ @ose_secret = ose_secret
14
+ @type = type || 'credentials'
15
+ end
16
+
17
+ def to_json(*_args)
18
+ AccountSerializer.to_json(self)
19
+ end
20
+
21
+ def to_yaml
22
+ AccountSerializer.to_yaml(self)
23
+ end
24
+
25
+ def to_osesecret
26
+ AccountSerializer.to_osesecret(self)
27
+ end
28
+
29
+ class << self
30
+ def find(id)
31
+ AccountSerializer.from_json(CryptopusAdapter.new.get("accounts/#{id}"))
32
+ end
33
+
34
+ def find_by_name_and_folder_id(name, id)
35
+ Folder.find(id).accounts.find do |account|
36
+ account.accountname.downcase == name.downcase
37
+ end
38
+ end
39
+
40
+ def from_json(json)
41
+ AccountSerializer.from_json(json)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Folder
4
+ attr_reader :name, :id, :accounts
5
+
6
+ def initialize(name: nil, id: nil, accounts: [])
7
+ @name = name
8
+ @id = id
9
+ @accounts = accounts
10
+ end
11
+
12
+ class << self
13
+ def find(id)
14
+ json = JSON.parse(CryptopusAdapter.new.get("folders/#{id}"),
15
+ symbolize_names: true)
16
+ included = json[:included] || []
17
+ name = json[:data][:attributes][:name]
18
+ accounts = included.map do |record|
19
+ Account.from_json(record.to_json) if %w[account_ose_secrets
20
+ account_credentials].include? record[:type]
21
+ end.compact
22
+ Folder.new(id: id, name: name, accounts: accounts)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './ose_secret'
4
+
5
+ class K8SSecret < OSESecret
6
+ class << self
7
+ def all
8
+ K8SAdapter.new.fetch_all_secrets.map { |s| OSESecretSerializer.from_yaml(s) }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ class OSESecret
4
+ attr_reader :name, :ose_secret
5
+
6
+ def initialize(name, ose_secret)
7
+ @name = name
8
+ @ose_secret = ose_secret
9
+ end
10
+
11
+ def to_account
12
+ OSESecretSerializer.to_account(self)
13
+ end
14
+
15
+ def to_yaml
16
+ OSESecretSerializer.to_yaml(self)
17
+ end
18
+
19
+ class << self
20
+ def find_by_name(name)
21
+ OSESecretSerializer.from_yaml(OSEAdapter.new.fetch_secret(name))
22
+ end
23
+
24
+ def all
25
+ OSEAdapter.new.fetch_all_secrets.map { |s| OSESecretSerializer.from_yaml(s) }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Team
4
+ attr_reader :name, :id, :folders
5
+
6
+ def initialize(name: nil, folders: nil, id: nil)
7
+ @name = name
8
+ @folders = folders
9
+ @id = id
10
+ end
11
+
12
+ def render_list
13
+ TeamPresenter.render_list(self)
14
+ end
15
+
16
+ def folder_by_name(name)
17
+ folders.find do |folder|
18
+ folder.name.downcase.gsub(' ', '-') == name.downcase
19
+ end
20
+ end
21
+
22
+ class << self
23
+ def all
24
+ cryptopus_adapter = CryptopusAdapter.new
25
+ response = JSON.parse(cryptopus_adapter.get('teams'), symbolize_names: true)
26
+ response[:data].map do |team|
27
+ TeamSerializer.from_json(team.to_json, folders_json: included_folders(response))
28
+ end
29
+ end
30
+
31
+ def find_by_name(name)
32
+ Team.all.find do |team|
33
+ team.name.downcase.gsub(' ', '-') == name.downcase
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def included_folders(json)
40
+ json[:included].select do |folder|
41
+ folder[:type] == 'folders'
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TeamPresenter
4
+ class << self
5
+ def render_list(team)
6
+ team_name = team.name.downcase
7
+ despaced_team_name = team_name.gsub(' ', '-')
8
+ folder_rows = team.folders.map do |folder|
9
+ folder_name = folder.name.downcase
10
+ "#{folder_name} (cry use #{despaced_team_name}/#{folder_name.gsub(' ', '-')})"
11
+ end
12
+
13
+ team_name = "#{team_name} => "
14
+ joined_folder_rows = folder_rows.join("\n" + ' ' * team_name.length)
15
+ team_name + joined_folder_rows
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ class AccountSerializer
6
+ class << self
7
+ # rubocop:disable Metrics/MethodLength
8
+ def to_json(account)
9
+ {
10
+ data: {
11
+ type: 'accounts',
12
+ id: account.id,
13
+ attributes: {
14
+ accountname: account.accountname,
15
+ type: account.type,
16
+ cleartext_username: account.username,
17
+ cleartext_password: account.password,
18
+ ose_secret: account.ose_secret
19
+ },
20
+ relationships: {
21
+ folder: {
22
+ data: {
23
+ id: account.folder,
24
+ type: 'folders'
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }.compact.to_json
30
+ end
31
+ # rubocop:enable Metrics/MethodLength
32
+
33
+ def to_yaml(account)
34
+ { 'id' => account.id,
35
+ 'accountname' => account.accountname,
36
+ 'username' => account.username,
37
+ 'password' => account.password,
38
+ 'type' => account.type }.to_yaml
39
+ end
40
+
41
+ def from_json(json)
42
+ json = JSON.parse(json, symbolize_names: true)
43
+ data = json[:data] || json
44
+ attributes = data[:attributes]
45
+ Account.new(accountname: attributes[:accountname],
46
+ username: attributes[:cleartext_username],
47
+ password: attributes[:cleartext_password],
48
+ ose_secret: attributes[:ose_secret],
49
+ type: attributes[:type],
50
+ id: data[:id])
51
+ end
52
+
53
+ def to_osesecret(account)
54
+ OSESecret.new(account.accountname, account.ose_secret)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FolderSerializer
4
+ class << self
5
+ def from_json(json)
6
+ json = JSON.parse(json, symbolize_names: true)
7
+ data = json[:data] || json
8
+ attributes = data[:attributes]
9
+ Folder.new(name: attributes[:name], id: data[:id])
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'psych'
4
+
5
+ class OSESecretSerializer
6
+ class << self
7
+ def from_yaml(yaml)
8
+ secret_hash = Psych.load(yaml, symbolize_names: true)
9
+ OSESecret.new(secret_hash.dig(:metadata, :name), yaml)
10
+ end
11
+
12
+ def to_account(secret)
13
+ Account.new(accountname: secret.name, ose_secret: secret.ose_secret, type: 'ose_secret')
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TeamSerializer
4
+ class << self
5
+ def from_json(json, folders_json: [])
6
+ json = JSON.parse(json, symbolize_names: true)
7
+ data = json[:data] || json
8
+ attributes = data[:attributes]
9
+ folder_ids = data[:relationships][:folders][:data].map { |folder| folder[:id] }
10
+ folders = folders_json.map do |folder|
11
+ FolderSerializer.from_json(folder.to_json) if folder_ids.include?(folder[:id])
12
+ end.compact
13
+ Team.new(name: attributes[:name],
14
+ folders: folders,
15
+ id: data[:id])
16
+ end
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ccli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nils Rauch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-10-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: commander
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.5'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 4.5.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '4.5'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 4.5.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: tty-command
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: tty-exit
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: tty-logger
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ description:
76
+ email: rauch@puzzle.ch
77
+ executables:
78
+ - cry
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - ".rubocop.yml"
83
+ - ".travis.yml"
84
+ - Gemfile
85
+ - Gemfile.lock
86
+ - README.md
87
+ - bin/cry
88
+ - ccli.gemspec
89
+ - lib/adapters/cluster_secret_adapter.rb
90
+ - lib/adapters/cryptopus_adapter.rb
91
+ - lib/adapters/k8s_adapter.rb
92
+ - lib/adapters/ose_adapter.rb
93
+ - lib/adapters/session_adapter.rb
94
+ - lib/cli.rb
95
+ - lib/errors.rb
96
+ - lib/models/account.rb
97
+ - lib/models/folder.rb
98
+ - lib/models/k8s_secret.rb
99
+ - lib/models/ose_secret.rb
100
+ - lib/models/team.rb
101
+ - lib/presenters/team_presenter.rb
102
+ - lib/serializers/account_serializer.rb
103
+ - lib/serializers/folder_serializer.rb
104
+ - lib/serializers/ose_secret_serializer.rb
105
+ - lib/serializers/team_serializer.rb
106
+ homepage:
107
+ licenses: []
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '2.0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.7.9
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Command line client for the opensource password manager Cryptopus
129
+ test_files: []