passwordstate 0.0.3 → 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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +33 -0
  3. data/.gitignore +2 -1
  4. data/.gitlab-ci.yml +10 -7
  5. data/.rubocop.yml +6 -9
  6. data/CHANGELOG.md +11 -0
  7. data/README.md +64 -16
  8. data/Rakefile +2 -2
  9. data/lib/passwordstate/client.rb +55 -16
  10. data/lib/passwordstate/errors.rb +6 -1
  11. data/lib/passwordstate/resource.rb +131 -49
  12. data/lib/passwordstate/resource_list.rb +56 -42
  13. data/lib/passwordstate/resources/active_directory.rb +23 -0
  14. data/lib/passwordstate/resources/address_book.rb +28 -0
  15. data/lib/passwordstate/resources/document.rb +32 -3
  16. data/lib/passwordstate/resources/folder.rb +6 -3
  17. data/lib/passwordstate/resources/host.rb +2 -0
  18. data/lib/passwordstate/resources/password.rb +50 -15
  19. data/lib/passwordstate/resources/password_list.rb +41 -8
  20. data/lib/passwordstate/resources/permission.rb +2 -0
  21. data/lib/passwordstate/resources/privileged_account.rb +32 -0
  22. data/lib/passwordstate/resources/remote_site.rb +26 -0
  23. data/lib/passwordstate/resources/report.rb +2 -0
  24. data/lib/passwordstate/util.rb +22 -2
  25. data/lib/passwordstate/version.rb +3 -1
  26. data/lib/passwordstate.rb +4 -1
  27. data/passwordstate.gemspec +9 -3
  28. data/test/client_test.rb +39 -0
  29. data/test/fixtures/get_password.json +31 -0
  30. data/test/fixtures/get_password_list.json +42 -0
  31. data/test/fixtures/get_password_otp.json +5 -0
  32. data/test/fixtures/password_list_search_passwords.json +60 -0
  33. data/test/fixtures/update_password.json +31 -0
  34. data/test/fixtures/update_password_managed.json +8 -0
  35. data/test/passwordstate_test.rb +10 -2
  36. data/test/resources/password_list_test.rb +81 -0
  37. data/test/resources/password_test.rb +105 -0
  38. data/test/test_helper.rb +8 -0
  39. metadata +56 -15
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordstate
2
4
  module Resources
3
5
  class Password < Passwordstate::Resource
@@ -5,6 +7,7 @@ module Passwordstate
5
7
 
6
8
  index_field :password_id
7
9
 
10
+ # rubocop:disable Naming/VariableNumber
8
11
  accessor_fields :title,
9
12
  :domain,
10
13
  :host_name,
@@ -20,6 +23,7 @@ module Passwordstate
20
23
  :generic_field_8, { name: 'GenericField8' },
21
24
  :generic_field_9, { name: 'GenericField9' },
22
25
  :generic_field_10, { name: 'GenericField10' },
26
+ :generic_field_info,
23
27
  :account_type_id, { name: 'AccountTypeID' },
24
28
  :notes,
25
29
  :url,
@@ -28,11 +32,17 @@ module Passwordstate
28
32
  :allow_export,
29
33
  :web_user_id, { name: 'WebUser_ID' },
30
34
  :web_password_id, { name: 'WebPassword_ID' },
31
- :password_list_id, { name: 'PasswordListID' } # Note: POST only # rubocop:disable Style/BracesAroundHashParameters
35
+ :password_list_id, { name: 'PasswordListID' } # NB: POST only
36
+ # rubocop:enable Naming/VariableNumber
32
37
 
33
38
  read_fields :account_type,
34
39
  :password_id, { name: 'PasswordID' },
35
- :password_list
40
+ :password_list,
41
+ :otp,
42
+ # For 'Managed' passwords
43
+ :status,
44
+ :current_password,
45
+ :new_password
36
46
 
37
47
  # Things that can be set in a POST/PUT request
38
48
  # TODO: Do this properly
@@ -47,18 +57,41 @@ module Passwordstate
47
57
  :heartbeat_enabled,
48
58
  :heartbeat_schedule,
