esp_sdk 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +15 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +1185 -0
  9. data/Rakefile +9 -0
  10. data/esp_sdk.gemspec +33 -0
  11. data/lib/esp_sdk/api.rb +29 -0
  12. data/lib/esp_sdk/client.rb +59 -0
  13. data/lib/esp_sdk/configure.rb +36 -0
  14. data/lib/esp_sdk/end_points/base.rb +86 -0
  15. data/lib/esp_sdk/end_points/contact_requests.rb +6 -0
  16. data/lib/esp_sdk/end_points/custom_signatures.rb +41 -0
  17. data/lib/esp_sdk/end_points/dashboard.rb +30 -0
  18. data/lib/esp_sdk/end_points/external_accounts.rb +9 -0
  19. data/lib/esp_sdk/end_points/organizations.rb +6 -0
  20. data/lib/esp_sdk/end_points/reports.rb +6 -0
  21. data/lib/esp_sdk/end_points/services.rb +6 -0
  22. data/lib/esp_sdk/end_points/signatures.rb +39 -0
  23. data/lib/esp_sdk/end_points/sub_organizations.rb +6 -0
  24. data/lib/esp_sdk/end_points/teams.rb +6 -0
  25. data/lib/esp_sdk/end_points/users.rb +6 -0
  26. data/lib/esp_sdk/exceptions.rb +7 -0
  27. data/lib/esp_sdk/extensions/rest_client/request.rb +9 -0
  28. data/lib/esp_sdk/version.rb +3 -0
  29. data/lib/esp_sdk.rb +45 -0
  30. data/test/esp_sdk/api_test.rb +36 -0
  31. data/test/esp_sdk/client_test.rb +119 -0
  32. data/test/esp_sdk/configure_test.rb +49 -0
  33. data/test/esp_sdk/end_points/.keep +0 -0
  34. data/test/esp_sdk/end_points/base_test.rb +175 -0
  35. data/test/esp_sdk/end_points/custom_signatures_test.rb +90 -0
  36. data/test/esp_sdk/end_points/dashboard_test.rb +55 -0
  37. data/test/esp_sdk/end_points/external_accounts_test.rb +20 -0
  38. data/test/esp_sdk/end_points/signatures_test.rb +83 -0
  39. data/test/esp_sdk/exceptions_test.rb +35 -0
  40. data/test/esp_sdk_test.rb +70 -0
  41. data/test/test_helper.rb +20 -0
  42. metadata +264 -0
