zanshin 1.0.1
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/LICENSE.md +20 -0
- data/README.md +135 -0
- data/lib/zanshin/account.rb +96 -0
- data/lib/zanshin/alerts.rb +368 -0
- data/lib/zanshin/client.rb +189 -0
- data/lib/zanshin/organization_followers.rb +94 -0
- data/lib/zanshin/organization_following.rb +98 -0
- data/lib/zanshin/organization_members.rb +167 -0
- data/lib/zanshin/organization_scan_targets.rb +177 -0
- data/lib/zanshin/organizations.rb +52 -0
- data/lib/zanshin/request/zanshin_request.rb +51 -0
- data/lib/zanshin/request/zanshin_request_error.rb +22 -0
- data/lib/zanshin/scan_target.rb +114 -0
- data/lib/zanshin/summaries.rb +80 -0
- data/lib/zanshin/version.rb +8 -0
- data/lib/zanshin.rb +17 -0
- metadata +188 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1e4c4177cdf64faab3875bd1fe144c21284530f211812969e0bd3ec5ab438d56
|
4
|
+
data.tar.gz: abd2455541e409bb6a018f12ba3e644fd32132ebd221f927f257a26d1e81e3b1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0ca6218cf76d9642937df5f15b68c2bec389cd147bc68af25aa2969dcd6a42e3c2722d1fe56a54db17844de2e9222b29b10e6386d2fa152ee243e952001330c9
|
7
|
+
data.tar.gz: fea40647b2780b2059188a477e4644426903164429bc5ae951f69950d78697cb080ca0634da6b6d306e16396fda12012b905b83d1e3d15b2d0e03f246c6d96d1
|
data/LICENSE.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2022 Tenchi Security.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
[](https://badge.fury.io/rb/zanshin)
|
2
|
+
|
3
|
+
# Zanshin Ruby SDK
|
4
|
+
|
5
|
+
This Ruby gem contains an SDK to interact with the [API of the Zanshin](https://api.zanshin.tenchisecurity.com) from [Tenchi Security](https://www.tenchisecurity.com).
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Install the gem and add to the application's Gemfile by executing:
|
10
|
+
|
11
|
+
```shell
|
12
|
+
bundle add zanshin
|
13
|
+
```
|
14
|
+
|
15
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
16
|
+
|
17
|
+
```shell
|
18
|
+
gem install zanshin
|
19
|
+
```
|
20
|
+
|
21
|
+
## Setting up Credentials
|
22
|
+
|
23
|
+
There are three ways that the SDK handles credentials. The order of evaluation is:
|
24
|
+
- [**1st** Client Parameters](#client-parameters)
|
25
|
+
- [**2nd** Environment Variables](#environment-variables)
|
26
|
+
- [**3rd** Config File](#config-file)
|
27
|
+
|
28
|
+
### Client Parameters
|
29
|
+
|
30
|
+
When calling the `Client` class, you can pass the values API Key(`api_key`), API URL(`api_url`), User Agent(`user_agent`) and Proxy URL(`proxy_url`) you want to use as below:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
client = Zanshin::SDK::Client.new(api_key: "my_zanshin_api_key")
|
34
|
+
puts client.get_me
|
35
|
+
```
|
36
|
+
|
37
|
+
> These values will overwrite anything you set as Environment Variables or in the Config File.
|
38
|
+
|
39
|
+
### Environment Variables
|
40
|
+
|
41
|
+
You can use the following Environment Variables to configure Zanshin SDK:
|
42
|
+
- `ZANSHIN_API_KEY`: Will setup your Zanshin credentials
|
43
|
+
- `ZANSHIN_API_URL`: Will define the API URL. Default is `https://api.zanshin.tenchisecurity.com`
|
44
|
+
- `ZANSHIN_USER_AGENT`: If you want to overwrite the User Agent when calling Zanshin API (The value passed will be concatenated to the SDK's default value `Zanshin Ruby SDK 1.0.0`)
|
45
|
+
- `HTTP_PROXY | HTTPS_PROXY`: Zanshin SDK uses `Net::HTTP` under the hood, checkout the [Net::HTTP RDoc](https://ruby-doc.org/stdlib-3.1.2/libdoc/net/http/rdoc/Net/HTTP.html) section of their documentation for more use cases
|
46
|
+
|
47
|
+
#### Example
|
48
|
+
|
49
|
+
```shell
|
50
|
+
export ZANSHIN_API_KEY="my_zanshin_api_key"
|
51
|
+
```
|
52
|
+
|
53
|
+
> These Environment Variables will overwrite anything you set on the Config File.
|
54
|
+
|
55
|
+
### Config File
|
56
|
+
|
57
|
+
This `Ruby SDK` was built to be used under the same conditions as the [Python SDK](https://github.com/tenchi-security/zanshin-sdk-python), so the configuration file is in the format created by the Python [RawConfigParser](https://docs.python.org/3/library/configparser.html#configparser.RawConfigParser) class.
|
58
|
+
|
59
|
+
The file is located at `~/.tenchi/config`, where `~` is the [current user's home directory](https://docs.python.org/3/library/pathlib.html#pathlib.Path.home).
|
60
|
+
|
61
|
+
Each section is treated as a configuration profile, and the SDK will look for a section called `default` if another is not explicitly selected.
|
62
|
+
|
63
|
+
These are the supported options:
|
64
|
+
|
65
|
+
* `api_key` (required) which contains the Zanshin API key obtained at the [Zanshin web portal](https://zanshin.tenchisecurity.com/my-profile).
|
66
|
+
* `api_url` (optional) directs the SDK to use a different API endpoint than the default (https://api.zanshin.tenchisecurity.com).
|
67
|
+
* `user_agent` (optional) allows you to override the default user-agent header used by the SDK when making API requests (The value passed will be concatenated to the SDK's default value `Zanshin Ruby SDK 1.0.0`).
|
68
|
+
* `proxy_url` (optional) directs the SDK to use a Proxy.
|
69
|
+
|
70
|
+
This is what a minimal configuration file looks like:
|
71
|
+
```ini
|
72
|
+
[default]
|
73
|
+
api_key=my_zanshin_api_key
|
74
|
+
```
|
75
|
+
|
76
|
+
## The SDK
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
client = Zanshin::SDK::Client.new
|
80
|
+
client.get_me
|
81
|
+
```
|
82
|
+
|
83
|
+
## Usage
|
84
|
+
|
85
|
+
### Create instance
|
86
|
+
```ruby
|
87
|
+
client = Zanshin::SDK::Client.new # loads API key from the "default" profile in ~/.tenchi/config
|
88
|
+
```
|
89
|
+
|
90
|
+
### Get logged user info
|
91
|
+
```ruby
|
92
|
+
client.get_me # calls /me API endpoint
|
93
|
+
```
|
94
|
+
|
95
|
+
### Get logged user info
|
96
|
+
|
97
|
+
Methods with prefix `iter_*` return an [Enumerator](https://ruby-doc.org/core-2.6/Enumerator.html), you can use it however you want, in this example we use `to_a` to convert the Enumerator into an Array.
|
98
|
+
```ruby
|
99
|
+
client.iter_organizations.to_a # calls /organizations API endpoint
|
100
|
+
```
|
101
|
+
|
102
|
+
## Support
|
103
|
+
|
104
|
+
If you are a Zanshin customer and have any questions regarding the use of the service, its API or this SDK package, please get in touch via e-mail at `support@tenchisecurity.com` or via the support widget on the [Zanshin Portal](https://zanshin.tenchisecurity.com).
|
105
|
+
|
106
|
+
## Development
|
107
|
+
|
108
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
109
|
+
|
110
|
+
## Contributing
|
111
|
+
|
112
|
+
Bug reports and pull requests are welcome on GitHub at `https://github.com/tenchi-security/zanshin-sdk-ruby`. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/tenchi-security/zanshin-sdk-ruby/blob/main/CODE_OF_CONDUCT.md).
|
113
|
+
|
114
|
+
## Unit Test
|
115
|
+
|
116
|
+
Currently, the Unit Test only checks if the API call was made in the way it should, after implementing the input validations the tests will be better.
|
117
|
+
|
118
|
+
## TODO
|
119
|
+
|
120
|
+
- Input validation
|
121
|
+
- Coverage badge
|
122
|
+
- File Persistent Alerts Iterator
|
123
|
+
- Onboard Scan Targets (AWS)
|
124
|
+
|
125
|
+
## License
|
126
|
+
|
127
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
128
|
+
|
129
|
+
## Code of Conduct
|
130
|
+
|
131
|
+
Everyone interacting in the `Zanshin Ruby SDK` project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/tenchi-security/zanshin-sdk-ruby/blob/main/CODE_OF_CONDUCT.md).
|
132
|
+
|
133
|
+
## Changelog
|
134
|
+
|
135
|
+
See [CHANGELOG](https://github.com/tenchi-security/zanshin-sdk-ruby/blob/main/CHANGELOG.md) for a list of changes.
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zanshin
|
4
|
+
module SDK
|
5
|
+
# Zanshin SDK Account
|
6
|
+
module Account
|
7
|
+
###################################################
|
8
|
+
# Account
|
9
|
+
###################################################
|
10
|
+
|
11
|
+
# Returns the details of the user account that owns the API key used by this Connection instance
|
12
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/getMe)
|
13
|
+
#
|
14
|
+
# @return an Object representing the user
|
15
|
+
def get_me
|
16
|
+
@http.request('GET', '/me')
|
17
|
+
end
|
18
|
+
|
19
|
+
###################################################
|
20
|
+
# Account Invites
|
21
|
+
###################################################
|
22
|
+
|
23
|
+
# Invites Enumerator of current logged user
|
24
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/getInvites)
|
25
|
+
#
|
26
|
+
# @return an Invites Enumerator object
|
27
|
+
def iter_invites
|
28
|
+
Enumerator.new do |yielder|
|
29
|
+
@http.request('GET', '/me/invites').each do |e|
|
30
|
+
yielder.yield e
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Gets a specific invitation details, it only works if the invitation was made for the current logged user
|
36
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/getInviteById)
|
37
|
+
#
|
38
|
+
# @param invite_id [UUID] of the invite
|
39
|
+
#
|
40
|
+
# @return an Object representing the invite
|
41
|
+
def get_invite(invite_id)
|
42
|
+
@http.request('GET', "/me/invites/#{validate_uuid(invite_id)}")
|
43
|
+
end
|
44
|
+
|
45
|
+
# Accepts an invitation with the informed ID, it only works if the user accepting the invitation is the user that
|
46
|
+
# received the invitation
|
47
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/acceptInviteById)
|
48
|
+
#
|
49
|
+
# @param invite_id [UUID] of the invite
|
50
|
+
#
|
51
|
+
# @return an Object representing the organization of this invite
|
52
|
+
def accept_invite(invite_id)
|
53
|
+
@http.request('POST', "/me/invites/#{validate_uuid(invite_id)}/accept")
|
54
|
+
end
|
55
|
+
|
56
|
+
###################################################
|
57
|
+
# Account API key
|
58
|
+
###################################################
|
59
|
+
|
60
|
+
# API keys Enumerator of current logged user
|
61
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/getMyApiKeys)
|
62
|
+
#
|
63
|
+
# @return an API keys Enumerator object
|
64
|
+
def iter_api_keys
|
65
|
+
Enumerator.new do |yielder|
|
66
|
+
@http.request('GET', '/me/apikeys').each do |e|
|
67
|
+
yielder.yield e
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Creates a new API key for the current logged user, API Keys can be used to interact with the zanshin api
|
73
|
+
# directly on behalf of that user
|
74
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/createApiKeys)
|
75
|
+
#
|
76
|
+
# @param name [String] of your new API key
|
77
|
+
#
|
78
|
+
# @return an Object representing the user api key
|
79
|
+
def create_api_key(name)
|
80
|
+
body = {}
|
81
|
+
body['name'] = name
|
82
|
+
@http.request('POST', '/me/apikeys', body)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Deletes a given API key by its id, it will only work if the informed ID belongs to the current logged user
|
86
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/deleteApiKey)
|
87
|
+
#
|
88
|
+
# @param api_key_id [UUID] of your new API key
|
89
|
+
#
|
90
|
+
# @return a Boolean with result
|
91
|
+
def delete_api_key(api_key_id)
|
92
|
+
@http.request('DELETE', "/me/apikeys/#{validate_uuid(api_key_id)}")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,368 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zanshin
|
4
|
+
module SDK
|
5
|
+
# Zanshin SDK Alerts
|
6
|
+
module Alerts
|
7
|
+
###################################################
|
8
|
+
# Alerts
|
9
|
+
###################################################
|
10
|
+
|
11
|
+
# Alerts Enumerator of an organization by loading them, transparently paginating on the API
|
12
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/listAllAlert)
|
13
|
+
#
|
14
|
+
# @param organization_id [UUID] of the organization
|
15
|
+
# @param scan_target_ids [Array<UUID>] Optional list of scan target IDs to list alerts from, defaults to all
|
16
|
+
# @param rule [String] to filter alerts from (rule), not passing the field will fetch all
|
17
|
+
# @param states [Array<'OPEN', 'ACTIVE', 'IN_PROGRESS', 'RISK_ACCEPTED', 'CLOSED'>] Optional list of states to
|
18
|
+
# filter returned alerts, defaults to all
|
19
|
+
# @param severities [Array<'CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO'>] optional list of severities to filter
|
20
|
+
# returned alerts, defaults to all
|
21
|
+
# @param page_size [Integer] the number of alerts to load from the API at a time
|
22
|
+
# @param language ['en-US', 'pt-BR'] Language of the rule will be returned
|
23
|
+
# @param created_at_start [String] Search alerts by creation date - greater or equals than
|
24
|
+
# @param created_at_end [String] Search alerts by creation date - less or equals than
|
25
|
+
# @param updated_at_start [String] Search alerts by update date - greater or equals than
|
26
|
+
# @param updated_at_end [String] Search alerts by update date - less or equals than
|
27
|
+
#
|
28
|
+
# @return an Alerts Enumerator object
|
29
|
+
def iter_alerts(organization_id,
|
30
|
+
scan_target_ids: [],
|
31
|
+
rule: nil,
|
32
|
+
states: nil,
|
33
|
+
severities: nil,
|
34
|
+
page_size: 100,
|
35
|
+
language: nil,
|
36
|
+
created_at_start: nil,
|
37
|
+
created_at_end: nil,
|
38
|
+
updated_at_start: nil,
|
39
|
+
updated_at_end: nil)
|
40
|
+
body = {
|
41
|
+
'organizationId' => validate_uuid(organization_id),
|
42
|
+
'page' => 0,
|
43
|
+
'pageSize' => page_size,
|
44
|
+
'scanTargetIds' => scan_target_ids.each { |scan_target_id| validate_uuid(scan_target_id) },
|
45
|
+
'rule' => rule,
|
46
|
+
'states' => states,
|
47
|
+
'severities' => severities,
|
48
|
+
'lang' => language,
|
49
|
+
'CreatedAtStart' => created_at_start,
|
50
|
+
'CreatedAtEnd' => created_at_end,
|
51
|
+
'UpdatedAtStart' => updated_at_start,
|
52
|
+
'UpdatedAtEnd' => updated_at_end
|
53
|
+
}
|
54
|
+
|
55
|
+
Enumerator.new do |yielder|
|
56
|
+
loop do
|
57
|
+
body['page'] += 1
|
58
|
+
data = @http.request('POST', '/alerts', body.compact)
|
59
|
+
data['data'].each do |e|
|
60
|
+
yielder.yield e
|
61
|
+
end
|
62
|
+
break if body['page'] == (data['total'] / body['pageSize']).ceil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Alerts Following Enumerator over the following alerts froms organizations being followed by
|
68
|
+
# transparently paginating on the API
|
69
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/listFollowingAlerts)
|
70
|
+
#
|
71
|
+
# @param organization_id [UUID] of the organization
|
72
|
+
# @param following_ids [Array<UUID>] Optional list of IDs of organizations you are following to
|
73
|
+
# list alerts from, defaults to all
|
74
|
+
# @param rule [String] to filter alerts from (rule), not passing the field will fetch all
|
75
|
+
# @param states [Array<'OPEN', 'ACTIVE', 'IN_PROGRESS', 'RISK_ACCEPTED', 'CLOSED'>] Optional list of states to
|
76
|
+
# filter returned alerts, defaults to all
|
77
|
+
# @param severities [Array<'CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO'>] optional list of severities to filter
|
78
|
+
# returned alerts, defaults to all
|
79
|
+
# @param page_size [Integer] the number of alerts to load from the API at a time
|
80
|
+
# @param language ['en-US', 'pt-BR'] Language of the rule will be returned
|
81
|
+
# @param created_at_start [String] Search alerts by creation date - greater or equals than
|
82
|
+
# @param created_at_end [String] Search alerts by creation date - less or equals than
|
83
|
+
# @param updated_at_start [String] Search alerts by update date - greater or equals than
|
84
|
+
# @param updated_at_end [String] Search alerts by update date - less or equals than
|
85
|
+
#
|
86
|
+
# @return an Alerts Enumerator object
|
87
|
+
def iter_following_alerts(organization_id,
|
88
|
+
following_ids: [],
|
89
|
+
rule: nil,
|
90
|
+
states: nil,
|
91
|
+
severities: nil,
|
92
|
+
page_size: 100,
|
93
|
+
language: nil,
|
94
|
+
created_at_start: nil,
|
95
|
+
created_at_end: nil,
|
96
|
+
updated_at_start: nil,
|
97
|
+
updated_at_end: nil)
|
98
|
+
body = {
|
99
|
+
'organizationId' => validate_uuid(organization_id),
|
100
|
+
'page' => 0,
|
101
|
+
'pageSize' => page_size,
|
102
|
+
'followingIds' => following_ids.each { |following_id| validate_uuid(following_id) },
|
103
|
+
'rule' => rule,
|
104
|
+
'states' => states,
|
105
|
+
'severities' => severities,
|
106
|
+
'lang' => language,
|
107
|
+
'CreatedAtStart' => created_at_start,
|
108
|
+
'CreatedAtEnd' => created_at_end,
|
109
|
+
'UpdatedAtStart' => updated_at_start,
|
110
|
+
'UpdatedAtEnd' => updated_at_end
|
111
|
+
}
|
112
|
+
|
113
|
+
Enumerator.new do |yielder|
|
114
|
+
loop do
|
115
|
+
body['page'] += 1
|
116
|
+
data = @http.request('POST', '/alerts/following', body.compact)
|
117
|
+
data['data'].each do |e|
|
118
|
+
yielder.yield e
|
119
|
+
end
|
120
|
+
break if body['page'] == (data['total'] / body['pageSize']).ceil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Alerts History Enumerator of an organization by loading them, transparently paginating on the API
|
126
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/listAllAlertsHistory)
|
127
|
+
#
|
128
|
+
# @param organization_id [UUID] of the organization
|
129
|
+
# @param scan_target_ids [Array<UUID>] Optional list of scan target IDs to list alerts from, defaults to all
|
130
|
+
# @param page_size [Integer] the number of alerts to load from the API at a time
|
131
|
+
# @param language ['en-US', 'pt-BR'] Language of the rule will be returned
|
132
|
+
# @param cursor [String] Alert Cursor of the last alert consumed, when this value is passed, subsequent
|
133
|
+
# alert histories will be returned
|
134
|
+
#
|
135
|
+
# @return an Alerts History Enumerator object
|
136
|
+
def iter_alerts_history(organization_id,
|
137
|
+
scan_target_ids: [],
|
138
|
+
page_size: 100,
|
139
|
+
language: nil,
|
140
|
+
cursor: nil)
|
141
|
+
body = {
|
142
|
+
'organizationId' => validate_uuid(organization_id),
|
143
|
+
'page' => 0,
|
144
|
+
'pageSize' => page_size,
|
145
|
+
'scanTargetIds' => scan_target_ids.each { |scan_target_id| validate_uuid(scan_target_id) },
|
146
|
+
'lang' => language,
|
147
|
+
'cursor' => cursor
|
148
|
+
}
|
149
|
+
|
150
|
+
Enumerator.new do |yielder|
|
151
|
+
loop do
|
152
|
+
body['page'] += 1
|
153
|
+
data = @http.request('POST', '/alerts/history', body.compact)
|
154
|
+
break if data['data'].empty?
|
155
|
+
|
156
|
+
body['cursor'] = data['data'].last['cursor']
|
157
|
+
data['data'].each do |e|
|
158
|
+
yielder.yield e
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Alerts Following History Enumerator of an organization by loading them, transparently paginating on the API
|
165
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/listAllAlertsHistoryFollowing)
|
166
|
+
#
|
167
|
+
# @param organization_id [UUID] of the organization
|
168
|
+
# @param following_ids [Array<UUID>] Optional list of IDs of organizations you are following to
|
169
|
+
# list alerts from, defaults to all
|
170
|
+
# @param page_size [Integer] the number of alerts to load from the API at a time
|
171
|
+
# @param language ['en-US', 'pt-BR'] Language of the rule will be returned
|
172
|
+
# @param cursor [String] Alert Cursor of the last alert consumed, when this value is passed, subsequent
|
173
|
+
# alert histories will be returned
|
174
|
+
#
|
175
|
+
# @return an Alerts Following History Enumerator object
|
176
|
+
def iter_alerts_following_history(organization_id,
|
177
|
+
following_ids: [],
|
178
|
+
page_size: 100,
|
179
|
+
language: nil,
|
180
|
+
cursor: nil)
|
181
|
+
body = {
|
182
|
+
'organizationId' => validate_uuid(organization_id),
|
183
|
+
'page' => 0,
|
184
|
+
'pageSize' => page_size,
|
185
|
+
'followingIds' => following_ids.each { |following_id| validate_uuid(following_id) },
|
186
|
+
'lang' => language,
|
187
|
+
'cursor' => cursor
|
188
|
+
}
|
189
|
+
|
190
|
+
Enumerator.new do |yielder|
|
191
|
+
loop do
|
192
|
+
body['page'] += 1
|
193
|
+
data = @http.request('POST', '/alerts/history/following', body.compact)
|
194
|
+
break if data['data'].empty?
|
195
|
+
|
196
|
+
body['cursor'] = data['data'].last['cursor']
|
197
|
+
data['data'].each do |e|
|
198
|
+
yielder.yield e
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Grouped Alerts Enumerator of an organization by loading them, transparently paginating on the API
|
205
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/listAllAlertRules)
|
206
|
+
#
|
207
|
+
# @param organization_id [UUID] of the organization
|
208
|
+
# @param scan_target_ids [Array<UUID>] Optional list of scan target IDs to list alerts from, defaults to all
|
209
|
+
# @param states [Array<'OPEN', 'ACTIVE', 'IN_PROGRESS', 'RISK_ACCEPTED', 'CLOSED'>] Optional list of states to
|
210
|
+
# filter returned alerts, defaults to all
|
211
|
+
# @param severities [Array<'CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO'>] optional list of severities to filter
|
212
|
+
# returned alerts, defaults to all
|
213
|
+
# @param page_size [Integer] the number of alerts to load from the API at a time
|
214
|
+
#
|
215
|
+
# @return an Grouped Alerts Enumerator object
|
216
|
+
def iter_grouped_alerts(organization_id,
|
217
|
+
scan_target_ids: [],
|
218
|
+
states: nil,
|
219
|
+
severities: nil,
|
220
|
+
page_size: 100)
|
221
|
+
body = {
|
222
|
+
'organizationId' => validate_uuid(organization_id),
|
223
|
+
'page' => 0,
|
224
|
+
'pageSize' => page_size,
|
225
|
+
'scanTargetIds' => scan_target_ids.each { |scan_target_id| validate_uuid(scan_target_id) },
|
226
|
+
'states' => states,
|
227
|
+
'severities' => severities
|
228
|
+
}
|
229
|
+
|
230
|
+
Enumerator.new do |yielder|
|
231
|
+
loop do
|
232
|
+
body['page'] += 1
|
233
|
+
data = @http.request('POST', '/alerts/rules', body.compact)
|
234
|
+
data['data'].each do |e|
|
235
|
+
yielder.yield e
|
236
|
+
end
|
237
|
+
break if body['page'] == (data['total'] / body['pageSize']).ceil
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# Grouped Alerts Following Enumerator of an organization by loading them, transparently paginating on the API
|
243
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/listAllAlertRulesFollowing)
|
244
|
+
#
|
245
|
+
# @param organization_id [UUID] of the organization
|
246
|
+
# @param following_ids [Array<UUID>] Optional list of IDs of organizations you are following to
|
247
|
+
# list alerts from, defaults to all
|
248
|
+
# @param states [Array<'OPEN', 'ACTIVE', 'IN_PROGRESS', 'RISK_ACCEPTED', 'CLOSED'>] Optional list of states to
|
249
|
+
# filter returned alerts, defaults to all
|
250
|
+
# @param severities [Array<'CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO'>] optional list of severities to filter
|
251
|
+
# returned alerts, defaults to all
|
252
|
+
# @param page_size [Integer] the number of alerts to load from the API at a time
|
253
|
+
#
|
254
|
+
# @return an Grouped Alerts Following Enumerator object
|
255
|
+
def iter_grouped_following_alerts(organization_id,
|
256
|
+
following_ids: [],
|
257
|
+
states: nil,
|
258
|
+
severities: nil,
|
259
|
+
page_size: 100)
|
260
|
+
body = {
|
261
|
+
'organizationId' => validate_uuid(organization_id),
|
262
|
+
'page' => 0,
|
263
|
+
'pageSize' => page_size,
|
264
|
+
'followingIds' => following_ids.each { |following_id| validate_uuid(following_id) },
|
265
|
+
'states' => states,
|
266
|
+
'severities' => severities
|
267
|
+
}
|
268
|
+
|
269
|
+
Enumerator.new do |yielder|
|
270
|
+
loop do
|
271
|
+
body['page'] += 1
|
272
|
+
data = @http.request('POST', '/alerts/rules/following', body.compact)
|
273
|
+
data['data'].each do |e|
|
274
|
+
yielder.yield e
|
275
|
+
end
|
276
|
+
break if body['page'] == (data['total'] / body['pageSize']).ceil
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# Returns the detailed object that describes an alert
|
282
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/getAlertById)
|
283
|
+
#
|
284
|
+
# @param alert_id [UUID] of the alert
|
285
|
+
#
|
286
|
+
# @return a Object representing the alert
|
287
|
+
def get_alert(alert_id)
|
288
|
+
@http.request('GET', "/alerts/#{validate_uuid(alert_id)}")
|
289
|
+
end
|
290
|
+
|
291
|
+
# Alert History Enumerator over the history of an alert
|
292
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/listAllAlertHistory)
|
293
|
+
#
|
294
|
+
# @param alert_id [UUID] of the alert
|
295
|
+
#
|
296
|
+
# @return an Alert History Enumerator object
|
297
|
+
def iter_alert_history(alert_id)
|
298
|
+
Enumerator.new do |yielder|
|
299
|
+
@http.request('GET', "/alerts/#{validate_uuid(alert_id)}/history").each do |e|
|
300
|
+
yielder.yield e
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
# Alert Comments Enumerator over the comment of an alert
|
306
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/listAllAlertComments)
|
307
|
+
#
|
308
|
+
# @param alert_id [UUID] of the alert
|
309
|
+
#
|
310
|
+
# @return an Alert Comments Enumerator object
|
311
|
+
def iter_alert_comments(alert_id)
|
312
|
+
Enumerator.new do |yielder|
|
313
|
+
@http.request('GET', "/alerts/#{validate_uuid(alert_id)}/comments").each do |e|
|
314
|
+
yielder.yield e
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
# Update alert
|
320
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/editOrganizationScanTargetAlertById)
|
321
|
+
#
|
322
|
+
# @param organization_id [UUID] of the organization
|
323
|
+
# @param scan_target_id [UUID] of the scan target
|
324
|
+
# @param alert_id [UUID] of the alert
|
325
|
+
# @param state ['OPEN', 'ACTIVE', 'IN_PROGRESS', 'RISK_ACCEPTED']
|
326
|
+
# @param labels [Array<String>] Optional labels to alert
|
327
|
+
# @param comment [String] Accepted and required only when change :state to 'IN_PROGRESS'
|
328
|
+
#
|
329
|
+
# @return a Object representing the alert updated
|
330
|
+
def update_alert(organization_id, scan_target_id, alert_id, state = nil, labels = nil, comment = nil)
|
331
|
+
body = {
|
332
|
+
'state' => state,
|
333
|
+
'labels' => labels,
|
334
|
+
'comment' => comment
|
335
|
+
}
|
336
|
+
|
337
|
+
@http.request(
|
338
|
+
'PUT',
|
339
|
+
"/organizations/#{validate_uuid(organization_id)}/scantargets/#{
|
340
|
+
validate_uuid(scan_target_id)}/alerts/#{validate_uuid(alert_id)}",
|
341
|
+
body.compact
|
342
|
+
)
|
343
|
+
end
|
344
|
+
|
345
|
+
# Create comment in alert
|
346
|
+
# [#reference](https://api.zanshin.tenchisecurity.com/#operation/listAllAlertComments)
|
347
|
+
#
|
348
|
+
# @param organization_id [UUID] of the organization
|
349
|
+
# @param scan_target_id [UUID] of the scan target
|
350
|
+
# @param alert_id [UUID] of the alert
|
351
|
+
# @param comment [String] in HTML format
|
352
|
+
#
|
353
|
+
# @return a Object representing the alert comment
|
354
|
+
def create_alert_comment(organization_id, scan_target_id, alert_id, comment)
|
355
|
+
body = {
|
356
|
+
'comment' => comment
|
357
|
+
}
|
358
|
+
|
359
|
+
@http.request(
|
360
|
+
'POST',
|
361
|
+
"/organizations/#{validate_uuid(organization_id)}/scantargets/#{
|
362
|
+
validate_uuid(scan_target_id)}/alerts/#{validate_uuid(alert_id)}/comments",
|
363
|
+
body.compact
|
364
|
+
)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|