sophos_central_api 0.2.0 → 0.2.2
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 +4 -4
- data/CHANGELOG.md +14 -1
- data/Gemfile +1 -1
- data/README.md +42 -27
- data/lib/sophos/api.rb +30 -7
- data/lib/sophos/authentication.rb +60 -24
- data/lib/sophos/client/common.rb +25 -4
- data/lib/sophos/client/endpoint.rb +29 -3
- data/lib/sophos/client/helper.rb +68 -31
- data/lib/sophos/client/partner.rb +26 -9
- data/lib/sophos/client.rb +43 -18
- data/lib/sophos/configuration.rb +23 -15
- data/lib/sophos/error.rb +11 -5
- data/lib/sophos/pagination.rb +40 -26
- data/lib/sophos/version.rb +1 -1
- data/lib/sophos_central_api.rb +27 -2
- metadata +3 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d47cbadb0dff8019efbbac91b9690e5155653a24ae60eeb724fff45edaa90d87
|
4
|
+
data.tar.gz: a3a28af07f86c764b7fbfbcb03dcfaf47fce8ab23d30a8ddeea4d95407f8909f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ddc293f17bf92585c4cd21517ca405ab985a7d848d73195b9a4e59649be8950ff773faeba68cc21d895e4e3885600c9add869710cfcd6a68f65472152c34e09
|
7
|
+
data.tar.gz: 40c45c25bd5d6b4d8261b0fa39313f081e81ce350a2818732071a11b9f4347ceb7b3bb42adab53d39513dfca23563d55d01423d263f65cdfeab4b943c9fb6e20
|
data/CHANGELOG.md
CHANGED
@@ -1,13 +1,26 @@
|
|
1
|
-
|
1
|
+
# Changelog
|
2
2
|
|
3
3
|
## [0.1.0] - 2024-02-14
|
4
|
+
|
4
5
|
- Initial release
|
5
6
|
|
6
7
|
## [0.1.1] - 2024-02-14
|
8
|
+
|
7
9
|
- Convienience method added to get client for a teannt api host
|
8
10
|
|
9
11
|
## [0.1.2] - 2024-02-15
|
12
|
+
|
10
13
|
- Fix initialization issue
|
11
14
|
|
12
15
|
## [0.2.0] - 2024-02-20
|
16
|
+
|
13
17
|
- Configuration and authentication exceptions changed
|
18
|
+
|
19
|
+
## [0.2.1] - 2024-07-17
|
20
|
+
|
21
|
+
- Fix issue with paging for endpoints
|
22
|
+
|
23
|
+
## [0.2.2] - 2025-03-21
|
24
|
+
|
25
|
+
- Update docs, formatting
|
26
|
+
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# Sophos Central Partner API
|
2
|
+
|
2
3
|
[](https://rubygems.org/gems/sophos_central_api)
|
3
4
|
[](https://codeclimate.com/github/jancotanis/sophos/maintainability)
|
4
5
|
[](https://codeclimate.com/github/jancotanis/sophos/test_coverage)
|
5
6
|
|
6
|
-
This is a wrapper for the Sophos Central Partner API.
|
7
|
+
This is a wrapper for the Sophos Central Partner API.
|
8
|
+
You can see the [API endpoints](https://developer.sophos.com/getting-started)
|
7
9
|
|
8
|
-
Currently only the GET requests to customers, endpoints and
|
10
|
+
Currently only the GET requests to customers, endpoints and
|
11
|
+
alerts are implemented (readonly).
|
9
12
|
|
10
13
|
## Installation
|
11
14
|
|
@@ -17,17 +20,22 @@ gem 'sophos_central_api'
|
|
17
20
|
|
18
21
|
And then execute:
|
19
22
|
|
20
|
-
|
23
|
+
```console
|
24
|
+
> bundle install
|
25
|
+
```
|
21
26
|
|
22
27
|
Or install it yourself as:
|
23
28
|
|
24
|
-
|
29
|
+
```console
|
30
|
+
> gem install sophos_central_api
|
31
|
+
```
|
25
32
|
|
26
33
|
## Usage
|
27
34
|
|
28
|
-
Before you start making the requests to API provide the client id and client secret
|
35
|
+
Before you start making the requests to API provide the client id and client secret
|
36
|
+
and email/password using the configuration wrapping.
|
29
37
|
|
30
|
-
```
|
38
|
+
```ruby
|
31
39
|
require 'sophos_central_api'
|
32
40
|
|
33
41
|
Sophos.configure do |config|
|
@@ -45,20 +53,25 @@ end
|
|
45
53
|
```
|
46
54
|
|
47
55
|
## Resources
|
56
|
+
|
48
57
|
### Authentication
|
49
|
-
|
58
|
+
|
59
|
+
```ruby
|
50
60
|
# setup configuration
|
51
61
|
#
|
52
62
|
client.login
|
53
63
|
```
|
64
|
+
|
54
65
|
|Resource|API endpoint|Description|
|
55
66
|
|:--|:--|:--|
|
56
|
-
|.login
|
67
|
+
|.login|||
|
57
68
|
|
58
69
|
|
59
70
|
### Partner
|
60
|
-
|
61
|
-
|
71
|
+
|
72
|
+
Endpoint for partner related requests
|
73
|
+
|
74
|
+
```ruby
|
62
75
|
roles = client.roles
|
63
76
|
```
|
64
77
|
|
@@ -69,14 +82,14 @@ roles = client.roles
|
|
69
82
|
|.admins, .admin(id) |/partner/v1/admins/{id}|
|
70
83
|
|.admin_role_assignments(admin_id)|/partner/v1/admins/{admin_id}/role-assignments|
|
71
84
|
|.admin_role_assignment(admin_id,assignment_id)|/partner/v1/admins/{admin_id}/role-assignments/{assignment_id}|
|
72
|
-
|.permission_sets
|
73
|
-
|.billing_usage(year, month)
|
74
|
-
|
85
|
+
|.permission_sets |/partner/v1/roles/permission-sets|
|
86
|
+
|.billing_usage(year, month) |/partner/v1/billing-usage/{year}/{month}|
|
75
87
|
|
76
88
|
### Common
|
89
|
+
|
77
90
|
This is the OAS 3.0 specification for the Common API in Sophos Central.
|
78
91
|
|
79
|
-
```
|
92
|
+
```ruby
|
80
93
|
@client = Sophos.client()
|
81
94
|
@client.login
|
82
95
|
:
|
@@ -88,15 +101,17 @@ tenant = @client.tenant(id)
|
|
88
101
|
|
89
102
|
|Resource|API endpoint|
|
90
103
|
|:--|:--|
|
91
|
-
|.alerts, .alert(id)
|
104
|
+
|.alerts, .alert(id) |.../alerts/|
|
92
105
|
|.directory_user_groups, .directory_user_groups(id) |.../directory/user-groups|
|
93
|
-
|.directory_user_group_users(id)
|
94
|
-
|.directory_users, .directory_user(id)
|
95
|
-
|.directory_user_groups(id)
|
106
|
+
|.directory_user_group_users(id) |.../directory/user-groups/{id}/users|
|
107
|
+
|.directory_users, .directory_user(id) |.../directory/users|
|
108
|
+
|.directory_user_groups(id) |.../directory/users/{id}/groups|
|
96
109
|
|
97
110
|
### Endpoints
|
111
|
+
|
98
112
|
Returns endpoint for a provided tenant
|
99
|
-
|
113
|
+
|
114
|
+
```ruby
|
100
115
|
@client = Sophos.client()
|
101
116
|
@client.login
|
102
117
|
:
|
@@ -107,18 +122,18 @@ tenant = @client.tenant(id)
|
|
107
122
|
|
108
123
|
|Resource|API endpoint|
|
109
124
|
|:--|:--|
|
110
|
-
|.downloads
|
111
|
-
|.endpoint_groups, .endpoint_group(id)
|
112
|
-
|.migrations, .migration(id)
|
113
|
-
|.migration_endpoints(migration_id)
|
114
|
-
|.policies, .policy(id)
|
115
|
-
|.endpoints
|
116
|
-
|.endpoint_isolation(endpoint_id)
|
125
|
+
|.downloads |.../downloads/|
|
126
|
+
|.endpoint_groups, .endpoint_group(id) |.../endpoint-groupss/|
|
127
|
+
|.migrations, .migration(id) |.../migrations|
|
128
|
+
|.migration_endpoints(migration_id) |.../migrations/{migration_id}/endpoints|
|
129
|
+
|.policies, .policy(id) |.../policies/{id}|
|
130
|
+
|.endpoints |.../endpoints|
|
131
|
+
|.endpoint_isolation(endpoint_id) |.../endpoints/{id}/isolation|
|
117
132
|
|.endpoint_tamper_protection(endpoint_id)|.../endpoints/{id}/tamper-protection|
|
118
133
|
|
119
134
|
## Contributing
|
120
135
|
|
121
|
-
Bug reports and pull requests are welcome on GitHub
|
136
|
+
Bug reports and pull requests are welcome on [GitHub](https://github.com/jancotanis/sophos).
|
122
137
|
|
123
138
|
## License
|
124
139
|
|
data/lib/sophos/api.rb
CHANGED
@@ -1,30 +1,53 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'wrapi'
|
2
4
|
require File.expand_path('configuration', __dir__)
|
3
5
|
require File.expand_path('authentication', __dir__)
|
4
6
|
|
5
7
|
module Sophos
|
6
|
-
#
|
7
|
-
|
8
|
+
# Handles API configuration, connections, and authentication.
|
9
|
+
# This class manages settings such as API keys, tokens, and endpoint configurations,
|
10
|
+
# and includes necessary modules for making authenticated API calls.
|
8
11
|
class API
|
9
|
-
#
|
10
|
-
|
12
|
+
# Attribute accessors for configuration keys
|
13
|
+
# These keys include essential settings such as client ID, client secret, and API endpoint.
|
14
|
+
attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
|
11
15
|
|
12
|
-
#
|
16
|
+
# Initializes a new API instance and applies configuration settings.
|
17
|
+
#
|
18
|
+
# @param options [Hash] A hash of options to configure the API.
|
19
|
+
# These options are merged with global configuration settings.
|
20
|
+
#
|
21
|
+
# @example Initialize a new API instance with custom options:
|
22
|
+
# api = Sophos::API.new(client_id: 'your_client_id', client_secret: 'your_client_secret')
|
23
|
+
#
|
13
24
|
def initialize(options = {})
|
25
|
+
# Merge provided options with the global Sophos configuration
|
14
26
|
options = Sophos.options.merge(options)
|
27
|
+
|
28
|
+
# Set instance variables for each valid configuration key
|
15
29
|
Configuration::VALID_OPTIONS_KEYS.each do |key|
|
16
30
|
send("#{key}=", options[key])
|
17
31
|
end
|
18
32
|
end
|
19
33
|
|
34
|
+
# Returns the current API configuration as a hash.
|
35
|
+
#
|
36
|
+
# @return [Hash] A hash of the current API configuration.
|
37
|
+
#
|
38
|
+
# @example Retrieve the current API configuration:
|
39
|
+
# api = Sophos::API.new
|
40
|
+
# api.config # => { client_id: 'abc', client_secret: 'xyz' }
|
41
|
+
#
|
20
42
|
def config
|
21
43
|
conf = {}
|
22
44
|
Configuration::VALID_OPTIONS_KEYS.each do |key|
|
23
|
-
conf[key] = send
|
45
|
+
conf[key] = send(key)
|
24
46
|
end
|
25
47
|
conf
|
26
48
|
end
|
27
49
|
|
50
|
+
# Including modules for API connection, request handling, and authentication
|
28
51
|
include Configuration
|
29
52
|
include WrAPI::Connection
|
30
53
|
include WrAPI::Request
|
@@ -1,39 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday'
|
2
4
|
require 'json'
|
3
5
|
require 'uri'
|
4
6
|
require File.expand_path('error', __dir__)
|
5
7
|
|
6
8
|
module Sophos
|
7
|
-
#
|
9
|
+
# Handles authentication flow for accessing Sophos APIs and stores tokens in global configuration.
|
10
|
+
# This module manages OAuth2-based token generation and sets up the API connection with authorization headers.
|
11
|
+
#
|
12
|
+
# @note Ensure that `client_id` and `client_secret` are configured before calling authentication methods.
|
13
|
+
# @see https://developer.sophos.com/getting-started
|
8
14
|
module Authentication
|
9
15
|
|
10
|
-
#
|
11
|
-
#
|
12
|
-
|
16
|
+
# Authorizes with the Sophos portal and retrieves an access token.
|
17
|
+
# This method performs an OAuth2 client credentials flow, returning a valid token.
|
18
|
+
#
|
19
|
+
# @param _options [Hash] (optional) Any additional options for the request.
|
20
|
+
# @return [String] Access token for the Sophos API.
|
21
|
+
# @raise [ConfigurationError] If `client_id` or `client_secret` is not set.
|
22
|
+
# @raise [AuthenticationError] If authentication fails due to invalid credentials or other errors.
|
23
|
+
#
|
24
|
+
# @example Authenticate and retrieve a token:
|
25
|
+
# api.auth_token
|
26
|
+
#
|
27
|
+
def auth_token(_options = {})
|
13
28
|
raise ConfigurationError.new 'Client id and/or secret not configured' unless client_id && client_secret
|
14
|
-
|
15
|
-
|
29
|
+
|
30
|
+
# POST request to obtain the OAuth2 token using client credentials
|
31
|
+
response = connection.post("#{id_endpoint}/api/v2/oauth2/token") do |request|
|
16
32
|
request.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
17
|
-
request.body = URI.encode_www_form(
|
33
|
+
request.body = URI.encode_www_form(api_access_token_params)
|
18
34
|
end
|
35
|
+
|
19
36
|
api_process_token(response.body)
|
37
|
+
setup_connection
|
20
38
|
|
21
|
-
#
|
22
|
-
|
23
|
-
if 'partner'.eql?(partner.idType) && partner.id
|
24
|
-
self.partner_id = partner.id
|
25
|
-
self.endpoint = partner.apiHosts.global
|
26
|
-
self.connection_options = { headers: { 'X-partner-id': self.partner_id } }
|
27
|
-
else
|
28
|
-
raise AuthenticationError.new 'Partner id not returned; response ' + response.to_s
|
29
|
-
end
|
39
|
+
# Returns the generated access token
|
40
|
+
self.access_token
|
30
41
|
rescue Faraday::UnauthorizedError => e
|
31
|
-
|
42
|
+
raise AuthenticationError.new "Unauthorized; response #{e}"
|
32
43
|
end
|
33
44
|
alias login auth_token
|
34
45
|
|
35
|
-
|
46
|
+
private
|
36
47
|
|
48
|
+
# Builds the request body parameters for the token request.
|
49
|
+
#
|
50
|
+
# @return [Hash] Parameters required for the client credentials grant type.
|
37
51
|
def api_access_token_params
|
38
52
|
{
|
39
53
|
grant_type: 'client_credentials',
|
@@ -43,14 +57,36 @@ module Sophos
|
|
43
57
|
}
|
44
58
|
end
|
45
59
|
|
60
|
+
# Processes the token response and extracts authentication details.
|
61
|
+
#
|
62
|
+
# @param response [Hash] The HTTP response body containing the OAuth2 token data.
|
63
|
+
# @raise [AuthenticationError] If `access_token` is missing or invalid.
|
46
64
|
def api_process_token(response)
|
47
|
-
|
48
|
-
self.token_type
|
49
|
-
self.refresh_token
|
50
|
-
self.token_expires
|
51
|
-
raise AuthenticationError.new 'Could not find valid access_token; response ' + response.to_s if at.nil? || at.empty?
|
65
|
+
self.access_token = response['access_token']
|
66
|
+
self.token_type = response['token_type']
|
67
|
+
self.refresh_token = response['refresh_token']
|
68
|
+
self.token_expires = response['expires_in']
|
52
69
|
|
53
|
-
|
70
|
+
if self.access_token.nil? || self.access_token.empty?
|
71
|
+
raise AuthenticationError.new "Could not find valid access_token; response #{response}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Sets up the API connection using the authenticated token and partner-specific settings.
|
76
|
+
#
|
77
|
+
# This method retrieves the partner ID, sets the global endpoint, and configures headers.
|
78
|
+
#
|
79
|
+
# @raise [AuthenticationError] If the partner ID is not returned in the `whoami` response.
|
80
|
+
def setup_connection
|
81
|
+
partner = self.get("/whoami/v1")
|
82
|
+
|
83
|
+
if 'partner'.eql?(partner.idType) && partner.id
|
84
|
+
self.partner_id = partner.id
|
85
|
+
self.endpoint = partner.apiHosts.global
|
86
|
+
self.connection_options = { headers: { 'X-partner-id': self.partner_id } }
|
87
|
+
else
|
88
|
+
raise AuthenticationError.new "Partner id not returned; response #{partner}"
|
89
|
+
end
|
54
90
|
end
|
55
91
|
end
|
56
92
|
end
|
data/lib/sophos/client/common.rb
CHANGED
@@ -1,25 +1,46 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Sophos
|
3
4
|
class Client
|
4
5
|
require File.expand_path('helper', __dir__)
|
5
6
|
include Sophos::Client::Helper
|
6
7
|
|
7
|
-
#
|
8
|
+
# Common API module for handling various endpoints in Sophos Central.
|
9
|
+
# This module provides access to alerts, directory users, and user groups.
|
8
10
|
# @see https://developer.sophos.com/docs/common-v1/1/overview
|
9
11
|
module Common
|
10
|
-
|
12
|
+
# Define API calls using helper methods for common endpoints.
|
13
|
+
# These methods automatically create GET calls to the specified URL.
|
14
|
+
#
|
11
15
|
# @see https://developer.sophos.com/docs/common-v1/1/routes/alerts/get
|
12
16
|
Helper::def_api_call :alerts, Helper::common_url(:alerts)
|
17
|
+
|
13
18
|
# @see https://developer.sophos.com/docs/common-v1/1/routes/directory/user-groups/get
|
14
19
|
Helper::def_api_call :directory_user_groups, Helper::common_url('directory/user-groups')
|
20
|
+
|
21
|
+
# Fetch paginated users in a specified user group.
|
22
|
+
# @param group_id [String] The ID of the user group.
|
23
|
+
# @param params [Hash] Additional query parameters (e.g., `pageSize`, `page`).
|
24
|
+
# @return [Hash] API response containing users in the specified group.
|
25
|
+
# @see https://developer.sophos.com/docs/common-v1/1/routes/directory/user-groups/get
|
15
26
|
def directory_user_group_users(group_id, params = {})
|
16
27
|
get_paged(Helper::common_url("directory/user-groups/#{group_id}/users"), params)
|
17
28
|
end
|
29
|
+
|
30
|
+
# Define an API call to fetch all directory users.
|
31
|
+
# @see https://developer.sophos.com/docs/common-v1/1/routes/directory/users/get
|
18
32
|
Helper::def_api_call :directory_users, Helper::common_url('directory/users')
|
33
|
+
|
34
|
+
# Fetch paginated user groups for a specified user.
|
35
|
+
# @param user_id [String] The ID of the user.
|
36
|
+
# @param params [Hash] Additional query parameters (e.g., `pageSize`, `page`).
|
37
|
+
# @return [Hash] API response containing groups the user belongs to.
|
38
|
+
# @see https://developer.sophos.com/docs/common-v1/1/routes/directory/users/get
|
19
39
|
def directory_user_groups(user_id, params = {})
|
20
40
|
get_paged(Helper::common_url("directory/users/#{user_id}/groups"), params)
|
21
41
|
end
|
22
|
-
|
42
|
+
|
43
|
+
# Additional methods for roles and admins can be retrieved using the partner API.
|
23
44
|
end
|
24
45
|
end
|
25
46
|
end
|
@@ -1,40 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sophos
|
2
4
|
class Client
|
3
5
|
require File.expand_path('helper', __dir__)
|
4
6
|
include Sophos::Client::Helper
|
5
7
|
|
6
|
-
# Sophos Endpoint
|
8
|
+
# Module to interact with Sophos Endpoint API
|
7
9
|
# @see https://developer.sophos.com/docs/endpoint-v1/1/overview
|
8
10
|
module Endpoint
|
9
11
|
|
12
|
+
# Define API calls with dynamic helper methods for common endpoints.
|
13
|
+
|
14
|
+
# Fetch available software downloads.
|
10
15
|
# @see https://developer.sophos.com/docs/endpoint-v1/1/routes/downloads/get
|
11
16
|
Helper::def_api_call :downloads, Helper::endpoint_url(:downloads)
|
12
17
|
|
18
|
+
# Fetch all endpoint groups.
|
13
19
|
# @see https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoint-groups/get
|
14
20
|
Helper::def_api_call :endpoint_groups, Helper::endpoint_url(:endpoint_groups), :endpoint_group
|
21
|
+
|
22
|
+
# Fetch endpoints belonging to a specific endpoint group.
|
23
|
+
# @param group_id [String] The ID of the endpoint group.
|
24
|
+
# @return [Array<Hash>] Paginated response with endpoint details.
|
15
25
|
def endpoint_group_endpoints(group_id)
|
16
26
|
get_paged Helper::endpoint_url("endpoint-groups/#{group_id}/endpoints")
|
17
27
|
end
|
18
28
|
|
29
|
+
# Fetch details on endpoint migrations.
|
19
30
|
# @see https://developer.sophos.com/docs/endpoint-v1/1/routes/migrations/get
|
20
31
|
Helper::def_api_call :migrations, Helper::endpoint_url(:migrations), :migration
|
32
|
+
|
33
|
+
# Fetch endpoints involved in a specific migration.
|
34
|
+
# @param migration_id [String] The ID of the migration.
|
35
|
+
# @return [Array<Hash>] Paginated response with endpoints involved in the migration.
|
21
36
|
def migration_endpoints(migration_id)
|
22
37
|
get_paged Helper::endpoint_url("migrations/#{migration_id}/endpoints")
|
23
38
|
end
|
24
39
|
|
40
|
+
# Fetch policy details for the tenant.
|
25
41
|
# @see https://developer.sophos.com/docs/endpoint-v1/1/routes/policies/get
|
26
42
|
Helper::def_api_call :policies, Helper::endpoint_url(:policies), :policy
|
27
43
|
|
28
|
-
#
|
44
|
+
# Fetch all endpoints for the specified tenant.
|
45
|
+
# @note No specific `endpoint` method due to potential name conflicts with the base API method.
|
29
46
|
# @see https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoints/get
|
30
47
|
Helper::def_api_call :endpoints, Helper::endpoint_url(:endpoints)
|
48
|
+
|
49
|
+
# Fetch the isolation status for a specific endpoint.
|
50
|
+
# @param endpoint_id [String] The ID of the endpoint.
|
51
|
+
# @return [Hash] Response with the isolation status of the endpoint.
|
52
|
+
# @see https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoints/get
|
31
53
|
def endpoint_isolation(endpoint_id)
|
32
54
|
get Helper::endpoint_url("endpoints/#{endpoint_id}/isolation")
|
33
55
|
end
|
56
|
+
|
57
|
+
# Fetch tamper protection settings for a specific endpoint.
|
58
|
+
# @param endpoint_id [String] The ID of the endpoint.
|
59
|
+
# @return [Hash] Response containing tamper protection details.
|
60
|
+
# @see https://developer.sophos.com/docs/endpoint-v1/1/routes/endpoints/get
|
34
61
|
def endpoint_tamper_protection(endpoint_id)
|
35
62
|
get Helper::endpoint_url("endpoints/#{endpoint_id}/tamper-protection")
|
36
63
|
end
|
37
|
-
|
38
64
|
end
|
39
65
|
end
|
40
66
|
end
|
data/lib/sophos/client/helper.rb
CHANGED
@@ -1,49 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sophos
|
2
|
-
|
3
|
-
# Generate generic api methods
|
4
|
+
# Generate generic API methods dynamically for various Sophos APIs.
|
4
5
|
class Client
|
5
6
|
module Helper
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
# Convert method names to URL-safe format (e.g., 'user_groups' => 'user-groups')
|
9
|
+
# @param method_name [Symbol, String] Method name to be sanitized
|
10
|
+
# @return [String] Sanitized method name for use in URL paths
|
11
|
+
def self.sanitize(method_name)
|
12
|
+
method_name.to_s.tr('_', '-')
|
13
|
+
end
|
14
|
+
|
15
|
+
# Generate a URL path for the common API
|
16
|
+
# @param method [Symbol, String] Method name for the API endpoint
|
17
|
+
# @return [String] Full path for the common API endpoint
|
18
|
+
def self.common_url(method)
|
19
|
+
url('common', method)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Generate a URL path for the endpoint API
|
23
|
+
def self.endpoint_url(method)
|
24
|
+
url('endpoint', method)
|
9
25
|
end
|
10
26
|
|
11
|
-
|
12
|
-
def self.
|
13
|
-
|
14
|
-
|
15
|
-
|
27
|
+
# Generate a URL path for the partner API
|
28
|
+
def self.partner_url(method)
|
29
|
+
url('partner', method)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Generic method to generate API URLs
|
33
|
+
# @param api [String] API type (e.g., 'common', 'endpoint', 'partner')
|
34
|
+
# @param method [Symbol, String] Endpoint method name
|
35
|
+
# @return [String] Full API URL path
|
36
|
+
def self.url(api, method)
|
16
37
|
"/#{api}/v1/#{sanitize(method)}"
|
17
38
|
end
|
18
39
|
|
19
|
-
#
|
40
|
+
# Dynamically define API methods for both singular and plural endpoints.
|
41
|
+
# It supports paginated or non-paginated responses.
|
42
|
+
#
|
43
|
+
# @param method [Symbol] Plural method name (e.g., `:alerts`)
|
44
|
+
# @param url [String] Endpoint URL path
|
45
|
+
# @param singular_method [Symbol, nil] Singular method name (e.g., `:alert`), optional
|
46
|
+
# @param paged [Boolean] If true, generate paginated API calls (default: true)
|
20
47
|
def self.def_api_call(method, url, singular_method = nil, paged = true)
|
21
48
|
if singular_method
|
22
|
-
|
23
|
-
if id
|
24
|
-
get("#{url}/#{id}", params)
|
25
|
-
else
|
26
|
-
get_paged(url, params)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
# strip trailing 's'
|
30
|
-
self.send(:define_method, singular_method) do |id, params = {}|
|
31
|
-
get("#{url}/#{id}", params)
|
32
|
-
end
|
49
|
+
define_singular_and_plural_methods(method, url, singular_method)
|
33
50
|
else
|
34
|
-
|
35
|
-
self.send(:define_method, method) do |params = {}|
|
36
|
-
get_paged(url, params)
|
37
|
-
end
|
38
|
-
else
|
39
|
-
self.send(:define_method, method) do |params = {}|
|
40
|
-
get(url, params)
|
41
|
-
end
|
42
|
-
end
|
51
|
+
paged ? define_paged_method(method, url) : define_plain_method(method, url)
|
43
52
|
end
|
44
53
|
end
|
45
54
|
|
55
|
+
private
|
56
|
+
|
57
|
+
# Define both singular and plural methods.
|
58
|
+
# Example: `alerts` (for paginated results) and `alert(id)` (for single alert).
|
59
|
+
def self.define_singular_and_plural_methods(method, url, singular_method)
|
60
|
+
# Define plural method: paginated call if no ID, otherwise fetch singular resource.
|
61
|
+
define_method(method) do |id = nil, params = {}|
|
62
|
+
id ? get("#{url}/#{id}", params) : get_paged(url, params)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Define singular method explicitly for single resource retrieval.
|
66
|
+
define_method(singular_method) do |id, params = {}|
|
67
|
+
get("#{url}/#{id}", params)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Define a paginated method for list-based API endpoints.
|
72
|
+
def self.define_paged_method(method, url)
|
73
|
+
define_method(method) do |params = {}|
|
74
|
+
get_paged(url, params)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Define a simple, non-paginated API method.
|
79
|
+
def self.define_plain_method(method, url)
|
80
|
+
define_method(method) do |params = {}|
|
81
|
+
get(url, params)
|
82
|
+
end
|
83
|
+
end
|
46
84
|
end
|
47
85
|
end
|
48
|
-
|
49
86
|
end
|
@@ -1,44 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sophos
|
2
4
|
class Client
|
3
5
|
require File.expand_path('helper', __dir__)
|
4
6
|
include Sophos::Client::Helper
|
5
7
|
|
6
|
-
# Sophos
|
8
|
+
# Sophos Partner API module, providing access to tenants, roles, admins, and billing usage data.
|
7
9
|
# @see https://developer.sophos.com/docs/partner-v1/1/overview
|
8
10
|
module Partner
|
9
|
-
|
11
|
+
# Retrieve a list of tenants or a single tenant by ID.
|
10
12
|
# @see https://developer.sophos.com/docs/partner-v1/1/routes/tenants/get
|
11
13
|
Helper::def_api_call :tenants, Helper::partner_url(:tenants), :tenant
|
12
14
|
|
15
|
+
# Retrieve a list of roles or a single role by ID.
|
13
16
|
# @see https://developer.sophos.com/docs/partner-v1/1/routes/roles/get
|
14
17
|
Helper::def_api_call :roles, Helper::partner_url(:roles), :role
|
15
18
|
|
19
|
+
# Retrieve a list of admins or a single admin by ID.
|
16
20
|
# @see https://developer.sophos.com/docs/partner-v1/1/routes/admins/get
|
17
21
|
Helper::def_api_call :admins, Helper::partner_url(:admins), :admin
|
18
22
|
|
19
|
-
#
|
23
|
+
# Retrieve the role assignments for a given admin.
|
24
|
+
# @param admin_id [String] Admin ID for whom role assignments are requested
|
25
|
+
# @param params [Hash] Optional query parameters
|
26
|
+
# @return [Hash] List of role assignments
|
20
27
|
# @see https://developer.sophos.com/docs/partner-v1/1/routes/admins/%7BadminId%7D/role-assignments/get
|
21
28
|
def admin_role_assignments(admin_id, params = {})
|
22
29
|
get(Helper::partner_url("admins/#{admin_id}/role-assignments"), params)
|
23
30
|
end
|
24
|
-
|
31
|
+
|
32
|
+
# Retrieve a specific role assignment for an admin by assignment ID.
|
33
|
+
# @param admin_id [String] Admin ID
|
34
|
+
# @param assignment_id [String] Role assignment ID
|
35
|
+
# @param params [Hash] Optional query parameters
|
36
|
+
# @return [Hash] Details of the specific role assignment
|
25
37
|
# @see https://developer.sophos.com/docs/partner-v1/1/routes/admins/%7BadminId%7D/role-assignments/%7BassignmentId%7D/get
|
26
38
|
def admin_role_assignment(admin_id, assignment_id, params = {})
|
27
39
|
get(Helper::partner_url("admins/#{admin_id}/role-assignments/#{assignment_id}"), params)
|
28
40
|
end
|
29
41
|
|
30
|
-
|
31
|
-
#
|
32
|
-
|
42
|
+
# Retrieve the list of permission sets.
|
43
|
+
# @param params [Hash] Optional query parameters
|
44
|
+
# @return [Array<Hash>] List of permission sets
|
45
|
+
# @see https://developer.sophos.com/docs/partner-v1/1/routes/roles/permission-sets/get
|
46
|
+
def permission_sets(params = {})
|
33
47
|
get(Helper::partner_url('roles/permission-sets'), params)
|
34
48
|
end
|
35
49
|
|
36
|
-
#
|
50
|
+
# Retrieve the billing usage report for a specific year and month.
|
51
|
+
# @param year [Integer] Year of the billing report (e.g., 2025)
|
52
|
+
# @param month [Integer] Month of the billing report (e.g., 1 for January)
|
53
|
+
# @param params [Hash] Optional query parameters
|
54
|
+
# @return [Hash] Billing usage data for the specified month
|
37
55
|
# @see https://developer.sophos.com/docs/partner-v1/1/routes/billing/usage/%7Byear%7D/%7Bmonth%7D/get
|
38
56
|
def billing_usage(year, month, params = {})
|
39
57
|
get_paged(Helper::partner_url("billing/usage/#{year}/#{month}"), params)
|
40
58
|
end
|
41
|
-
|
42
59
|
end
|
43
60
|
end
|
44
61
|
end
|
data/lib/sophos/client.rb
CHANGED
@@ -1,42 +1,67 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Sophos
|
4
|
-
|
5
|
-
#
|
4
|
+
# Wrapper for the Sophos Central REST API.
|
5
|
+
#
|
6
|
+
# This class acts as the main client for interacting with Sophos APIs and provides
|
7
|
+
# methods to create specific clients for tenants.
|
6
8
|
#
|
7
|
-
# @note All methods
|
9
|
+
# @note All methods are separated into modules based on the Sophos API documentation structure.
|
8
10
|
# @see https://developer.sophos.com/getting-started
|
9
11
|
class Client < API
|
10
12
|
require File.expand_path('client/partner', __dir__)
|
11
13
|
|
12
|
-
#
|
13
|
-
#
|
14
|
+
# Returns a tenant-specific client to access the API host for the given tenant.
|
15
|
+
#
|
16
|
+
# @param tenant [Hash] The tenant object containing API host and tenant ID.
|
17
|
+
# @return [TenantClient, nil] A configured tenant client, or nil if the tenant is not provided.
|
18
|
+
#
|
19
|
+
# @example Access tenant-specific APIs:
|
20
|
+
# tenant_client = client(tenant)
|
21
|
+
# tenant_client.some_tenant_specific_api_call
|
14
22
|
def client(tenant)
|
15
23
|
tenant_client(tenant.apiHost, tenant.id) if tenant
|
16
24
|
end
|
17
25
|
|
18
|
-
#
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
# Returns a configured tenant client to access APIs for a specific tenant ID and API host.
|
27
|
+
#
|
28
|
+
# @param api_host [String] The API host for the tenant.
|
29
|
+
# @param tenant_id [String] The tenant's unique ID.
|
30
|
+
# @return [TenantClient] A client configured with the tenant's API endpoint and headers.
|
31
|
+
#
|
32
|
+
# @example Create a tenant client and access tenant data:
|
33
|
+
# api_host = tenant.apiHost
|
34
|
+
# tenant_id = tenant.id
|
35
|
+
# tenant_client = tenant_client(api_host, tenant_id)
|
36
|
+
def tenant_client(api_host, tenant_id)
|
37
|
+
TenantClient.new(
|
38
|
+
self.config.merge(
|
39
|
+
{
|
40
|
+
access_token: access_token,
|
41
|
+
endpoint: api_host,
|
42
|
+
tenant_id: tenant_id,
|
43
|
+
connection_options: { headers: { 'X-Tenant-ID': tenant_id } }
|
44
|
+
}
|
45
|
+
)
|
46
|
+
)
|
28
47
|
end
|
29
48
|
|
49
|
+
# Includes partner-related API methods.
|
30
50
|
include Sophos::Client::Partner
|
31
51
|
end
|
32
52
|
|
33
|
-
# Wrapper for the Sophos Central REST API for tenant
|
53
|
+
# Wrapper for the Sophos Central REST API for tenant-related calls.
|
34
54
|
#
|
35
|
-
#
|
55
|
+
# This class inherits from `Sophos::Client` and includes additional modules
|
56
|
+
# for tenant-specific endpoints and common API methods.
|
57
|
+
#
|
58
|
+
# @note All tenant methods are separated into modules based on the Sophos API documentation.
|
36
59
|
# @see https://developer.sophos.com/getting-started
|
37
60
|
class TenantClient < Client
|
38
61
|
require File.expand_path('client/common', __dir__)
|
39
62
|
require File.expand_path('client/endpoint', __dir__)
|
63
|
+
|
64
|
+
# Includes modules for tenant-related and common API endpoints.
|
40
65
|
include Sophos::Client::Common
|
41
66
|
include Sophos::Client::Endpoint
|
42
67
|
end
|
data/lib/sophos/configuration.rb
CHANGED
@@ -1,37 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'wrapi'
|
2
4
|
require File.expand_path('version', __dir__)
|
3
5
|
require File.expand_path('pagination', __dir__)
|
4
6
|
|
5
7
|
module Sophos
|
6
|
-
#
|
8
|
+
# Configuration module for setting API-related options and defaults.
|
9
|
+
#
|
10
|
+
# This module extends `WrAPI::Configuration` and defines additional constants,
|
11
|
+
# default values, and methods to handle the configuration of the Sophos API wrapper.
|
7
12
|
module Configuration
|
8
13
|
include WrAPI::Configuration
|
9
14
|
|
10
|
-
#
|
11
|
-
VALID_OPTIONS_KEYS = (WrAPI::Configuration::VALID_OPTIONS_KEYS + [
|
15
|
+
# Additional valid configuration keys for [Sophos::API].
|
16
|
+
VALID_OPTIONS_KEYS = (WrAPI::Configuration::VALID_OPTIONS_KEYS + %i[
|
17
|
+
partner_id tenant_id id_endpoint
|
18
|
+
])
|
12
19
|
|
13
|
-
|
14
|
-
attr_accessor *VALID_OPTIONS_KEYS
|
20
|
+
attr_accessor(*VALID_OPTIONS_KEYS)
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
22
|
+
# Default settings
|
23
|
+
DEFAULT_ENDPOINT = 'https://api.central.sophos.com'
|
24
|
+
DEFAULT_ID_ENDPOINT = 'https://id.sophos.com'
|
25
|
+
DEFAULT_USER_AGENT = "Sophos Ruby API wrapper #{Sophos::VERSION}"
|
19
26
|
DEFAULT_PAGINATION = Sophos::RequestPagination::PagesPagination
|
20
27
|
DEFAULT_PAGE_SIZE = 100
|
21
28
|
|
22
|
-
#
|
29
|
+
# Initialize configuration defaults when this module is extended.
|
23
30
|
def self.extended(base)
|
24
31
|
base.reset
|
25
32
|
end
|
26
33
|
|
27
|
-
#
|
34
|
+
# Returns the current configuration as a hash of key-value pairs.
|
35
|
+
#
|
36
|
+
# @return [Hash] Current configuration options.
|
28
37
|
def options
|
29
|
-
VALID_OPTIONS_KEYS.
|
30
|
-
option
|
38
|
+
VALID_OPTIONS_KEYS.each_with_object({}) do |key, option|
|
39
|
+
option[key] = send(key)
|
31
40
|
end
|
32
41
|
end
|
33
42
|
|
34
|
-
#
|
43
|
+
# Resets all configuration options to their default values.
|
35
44
|
def reset
|
36
45
|
super
|
37
46
|
self.partner_id = nil
|
@@ -39,10 +48,9 @@ module Sophos
|
|
39
48
|
|
40
49
|
self.endpoint = DEFAULT_ENDPOINT
|
41
50
|
self.id_endpoint = DEFAULT_ID_ENDPOINT
|
42
|
-
self.user_agent =
|
51
|
+
self.user_agent = DEFAULT_USER_AGENT
|
43
52
|
self.page_size = DEFAULT_PAGE_SIZE
|
44
53
|
self.pagination_class = DEFAULT_PAGINATION
|
45
54
|
end
|
46
55
|
end
|
47
56
|
end
|
48
|
-
|
data/lib/sophos/error.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sophos
|
2
|
-
|
3
|
-
#
|
4
|
+
# Base class for all custom errors in the Sophos module.
|
5
|
+
# Allows rescuing all Sophos-related exceptions with a single error class.
|
4
6
|
class SophosError < StandardError; end
|
5
7
|
|
6
|
-
# Raised when
|
8
|
+
# Raised when configuration is incomplete or invalid.
|
7
9
|
class ConfigurationError < SophosError; end
|
8
10
|
|
9
|
-
#
|
11
|
+
# Raised when authentication to the Sophos API fails.
|
10
12
|
class AuthenticationError < SophosError; end
|
11
|
-
|
13
|
+
|
14
|
+
# Raised when API requests encounter general HTTP-related errors (optional future usage).
|
15
|
+
# Uncomment or extend if needed.
|
16
|
+
# class ApiError < SophosError; end
|
17
|
+
end
|
data/lib/sophos/pagination.rb
CHANGED
@@ -1,63 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module Sophos
|
4
6
|
# Defines HTTP request methods
|
5
7
|
# required attributes format
|
6
8
|
module RequestPagination
|
7
|
-
|
8
|
-
# Sophos
|
9
|
+
# Defines HTTP request pagination logic for Sophos APIs.
|
10
|
+
# Sophos supports different pagination approaches for the global API and tenant APIs.
|
9
11
|
#
|
10
|
-
# response structure:
|
11
|
-
# {
|
12
|
-
#
|
13
|
-
# "
|
14
|
-
# "
|
15
|
-
# "
|
16
|
-
# "
|
12
|
+
# Expected response structure:
|
13
|
+
# {
|
14
|
+
# "pages": {
|
15
|
+
# "current": 1, # Current page number (optional)
|
16
|
+
# "size": 50, # Items per page
|
17
|
+
# "total": 3, # Total pages (optional)
|
18
|
+
# "items": 123, # Total items (optional)
|
19
|
+
# "maxSize": 100, # Maximum items per page allowed (optional)
|
20
|
+
# "nextKey": "abc123" # Key for fetching the next page, used when available
|
17
21
|
# },
|
18
|
-
#
|
19
|
-
#
|
22
|
+
# "items": [] # Array of data items for the current page
|
23
|
+
# }
|
20
24
|
class PagesPagination
|
21
25
|
attr_reader :current, :total, :page_size
|
22
26
|
|
23
27
|
def initialize(page_size)
|
24
|
-
# ignore page size
|
25
28
|
@page_size = page_size
|
26
|
-
@total =
|
29
|
+
@total = 1 # Default total pages
|
30
|
+
@current = 1 # Start at the first page
|
31
|
+
@next_key = nil # Key for fetching the next page if provided by the API
|
27
32
|
end
|
28
33
|
|
34
|
+
# Returns options to be passed as query parameters for the next API request.
|
29
35
|
def page_options
|
30
|
-
{
|
36
|
+
options = { page: @current, pageSize: @page_size, pageTotal: true }
|
37
|
+
options[:pageFromKey] = @next_key if @current > 1 && @next_key # wellicht nil zetten zonder && @next_key?
|
38
|
+
options
|
31
39
|
end
|
32
40
|
|
41
|
+
# Updates the pagination state based on the API response data.
|
33
42
|
def next_page!(data)
|
34
|
-
|
35
43
|
pages = page_info(data)
|
36
44
|
if pages
|
37
|
-
|
38
|
-
if pages['current']
|
39
|
-
@current = pages['current'].to_i + 1
|
40
|
-
else
|
41
|
-
@current += 1
|
42
|
-
end
|
45
|
+
set_page_state(pages)
|
43
46
|
else
|
44
|
-
#
|
47
|
+
# Assume a single-page request if no pagination info is available.
|
45
48
|
@total = 0
|
46
49
|
end
|
47
50
|
end
|
48
51
|
|
49
|
-
|
52
|
+
# Extracts the 'pages' metadata from the response body.
|
53
|
+
def page_info(body)
|
50
54
|
body['pages']
|
51
55
|
end
|
52
56
|
|
53
|
-
|
54
|
-
|
57
|
+
# Extracts the relevant data items from the API response.
|
58
|
+
def self.data(body)
|
59
|
+
body['items'] || body
|
55
60
|
end
|
56
61
|
|
57
|
-
#
|
62
|
+
# Returns true if more pages are available.
|
58
63
|
def more_pages?
|
59
64
|
@current <= @total
|
60
65
|
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Updates the current page, total pages, and next key (if present) from the pages metadata.
|
70
|
+
def set_page_state(pages)
|
71
|
+
@total = pages['total'].to_i if pages['total']
|
72
|
+
@current = pages['current'] ? pages['current'].to_i + 1 : @current + 1
|
73
|
+
@next_key = pages['nextKey'] if pages['nextKey']
|
74
|
+
end
|
61
75
|
end
|
62
76
|
end
|
63
77
|
end
|
data/lib/sophos/version.rb
CHANGED
data/lib/sophos_central_api.rb
CHANGED
@@ -1,13 +1,38 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'wrapi'
|
2
4
|
require File.expand_path('sophos/api', __dir__)
|
3
5
|
require File.expand_path('sophos/client', __dir__)
|
4
6
|
|
7
|
+
# Main module to interact with the Sophos API.
|
8
|
+
# This module provides access to the Sophos client, which handles API calls and manages configurations.
|
9
|
+
#
|
10
|
+
# @example Initialize a Sophos client:
|
11
|
+
# client = Sophos.client(
|
12
|
+
# client_id: 'your_client_id',
|
13
|
+
# client_secret: 'your_client_secret'
|
14
|
+
# )
|
15
|
+
#
|
5
16
|
module Sophos
|
6
17
|
extend Configuration
|
7
18
|
extend WrAPI::RespondTo
|
8
19
|
|
20
|
+
# Initializes and returns a new instance of the Sophos client.
|
21
|
+
#
|
22
|
+
# @param options [Hash] A hash of options to configure the client.
|
23
|
+
# Supported options include:
|
24
|
+
# - `:client_id` [String] - Your Sophos API client ID.
|
25
|
+
# - `:client_secret` [String] - Your Sophos API client secret.
|
26
|
+
# - `:endpoint` [String] - The base URL for the API (default: Sophos Central endpoint).
|
27
|
+
#
|
28
|
+
# @return [Sophos::Client] An instance of the Sophos client with the provided configuration.
|
29
|
+
#
|
30
|
+
# @example Create a client with default settings:
|
31
|
+
# Sophos.client
|
32
|
+
#
|
33
|
+
# @example Create a client with custom options:
|
34
|
+
# Sophos.client(client_id: 'abc123', client_secret: 'xyz789')
|
9
35
|
#
|
10
|
-
# @return [Sophos::Client]
|
11
36
|
def self.client(options = {})
|
12
37
|
Sophos::Client.new(options)
|
13
38
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sophos_central_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janco Tanis
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-03-21 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: faraday
|
@@ -94,7 +93,6 @@ dependencies:
|
|
94
93
|
- - ">="
|
95
94
|
- !ruby/object:Gem::Version
|
96
95
|
version: '0'
|
97
|
-
description:
|
98
96
|
email: gems@jancology.com
|
99
97
|
executables: []
|
100
98
|
extensions: []
|
@@ -126,7 +124,6 @@ licenses:
|
|
126
124
|
metadata:
|
127
125
|
homepage_uri: https://rubygems.org/gems/sophos
|
128
126
|
source_code_uri: https://github.com/jancotanis/sophos
|
129
|
-
post_install_message:
|
130
127
|
rdoc_options: []
|
131
128
|
require_paths:
|
132
129
|
- lib
|
@@ -141,8 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
138
|
- !ruby/object:Gem::Version
|
142
139
|
version: '0'
|
143
140
|
requirements: []
|
144
|
-
rubygems_version: 3.2
|
145
|
-
signing_key:
|
141
|
+
rubygems_version: 3.6.2
|
146
142
|
specification_version: 4
|
147
143
|
summary: A Ruby wrapper for the Sophos Central REST APIs (readonly)
|
148
144
|
test_files: []
|