49
59
  :validation_script_id, { name: 'ValidationScriptID' },
50
- :host_name,
51
60
  :ad_domain_netbios, { name: 'ADDomainNetBIOS' },
52
61
  :validate_with_priv_account
53
62
 
63
+ def otp!
64
+ client.request(:get, "onetimepassword/#{password_id}").first['OTP']
65
+ end
66
+
54
67
  def check_in
55
- client.request :get, "passwords/#{password_id}", query: passwordstatify_hash(check_in: nil)
68
+ client.request :get, "passwords/#{password_id}", query: self.class.passwordstateify_hash(check_in: nil)
69
+ end
70
+
71
+ def send_selfdestruct(email, expires_at:, view_count:, reason: nil, **params)
72
+ data = {
73
+ password_id: password_id,
74
+ to_email_address: email,
75
+ expires_at: expires_at,
76
+ no_views: view_count
77
+ }
78
+ data[:message] = params[:message] if params.key? :message
79
+ data[:prefix_message_content] = params[:prefix_message] if params.key? :prefix_message
80
+ data[:append_message_content] = params[:suffix_message] if params.key? :suffix_message
81
+ data[:to_first_name] = params[:name] if params.key? :name
82
+ data[:email_subject] = params[:subject] if params.key? :subject
83
+ data[:email_body] = params[:body] if params.key? :body
84
+ data[:passphrase] = params[:passphrase] if params.key? :passphrase
85
+ data[:reason] = reason if reason
86
+
87
+ client.request :post, 'selfdestruct', data: data
56
88
  end
57
89
 
58
90
  def history
59
91
  raise 'Password history only available on stored passwords' unless stored?
60
92
 
61
- Passwordstate::ResourceList.new client, PasswordHistory,
93
+ Passwordstate::ResourceList.new PasswordHistory,
94
+ client: client,
62
95
  all_path: "passwordhistory/#{password_id}",
63
96
  only: :all
64
97
  end
@@ -68,25 +101,25 @@ module Passwordstate
68
101
  PasswordPermission.new(_client: client, password_id: password_id)
69
102
  end
70
103
 
71
- def delete(recycle = false, query = {})
72
- super query.merge(move_to_recycle_bin: recycle)
104
+ def delete(recycle: false, **query)
105
+ super(**query.merge(move_to_recycle_bin: recycle))
73
106
  end
74
107
 
75
- def add_dependency(data = {})
108
+ def add_dependency(**data)
76
109
  raise 'Password dependency creation only available for stored passwords' unless stored?
77
110
 
78
111
  client.request :post, 'dependencies', body: self.class.passwordstatify_hash(data.merge(password_id: password_id))
79
112
  end
80
113
 
81
- def self.all(client, query = {})
82
- super client, { query_all: true }.merge(query)
114
+ def self.all(client, **query)
115
+ super client, **{ query_all: true }.merge(query)
83
116
  end
84
117
 
85
- def self.search(client, query = {})
86
- super client, { _api_path: 'searchpasswords' }.merge(query)
118
+ def self.search(client, **query)
119
+ super client, **{ _api_path: 'searchpasswords' }.merge(query)
87
120
  end
88
121
 
89
- def self.generate(client, options = {})
122
+ def self.generate(client, **options)
90
123
  results = client.request(:get, 'generatepassword', query: options).map { |r| r['Password'] }
91
124
  return results.first if results.count == 1
92
125
 
@@ -109,6 +142,7 @@ module Passwordstate
109
142
  :surname
110
143
 
111
144
  # Password object fields
145
+ # rubocop:disable Naming/VariableNumber
112
146
  read_fields :title,
113
147
  :domain,
114
148
  :host_name,
@@ -133,7 +167,8 @@ module Passwordstate
133
167
  :expiry_date, { is: Time },
134
168
  :allow_export,
135
169
  :web_user_id, { name: 'WebUser_ID' },
136
- :web_password_id, { name: 'WebPassword_ID' } # rubocop:disable Style/BracesAroundHashParameters
170
+ :web_password_id, { name: 'WebPassword_ID' }
171
+ # rubocop:enable Naming/VariableNumber
137
172
 