data/README.md ADDED
@@ -0,0 +1,1185 @@
1
+ [![Build Status](https://travis-ci.org/EvidentSecurity/esp_sdk.svg?branch=master)](https://travis-ci.org/EvidentSecurity/esp_sdk)
2
+ [![Code Climate](https://codeclimate.com/repos/546a526f6956800d2900e3fb/badges/841000b5295e533401c3/gpa.svg)](https://codeclimate.com/repos/546a526f6956800d2900e3fb/feed)
3
+ [![Test Coverage](https://codeclimate.com/repos/546a526f6956800d2900e3fb/badges/841000b5295e533401c3/coverage.svg)](https://codeclimate.com/repos/546a526f6956800d2900e3fb/feed)
4
+
5
+ # EspSdk
6
+
7
+ Ruby SDK for Evident.io API. Version 1.0.0 has a full test suite.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'esp_sdk'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install esp_sdk
22
+
23
+ ## Usage
24
+
25
+ ## Constructor
26
+
27
+ # Required :password, :email
28
+ # Optional :version
29
+ # Default and current version 'v1'
30
+ api = EspSdk::Api.new(email: 'me@google.com', password: 'password', version: 'optional')
31
+
32
+ ## Configuration
33
+
34
+ api.config => #<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>
35
+
36
+ # Authorization token
37
+ api.config.token => "6_4wys1a2FhqsECstavC"
38
+
39
+ # Token expiration. ActiveSupport::TimeWithZone
40
+ api.config.token_expires_at => Fri, 19 Sep 2014 15:39:10 UTC +00:00
41
+
42
+ # Authorization email
43
+ api.config.email => "me@gmail.com"
44
+
45
+ ## End points array
46
+
47
+ # Current and all endpoints in a single array
48
+
49
+ api.end_points =>
50
+ [
51
+ [0] #<EspSdk::EndPoints::Reports:0x000001019bc498 @config=#<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>,
52
+ [1] #<EspSdk::EndPoints::Users:0x000001019bc038 @config=#<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>,
53
+ [2] #<EspSdk::EndPoints::ExternalAccounts:0x000001028a3ab0 @config=#<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>,
54
+ [3] #<EspSdk::EndPoints::CustomSignatures:0x000001028a3560 @config=#<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>,
55
+ [4] #<EspSdk::EndPoints::Organizations:0x000001028a3100 @config=#<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>,
56
+ [5] #<EspSdk::EndPoints::SubOrganizations:0x000001028a2bb0 @config=#<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>,
57
+ [6] #<EspSdk::EndPoints::Teams:0x000001028a2750 @config=#<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>,
58
+ [7] #<EspSdk::EndPoints::Signatures:0x000001028a22f0 @config=#<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>,
59
+ [8] #<EspSdk::EndPoints::Dashboard:0x000001028a1e90 @config=#<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>,
60
+ [9] #<EspSdk::EndPoints::ContactRequests:0x000001028a1940 @config=#<EspSdk::Configure:0x00000102890f28 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>
61
+ [10] #<EspSdk::EndPoints::Services:0x000001031949f8 @config=#<EspSdk::Configure:0x000001010880e8 @email="me@gmail.com", @version="v1", @uri="https://api.evident.io/api", @token="6_4wys1a2FhqsECstavC", @token_expires_at=Fri, 19 Sep 2014 15:39:10 UTC +00:00>>
62
+ ]
63
+
64
+ ## Reports end point
65
+ ### List action
66
+ # List action is a pageable response with a total of 5 reports per page.
67
+ api.reports.list =>
68
+ {
69
+ "id" => 130,
70
+ "created_at" => "2014-08-06T19:59:57.540Z",
71
+ "team" => "Evident"
72
+ }
73
+
74
+ # Current page
75
+ api.reports.current_page
76
+
77
+ # Next page sets current_page with the next page results.
78
+ api.reports.next_page
79
+
80
+ # Previous page sets current_page with the previous page results.
81
+ api.reports.prev_page
82
+
83
+ ### Show action
84
+ # Show a specific report
85
+ # Required :id
86
+ api.reports.show(id: 130) =>
87
+ {
88
+ "report" => 130,
89
+ "created_at" => "2014-08-06T19:59:57.540Z",
90
+ "team" => "Evident",
91
+ "alerts" => [
92
+ [ 0] {
93
+ "signature" => "Sss Global Any Bucket Permissions",
94
+ "status" => "fail",
95
+ "region" => "us_east_1",
96
+ "external_account" => "Development",
97
+ "identifier" => "AWS:SSS-008",
98
+ "risk_level" => "Low",
99
+ "service" => "SSS",
100
+ "description" => "Check if S3 buckets have any global permissions enabled",
101
+ "resolution" => "This signature is under active development.",
102
+ "related_information" => {
103
+ "message" => "A permission is granted to Everyone on the 'evident-prod' bucket",
104
+ "bucket" => "evident-prod",
105
+ "deep_inspection" => nil
106
+ }
107
+ },
108
+ }
109
+
110
+ # Current record shows the current record
111
+ api.reports.current_record
112
+
113
+ ## Dashboard end point
114
+
115
+ ### List action
116
+
117
+ # List your current dashboard stats
118
+ api.dashboard.list =>
119
+ {
120
+ "enterprise" => true,
121
+ "teams" => [
122
+ [0] {
123
+ "report" => {
124
+ "name" => "Evident",
125
+ "team_id" => 1,
126
+ "sub_organization" => "Evident",
127
+ "created_at" => "2014-08-06T19:59:57.540Z",
128
+ "report_id" => 130,
129
+ "stats" => {
130
+ "total" => 196,
131
+ "regions" => [
132
+ [0] {
133
+ "code" => "ap_northeast_1",
134
+ "region_id" => 1,
135
+ "total" => 2,
136
+ "pass" => 5,
137
+ "high" => 1,
138
+ "medium" => 1,
139
+ "low" => 0
140
+ },
141
+ [1] {
142
+ "code" => "ap_southeast_1",
143
+ "region_id" => 2,
144
+ "total" => 2,
145
+ "pass" => 6,
146
+ "high" => 1,
147
+ "medium" => 1,
148
+ "low" => 0
149
+ },
150
+ [2] {
151
+ "code" => "eu_west_1",
152
+ "region_id" => 4,
153
+ "total" => 2,
154
+ "pass" => 5,
155
+ "high" => 1,
156
+ "medium" => 1,
157
+ "low" => 0
158
+ },
159
+ [3] {
160
+ "code" => "sa_east_1",
161
+ "region_id" => 5,
162
+ "total" => 2,
163
+ "pass" => 5,
164
+ "high" => 1,
165
+ "medium" => 1,
166
+ "low" => 0
167
+ },
168
+ [4] {
169
+ "code" => "ap_southeast_2",
170
+ "region_id" => 3,
171
+ "total" => 2,
172
+ "pass" => 5,
173
+ "high" => 1,
174
+ "medium" => 1,
175
+ "low" => 0
176
+ },
177
+ [5] {
178
+ "code" => "us_west_1",
179
+ "region_id" => 7,
180
+ "total" => 2,
181
+ "pass" => 5,
182
+ "high" => 1,
183
+ "medium" => 1,
184
+ "low" => 0
185
+ },
186
+ [6] {
187
+ "code" => "us_west_2",
188
+ "region_id" => 8,
189
+ "total" => 1,
190
+ "pass" => 7,
191
+ "high" => 0,
192
+ "medium" => 1,
193
+ "low" => 0
194
+ },
195
+ [7] {
196
+ "code" => "global",
197
+ "region_id" => 9,
198
+ "total" => 7,
199
+ "pass" => 13,
200
+ "high" => 1,
201
+ "medium" => 6,
202
+ "low" => 0
203
+ },
204
+ [8] {
205
+ "code" => "us_east_1",
206
+ "region_id" => 6,
207
+ "total" => 45,
208
+ "pass" => 80,
209
+ "high" => 0,
210
+ "medium" => 22,
211
+ "low" => 23
212
+ }
213
+ ],
214
+ "signatures" => [
215
+ [ 0] {
216
+ "signature_id" => 86,
217
+ "unique_id" => "AWS:EC2-030",
218
+ "total" => 2
219
+ },
220
+ [ 1] {
221
+ "signature_id" => 22,
222
+ "unique_id" => "AWS:VPC-009",
223
+ "total" => 6
224
+ },
225
+ [ 2] {
226
+ "signature_id" => 77,
227
+ "unique_id" => "AWS:ELB-001",
228
+ "total" => 6
229
+ },
230
+ [ 3] {
231
+ "signature_id" => 76,
232
+ "unique_id" => "AWS:EC2-032",
233
+ "total" => 21
234
+ },
235
+ [ 4] {
236
+ "signature_id" => 75,
237
+ "unique_id" => "AWS:EC2-031",
238
+ "total" => 8
239
+ },
240
+ [ 5] {
241
+ "signature_id" => 92,
242
+ "unique_id" => "AWS:ELB-007",
243
+ "total" => 1
244
+ },
245
+ [ 6] {
246
+ "signature_id" => 78,
247
+ "unique_id" => "AWS:IAM-008",
248
+ "total" => 1
249
+ },
250
+ [ 7] {
251
+ "signature_id" => 90,
252
+ "unique_id" => "AWS:SSS-006",
253
+ "total" => 1
254
+ },
255
+ [ 8] {
256
+ "signature_id" => 89,
257
+ "unique_id" => "AWS:SSS-007",
258
+ "total" => 1
259
+ },
260
+ [ 9] {
261
+ "signature_id" => 17,
262
+ "unique_id" => "AWS:EC2-001",
263
+ "total" => 17
264
+ },
265
+ [10] {
266
+ "signature_id" => 88,
267
+ "unique_id" => "AWS:SSS-008",
268
+ "total" => 1
269
+ }
270
+ ],
271
+ "services" => [
272
+ [0] {
273
+ "service" => "VPC",
274
+ "total" => 6,
275
+ "service_id" => 8
276
+ },
277
+ [1] {
278
+ "service" => "ELB",
279
+ "total" => 7,
280
+ "service_id" => 7
281
+ },
282
+ [2] {
283
+ "service" => "IAM",
284
+ "total" => 1,
285
+ "service_id" => 2
286
+ },
287
+ [3] {
288
+ "service" => "EC2",
289
+ "total" => 48,
290
+ "service_id" => 5
291
+ },
292
+ [4] {
293
+ "service" => "SSS",
294
+ "total" => 3,
295
+ "service_id" => 4
296
+ }
297
+ ],
298
+ "severities" => [
299
+ [0] {
300
+ "severity" => "medium",
301
+ "total" => 35
302
+ },
303
+ [1] {
304
+ "severity" => "high",
305
+ "total" => 7
306
+ },
307
+ [2] {
308
+ "severity" => "pass",
309
+ "total" => 131
310
+ },
311
+ [3] {
312
+ "severity" => "low",
313
+ "total" => 23
314
+ }
315
+ ]
316
+ }
317
+ }
318
+ }
319
+ ]
320
+ }
321
+
322
+ ### Timewarp action
323
+ #### This endpoint is used for returning dashboard stats at a specific hour in the past
324
+ # Required params: time: => '1413999010' Unix Time
325
+ # The time is floored and has five minutes subtracted. Then adds an hour for the end time. Any reports between that hour will have their stats returned.
326
+ # EX:
327
+ # start_time = DateTime.strptime('1413999010','%s').at_beginning_of_hour - 5.minutes
328
+ # end_time = start_time + 1.hour
329
+ api.dashboard.timewarp(time: '1413999010') =>
330
+ {
331
+ "enterprise" => false,
332
+ "teams" => [
333
+ [0] {
334
+ "name" => "Default Team",
335
+ "team_id" => 1,
336
+ "sub_organization" => "Default Sub Organization",
337
+ "created_at" => "2014-10-22T17:30:10.086Z",
338
+ "report_id" => 5,
339
+ "stats" => {
340
+ "total" => 356,
341
+ "regions" => [
342
+ [0] {
343
+ "code" => "global",
344
+ "region_id" => 9,
345
+ "total" => 23,
346
+ "pass" => 22,
347
+ "high" => 1,
348
+ "medium" => 22,
349
+ "low" => 0
350
+ },
351
+ [1] {
352
+ "code" => "us_east_1",
353
+ "region_id" => 6,
354
+ "total" => 139,
355
+ "pass" => 105,
356
+ "high" => 0,
357
+ "medium" => 67,
358
+ "low" => 72
359
+ },
360
+ [2] {
361
+ "code" => "eu_west_1",
362
+ "region_id" => 4,
363
+ "total" => 3,
364
+ "pass" => 6,
365
+ "high" => 2,
366
+ "medium" => 1,
367
+ "low" => 0
368
+ },
369
+ [3] {
370
+ "code" => "ap_northeast_1",
371
+ "region_id" => 1,
372
+ "total" => 3,
373
+ "pass" => 6,
374
+ "high" => 2,
375
+ "medium" => 1,
376
+ "low" => 0
377
+ },
378
+ [4] {
379
+ "code" => "us_west_1",
380
+ "region_id" => 7,
381
+ "total" => 3,
382
+ "pass" => 6,
383
+ "high" => 2,
384
+ "medium" => 1,
385
+ "low" => 0
386
+ },
387
+ [5] {
388
+ "code" => "ap_southeast_1",
389
+ "region_id" => 2,
390
+ "total" => 3,
391
+ "pass" => 7,
392
+ "high" => 2,
393
+ "medium" => 1,
394
+ "low" => 0
395
+ },
396
+ [6] {
397
+ "code" => "us_west_2",
398
+ "region_id" => 8,
399
+ "total" => 2,
400
+ "pass" => 10,
401
+ "high" => 1,
402
+ "medium" => 1,
403
+ "low" => 0
404
+ },
405
+ [7] {
406
+ "code" => "sa_east_1",
407
+ "region_id" => 5,
408
+ "total" => 3,
409
+ "pass" => 6,
410
+ "high" => 2,
411
+ "medium" => 1,
412
+ "low" => 0
413
+ },
414
+ [8] {
415
+ "code" => "ap_southeast_2",
416
+ "region_id" => 3,
417
+ "total" => 3,
418
+ "pass" => 6,
419
+ "high" => 2,
420
+ "medium" => 1,
421
+ "low" => 0
422
+ }
423
+ ],
424
+ "signatures" => [
425
+ [ 0] {
426
+ "signature_id" => 88,
427
+ "unique_id" => "AWS:SSS-006",
428
+ "total" => 1
429
+ },
430
+ [ 1] {
431
+ "signature_id" => 89,
432
+ "unique_id" => "AWS:SSS-008",
433
+ "total" => 1
434
+ },
435
+ [ 2] {
436
+ "signature_id" => 87,
437
+ "unique_id" => "AWS:SSS-007",
438
+ "total" => 1
439
+ },
440
+ [ 3] {
441
+ "signature_id" => 14,
442
+ "unique_id" => "AWS:EC2-001",
443
+ "total" => 21
444
+ },
445
+ [ 4] {
446
+ "signature_id" => 70,
447
+ "unique_id" => "AWS:SSS-001",
448
+ "total" => 1
449
+ },
450
+ [ 5] {
451
+ "signature_id" => 72,
452
+ "unique_id" => "AWS:CLT-001",
453
+ "total" => 7
454
+ },
455
+ [ 6] {
456
+ "signature_id" => 69,
457
+ "unique_id" => "AWS:EC2-031",
458
+ "total" => 44
459
+ },
460
+ [ 7] {
461
+ "signature_id" => 18,
462
+ "unique_id" => "AWS:VPC-009",
463
+ "total" => 6
464
+ },
465
+ [ 8] {
466
+ "signature_id" => 68,
467
+ "unique_id" => "AWS:IAM-008",
468
+ "total" => 1
469
+ },
470
+ [ 9] {
471
+ "signature_id" => 82,
472
+ "unique_id" => "AWS:ELB-007",
473
+ "total" => 43
474
+ },
475
+ [10] {
476
+ "signature_id" => 81,
477
+ "unique_id" => "AWS:SSS-003",
478
+ "total" => 1
479
+ },
480
+ [11] {
481
+ "signature_id" => 80,
482
+ "unique_id" => "AWS:ELB-001",
483
+ "total" => 8
484
+ },
485
+ [12] {
486
+ "signature_id" => 11,
487
+ "unique_id" => "AWS:IAM-007",
488
+ "total" => 14
489
+ },
490
+ [13] {
491
+ "signature_id" => 83,
492
+ "unique_id" => "AWS:ELB-008",
493
+ "total" => 4
494
+ },
495
+ [14] {
496
+ "signature_id" => 77,
497
+ "unique_id" => "AWS:RDS-002",
498
+ "total" => 2
499
+ },
500
+ [15] {
501
+ "signature_id" => 67,
502
+ "unique_id" => "AWS:EC2-032",
503
+ "total" => 24
504
+ },
505
+ [16] {
506
+ "signature_id" => 1,
507
+ "unique_id" => "AWS:EC2-030",
508
+ "total" => 3
509
+ }
510
+ ],
511
+ "services" => [
512
+ [0] {
513
+ "service" => "RDS",
514
+ "total" => 2,
515
+ "service_id" => 10
516
+ },
517
+ [1] {
518
+ "service" => "ELB",
519
+ "total" => 55,
520
+ "service_id" => 8
521
+ },
522
+ [2] {
523
+ "service" => "IAM",
524
+ "total" => 15,
525
+ "service_id" => 3
526
+ },
527
+ [3] {
528
+ "service" => "VPC",
529
+ "total" => 6,
530
+ "service_id" => 7
531
+ },
532
+ [4] {
533
+ "service" => "CLT",
534
+ "total" => 7,
535
+ "service_id" => 9
536
+ },
537
+ [5] {
538
+ "service" => "EC2",
539
+ "total" => 92,
540
+ "service_id" => 1
541
+ },
542
+ [6] {
543
+ "service" => "SSS",
544
+ "total" => 5,
545
+ "service_id" => 5
546
+ }
547
+ ],
548
+ "severities" => [
549
+ [0] {
550
+ "severity" => "high",
551
+ "total" => 14
552
+ },
553
+ [1] {
554
+ "severity" => "medium",
555
+ "total" => 96
556
+ },
557
+ [2] {
558
+ "severity" => "low",
559
+ "total" => 72
560
+ },
561
+ [3] {
562
+ "severity" => "pass",
563
+ "total" => 174
564
+ }
565
+ ]
566
+ }
567
+ }
568
+ ]
569
+ }
570
+
571
+
572
+ ## Services end point
573
+ #### *Note this end point is a read only end point, and requires the user to have manager role access
574
+ #### This end point can be used to for retrieving a service id to apply to a custom signature. Example your custom signature targets EC2 services.
575
+ ### List action
576
+ # list is a pageable response of 25 total signatures per page
577
+ api.services.list =>
578
+ [
579
+ [ 4] {
580
+ "id" => 5,
581
+ "name" => "EC2",
582
+ "code" => "EC2",
583
+ "created_at" => "2014-07-15T16:45:43.457Z",
584
+ "updated_at" => "2014-07-15T16:45:43.457Z"
585
+ }
586
+ ]
587
+
588
+ ### Show action
589
+ # Show a specific signature
590
+ # Required :id
591
+
592
+ api.show(id: 5) =>
593
+ {
594
+ "id" => 5,
595
+ "name" => "EC2",
596
+ "code" => "EC2",
597
+ "created_at" => "2014-07-15T16:45:43.457Z",
598
+ "updated_at" => "2014-07-15T16:45:43.457Z"
599
+ }
600
+
601
+
602
+
603
+ ## Custom Signatures end point
604
+ ### List action
605
+ # List is a pageable response of 25 total signatures per page
606
+ api.custom_signatures.list =>
607
+ [
608
+ [ 0] {
609
+ "id" => 4,
610
+ "organization_id" => 1,
611
+ "signature" => "// Demo Signature\r\ndsl.configure(function(c) {\r\n c.module = 'check_user_count_javascript'; // Required\r\n c.identifier = 'AWS:GLO-001'; // Required unique identifier for this signature\r\n c.description = 'Check IAM user count'; // Required short description\r\n c.valid_regions = ['us_east_1']; // Only run in us_east_1\r\n c.display_as = 'global'; // Display as region global instead of region us_east_1\r\n});\r\n\r\n// Required perform function\r\nfunction perform(aws) {\r\n try {\r\n var count = aws.iam.list_users().users.length || 0;\r\n if (count === 0) {\r\n return dsl.fail({\r\n user_count: count,\r\n condition: 'count == 0' });\r\n } else {\r\n return dsl.pass({\r\n user_count: count,\r\n condition: 'count >= 1' });\r\n }\r\n }\r\n catch(err) {\r\n return dsl.error({error: err.message});\r\n }\r\n}\r\n",
612
+ "description" => "test",
613
+ "resolution" => "test",
614
+ "name" => "Testing",
615
+ "active" => true,
616
+ "created_at" => "2014-07-21T20:09:24.809Z",
617
+ "updated_at" => "2014-08-04T14:15:28.326Z",
618
+ "risk_level" => "High",
619
+ "identifier" => nil,
620
+ "service_id" => nil,
621
+ "deleted_at" => nil
622
+ }
623
+ }
624
+
625
+ # Current page
626
+ api.custom_signatures.current_page
627
+
628
+ # Next page sets current page with the next page results.
629
+ api.custom_signatures.next_page
630
+
631
+ # Prev page sets current page with the previous page results.
632
+ api.custom_signatures.prev_page
633
+
634
+ ### Show action
635
+ # Show a specific custom signature
636
+ # Required :id
637
+
638
+ api.custom_signatures.show(id: 4) =>
639
+ {
640
+ "id" => 4,
641
+ "organization_id" => 1,
642
+ "signature" => "// Demo Signature\r\ndsl.configure(function(c) {\r\n c.module = 'check_user_count_javascript'; // Required\r\n c.identifier = 'AWS:GLO-001'; // Required unique identifier for this signature\r\n c.description = 'Check IAM user count'; // Required short description\r\n c.valid_regions = ['us_east_1']; // Only run in us_east_1\r\n c.display_as = 'global'; // Display as region global instead of region us_east_1\r\n});\r\n\r\n// Required perform function\r\nfunction perform(aws) {\r\n try {\r\n var count = aws.iam.list_users().users.length || 0;\r\n if (count === 0) {\r\n return dsl.fail({\r\n user_count: count,\r\n condition: 'count == 0' });\r\n } else {\r\n return dsl.pass({\r\n user_count: count,\r\n condition: 'count >= 1' });\r\n }\r\n }\r\n catch(err) {\r\n return dsl.error({error: err.message});\r\n }\r\n}\r\n",
643
+ "description" => "test",
644
+ "resolution" => "test",
645
+ "name" => "Testing",
646
+ "active" => true,
647
+ "created_at" => "2014-07-21T20:09:24.809Z",
648
+ "updated_at" => "2014-08-04T14:15:28.326Z",
649
+ "risk_level" => "High",
650
+ "identifier" => nil,
651
+ "service_id" => 11,
652
+ "deleted_at" => nil
653
+ }
654
+
655
+ ### Update action
656
+ # Update a custom signature
657
+ # Required :id
658
+ # Valid :description, :resolution, :name, :active, :signature, :risk_level
659
+ api.custom_signatures.update(id: 4, active: false, name: 'Updated Name') =>
660
+ {
661
+ "id" => 4,
662
+ "organization_id" => 1,
663
+ "signature" => "// Demo Signature\r\ndsl.configure(function(c) {\r\n c.module = 'check_user_count_javascript'; // Required\r\n c.identifier = 'AWS:GLO-001'; // Required unique identifier for this signature\r\n c.description = 'Check IAM user count'; // Required short description\r\n c.valid_regions = ['us_east_1']; // Only run in us_east_1\r\n c.display_as = 'global'; // Display as region global instead of region us_east_1\r\n c.deep_inspection = ['users'];\r\n c.unique_identifier = [{'user_name': 'user_id'}];\r\n});\r\n\r\n// Required perform function\r\nfunction perform(aws) {\r\n try {\r\n var count = aws.iam.list_users().users.length || 0;\r\n \r\n // Setup the deep inspection and unique identifier data\r\n dsl.set_data(aws.iam.list_users());\r\n if (count === 0) {\r\n return dsl.fail({\r\n user_count: count,\r\n condition: 'count == 0' });\r\n } else {\r\n return dsl.pass({\r\n user_count: count,\r\n condition: 'count >= 1' });\r\n }\r\n }\r\n catch(err) {\r\n return dsl.error({error: err.message});\r\n }\r\n}",
664
+ "description" => "test",
665
+ "resolution" => "test",
666
+ "name" => "Updated Name",
667
+ "active" => false,
668
+ "created_at" => "2014-07-21T20:09:24.809Z",
669
+ "updated_at" => "2014-09-24T20:48:21.822Z",
670
+ "risk_level" => "High",
671
+ "identifier" => nil,
672
+ "service_id" => 11,
673
+ "deleted_at" => nil
674
+ }
675
+
676
+ ### Create Action
677
+ # Create a new custom signature
678
+ # Required :signature, :name, :risk_level
679
+ signature = "// Demo Signature\r\ndsl.configure(function(c) {\r\n c.module = 'check_user_count_javascript'; // Required\r\n c.identifier = 'AWS:GLO-001'; // Required unique identifier for this signature\r\n c.description = 'Check IAM user count'; // Required short description\r\n c.valid_regions = ['us_east_1']; // Only run in us_east_1\r\n c.display_as = 'global'; // Display as region global instead of region us_east_1\r\n c.deep_inspection = ['users'];\r\n c.unique_identifier = [{'user_name': 'user_id'}];\r\n});\r\n\r\n// Required perform function\r\nfunction perform(aws) {\r\n try {\r\n var count = aws.iam.list_users().users.length || 0;\r\n \r\n // Setup the deep inspection and unique identifier data\r\n dsl.set_data(aws.iam.list_users());\r\n if (count === 0) {\r\n return dsl.fail({\r\n user_count: count,\r\n condition: 'count == 0' });\r\n } else {\r\n return dsl.pass({\r\n user_count: count,\r\n condition: 'count >= 1' });\r\n }\r\n }\r\n catch(err) {\r\n return dsl.error({error: err.message});\r\n }\r\n}"
680
+ api.custom_signatures.create(signature: signature, name: 'Demo Signature', risk_level: 'High') =>
681
+ {
682
+ "id" => 97,
683
+ "organization_id" => 1,
684
+ "signature" => "// Demo Signature\r\ndsl.configure(function(c) {\r\n c.module = 'check_user_count_javascript'; // Required\r\n c.identifier = 'AWS:GLO-001'; // Required unique identifier for this signature\r\n c.description = 'Check IAM user count'; // Required short description\r\n c.valid_regions = ['us_east_1']; // Only run in us_east_1\r\n c.display_as = 'global'; // Display as region global instead of region us_east_1\r\n c.deep_inspection = ['users'];\r\n c.unique_identifier = [{'user_name': 'user_id'}];\r\n});\r\n\r\n// Required perform function\r\nfunction perform(aws) {\r\n try {\r\n var count = aws.iam.list_users().users.length || 0;\r\n \r\n // Setup the deep inspection and unique identifier data\r\n dsl.set_data(aws.iam.list_users());\r\n if (count === 0) {\r\n return dsl.fail({\r\n user_count: count,\r\n condition: 'count == 0' });\r\n } else {\r\n return dsl.pass({\r\n user_count: count,\r\n condition: 'count >= 1' });\r\n }\r\n }\r\n catch(err) {\r\n return dsl.error({error: err.message});\r\n }\r\n}",
685
+ "description" => nil,
686
+ "resolution" => nil,
687
+ "name" => "Demo Signature",
688
+ "active" => nil,
689
+ "created_at" => "2014-09-24T20:51:08.901Z",
690
+ "updated_at" => "2014-09-24T20:51:08.901Z",
691
+ "risk_level" => "High",
692
+ "identifier" => nil,
693
+ "service_id" => 11,
694
+ "deleted_at" => nil
695
+ }
696
+
697
+ ### Destroy Action
698
+ # Destroy a custom signature
699
+ # Required :id
700
+ api.custom_signatures.destroy(id: 97) =>
701
+ {
702
+ "success" => "Demo Signature has been destroyed"
703
+ }
704
+
705
+ ### Run action
706
+ # Run a custom signature
707
+ # Required :id => ID of the custom signature to run
708
+ # Required :external_account_id => ID of the external account to use
709
+ # Required :regions => Array of regions to run the signature in
710
+
711
+ api.custom_signatures.run(id: 1, external_account_id: 1, regions: [:us_east_1]) =>
712
+ {
713
+ "alerts" => [
714
+ [0] {
715
+ "info" => {
716
+ "user_count" => 1,
717
+ "condition" => "count >= 1",
718
+ "deep_inspection" => [
719
+ [0] {
720
+ "users" => [
721
+ [ 0] {
722
+ "path" => "/",
723
+ "user_name" => "demouser",
724
+ "user_id" => "AIDAHJFKDHGFHFGKHKGFH",
725
+ "arn" => "arn:aws:iam::00000000:user/demouser",
726
+ "create_date" => "2014-01-16T19:05:36.000Z"
727
+ }
728
+ ]
729
+ }
730
+ ]
731
+ },
732
+ "status" => "pass",
733
+ "config" => {
734
+ "module" => "check_user_count_javascript",
735
+ "description" => "Check IAM user count",
736
+ "valid_regions" => [
737
+ [0] "us_east_1"
738
+ ],
739
+ "identifier" => "AWS:GLO-001",
740
+ "deep_inspection" => [
741
+ [0] "users"
742
+ ],
743
+ "unique_identifier" => [
744
+ [0] {
745
+ "user_name" => "user_id"
746
+ }
747
+ ],
748
+ "display_as" => "global",
749
+ "validation_context" => nil,
750
+ "errors" => {}
751
+ },
752
+ "region" => "us_east_1",
753
+ "unique_identifier" => {
754
+ "demouser" => "AIDAHJFKDHGFHFGKHKGFH",
755
+ }
756
+ }
757
+ ]
758
+ }
759
+
760
+ ### Run Raw action
761
+ # Run a raw custom signature
762
+ # Required: :signature => JavaScript signature to run as a string
763
+ # Required :external_account_id => ID of the external account to use
764
+ # Required :regions => Array of regions to run the signature in
765
+ api.custom_signatures.run_raw(signature: "Javascript", regions: [:us_east_1], external_account_id: 1) =>
766
+ {
767
+ "alerts" => [
768
+ [0] {
769
+ "info" => {
770
+ "user_count" => 1,
771
+ "condition" => "count >= 1",
772
+ "deep_inspection" => [
773
+ [0] {
774
+ "users" => [
775
+ [ 0] {
776
+ "path" => "/",
777
+ "user_name" => "demouser",
778
+ "user_id" => "AIDAHJFKDHGFHFGKHKGFH",
779
+ "arn" => "arn:aws:iam::00000000:user/demouser",
780
+ "create_date" => "2014-01-16T19:05:36.000Z"
781
+ }
782
+ ]
783
+ }
784
+ ]
785
+ },
786
+ "status" => "pass",
787
+ "config" => {
788
+ "module" => "check_user_count_javascript",
789
+ "description" => "Check IAM user count",
790
+ "valid_regions" => [
791
+ [0] "us_east_1"
792
+ ],
793
+ "identifier" => "AWS:GLO-001",
794
+ "deep_inspection" => [
795
+ [0] "users"
796
+ ],
797
+ "unique_identifier" => [
798
+ [0] {
799
+ "user_name" => "user_id"
800
+ }
801
+ ],
802
+ "display_as" => "global",
803
+ "validation_context" => nil,
804
+ "errors" => {}
805
+ },
806
+ "region" => "us_east_1",
807
+ "unique_identifier" => {
808
+ "demouser" => "AIDAHJFKDHGFHFGKHKGFH",
809
+ }
810
+ }
811
+ ]
812
+ }
813
+
814
+
815
+ ## Signatures end point
816
+ ### List action
817
+ # List is a pageable response of 25 total signatures per page.
818
+ api.signatures.list =>
819
+ [
820
+ [ 0] {
821
+ "id" => 35,
822
+ "name" => "Global Telnet",
823
+ "description" => "Globally Accessible Administrative Port -- Telnet (tcp/23)",
824
+ "provider" => "AWS",
825
+ "scope" => "Service",
826
+ "resolution" => "This alert triggers when global permission to access tcp port 23 (telnet) is detected in a security group. This is dangerous, as it permits the entire internet access to connect to tcp port 23 -- usually where a telnet daemon is listening. Reducing the permitted IP Addresses or ranges allowed to communicate to destination hosts on tcp port 23 is advised. We recommend utilizing the static office or home IP addresses of your employees as the permitted hosts, or deploying a bastion host with 2-factor authentication if this is infeasible. This bastion host is then the only permitted IP to communicate with any other nodes inside your account. If you must permit global access to tcp port 23 (telnet), then you may disable this alert to silence it.",
827
+ "risk_level" => "High",
828
+ "identifier" => "AWS:EC2-003",
829
+ "created_at" => "2014-06-23T18:53:25.988Z",
830
+ "updated_at" => "2014-07-21T16:36:29.427Z",
831
+ "service_id" => 5,
832
+ "service" => {
833
+ "name" => "EC2"
834
+ }
835
+ },
836
+ ]
837
+
838
+ # Current page
839
+ api.signatures.current_page
840
+
841
+ # Next page sets current page with the next page results.
842
+ api.signatures.next_page
843
+
844
+ # Prev page sets current page with the previous page results.
845
+ api.signatures.prev_page
846
+
847
+ ### Show action
848
+ # Show a specific signature
849
+ # Required :id
850
+ api.signatures.show(id: 35) =>
851
+ {
852
+ "id" => 35,
853
+ "name" => "Global Telnet",
854
+ "description" => "Globally Accessible Administrative Port -- Telnet (tcp/23)",
855
+ "provider" => "AWS",
856
+ "scope" => "Service",
857
+ "resolution" => "This alert triggers when global permission to access tcp port 23 (telnet) is detected in a security group. This is dangerous, as it permits the entire internet access to connect to tcp port 23 -- usually where a telnet daemon is listening. Reducing the permitted IP Addresses or ranges allowed to communicate to destination hosts on tcp port 23 is advised. We recommend utilizing the static office or home IP addresses of your employees as the permitted hosts, or deploying a bastion host with 2-factor authentication if this is infeasible. This bastion host is then the only permitted IP to communicate with any other nodes inside your account. If you must permit global access to tcp port 23 (telnet), then you may disable this alert to silence it.",
858
+ "risk_level" => "High",
859
+ "identifier" => "AWS:EC2-003",
860
+ "created_at" => "2014-06-23T18:53:25.988Z",
861
+ "updated_at" => "2014-07-21T16:36:29.427Z",
862
+ "service_id" => 5,
863
+ "service" => {
864
+ "name" => "EC2"
865
+ }
866
+ }
867
+
868
+ ### Names action
869
+
870
+ # List the names of signatures that can be run through the api
871
+ api.signatures.names =>
872
+ {
873
+ "names" => [
874
+ [ 0] "validate_cloud_formation_template",
875
+ [ 1] "cloud_trails_enabled",
876
+ [ 2] "frequent_snapshots",
877
+ [ 3] "security_group_check",
878
+ [ 4] "detect_unattached_ebs_volumes",
879
+ [ 5] "unused_security_groups",
880
+ [ 6] "ebs_encryption_enabled",
881
+ [ 7] "security_group_instance_map",
882
+ [ 8] "strong_ssl_ciphers",
883
+ [ 9] "heartbleed",
884
+ [10] "unused_security_groups_elb",
885
+ [11] "check_user_count",
886
+ [12] "api_keys_on_root",
887
+ [13] "one_user_with_api_keys",
888
+ [14] "user_console_access_strong_password",
889
+ [15] "mfa_on_root",
890
+ [16] "mfa_on_devices",
891
+ [17] "check_assigned_role",
892
+ [18] "third_party_account",
893
+ [19] "key_expiry_check",
894
+ [20] "count_privileged_users",
895
+ [21] "check_privileged_spofs",
896
+ [22] "restrict_s3_delete",
897
+ [23] "evident_role_permissions",
898
+ [24] "route53_in_use",
899
+ [25] "rds_backup_policy_too_short",
900
+ [26] "latest_restorable_time",
901
+ [27] "sss_object_versioning_enabled",
902
+ [28] "cloud_trails_bucket_iam_delete",
903
+ [29] "sss_global_edit_bucket_permissions",
904
+ [30] "sss_global_upload_bucket_permissions",
905
+ [31] "sss_global_list_bucket_permissions",
906
+ [32] "sss_global_view_bucket_permissions",
907
+ [33] "sss_global_any_bucket_permissions",
908
+ [34] "vpc_nacls",
909
+ [35] "nacls_on_subnets",
910
+ [36] "non_default_vpc_nacl"
911
+ ]
912
+ }
913
+
914
+ ### Run action
915
+
916
+ # Run an Evident Signature
917
+ Required :signature_name => name of signature to run
918
+ Required :external_account_id => ID of the external account with the ARN/External ID to use
919
+ Required :regions => Array of regions to run the signature in
920
+ # Requires manager role access
921
+
922
+ api.signatures.run(signature_name: 'validate_cloud_formation_template', regions: [:us_east_1], external_account_id: 1)
923
+ {
924
+ "alerts" => [
925
+ [0] {
926
+ "info" => {
927
+ "message" => "No CloudFormation template contains globally permissive traffic",
928
+ "deep_inspection" => nil
929
+ },
930
+ "status" => "pass",
931
+ "config" => {
932
+ "module" => "validate_cloud_formation_template",
933
+ "description" => "Validate security parameters in CloudFormation templates",
934
+ "valid_regions" => [
935
+ [0] "us_east_1"
936
+ ],
937
+ "identifier" => "AWS:CFM-001",
938
+ "usage" => "metascrape.signatures.validate_cloud_formation_template.perform metascrape.customers.evident.aws.us_east_1",
939
+ "tags" => [
940
+ [0] "cfm",
941
+ [1] "signature"
942
+ ],
943
+ "tests" => [
944
+ [0] "test_validate_cloud_formation_template"
945
+ ],
946
+ "validation_context" => nil,
947
+ "errors" => {}
948
+ },
949
+ "region" => "us_east_1",
950
+ "unique_identifier" => nil
951
+ }
952
+ ]
953
+ }
954
+
955
+ ## Organizations end point
956
+
957
+ ### List Action
958
+ # List your organizations information
959
+ api.organizations.list =>
960
+ [
961
+ [0] {
962
+ "id" => 1,
963
+ "name" => "Evident",
964
+ "created_at" => "2014-06-23T18:53:25.500Z",
965
+ "updated_at" => "2014-07-15T18:40:30.451Z",
966
+ "external_account_setup_complete" => true,
967
+ "encrypted_stripe_customer_identifier" => nil,
968
+ "enterprise" => true,
969
+ "enterprise_contract_expires_on" => "2034-06-23",
970
+ "plan_id" => 7,
971
+ "stripe_last_payment_successful" => true,
972
+ "stripe_subscription_active" => true,
973
+ "deleted_at" => nil,
974
+ "free_trial_expires_at" => nil,
975
+ "plan_setup_complete" => true,
976
+ "enable_sso" => false,
977
+ "sso_idp_id" => nil
978
+ }
979
+ ]
980
+
981
+ ### Show action
982
+ # Show your organizations information. Same as List just returns the object instead of an array with the object.
983
+ # Required :id
984
+ api.organizations.show(id: 1) =>
985
+ {
986
+ "id" => 1,
987
+ "name" => "Evident",
988
+ "created_at" => "2014-06-23T18:53:25.500Z",
989
+ "updated_at" => "2014-07-15T18:40:30.451Z",
990
+ "external_account_setup_complete" => true,
991
+ "encrypted_stripe_customer_identifier" => nil,
992
+ "enterprise" => true,
993
+ "enterprise_contract_expires_on" => "2034-06-23",
994
+ "plan_id" => 7,
995
+ "stripe_last_payment_successful" => true,
996
+ "stripe_subscription_active" => true,
997
+ "deleted_at" => nil,
998
+ "free_trial_expires_at" => nil,
999
+ "plan_setup_complete" => true,
1000
+ "enable_sso" => false,
1001
+ "sso_idp_id" => nil
1002
+ }
1003
+
1004
+
1005
+ ### Update action
1006
+ # Update your organizations information
1007
+ # Required :id
1008
+ # Valid Params :name
1009
+ api.organizations.update(id: 1, name: 'Updated Name') =>
1010
+ {
1011
+ "id" => 1,
1012
+ "name" => "Updated Name",
1013
+ "created_at" => "2014-06-23T18:53:25.500Z",
1014
+ "updated_at" => "2014-09-19T15:36:40.521Z",
1015
+ "external_account_setup_complete" => true,
1016
+ "encrypted_stripe_customer_identifier" => nil,
1017
+ "enterprise" => true,
1018
+ "enterprise_contract_expires_on" => "2034-06-23",
1019
+ "plan_id" => 7,
1020
+ "stripe_last_payment_successful" => true,
1021
+ "stripe_subscription_active" => true,
1022
+ "deleted_at" => nil,
1023
+ "free_trial_expires_at" => nil,
1024
+ "plan_setup_complete" => true,
1025
+ "enable_sso" => false,
1026
+ "sso_idp_id" => nil
1027
+ }
1028
+
1029
+ ## Sub Organizations end point
1030
+ ### List action
1031
+ # List is a pageable response of 25 total signatures per page.
1032
+ api.sub_organizations.list =>
1033
+ [
1034
+ [0] {
1035
+ "id" => 1,
1036
+ "organization_id" => 1,
1037
+ "name" => "Evident",
1038
+ "created_at" => "2014-06-23T18:53:25.531Z",
1039
+ "updated_at" => "2014-09-03T12:32:50.472Z"
1040
+ }
1041
+ ]
1042
+
1043
+ # Current page
1044
+ api.sub_organizations.current_page
1045
+
1046
+ # Next page sets current page with the next page results.
1047
+ api.sub_organizations.next_page
1048
+
1049
+ # Prev page sets current page with the previous page results.
1050
+ api.sub_organizations.prev_page
1051
+
1052
+ ### Show action
1053
+ # Show a specific sub organization
1054
+ # Required :id
1055
+ api.sub_organizations.show(id: 1) =>
1056
+ {
1057
+ "id" => 1,
1058
+ "organization_id" => 1,
1059
+ "name" => "Evident",
1060
+ "created_at" => "2014-06-23T18:53:25.531Z",
1061
+ "updated_at" => "2014-09-03T12:32:50.472Z"
1062
+ }
1063
+
1064
+
1065
+ ### Update action
1066
+ # Update a specific sub organization
1067
+ # Required :id
1068
+ # Valid param :name
1069
+ api.sub_organizations.update(id: 1, name: 'Test') =>
1070
+ {
1071
+ "id" => 1,
1072
+ "organization_id" => 1,
1073
+ "name" => "Test",
1074
+ "created_at" => "2014-06-23T18:53:25.531Z",
1075
+ "updated_at" => "2014-09-24T18:37:02.252Z"
1076
+ }
1077
+
1078
+ ### Create action
1079
+ # Create a new sub organization
1080
+ # Required :name
1081
+ api.sub_organizations.create(name: 'Test') =>
1082
+ {
1083
+ "id" => 3,
1084
+ "organization_id" => 1,
1085
+ "name" => "Test",
1086
+ "created_at" => "2014-09-24T18:39:25.493Z",
1087
+ "updated_at" => "2014-09-24T18:39:25.493Z"
1088
+ }
1089
+
1090
+ ### Destroy Action
1091
+ #### * Note this action will also destroy every team within the sub organization and any external accounts attached.
1092
+ # Destroy a sub organization
1093
+ # Required :id
1094
+ api.sub_organizations.destroy(id: 3) =>
1095
+ {
1096
+ "success" => "Test has been destroyed"
1097
+ }
1098
+
1099
+
1100
+ ## Teams end point
1101
+ ### List action
1102
+ # List is a pageable response of 25 total signatures per page.
1103
+ api.teams.list =>
1104
+ [
1105
+ [ 0] {
1106
+ "id" => 1,
1107
+ "sub_organization_id" => 1,
1108
+ "name" => "Evident",
1109
+ "created_at" => "2014-06-23T18:53:25.552Z",
1110
+ "updated_at" => "2014-06-23T18:53:25.552Z",
1111
+ "organization_id" => 1,
1112
+ "deleted_at" => nil
1113
+ },
1114
+ ]
1115
+
1116
+ # Current page
1117
+ api.teams.current_page
1118
+
1119
+ # Next page sets current page with the next page results.
1120
+ api.teams.next_page
1121
+
1122
+ # Prev page sets current page with the previous page results.
1123
+ api.teams.prev_page
1124
+
1125
+ ### Show action
1126
+ # Show a specific team
1127
+ # Required :id
1128
+ api.teams.show(id: 1) =>
1129
+ {
1130
+ "id" => 1,
1131
+ "sub_organization_id" => 1,
1132
+ "name" => "Evident",
1133
+ "created_at" => "2014-06-23T18:53:25.552Z",
1134
+ "updated_at" => "2014-06-23T18:53:25.552Z",
1135
+ "organization_id" => 1,
1136
+ "deleted_at" => nil
1137
+ }
1138
+
1139
+ ### Create action
1140
+ # Create a new team
1141
+ # Required :sub_organization_id => id of the sub organization to add this team to. Must have access to the sub organization as well.
1142
+ # Required :name
1143
+ api.teams.create(name: 'testing', sub_organization_id: 1) =>
1144
+ {
1145
+ "id" => 52,
1146
+ "sub_organization_id" => 1,
1147
+ "name" => "testing",
1148
+ "created_at" => "2014-09-24T18:51:28.517Z",
1149
+ "updated_at" => "2014-09-24T18:51:28.517Z",
1150
+ "organization_id" => 1,
1151
+ "deleted_at" => nil
1152
+ }
1153
+
1154
+ ### Update action
1155
+ # Update a team
1156
+ # Required :id
1157
+ # Valid :sub_organization_id, :name
1158
+ api.teams.update(id: 52, name: 'New Name') =>
1159
+ {
1160
+ "id" => 52,
1161
+ "sub_organization_id" => 1,
1162
+ "name" => "New Name",
1163
+ "created_at" => "2014-09-24T18:51:28.517Z",
1164
+ "updated_at" => "2014-09-24T18:53:20.313Z",
1165
+ "organization_id" => 1,
1166
+ "deleted_at" => nil
1167
+ }
1168
+
1169
+ ### Destroy Action
1170
+ #### * Note this will destroy any external accounts attached.
1171
+ # Destroy a team
1172
+ # Required :id
1173
+ api.teams.destroy(id: 52) =>
1174
+ {
1175
+ "success" => "New Name has been destroyed"
1176
+ }
1177
+
1178
+
1179
+ ## Contributing
1180
+
1181
+ 1. Fork it ( https://github.com/[my-github-username]/esp_sdk/fork )
1182
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
1183
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
1184
+ 4. Push to the branch (`git push origin my-new-feature`)
1185
+ 5. Create a new Pull Request