zanshin 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,189 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'configparser'
4
+ require 'uri'
5
+ require 'logger'
6
+
7
+ require_relative 'request/zanshin_request'
8
+ require_relative 'account'
9
+ require_relative 'alerts'
10
+ require_relative 'organization_followers'
11
+ require_relative 'organization_following'
12
+ require_relative 'organization_members'
13
+ require_relative 'organization_scan_targets'
14
+ require_relative 'organizations'
15
+ require_relative 'summaries'
16
+
17
+ module Zanshin
18
+ module SDK
19
+ # Zanshin SDK Client
20
+ class Client
21
+ include Zanshin::SDK::Account
22
+ include Zanshin::SDK::Alerts
23
+ include Zanshin::SDK::Organizations
24
+ include Zanshin::SDK::OrganizationFollowers
25
+ include Zanshin::SDK::OrganizationFollowing
26
+ include Zanshin::SDK::OrganizationMembers
27
+ include Zanshin::SDK::OrganizationScanTargets
28
+ include Zanshin::SDK::Summaries
29
+
30
+ # @overload api_key
31
+ # Gets the current value of api_key
32
+ # @return api_key
33
+ # @overload api_key=(value)
34
+ # Sets the api_key
35
+ # @param [value] the new api_key
36
+ attr_reader :api_key
37
+ # @overload api_url
38
+ # Gets the current value of api_url
39
+ # @return api_url
40
+ # @overload api_url=(value)
41
+ # Sets the api_url
42
+ # @param [value] the new api_url
43
+ attr_reader :api_url
44
+ # @overload user_agent
45
+ # Gets the current value of user_agent
46
+ # @return user_agent
47
+ # @overload user_agent=(value)
48
+ # Sets the user_agent
49
+ # @param [value] the new user_agent
50
+ attr_reader :user_agent
51
+ # @overload proxy_url
52
+ # Gets the current value of proxy_url
53
+ # @return proxy_url
54
+ # @overload proxy_url=(value)
55
+ # Sets the proxy_url
56
+ # @param [value] the new proxy_url
57
+ attr_reader :proxy_url
58
+
59
+ # @overload http
60
+ # Gets the current value of http
61
+ # @return http
62
+ # @overload http=(`:HTTPClient`)
63
+ # Sets the http
64
+ # @param [value] the new http
65
+ attr_accessor :http
66
+
67
+ # Initialize a new Zanshin SDK instance
68
+ # @overload initialize(profile, api_key, api_url, user_agent, proxy_url)
69
+ # @param profile [String] Which configuration file section to use for settings
70
+ # @param api_key [String] Optional override of the API key to use
71
+ # @param api_url [String] Optional override of the base URL of the Zanshin API to use
72
+ # @param user_agent [String] Optional addition of the user agent to use in requests performed
73
+ # @param proxy_url [String] Optional URL indicating which proxy server to use
74
+ def initialize(profile: 'default',
75
+ api_key: ENV.fetch('ZANSHIN_API_KEY', nil),
76
+ api_url: ENV.fetch('ZANSHIN_API_URL', nil) || ZANSHIN_API,
77
+ user_agent: ENV.fetch('ZANSHIN_USER_AGENT', nil),
78
+ proxy_url: ENV.fetch('HTTP_PROXY', ENV.fetch('HTTPS_PROXY', nil)))
79
+ @logger = Logger.new($stdout)
80
+ @logger.level = Logger::WARN
81
+
82
+ config = get_config(profile)
83
+
84
+ @api_key = api_key || config['api_key'] || raise('No API key found')
85
+ @api_url = validate_url(api_url || config['api_url'])
86
+ @user_agent = add_sdk_agent(user_agent || config['user_agent'])
87
+ @proxy_url = validate_proxy(proxy_url || config['proxy_url'])
88
+
89
+ update_request
90
+ @logger.debug('Zanshin SDK Initialized')
91
+ end
92
+
93
+ def api_key=(value)
94
+ raise('API key cannot be nil') unless value
95
+
96
+ @api_key = value
97
+
98
+ update_request
99
+ end
100
+
101
+ def api_url=(value)
102
+ @api_url = validate_url(value)
103
+
104
+ update_request
105
+ end
106
+
107
+ def user_agent=(value)
108
+ @user_agent = add_sdk_agent(value)
109
+
110
+ update_request
111
+ end
112
+
113
+ def proxy_url=(value)
114
+ @proxy_url = validate_proxy(value)
115
+
116
+ update_request
117
+ end
118
+
119
+ private
120
+
121
+ attr_accessor :logger
122
+
123
+ # Internal method to read user configuration file
124
+ def get_config(profile)
125
+ parser = if File.exist?(File.expand_path(CONFIG_FILE))
126
+ ConfigParser.new(CONFIG_FILE)
127
+ else
128
+ raise("Not found #{CONFIG_FILE}")
129
+ end
130
+ raise "Profile #{profile} not found in #{CONFIG_FILE}" unless parser[profile]
131
+
132
+ parser[profile]
133
+ end
134
+
135
+ # Internal method to validate URL
136
+ def validate_url(url)
137
+ raise 'API URL cannot be nil' unless url
138
+
139
+ uri = URI(url)
140
+ if (uri.scheme != 'https') ||
141
+ !uri.host ||
142
+ (uri.password || uri.user) ||
143
+ !uri.port.between?(0, 65_535)
144
+ raise "Invalid API URL: #{url}"
145
+ end
146
+
147
+ url
148
+ end
149
+
150
+ # Internal method to validate proxy
151
+ def validate_proxy(proxy_url)
152
+ return nil unless proxy_url
153
+
154
+ proxy = URI(proxy_url)
155
+ if !(%w[http https].include? proxy.scheme) ||
156
+ !proxy.host ||
157
+ (proxy.user && !proxy.password) ||
158
+ !proxy.port.between?(0, 65_535)
159
+ raise "Invalid proxy URL: #{proxy_url}"
160
+ end
161
+
162
+ proxy_url
163
+ end
164
+
165
+ # Internal method to concatenate user-agent with SDK pattern
166
+ def add_sdk_agent(agent)
167
+ if agent.to_s.strip.empty?
168
+ "Zanshin Ruby SDK #{Zanshin::SDK::VERSION}"
169
+ else
170
+ "#{agent}/Zanshin Ruby SDK #{Zanshin::SDK::VERSION}"
171
+ end
172
+ end
173
+
174
+ # Internal method to create a new pre-configured Zanshin::SDK::Request::HTTPClient instance when one
175
+ # of the relevant settings is changed (API key, API URL, user-agent or Proxy URL).
176
+ def update_request
177
+ @http = Zanshin::SDK::Request::HTTPClient.new(@api_key, @api_url, @user_agent, @proxy_url)
178
+ end
179
+
180
+ # Internal method to validate UUID
181
+ def validate_uuid(uuid)
182
+ uuid_regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
183
+ raise "#{uuid} is not a valid UUID" unless uuid_regex.match?(uuid.to_s.downcase)
184
+
185
+ uuid
186
+ end
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zanshin
4
+ module SDK
5
+ # Zanshin SDK Organization Followers
6
+ module OrganizationFollowers
7
+ ###################################################
8
+ # Organization Follower
9
+ ###################################################
10
+
11
+ # Organization Followers Enumerator of an organization
12
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrganizationFollowers)
13
+ #
14
+ # @param organization_id [UUID] of the organization
15
+ #
16
+ # @return an Organization Followers Enumerator object
17
+ def iter_organization_followers(organization_id)
18
+ Enumerator.new do |yielder|
19
+ @http.request('GET', "/organizations/#{validate_uuid(organization_id)}/followers").each do |e|
20
+ yielder.yield e
21
+ end
22
+ end
23
+ end
24
+
25
+ # Organization Followers Enumerator of an organization
26
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrganizationFollowers)
27
+ #
28
+ # @param organization_id [UUID] of the organization
29
+ # @param follower_id [UUID] of the follower
30
+ #
31
+ # @return a Boolean with result
32
+ def stop_organization_follower(organization_id, follower_id)
33
+ @http.request('DELETE',
34
+ "/organizations/#{validate_uuid(organization_id)}/followers/#{validate_uuid(follower_id)}")
35
+ end
36
+
37
+ ###################################################
38
+ # Organization Follower Request
39
+ ###################################################
40
+
41
+ # Organization Followers Requests Enumerator of an organization
42
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrganizationFollowRequests)
43
+ #
44
+ # @param organization_id [UUID] of the organization
45
+ #
46
+ # @return an Organization Followers Requests Enumerator object
47
+ def iter_organization_follower_requests(organization_id)
48
+ Enumerator.new do |yielder|
49
+ @http.request('GET', "/organizations/#{validate_uuid(organization_id)}/followers/requests").each do |e|
50
+ yielder.yield e
51
+ end
52
+ end
53
+ end
54
+
55
+ # Create organization follower request
56
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/createOrganizationFollowRequests)
57
+ #
58
+ # @param organization_id [UUID] of the organization
59
+ # @param token [UUID] of the follower request
60
+ #
61
+ # @return an Organization Followers Requests Enumerator object
62
+ def create_organization_follower_request(organization_id, token)
63
+ body = {
64
+ 'token' => validate_uuid(token)
65
+ }
66
+ @http.request('POST', "/organizations/#{validate_uuid(organization_id)}/followers/requests", body)
67
+ end
68
+
69
+ # Get organization follower request
70
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrganizationFollowRequestsByToken)
71
+ #
72
+ # @param organization_id [UUID] of the organization
73
+ # @param token [UUID] of the follower request
74
+ #
75
+ # @return an Object representing the organization follower
76
+ def get_organization_follower_request(organization_id, token)
77
+ @http.request('GET',
78
+ "/organizations/#{validate_uuid(organization_id)}/followers/requests/#{validate_uuid(token)}")
79
+ end
80
+
81
+ # Delete organization follower request
82
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/deleteOrganizationFollowRequestsbyToken)
83
+ #
84
+ # @param organization_id [UUID] of the organization
85
+ # @param token [UUID] of the follower request
86
+ #
87
+ # @return a Boolean with result
88
+ def delete_organization_follower_request(organization_id, token)
89
+ @http.request('DELETE',
90
+ "/organizations/#{validate_uuid(organization_id)}/followers/requests/#{validate_uuid(token)}")
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zanshin
4
+ module SDK
5
+ # Zanshin SDK Organization Following
6
+ module OrganizationFollowing
7
+ ###################################################
8
+ # Organization Following
9
+ ###################################################
10
+
11
+ # Organization Following Enumerator of an organization
12
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrganizationFollowing)
13
+ #
14
+ # @param organization_id [UUID] of the organization
15
+ #
16
+ # @return an Organization Following Enumerator object
17
+ def iter_organization_following(organization_id)
18
+ Enumerator.new do |yielder|
19
+ @http.request('GET', "/organizations/#{validate_uuid(organization_id)}/following").each do |e|
20
+ yielder.yield e
21
+ end
22
+ end
23
+ end
24
+
25
+ # Organization Followers Enumerator of an organization
26
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/removeOrganizationFollowingById)
27
+ #
28
+ # @param organization_id [UUID] of the organization
29
+ # @param following_id [UUID] of the follower
30
+ #
31
+ # @return a Boolean with result
32
+ def stop_organization_following(organization_id, following_id)
33
+ @http.request('DELETE',
34
+ "/organizations/#{validate_uuid(organization_id)}/following/#{validate_uuid(following_id)}")
35
+ end
36
+
37
+ ###################################################
38
+ # Organization Following Request
39
+ ###################################################
40
+
41
+ # Organization Following Requests Enumerator of an organization
42
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrganizationFollowingRequests)
43
+ #
44
+ # @param organization_id [UUID] of the organization
45
+ #
46
+ # @return an Organization Following Requests Enumerator object
47
+ def iter_organization_following_requests(organization_id)
48
+ Enumerator.new do |yielder|
49
+ @http.request('GET', "/organizations/#{validate_uuid(organization_id)}/following/requests").each do |e|
50
+ yielder.yield e
51
+ end
52
+ end
53
+ end
54
+
55
+ # Returns a request received by an organization to follow another
56
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrganizationFollowingRequestByToken)
57
+ #
58
+ # @param organization_id [UUID] of the organization
59
+ # @param following_id [UUID] of the follower request
60
+ #
61
+ # @return an Object representing the organization following request
62
+ def get_organization_following_request(organization_id, following_id)
63
+ @http.request(
64
+ 'GET',
65
+ "/organizations/#{validate_uuid(organization_id)}/following/requests/#{validate_uuid(following_id)}"
66
+ )
67
+ end
68
+
69
+ # Accepts a request to follow another organization
70
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/acceptOrganizationFollowingRequestByToken)
71
+ #
72
+ # @param organization_id [UUID] of the organization who was invited to follow another
73
+ # @param following_id [UUID] of the organization who is going to be followed
74
+ #
75
+ # @return an Object describing the newly established following relationship
76
+ def accept_organization_following_request(organization_id, following_id)
77
+ @http.request(
78
+ 'POST',
79
+ "/organizations/#{validate_uuid(organization_id)}/following/requests/#{validate_uuid(following_id)}/accept"
80
+ )
81
+ end
82
+
83
+ # Declines a request to follow another organization
84
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/declineOrganizationFollowingRequestByToken)
85
+ #
86
+ # @param organization_id [UUID] of the organization who was invited to follow another
87
+ # @param following_id [UUID] of the organization who is going to be followed
88
+ #
89
+ # @return an Object describing the newly established following relationship
90
+ def decline_organization_following_request(organization_id, following_id)
91
+ @http.request(
92
+ 'POST',
93
+ "/organizations/#{validate_uuid(organization_id)}/following/requests/#{validate_uuid(following_id)}/decline"
94
+ )
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zanshin
4
+ module SDK
5
+ # Zanshin SDK Organization Members
6
+ module OrganizationMembers
7
+ ###################################################
8
+ # Organization Member
9
+ ###################################################
10
+
11
+ # Organization Members Enumerator of the users which are members of an organization
12
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrganizationMembers)
13
+ #
14
+ # @param organization_id [UUID] of the organization
15
+ #
16
+ # @return an Organization Members Enumerator object
17
+ def iter_organization_members(organization_id)
18
+ Enumerator.new do |yielder|
19
+ @http.request('GET', "/organizations/#{validate_uuid(organization_id)}/members").each do |e|
20
+ yielder.yield e
21
+ end
22
+ end
23
+ end
24
+
25
+ # Get details on a user's organization membership
26
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrganizationMemberById)
27
+ #
28
+ # @param organization_id [UUID] of the organization
29
+ # @param member_id [UUID] of the member
30
+ #
31
+ # @return a Object representing the organization member
32
+ def get_organization_member(organization_id, member_id)
33
+ @http.request('GET',
34
+ "/organizations/#{validate_uuid(organization_id)}/members/#{validate_uuid(member_id)}")
35
+ end
36
+
37
+ # Update organization member
38
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/editOrganizationMembersById)
39
+ #
40
+ # @param organization_id [UUID] of the organization
41
+ # @param member_id [UUID] of the member
42
+ # @param roles ['ADMIN'] of the member
43
+ #
44
+ # @return a Object representing the organization member
45
+ def update_organization_member(organization_id, member_id, roles = nil)
46
+ body = {
47
+ 'roles' => [roles].compact
48
+ }
49
+ @http.request('PUT',
50
+ "/organizations/#{validate_uuid(organization_id)}/members/#{validate_uuid(member_id)}",
51
+ body)
52
+ end
53
+
54
+ # Delete organization member
55
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/removeOrganizationMemberById)
56
+ #
57
+ # @param organization_id [UUID] of the organization
58
+ # @param member_id [UUID] of the member
59
+ #
60
+ # @return a Boolean with result
61
+ def delete_organization_member(organization_id, member_id)
62
+ @http.request('DELETE',
63
+ "/organizations/#{validate_uuid(organization_id)}/members/#{validate_uuid(member_id)}")
64
+ end
65
+
66
+ # Reset organization member MFA
67
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/resetOrganizationMemberMfaById)
68
+ #
69
+ # @param organization_id [UUID] of the organization
70
+ # @param member_id [UUID] of the member
71
+ #
72
+ # @return a Boolean with result
73
+ def reset_organization_member_mfa(organization_id, member_id)
74
+ @http.request(
75
+ 'POST',
76
+ "/organizations/#{validate_uuid(organization_id)}/members/#{validate_uuid(member_id)}/mfa/reset"
77
+ )
78
+ end
79
+
80
+ # Reset organization member Password
81
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/resetOrganizationMemberPasswordById)
82
+ #
83
+ # @param organization_id [UUID] of the organization
84
+ # @param member_id [UUID] of the member
85
+ #
86
+ # @return a Boolean with result
87
+ def reset_organization_member_password(organization_id, member_id)
88
+ @http.request(
89
+ 'POST',
90
+ "/organizations/#{validate_uuid(organization_id)}/members/#{validate_uuid(member_id)}/password/reset"
91
+ )
92
+ end
93
+
94
+ ###################################################
95
+ # Organization Member Invite
96
+ ###################################################
97
+
98
+ # Organization Members Invites Enumerator of an organization
99
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrgamizationInvites)
100
+ #
101
+ # @param organization_id [UUID] of the organization
102
+ #
103
+ # @return an Organization Members Invites Enumerator object
104
+ def iter_organization_members_invites(organization_id)
105
+ Enumerator.new do |yielder|
106
+ @http.request('GET', "/organizations/#{validate_uuid(organization_id)}/invites").each do |e|
107
+ yielder.yield e
108
+ end
109
+ end
110
+ end
111
+
112
+ # Create organization member invite
113
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/createOrgamizationInvite)
114
+ #
115
+ # @param organization_id [UUID] of the organization
116
+ # @param email [String] of the new member
117
+ # @param roles ['ADMIN'] of the new member
118
+ #
119
+ # @return a Object representing the organization member invite
120
+ def create_organization_members_invite(organization_id, email, roles = nil)
121
+ body = {
122
+ 'email' => email,
123
+ 'roles' => [roles].compact
124
+ }
125
+ @http.request('POST',
126
+ "/organizations/#{validate_uuid(organization_id)}/invites",
127
+ body)
128
+ end
129
+
130
+ # Get organization member invite
131
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/getOrganizationInviteByEmail)
132
+ #
133
+ # @param organization_id [UUID] of the organization
134
+ # @param email [String] of the invited member
135
+ #
136
+ # @return a Object representing the organization member invite
137
+ def get_organization_member_invite(organization_id, email)
138
+ @http.request('GET',
139
+ "/organizations/#{validate_uuid(organization_id)}/invites/#{email}")
140
+ end
141
+
142
+ # Delete organization member invite
143
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/deleteOrganizationInviteByEmail)
144
+ #
145
+ # @param organization_id [UUID] of the organization
146
+ # @param email [String] of the invited member
147
+ #
148
+ # @return a Boolean with result
149
+ def delete_organization_member_invite(organization_id, email)
150
+ @http.request('DELETE',
151
+ "/organizations/#{validate_uuid(organization_id)}/invites/#{email}")
152
+ end
153
+
154
+ # Resend organization member invitation
155
+ # [#reference](https://api.zanshin.tenchisecurity.com/#operation/resendOrganizationInviteByEmail)
156
+ #
157
+ # @param organization_id [UUID] of the organization
158
+ # @param email [String] of the invited member
159
+ #
160
+ # @return a Boolean with result
161
+ def resend_organization_member_invite(organization_id, email)
162
+ @http.request('POST',
163
+ "/organizations/#{validate_uuid(organization_id)}/invites/#{email}/resend")
164
+ end
165
+ end
166
+ end
167
+ end