138
173
  def get
139
174
  raise 'Not applicable'
@@ -145,7 +180,7 @@ module Passwordstate
145
180
 
146
181
  index_field :password_id
147
182
 
148
- read_fields :password_id, { name: 'PasswordID' } # rubocop:disable Style/BracesAroundHashParameters
183
+ read_fields :password_id, { name: 'PasswordID' }
149
184
  end
150
185
  end
151
186
  end
@@ -1,7 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordstate
2
4
  module Resources
3
5
  class PasswordList < Passwordstate::Resource
6
+ HideConfig = Struct.new(:view, :modify, :admin) do
7
+ def self.parse(str)
8
+ view, modify, admin = str.split(':').map { |b| b.to_s.downcase == 'true' }
9
+
10
+ new view, modify, admin
11
+ end
12
+
13
+ def to_s
14
+ "#{view}:#{modify}:#{admin}"
15
+ end
16
+ end
17
+
4
18
  api_path 'passwordlists'
19
+ acceptable_methods :CR
5
20
 
6
21
  index_field :password_list_id
7
22
 
@@ -26,11 +41,13 @@ module Passwordstate
26
41
  :provide_access_reason,
27
42
  :password_reset_enabled,
28
43
  :force_password_generator,
29
- :hide_passwords,
44
+ :hide_passwords, { is: HideConfig },
30
45
  :show_guide,
31
46
  :enable_password_reset_schedule,
32
47
  :password_reset_schedule,
33
- :add_days_to_expiry_date
48
+ :add_to_expiry_date,
49
+ :add_to_expiry_date_interval,
50
+ :one_time_passwords
34
51
 
35
52
  read_fields :password_list_id, { name: 'PasswordListID' },
36
53
  :tree_path,
@@ -38,14 +55,27 @@ module Passwordstate
38
55
  :generator_name,
39
56
  :policy_name
40
57
 
58
+ write_fields :copy_settings_from_password_list_id, { name: 'CopySettinsgFromPasswordListID' },
59
+ :copy_settings_from_template_id, { name: 'CopySettingsFromTemplateID' },
60
+ :link_to_template,
61
+ :copy_permissions_from_password_list_id, { name: 'CopyPermissionsFromPasswordListID' },
62
+ :copy_permissions_from_template_id, { name: 'CopyPermissionsFromTemplateID' },
63
+ :nest_under_folder_id, { name: 'NestUnderFolderID' },
64
+ :apply_permissions_for_user_id, { name: 'ApplyPermissionsForUserID' },
65
+ :apply_permissions_for_security_group_id, { name: 'ApplyPermissionsForSecurityGroupID' },
66
+ :apply_permissions_for_security_group_name,
67
+ :permission,
68
+ :site_id, { name: 'SiteID' }
69
+
41
70
  alias title password_list
42
71
 
43
- def self.search(client, query = {})
44
- super client, query.merge(_api_path: 'searchpasswordlists')
72
+ def self.search(client, **query)
73
+ super client, **query.merge(_api_path: 'searchpasswordlists')
45
74
  end
46
75
 
47
76
  def passwords
48
- Passwordstate::ResourceList.new client, Passwordstate::Resources::Password,
77
+ Passwordstate::ResourceList.new Passwordstate::Resources::Password,
78
+ client: client,
49
79
  all_path: "passwords/#{password_list_id}",
50
80
  all_query: { query_all: nil },
51
81
  search_path: "searchpasswords/#{password_list_id}",
@@ -57,8 +87,11 @@ module Passwordstate
57
87
  PasswordListPermission.new(_client: client, password_list_id: password_list_id)
58
88
  end
59
89
 
60
- def full_path(unix = false)
61
- [tree_path, password_list].compact.join('\\').tap do |full|
90
+ def full_path(unix: false)
91
+ path = [tree_path]
92
+ path << password_list unless tree_path.end_with? password_list
93
+
94
+ path.compact.join('\\').tap do |full|
62
95
  full.tr!('\\', '/') if unix
63
96
  end
64
97
  end
