btps_client 1.0.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.
- checksums.yaml +7 -0
- data/README.md +444 -0
- data/lib/btps_client/api_operations/actionable.rb +22 -0
- data/lib/btps_client/api_operations/creatable.rb +16 -0
- data/lib/btps_client/api_operations/deletable.rb +15 -0
- data/lib/btps_client/api_operations/listable.rb +16 -0
- data/lib/btps_client/api_operations/movable.rb +17 -0
- data/lib/btps_client/api_operations/nested_listable.rb +23 -0
- data/lib/btps_client/api_operations/retrievable.rb +15 -0
- data/lib/btps_client/api_operations/scalar_creatable.rb +31 -0
- data/lib/btps_client/api_operations/searchable.rb +16 -0
- data/lib/btps_client/api_operations/updatable.rb +16 -0
- data/lib/btps_client/api_operations/uploadable.rb +29 -0
- data/lib/btps_client/api_requestor.rb +143 -0
- data/lib/btps_client/api_resource.rb +45 -0
- data/lib/btps_client/btps_object.rb +58 -0
- data/lib/btps_client/client.rb +37 -0
- data/lib/btps_client/configuration.rb +71 -0
- data/lib/btps_client/errors.rb +39 -0
- data/lib/btps_client/resources/credential.rb +98 -0
- data/lib/btps_client/resources/folder.rb +36 -0
- data/lib/btps_client/resources/managed_account.rb +97 -0
- data/lib/btps_client/resources/request.rb +107 -0
- data/lib/btps_client/resources/safe.rb +77 -0
- data/lib/btps_client/resources/secret.rb +179 -0
- data/lib/btps_client/schema_builder.rb +50 -0
- data/lib/btps_client/services/auth_service.rb +57 -0
- data/lib/btps_client/services/credentials_service.rb +36 -0
- data/lib/btps_client/services/folders_service.rb +37 -0
- data/lib/btps_client/services/managed_accounts_service.rb +48 -0
- data/lib/btps_client/services/requests_service.rb +44 -0
- data/lib/btps_client/services/safes_service.rb +48 -0
- data/lib/btps_client/services/secrets_safe_service.rb +25 -0
- data/lib/btps_client/services/secrets_service.rb +96 -0
- data/lib/btps_client/validator.rb +129 -0
- data/lib/btps_client/version.rb +5 -0
- data/lib/btps_client.rb +64 -0
- metadata +183 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BtpsClient
|
|
4
|
+
module Resources
|
|
5
|
+
# Swagger tag: Requests
|
|
6
|
+
# Endpoints:
|
|
7
|
+
# POST /requests — create release request
|
|
8
|
+
# GET /requests — list requests
|
|
9
|
+
# PUT /requests/{id}/checkin — check in a request
|
|
10
|
+
# PUT /requests/{id}/rotateoncheckin — set rotate-on-checkin
|
|
11
|
+
# PUT /requests/{id}/approve — approve a request
|
|
12
|
+
# PUT /requests/{id}/deny — deny a request
|
|
13
|
+
# POST /managedaccounts/{managedAccountID}/requests/terminate — terminate by account
|
|
14
|
+
# POST /managedsystems/{managedSystemID}/requests/terminate — terminate by system
|
|
15
|
+
class Request < ApiResource
|
|
16
|
+
resource_path 'requests'
|
|
17
|
+
|
|
18
|
+
extend ApiOperations::Listable # GET /requests
|
|
19
|
+
extend ApiOperations::ScalarCreatable # POST /requests — returns a plain integer (RequestID)
|
|
20
|
+
|
|
21
|
+
scalar_create_key 'RequestId'
|
|
22
|
+
|
|
23
|
+
# Create schema — maps to RequestAddModel
|
|
24
|
+
param_schema :create do
|
|
25
|
+
required 'SystemID', type: :integer
|
|
26
|
+
required 'AccountID', type: :integer
|
|
27
|
+
required 'DurationMinutes', type: :integer, minimum: 1, maximum: 525_600
|
|
28
|
+
optional 'Reason', type: :string, max_length: 1000, nullable: true
|
|
29
|
+
optional 'RotateOnCheckin', type: :boolean, nullable: true
|
|
30
|
+
optional 'AccessType', type: :string, values: %w[View RDP SSH App], nullable: true
|
|
31
|
+
optional 'ConflictOption', type: :string, values: %w[reuse renew], nullable: true
|
|
32
|
+
optional 'TicketNumber', type: :string, max_length: 20, nullable: true
|
|
33
|
+
optional 'TicketSystemID', type: :integer, nullable: true
|
|
34
|
+
optional 'AccessPolicyScheduleID', type: :integer, nullable: true
|
|
35
|
+
optional 'ApplicationID', type: :integer, nullable: true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Approve/Deny schemas — map to RequestReasonModel (all optional)
|
|
39
|
+
param_schema :approve do
|
|
40
|
+
optional 'Reason', type: :string, max_length: 1000, nullable: true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
param_schema :deny do
|
|
44
|
+
optional 'Reason', type: :string, max_length: 1000, nullable: true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# ── Request lifecycle methods ──────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
# PUT /requests/{id}/checkin
|
|
50
|
+
# Checks in a request, releasing the credential lock.
|
|
51
|
+
def self.checkin(id, params: {}, config: BtpsClient.config)
|
|
52
|
+
requestor = ApiRequestor.new(config)
|
|
53
|
+
# API requires a non-empty body — send params or an empty JSON object
|
|
54
|
+
body = params.empty? ? {} : params
|
|
55
|
+
data = requestor.request(:put, "#{resource_url(id)}/checkin", body: body)
|
|
56
|
+
data ? new(data) : true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# PUT /requests/{id}/rotateoncheckin
|
|
60
|
+
# Sets or clears the rotate-on-checkin flag for an active request.
|
|
61
|
+
def self.rotate_on_checkin(id, params: {}, config: BtpsClient.config)
|
|
62
|
+
requestor = ApiRequestor.new(config)
|
|
63
|
+
body = params.empty? ? nil : params
|
|
64
|
+
data = requestor.request(:put, "#{resource_url(id)}/rotateoncheckin", body: body)
|
|
65
|
+
data ? new(data) : true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# PUT /requests/{id}/approve
|
|
69
|
+
# Approves a pending request, with an optional reason.
|
|
70
|
+
def self.approve(id, params = {}, config: BtpsClient.config)
|
|
71
|
+
Validator.validate!(schema_for(:approve), params)
|
|
72
|
+
requestor = ApiRequestor.new(config)
|
|
73
|
+
body = params.empty? ? nil : params
|
|
74
|
+
data = requestor.request(:put, "#{resource_url(id)}/approve", body: body)
|
|
75
|
+
data ? new(data) : true
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# PUT /requests/{id}/deny
|
|
79
|
+
# Denies a pending request, with an optional reason.
|
|
80
|
+
def self.deny(id, params = {}, config: BtpsClient.config)
|
|
81
|
+
Validator.validate!(schema_for(:deny), params)
|
|
82
|
+
requestor = ApiRequestor.new(config)
|
|
83
|
+
body = params.empty? ? nil : params
|
|
84
|
+
data = requestor.request(:put, "#{resource_url(id)}/deny", body: body)
|
|
85
|
+
data ? new(data) : true
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# ── Terminate helpers ────────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
# POST /managedaccounts/{managedAccountID}/requests/terminate
|
|
91
|
+
# Terminates all active requests for a given managed account.
|
|
92
|
+
def self.terminate_by_account(managed_account_id, config: BtpsClient.config)
|
|
93
|
+
requestor = ApiRequestor.new(config)
|
|
94
|
+
requestor.request(:post, "managedaccounts/#{managed_account_id}/requests/terminate")
|
|
95
|
+
true
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# POST /managedsystems/{managedSystemID}/requests/terminate
|
|
99
|
+
# Terminates all active requests for a given managed system.
|
|
100
|
+
def self.terminate_by_system(managed_system_id, config: BtpsClient.config)
|
|
101
|
+
requestor = ApiRequestor.new(config)
|
|
102
|
+
requestor.request(:post, "managedsystems/#{managed_system_id}/requests/terminate")
|
|
103
|
+
true
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BtpsClient
|
|
4
|
+
module Resources
|
|
5
|
+
# Swagger tag: Secrets Safe Safes
|
|
6
|
+
# Endpoints: POST/GET /secrets-safe/safes
|
|
7
|
+
# GET/PUT/DELETE /secrets-safe/safes/{id}
|
|
8
|
+
# GET /secrets-safe/safes/safe-permissions
|
|
9
|
+
# GET/PUT/DELETE /secrets-safe/safes/{id}/safe-permissions
|
|
10
|
+
class Safe < ApiResource
|
|
11
|
+
resource_path 'secrets-safe/safes'
|
|
12
|
+
|
|
13
|
+
extend ApiOperations::Listable # GET /secrets-safe/safes
|
|
14
|
+
extend ApiOperations::Retrievable # GET /secrets-safe/safes/{id}
|
|
15
|
+
extend ApiOperations::Creatable # POST /secrets-safe/safes
|
|
16
|
+
extend ApiOperations::Updatable # PUT /secrets-safe/safes/{id}
|
|
17
|
+
extend ApiOperations::Deletable # DELETE /secrets-safe/safes/{id}
|
|
18
|
+
|
|
19
|
+
param_schema :create do
|
|
20
|
+
required 'Name', type: :string, min_length: 1, max_length: 256
|
|
21
|
+
optional 'Description', type: :string, max_length: 256, nullable: true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
param_schema :update do
|
|
25
|
+
required 'Name', type: :string, min_length: 1, max_length: 256
|
|
26
|
+
optional 'Description', type: :string, max_length: 256, nullable: true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
param_schema :assign_permission do
|
|
30
|
+
required 'PrincipalID', type: :integer
|
|
31
|
+
required 'PrincipalType', type: :integer
|
|
32
|
+
optional 'ExpiresOn', type: :string, nullable: true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
param_schema :revoke_permission do
|
|
36
|
+
required 'PrincipalID', type: :integer
|
|
37
|
+
required 'PrincipalType', type: :integer
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# GET /secrets-safe/safes/safe-permissions
|
|
41
|
+
# Returns all possible safe permission definitions.
|
|
42
|
+
# The API returns a plain array of strings, not objects, so items are
|
|
43
|
+
# returned as-is rather than wrapped in BtpsObject.
|
|
44
|
+
def self.all_permissions(config: BtpsClient.config)
|
|
45
|
+
requestor = ApiRequestor.new(config)
|
|
46
|
+
data = requestor.request(:get, 'secrets-safe/safes/safe-permissions')
|
|
47
|
+
Array(data).map { |item| item.is_a?(Hash) ? BtpsObject.new(item) : item }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# GET /secrets-safe/safes/{id}/safe-permissions
|
|
51
|
+
# Returns permissions currently assigned to the given safe.
|
|
52
|
+
def self.permissions(id, config: BtpsClient.config)
|
|
53
|
+
requestor = ApiRequestor.new(config)
|
|
54
|
+
data = requestor.request(:get, "#{resource_url(id)}/safe-permissions")
|
|
55
|
+
Array(data).map { |item| BtpsObject.new(item) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# PUT /secrets-safe/safes/{id}/safe-permissions
|
|
59
|
+
# Assigns or updates permissions for a user or group on the safe.
|
|
60
|
+
def self.update_permissions(id, params, config: BtpsClient.config)
|
|
61
|
+
Validator.validate!(schema_for(:assign_permission), params)
|
|
62
|
+
requestor = ApiRequestor.new(config)
|
|
63
|
+
requestor.request(:put, "#{resource_url(id)}/safe-permissions", body: params)
|
|
64
|
+
true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# DELETE /secrets-safe/safes/{id}/safe-permissions
|
|
68
|
+
# Revokes permissions for a user or group on the safe.
|
|
69
|
+
def self.revoke_permissions(id, params, config: BtpsClient.config)
|
|
70
|
+
Validator.validate!(schema_for(:revoke_permission), params)
|
|
71
|
+
requestor = ApiRequestor.new(config)
|
|
72
|
+
requestor.request(:delete, "#{resource_url(id)}/safe-permissions", body: params)
|
|
73
|
+
true
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BtpsClient
|
|
4
|
+
module Resources
|
|
5
|
+
# Swagger tag: Secrets Safe Secrets (19 endpoints)
|
|
6
|
+
# Standard operations via mixins + typed create/retrieve/update/share methods.
|
|
7
|
+
class Secret < ApiResource
|
|
8
|
+
resource_path 'secrets-safe/secrets'
|
|
9
|
+
|
|
10
|
+
extend ApiOperations::Listable # GET /secrets-safe/secrets
|
|
11
|
+
extend ApiOperations::Retrievable # GET /secrets-safe/secrets/{secretId}
|
|
12
|
+
extend ApiOperations::Updatable # PUT /secrets-safe/secrets/{secretId} (credential)
|
|
13
|
+
extend ApiOperations::Deletable # DELETE /secrets-safe/secrets/{secretId}
|
|
14
|
+
extend ApiOperations::Uploadable # multipart helper used by create_file_in_folder + upload_csv
|
|
15
|
+
|
|
16
|
+
param_schema :create_credential do
|
|
17
|
+
required 'Title', type: :string, max_length: 256
|
|
18
|
+
required 'Username', type: :string, max_length: 256
|
|
19
|
+
optional 'Password', type: :string, max_length: 256, nullable: true
|
|
20
|
+
optional 'PasswordRuleID', type: :integer, minimum: 0, maximum: 32_767, nullable: true
|
|
21
|
+
optional 'Description', type: :string, max_length: 256, nullable: true
|
|
22
|
+
optional 'Notes', type: :string, max_length: 4_000, nullable: true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
param_schema :create_text do
|
|
26
|
+
required 'Title', type: :string, max_length: 256
|
|
27
|
+
required 'Text', type: :string, max_length: 4_096
|
|
28
|
+
optional 'Description', type: :string, max_length: 256, nullable: true
|
|
29
|
+
optional 'Notes', type: :string, max_length: 4_000, nullable: true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
param_schema :update_text do
|
|
33
|
+
required 'Title', type: :string, max_length: 256
|
|
34
|
+
required 'Text', type: :string, max_length: 4_096
|
|
35
|
+
optional 'Description', type: :string, max_length: 256, nullable: true
|
|
36
|
+
optional 'Notes', type: :string, max_length: 4_000, nullable: true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
param_schema :move do
|
|
40
|
+
required 'SecretIds', type: :array
|
|
41
|
+
required 'ShareIds', type: :array
|
|
42
|
+
required 'DestinationFolderId', type: :string, format: :uuid
|
|
43
|
+
required 'DuplicateNameAction', type: :string, values: %w[Rename Replace Abort]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# ── Folder-scoped create methods ─────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
# POST /secrets-safe/folders/{folderId}/secrets
|
|
49
|
+
# Creates a credential secret inside the given folder.
|
|
50
|
+
def self.create_in_folder(folder_id, params, config: BtpsClient.config)
|
|
51
|
+
Validator.validate!(schema_for(:create_credential), params)
|
|
52
|
+
requestor = ApiRequestor.new(config)
|
|
53
|
+
data = requestor.request(:post, "secrets-safe/folders/#{folder_id}/secrets", body: params)
|
|
54
|
+
new(data)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# POST /secrets-safe/folders/{folderId}/secrets/text
|
|
58
|
+
# Creates a text secret inside the given folder.
|
|
59
|
+
def self.create_text_in_folder(folder_id, params, config: BtpsClient.config)
|
|
60
|
+
Validator.validate!(schema_for(:create_text), params)
|
|
61
|
+
requestor = ApiRequestor.new(config)
|
|
62
|
+
data = requestor.request(:post, "secrets-safe/folders/#{folder_id}/secrets/text", body: params)
|
|
63
|
+
new(data)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# POST /secrets-safe/folders/{folderId}/secrets/file (multipart/form-data)
|
|
67
|
+
# Creates a file secret inside the given folder.
|
|
68
|
+
def self.create_file_in_folder(folder_id, file:, metadata: {}, config: BtpsClient.config)
|
|
69
|
+
upload(folder_id, file: file, metadata: metadata,
|
|
70
|
+
base_path: 'secrets-safe/folders', sub_path: 'secrets/file', config: config)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# ── Folder-scoped list ────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
# GET /secrets-safe/folders/{folderId}/secrets
|
|
76
|
+
# Returns all secrets in the given folder.
|
|
77
|
+
def self.list_in_folder(folder_id, params = {}, config: BtpsClient.config)
|
|
78
|
+
requestor = ApiRequestor.new(config)
|
|
79
|
+
data = requestor.request(:get, "secrets-safe/folders/#{folder_id}/secrets", params: params)
|
|
80
|
+
Array(data).map { |item| new(item) }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# ── Typed retrieve methods ────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
# GET /secrets-safe/secrets/{secretId}/text
|
|
86
|
+
# Returns text-secret content as a BtpsObject.
|
|
87
|
+
def self.retrieve_text(id, config: BtpsClient.config)
|
|
88
|
+
requestor = ApiRequestor.new(config)
|
|
89
|
+
data = requestor.request(:get, "#{resource_url(id)}/text")
|
|
90
|
+
BtpsObject.new(data || {})
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# GET /secrets-safe/secrets/{secretId}/file
|
|
94
|
+
# Returns file-secret metadata as a BtpsObject (JSON, not binary).
|
|
95
|
+
def self.retrieve_file(id, config: BtpsClient.config)
|
|
96
|
+
requestor = ApiRequestor.new(config)
|
|
97
|
+
data = requestor.request(:get, "#{resource_url(id)}/file")
|
|
98
|
+
BtpsObject.new(data || {})
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# GET /secrets-safe/secrets/{secretId}/file/download
|
|
102
|
+
# Returns the raw binary content of the file secret.
|
|
103
|
+
def self.download_file(id, config: BtpsClient.config)
|
|
104
|
+
requestor = ApiRequestor.new(config)
|
|
105
|
+
requestor.request(:get, "#{resource_url(id)}/file/download")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# ── Typed update methods ──────────────────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
# PUT /secrets-safe/secrets/{secretId}/text
|
|
111
|
+
def self.update_text(id, params, config: BtpsClient.config)
|
|
112
|
+
Validator.validate!(schema_for(:update_text), params)
|
|
113
|
+
requestor = ApiRequestor.new(config)
|
|
114
|
+
data = requestor.request(:put, "#{resource_url(id)}/text", body: params)
|
|
115
|
+
data ? new(data) : true
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# PUT /secrets-safe/secrets/{secretId}/file (multipart/form-data)
|
|
119
|
+
def self.update_file(id, file:, metadata: {}, config: BtpsClient.config)
|
|
120
|
+
requestor = ApiRequestor.new(config)
|
|
121
|
+
body = { file: file }
|
|
122
|
+
body['secretmetadata'] = metadata.is_a?(String) ? metadata : metadata.to_json unless metadata.empty?
|
|
123
|
+
data = requestor.request(:put, "#{resource_url(id)}/file", body: body, opts: { multipart: true })
|
|
124
|
+
data ? new(data) : true
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# ── Bulk move ─────────────────────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
# PUT /secrets-safe/secrets/move
|
|
130
|
+
# Moves one or more secrets/shares to the destination folder.
|
|
131
|
+
# params: { SecretIds: [...], ShareIds: [...], DestinationFolderId: '...', DuplicateNameAction: '...' }
|
|
132
|
+
def self.move(params, config: BtpsClient.config)
|
|
133
|
+
Validator.validate!(schema_for(:move), params)
|
|
134
|
+
requestor = ApiRequestor.new(config)
|
|
135
|
+
data = requestor.request(:put, 'secrets-safe/secrets/move', body: params)
|
|
136
|
+
data ? BtpsObject.new(data) : true
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# ── CSV bulk upload ───────────────────────────────────────────────────────
|
|
140
|
+
|
|
141
|
+
# POST /secrets-safe/folders/{folderId}/upload
|
|
142
|
+
# Imports a CSV file of secrets into the given folder.
|
|
143
|
+
def self.upload_csv(folder_id, file:, config: BtpsClient.config)
|
|
144
|
+
upload(folder_id, file: file,
|
|
145
|
+
base_path: 'secrets-safe/folders', sub_path: 'upload', config: config)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# ── Shares sub-resource ───────────────────────────────────────────────────
|
|
149
|
+
|
|
150
|
+
# GET /secrets-safe/secrets/{secretId}/shares
|
|
151
|
+
def self.shares(secret_id, config: BtpsClient.config)
|
|
152
|
+
requestor = ApiRequestor.new(config)
|
|
153
|
+
data = requestor.request(:get, "#{resource_url(secret_id)}/shares")
|
|
154
|
+
Array(data).map { |item| BtpsObject.new(item) }
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# POST /secrets-safe/secrets/{secretId}/shares/{folderId}
|
|
158
|
+
def self.share_to_folder(secret_id, folder_id, config: BtpsClient.config)
|
|
159
|
+
requestor = ApiRequestor.new(config)
|
|
160
|
+
requestor.request(:post, "#{resource_url(secret_id)}/shares/#{folder_id}")
|
|
161
|
+
true
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# DELETE /secrets-safe/secrets/{secretId}/shares/{folderId}
|
|
165
|
+
def self.unshare_from_folder(secret_id, folder_id, config: BtpsClient.config)
|
|
166
|
+
requestor = ApiRequestor.new(config)
|
|
167
|
+
requestor.request(:delete, "#{resource_url(secret_id)}/shares/#{folder_id}")
|
|
168
|
+
true
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# DELETE /secrets-safe/secrets/{secretId}/shares
|
|
172
|
+
def self.unshare_all(secret_id, config: BtpsClient.config)
|
|
173
|
+
requestor = ApiRequestor.new(config)
|
|
174
|
+
requestor.request(:delete, "#{resource_url(secret_id)}/shares")
|
|
175
|
+
true
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BtpsClient
|
|
4
|
+
# DSL for declaring parameter schemas inline on resource classes.
|
|
5
|
+
#
|
|
6
|
+
# Used inside param_schema blocks on ApiResource subclasses:
|
|
7
|
+
#
|
|
8
|
+
# param_schema :create do
|
|
9
|
+
# required 'Name', type: :string, min_length: 1, max_length: 256
|
|
10
|
+
# optional 'Description', type: :string, max_length: 256
|
|
11
|
+
# optional 'ParentId', type: :string, format: :uuid
|
|
12
|
+
# optional 'Notes', type: :string, max_length: 4_000, nullable: true
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# Produces a plain Hash passed directly to Validator.validate!.
|
|
16
|
+
#
|
|
17
|
+
# Supported rules:
|
|
18
|
+
# type — :string, :integer, :array, :boolean
|
|
19
|
+
# min_length — minimum string length (inclusive)
|
|
20
|
+
# max_length — maximum string length (inclusive)
|
|
21
|
+
# minimum — minimum integer value (inclusive)
|
|
22
|
+
# maximum — maximum integer value (inclusive)
|
|
23
|
+
# format — :uuid
|
|
24
|
+
# values — Array of allowed string values (enum)
|
|
25
|
+
# nullable — when true, an explicit nil value is accepted and all
|
|
26
|
+
# other rules (type, length, etc.) are skipped for that field
|
|
27
|
+
class SchemaBuilder
|
|
28
|
+
def initialize
|
|
29
|
+
@required = []
|
|
30
|
+
@fields = {}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Declares a required field with optional constraint rules.
|
|
34
|
+
def required(name, **rules)
|
|
35
|
+
n = name.to_s
|
|
36
|
+
@required << n
|
|
37
|
+
@fields[n] = rules
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Declares an optional field with optional constraint rules.
|
|
41
|
+
def optional(name, **rules)
|
|
42
|
+
@fields[name.to_s] = rules
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Returns the frozen schema hash consumed by Validator.validate!
|
|
46
|
+
def to_h
|
|
47
|
+
{ required: @required.freeze, fields: @fields.freeze }.freeze
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
5
|
+
module BtpsClient
|
|
6
|
+
module Services
|
|
7
|
+
# Standalone service for Auth endpoints — does not extend ApiResource.
|
|
8
|
+
# Swagger tag: Auth + Password Safe OAuth Proxy
|
|
9
|
+
#
|
|
10
|
+
# client.auth.sign_in → POST /auth/signappin
|
|
11
|
+
# client.auth.sign_out → POST /auth/signout
|
|
12
|
+
# client.auth.acquire_token → POST /auth/connect/token (form-encoded)
|
|
13
|
+
class AuthService
|
|
14
|
+
def initialize(config)
|
|
15
|
+
@config = config
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# POST /api/public/v3/auth/signappin
|
|
19
|
+
# Authenticates credentials and creates a session.
|
|
20
|
+
# Returns a BtpsObject wrapping the AuthUserModel response.
|
|
21
|
+
def sign_in(params = {})
|
|
22
|
+
requestor = ApiRequestor.new(@config)
|
|
23
|
+
data = requestor.request(:post, 'auth/signappin', body: params)
|
|
24
|
+
BtpsObject.new(data || {})
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# POST /api/public/v3/auth/signout
|
|
28
|
+
# Terminates the current session.
|
|
29
|
+
# Returns true on success.
|
|
30
|
+
def sign_out
|
|
31
|
+
requestor = ApiRequestor.new(@config)
|
|
32
|
+
requestor.request(:post, 'auth/signout')
|
|
33
|
+
true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# POST /api/public/v3/auth/connect/token
|
|
37
|
+
# OAuth2 Client Credentials flow — returns AccessTokenResponse as BtpsObject.
|
|
38
|
+
# Merges client_id/client_secret from config unless overridden in params.
|
|
39
|
+
# Params keys are normalised to symbols so both string and symbol overrides work.
|
|
40
|
+
def acquire_token(params = {})
|
|
41
|
+
requestor = ApiRequestor.new(@config)
|
|
42
|
+
|
|
43
|
+
normalised = params.transform_keys(&:to_sym)
|
|
44
|
+
token_params = {
|
|
45
|
+
grant_type: 'client_credentials',
|
|
46
|
+
client_id: @config.client_id,
|
|
47
|
+
client_secret: @config.client_secret
|
|
48
|
+
}.merge(normalised)
|
|
49
|
+
|
|
50
|
+
form_body = URI.encode_www_form(token_params)
|
|
51
|
+
data = requestor.request(:post, 'auth/connect/token',
|
|
52
|
+
body: form_body, opts: { form_encoded: true })
|
|
53
|
+
BtpsObject.new(data || {})
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BtpsClient
|
|
4
|
+
module Services
|
|
5
|
+
# Thin façade over Resources::Credential.
|
|
6
|
+
class CredentialsService
|
|
7
|
+
def initialize(config)
|
|
8
|
+
@config = config
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def retrieve_by_request(request_id)
|
|
12
|
+
Resources::Credential.retrieve_by_request(request_id, config: @config)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def update_global(params)
|
|
16
|
+
Resources::Credential.update_global(params, config: @config)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def retrieve_for_account(managed_account_id, params = {})
|
|
20
|
+
Resources::Credential.retrieve_for_account(managed_account_id, params, config: @config)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def update_for_account(managed_account_id, params)
|
|
24
|
+
Resources::Credential.update_for_account(managed_account_id, params, config: @config)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_for_account(managed_account_id)
|
|
28
|
+
Resources::Credential.test_for_account(managed_account_id, config: @config)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def change_for_account(managed_account_id, params = {})
|
|
32
|
+
Resources::Credential.change_for_account(managed_account_id, params, config: @config)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BtpsClient
|
|
4
|
+
module Services
|
|
5
|
+
# Thin façade over Resources::Folder.
|
|
6
|
+
# All credentials are bound to the config passed at construction time.
|
|
7
|
+
class FoldersService
|
|
8
|
+
def initialize(config)
|
|
9
|
+
@config = config
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def list(params = {})
|
|
13
|
+
Resources::Folder.list(params, config: @config)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def retrieve(id)
|
|
17
|
+
Resources::Folder.retrieve(id, config: @config)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create(params)
|
|
21
|
+
Resources::Folder.create(params, config: @config)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def update(id, params)
|
|
25
|
+
Resources::Folder.update(id, params, config: @config)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete(id)
|
|
29
|
+
Resources::Folder.delete(id, config: @config)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def move(id, params)
|
|
33
|
+
Resources::Folder.move(id, params, config: @config)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BtpsClient
|
|
4
|
+
module Services
|
|
5
|
+
# Thin façade over Resources::ManagedAccount.
|
|
6
|
+
class ManagedAccountsService
|
|
7
|
+
def initialize(config)
|
|
8
|
+
@config = config
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def list(params = {})
|
|
12
|
+
Resources::ManagedAccount.list(params, config: @config)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def retrieve(id)
|
|
16
|
+
Resources::ManagedAccount.retrieve(id, config: @config)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update(id, params)
|
|
20
|
+
Resources::ManagedAccount.update(id, params, config: @config)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def delete(id)
|
|
24
|
+
Resources::ManagedAccount.delete(id, config: @config)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def list_by_system(system_id, params = {})
|
|
28
|
+
Resources::ManagedAccount.list_by_system(system_id, params, config: @config)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def create_in_system(system_id, params)
|
|
32
|
+
Resources::ManagedAccount.create_in_system(system_id, params, config: @config)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def delete_all_in_system(system_id)
|
|
36
|
+
Resources::ManagedAccount.delete_all_in_system(system_id, config: @config)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def delete_by_system_and_name(system_id, account_name)
|
|
40
|
+
Resources::ManagedAccount.delete_by_system_and_name(system_id, account_name, config: @config)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def list_by_smart_rule(smart_rule_id, params = {})
|
|
44
|
+
Resources::ManagedAccount.list_by_smart_rule(smart_rule_id, params, config: @config)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BtpsClient
|
|
4
|
+
module Services
|
|
5
|
+
# Thin façade over Resources::Request.
|
|
6
|
+
class RequestsService
|
|
7
|
+
def initialize(config)
|
|
8
|
+
@config = config
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def list(params = {})
|
|
12
|
+
Resources::Request.list(params, config: @config)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def create(params)
|
|
16
|
+
Resources::Request.create(params, config: @config)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def checkin(id, params: {})
|
|
20
|
+
Resources::Request.checkin(id, params: params, config: @config)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def rotate_on_checkin(id, params: {})
|
|
24
|
+
Resources::Request.rotate_on_checkin(id, params: params, config: @config)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def approve(id, params = {})
|
|
28
|
+
Resources::Request.approve(id, params, config: @config)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def deny(id, params = {})
|
|
32
|
+
Resources::Request.deny(id, params, config: @config)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def terminate_by_account(managed_account_id)
|
|
36
|
+
Resources::Request.terminate_by_account(managed_account_id, config: @config)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def terminate_by_system(managed_system_id)
|
|
40
|
+
Resources::Request.terminate_by_system(managed_system_id, config: @config)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|