@@ -69,7 +102,7 @@ module Passwordstate
69
102
 
70
103
  index_field :password_list_id
71
104
 
72
- read_fields :password_list_id, { name: 'PasswordListID' } # rubocop:disable Style/BracesAroundHashParameters
105
+ read_fields :password_list_id, { name: 'PasswordListID' }
73
106
  end
74
107
  end
75
108
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordstate
2
4
  module Resources
3
5
  class Permission < Passwordstate::Resource
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Passwordstate
4
+ module Resources
5
+ class PrivilegedAccount < Passwordstate::Resource
6
+ api_path 'privaccount'
7
+
8
+ index_field :privileged_account_id
9
+
10
+ accessor_fields :description,
11
+ :user_name,
12
+ :password,
13
+ :password_id, { name: 'PasswordID' },
14
+ :key_type,
15
+ :pass_phrase,
16
+ :private_key,
17
+ :site_id, { name: 'SiteID' },
18
+ :account_type,
19
+ :enable_password
20
+
21
+ read_fields :privileged_account_id
22
+ end
23
+
24
+ class PrivilegedAccountPermission < Permission
25
+ api_path 'privaccountpermissions'
26
+
27
+ index_field :privileged_account_id
28
+
29
+ read_fields :privileged_account_id, { name: 'PrivilegedAccountID' }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Passwordstate
4
+ module Resources
5
+ class RemoteSite < Passwordstate::Resource
6
+ api_path 'remotesitelocations'
7
+
8
+ index_field :site_id
9
+
10
+ accessor_fields :site_location,
11
+ :poll_frequency,
12
+ :maintenance_start,
13
+ :maintenance_end,
14
+ :gateway_url, { name: 'GatewayURL' },
15
+ :purge_session_recordings,
16
+ :discovery_threads,
17
+ :allowed_ip_ranges, { name: 'AllowedIPRanges' }
18
+
19
+ read_fields :site_id, { name: 'SiteID' }
20
+
21
+ def self.installer_instructions
22
+ client.request :get, "#{api_path}/exportinstallerinstructions"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordstate
2
4
  module Resources
3
5
  class Report < Passwordstate::Resource
@@ -1,7 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'net/http'
2
4
  require 'net/ntlm'
3
5
 
4
6
  module Net
7
+ # NTLM header extension
8
+ #
9
+ # @example Setting NTLM auth
10
+ # req = Net::HTTP::Get.new URI('https://example.com')
11
+ # req.ntlm_auth 'username', 'password'
5
12
  module HTTPHeader
6
13
  attr_reader :ntlm_auth_information, :ntlm_auth_options
7
14
 
@@ -20,10 +27,12 @@ module Net
20
27
  end
21
28
 
22
29
  class String
30
+ # Convert a snake_case string to CamelCase
23
31
  def camel_case
24
32
  split('_').collect(&:capitalize).join
25
33
  end
26
34
 
35
+ # Convert a CamelCase string to snake_case
27
36
  def snake_case
28
37
  gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
29
38
  .gsub(/([a-z\d])([A-Z])/, '\1_\2')
@@ -31,6 +40,7 @@ class String
31
40
  .downcase
32
41
  end
33
42
 
43
+ # Find a specific line in a block of text
34
44
  def find_line(&_block)
35
45
  raise ArgumentError, 'No block given' unless block_given?
36
46
 
@@ -41,6 +51,16 @@ class String
41
51
  end
42
52
 
43
53
  module Passwordstate
54
+ # Extensions on Net::HTTP to allow NTLM digest auth
55
+ #
56
+ # @example Using NTLM auth
57
+ # uri = URI('https://example.com/some_object')
58
+ # Net::HTTP.start uri.host, uri.port { |http|
59
+ # req = Net::HTTP::Get.new uri
60
+ # req.ntlm_auth 'username', 'password'
61
+ #
62
+ # http.request req
63
+ # }
44
64
  module NetHTTPExtensions
45
65
  def request(req, body = nil, &block)
46
66
  return super(req, body, &block) if req.ntlm_auth_information.nil?
@@ -55,7 +75,7 @@ module Passwordstate
55
75
  end
56
76
 
57
77
  type1 = Net::NTLM::Message::Type1.new
58
- req['authorization'] = 'NTLM ' + type1.encode64
78
+ req['authorization'] = "NTLM #{type1.encode64}"
59
79
  res = super(req, body)
60
80
 
61
81
  challenge = res['www-authenticate'][/(?:NTLM|Negotiate) (.+)/, 1]
@@ -64,7 +84,7 @@ module Passwordstate
64
84
  type2 = Net::NTLM::Message.decode64 challenge
65
85
  type3 = type2.response(req.ntlm_auth_information, req.ntlm_auth_options.dup)
66
86
 
67
- req['authorization'] = 'NTLM ' + type3.encode64
87
+ req['authorization'] = "NTLM #{type3.encode64}"
68
88
  req.body_stream.rewind if req.body_stream
69
89
  req.body = @last_body if @last_body
70
90
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordstate
2
- VERSION = '0.0.3'.freeze
4
+ VERSION = '0.1.0'
3
5
  end
data/lib/passwordstate.rb CHANGED
@@ -1,10 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logging'
4
+ require 'pp'
5
+ require 'passwordstate/version'
2
6
  require 'passwordstate/client'
3
7
  require 'passwordstate/errors'
4
8
  require 'passwordstate/resource'
5
9
  require 'passwordstate/resource_list'
6
10
  require 'passwordstate/util'
7
- require 'passwordstate/version'
8
11
 
9
12
  module Passwordstate
10
13
  def self.debug!
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.join File.expand_path('lib', __dir__), 'passwordstate/version'
2
4
 
3
5
  Gem::Specification.new do |spec|
@@ -11,15 +13,19 @@ Gem::Specification.new do |spec|
11
13
  spec.homepage = 'https://github.com/ananace/ruby-passwordstate'
12
14
  spec.license = 'MIT'
13
15
 
16
+ spec.required_ruby_version = '>= 2.7'
17
+ spec.metadata['rubygems_mfa_required'] = 'true'
18
+
14
19
  spec.files = `git ls-files -z`.split("\x0")
15
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
20
  spec.require_paths = ['lib']
17
21
 
18
- spec.add_dependency 'logging', '~> 2.2'
19
- spec.add_dependency 'rubyntlm', '~> 0.6'
22
+ spec.add_dependency 'logging', '~> 2'
23
+ spec.add_dependency 'rubyntlm', '~> 0'
20
24
 
21
25
  spec.add_development_dependency 'bundler'
22
26
  spec.add_development_dependency 'minitest'
27
+ spec.add_development_dependency 'minitest-reporters'
28
+ spec.add_development_dependency 'mocha'
23
29
  spec.add_development_dependency 'rake'
24
30
  spec.add_development_dependency 'rubocop'
25
31
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class ClientTest < Minitest::Test
6
+ def setup
7
+ Net::HTTP.any_instance.expects(:start).never
8
+
9
+ @client = Passwordstate::Client.new 'http://passwordstate.example.com'
10
+ end
11
+
12
+ def test_version
13
+ @client.expects(:request).with(:get, '', allow_html: true).returns <<~HTML
14
+ <html>
15
+ Lorem ipsum
16
+ <div><span>V</span>9.3 (Build 9200)</div>
17
+ </html>
18
+ HTML
19
+
20
+ assert_equal '9.3.9200', @client.version
21
+ assert @client.version? '~> 9.3'
22
+ end
23
+
24
+ # Passwordstate version 9.6 has started doing stupid things.
25
+ # There are no longer any available method to see the version.
26
+ def test_broken_version
27
+ @client.stubs(:request).with(:get, '', allow_html: true).returns <<~HTML
28
+
29
+
30
+
31
+ <script>
32
+ window.location.href = '/help/manuals/api/index.html';
33
+ </script>
34
+ HTML
35
+
36
+ assert_nil @client.version
37
+ assert @client.version? '~> 9.3'
38
+ end
39
+ end
@@ -0,0 +1,31 @@
1
+ [
2
+ {
3
+ "PasswordListID": "100",
4
+ "PasswordList": "Managed Passwords",
5
+ "PasswordID": 18075,
6
+ "Title": "borgdrone-4673615 @ Unimatrix Zero",
7
+ "Domain": "",
8
+ "HostName": "",
9
+ "UserName": "borgdrone-4673615",
10
+ "Description": "Unimatrix Zero access key for borgdrone-4673615",
11
+ "GenericField1": "",
12
+ "GenericField2": "",
13
+ "GenericField3": "",
14
+ "GenericField4": "",
15
+ "GenericField5": "",
16
+ "GenericField6": "",
17
+ "GenericField7": "",
18
+ "GenericField8": "",
19
+ "GenericField9": "",
20
+ "GenericField10": "",
21
+ "GenericFieldInfo": [],
22
+ "AccountTypeID": 0,
23
+ "Notes": "",
24
+ "URL": "",
25
+ "Password": "weishe4uChee0woh4ahquineibahpheiquaiy2yuRohjohChee6eet6rahbaiceetucoothooph8ooKahwoh5Teepah3ieLohwahkeigh4eefeivoohee8quee5oohoe",
26
+ "ExpiryDate": "",
27
+ "AllowExport": true,
28
+ "AccountType": "",
29
+ "OTP": null
30
+ }
31
+ ]
@@ -0,0 +1,42 @@
1
+ [
2
+ {
3
+ "PasswordListID": 100,
4
+ "PasswordList": "Managed Passwords",
5
+ "Description": "Someone's managed passwords",
6
+ "ImageFileName": "system.png",
7
+ "Guide": "",
8
+ "AllowExport": false,
9
+ "PrivatePasswordList": false,
10
+ "NoApprovers": "1",
11
+ "DisableNotifications": false,
12
+ "TimeBasedAccessRequired": false,
13
+ "PasswordStrengthPolicyID": 1,
14
+ "PasswordGeneratorID": 1,
15
+ "CodePage": "Using Passwordstate Default Code Page",
16
+ "PreventPasswordReuse": 0,
17
+ "AuthenticationType": "Use RADIUS Authentication",
18
+ "AuthenticationPerSession": false,
19
+ "PreventExpiryDateModification": true,
20
+ "SetExpiryDate": 0,
21
+ "ResetExpiryDate": 0,
22
+ "PreventDragDrop": true,
23
+ "PreventBadPasswordUse": false,
24
+ "ProvideAccessReason": true,
25
+ "TreePath": "\\Shared\\Somewhere\\Managed Passwords",
26
+ "TotalPasswords": 656,
27
+ "GeneratorName": "Corporate Password Generator",
28
+ "PolicyName": "Corporate Password Strength Policy",
29
+ "PasswordResetEnabled": false,
30
+ "ForcePasswordGenerator": false,
31
+ "HidePasswords": "False:True:False",
32
+ "ShowGuide": false,
33
+ "EnablePasswordResetSchedule": false,
34
+ "PasswordResetSchedule": "00:00:00:00",
35
+ "AddToExpiryDate": 90,
36
+ "AddToExpiryDateInterval": "Days",
37
+ "SiteID": 0,
38
+ "SiteLocation": "Internal",
39
+ "OneTimePasswords": false,
40
+ "DisableInheritance": true
41
+ }
42
+ ]
@@ -0,0 +1,5 @@
1
+ [
2
+ {
3
+ "OTP": "123456"
4
+ }
5
+ ]
@@ -0,0 +1,60 @@
1
+ [
2
+ {
3
+ "PasswordListID": "100",
4
+ "PasswordList": "Managed Passwords",
5
+ "PasswordID": 18075,
6
+ "Title": "borgdrone-4673615 @ Unimatrix Zero",
7
+ "Domain": "",
8
+ "HostName": "",
9
+ "UserName": "borgdrone-4673615",
10
+ "Description": "Unimatrix Zero access key for borgdrone-4673615",
11
+ "GenericField1": "",
12
+ "GenericField2": "",
13
+ "GenericField3": "",
14
+ "GenericField4": "",
15
+ "GenericField5": "",
16
+ "GenericField6": "",
17
+ "GenericField7": "",
18
+ "GenericField8": "",
19
+ "GenericField9": "",
20
+ "GenericField10": "",
21
+ "GenericFieldInfo": [],
22
+ "AccountTypeID": 0,
23
+ "Notes": "",
24
+ "URL": "",
25
+ "Password": "weishe4uChee0woh4ahquineibahpheiquaiy2yuRohjohChee6eet6rahbaiceetucoothooph8ooKahwoh5Teepah3ieLohwahkeigh4eefeivoohee8quee5oohoe",
26
+ "ExpiryDate": "",
27
+ "AllowExport": true,
28
+ "AccountType": "",
29
+ "OTP": null
30
+ },
31
+ {
32
+ "PasswordListID": "100",
33
+ "PasswordList": "Managed Passwords",
34
+ "PasswordID": 29467,
35
+ "Title": "borgdrone-9342756 @ Unimatrix Zero",
36
+ "Domain": "",
37
+ "HostName": "",
38
+ "UserName": "borgdrone-9342756",
39
+ "Description": "Unimatrix Zero access key for borgdrone-9342756",
40
+ "GenericField1": "",
41
+ "GenericField2": "",
42
+ "GenericField3": "",
43
+ "GenericField4": "",
44
+ "GenericField5": "",
45
+ "GenericField6": "",
46
+ "GenericField7": "",
47
+ "GenericField8": "",
48
+ "GenericField9": "",
49
+ "GenericField10": "",
50
+ "GenericFieldInfo": [],
51
+ "AccountTypeID": 0,
52
+ "Notes": "",
53
+ "URL": "",
54
+ "Password": "chaihohd6aemeitivaefei0zahjee0IN7aevaisoGohrae5ileeHaquaik7lo1aicoo3lohchae2nujohRu2oofiizieth6aezahng8ohp9siesaemahKaifah8Ooyoo",
55
+ "ExpiryDate": "",
56
+ "AllowExport": true,
57
+ "AccountType": "",
58
+ "OTP": null
59
+ }
60
+ ]
@@ -0,0 +1,31 @@
1
+ [
2
+ {
3
+ "PasswordListID": "100",
4
+ "PasswordList": "Managed Passwords",
5
+ "PasswordID": 18075,
6
+ "Title": "borgdrone-4673615 @ Unimatrix Zero",
7
+ "Domain": "1c0389a1-6e63-4276-8500-1e595f0288e9.cube.collective",
8
+ "HostName": "",
9
+ "UserName": "borgdrone-4673615",
10
+ "Description": "Unimatrix Zero access key for borgdrone-4673615",
11
+ "GenericField1": "",
12
+ "GenericField2": "",
13
+ "GenericField3": "",
14
+ "GenericField4": "",
15
+ "GenericField5": "",
16
+ "GenericField6": "",
17
+ "GenericField7": "",
18
+ "GenericField8": "",
19
+ "GenericField9": "",
20
+ "GenericField10": "",
21
+ "GenericFieldInfo": [],
22
+ "AccountTypeID": 0,
23
+ "Notes": "",
24
+ "URL": "",
25
+ "Password": "weishe4uChee0woh4ahquineibahpheiquaiy2yuRohjohChee6eet6rahbaiceetucoothooph8ooKahwoh5Teepah3ieLohwahkeigh4eefeivoohee8quee5oohoe",
26
+ "ExpiryDate": "",
27
+ "AllowExport": true,
28
+ "AccountType": "",
29
+ "OTP": null
30
+ }
31
+ ]
@@ -0,0 +1,8 @@
1
+ [
2
+ {
3
+ "PasswordID": 18075,
4
+ "Status": "Password Queued for Reset(s). Check auditing data, or UI for results.",
5
+ "CurrentPassword": "weishe4uChee0woh4ahquineibahpheiquaiy2yuRohjohChee6eet6rahbaiceetucoothooph8ooKahwoh5Teepah3ieLohwahkeigh4eefeivoohee8quee5oohoe",
6
+ "NewPassword": "<redacted>"
7
+ }
8
+ ]