aws.rb 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. # frozen_string_literal: true
  2. require 'accounts'
  3. require 'regions'
  4. require 'mime-types'
  5. require 'fog-aws'
  6. require 's3'
  7. require 'sqs'
  8. require 'date'
  9. require 'ipaddr'
  10. require 'neo4j'
  11. require 'rds'
  12. require 'lambdas'
  13. require 'neoinfra/config'
  14. require 'neoinfra/cloudwatch'
  15. RFC_1918 = [
  16. IPAddr.new('10.0.0.0/8'),
  17. IPAddr.new('172.16.0.0/12'),
  18. IPAddr.new('192.168.0.0/16')
  19. ].freeze
  20. # NeoInfra Account information
  21. module NeoInfra
  22. # Provide informations about the accounts available
  23. class Aws
  24. def initialize
  25. @cfg = NeoInfra::Config.new
  26. neo4j_url = "http://#{@cfg.neo4j[:host]}:#{@cfg.neo4j[:port]}"
  27. Neo4j::Session.open(:server_db, neo4j_url)
  28. end
  29. def regions
  30. account = @cfg.accounts.first
  31. base_conf = {
  32. provider: 'AWS',
  33. aws_access_key_id: account[:key],
  34. aws_secret_access_key: account[:secret]
  35. }
  36. conn = Fog::Compute.new(base_conf)
  37. conn.describe_regions.data[:body]['regionInfo'].collect { |x| x['regionName'] }
  38. end
  39. def region_count
  40. Region.all.length
  41. end
  42. def az_count
  43. Az.all.length
  44. end
  45. def azs(region)
  46. azs = []
  47. @cfg.accounts.each do |account|
  48. base_conf = {
  49. provider: 'AWS',
  50. aws_access_key_id: account[:key],
  51. aws_secret_access_key: account[:secret],
  52. region: region
  53. }
  54. begin
  55. conn = Fog::Compute.new(base_conf)
  56. conn.describe_availability_zones.data[:body]['availabilityZoneInfo'].collect { |x| x['zoneName'] }.each do |z|
  57. azs << z
  58. end
  59. rescue Exception => e
  60. puts "Zone couldn't load region #{region}: #{e.message}"
  61. end
  62. end
  63. azs.uniq
  64. end
  65. def load_regions
  66. regions.each do |region|
  67. next unless Region.where(region: region).empty?
  68. r = Region.new(
  69. region: region
  70. )
  71. r.save
  72. azs(region).each do |az|
  73. next unless Az.where(az: az).empty?
  74. a = Az.new(az: az)
  75. a.save
  76. AzRegion.create(from_node: a, to_node: Region.where(region: region).first)
  77. end
  78. end
  79. end
  80. def list_buckets
  81. buckets = []
  82. Bucket.all.order('n.size DESC').each do |b|
  83. buckets << {
  84. 'name' => b.name,
  85. 'size' => b.size,
  86. 'versioning' => b.versioning,
  87. 'creation' => b.creation,
  88. 'region' => b.region.region,
  89. 'owner' => b.owner.name
  90. }
  91. end
  92. buckets
  93. end
  94. def load_buckets
  95. aws = NeoInfra::Aws.new
  96. cw = NeoInfra::Cloudwatch.new
  97. @cfg.accounts.each do |account|
  98. base_conf = {
  99. provider: 'AWS',
  100. aws_access_key_id: account[:key],
  101. aws_secret_access_key: account[:secret]
  102. }
  103. aws.regions.each do |region|
  104. region_conf = { region: region }
  105. s = Fog::Storage.new(region_conf.merge(base_conf))
  106. s.directories.each do |bucket|
  107. next unless bucket.location == region
  108. next unless Bucket.where(name: bucket.key).empty?
  109. vers = bucket.versioning?.to_s
  110. crea = bucket.creation_date.to_s
  111. b = Bucket.new(
  112. name: bucket.key,
  113. versioning: vers,
  114. creation: crea,
  115. size: cw.get_bucket_size(account[:key], account[:secret], bucket.location, bucket.key)
  116. )
  117. b.save
  118. BucketRegion.create(from_node: b, to_node: Region.where(region: bucket.location).first)
  119. BucketAccount.create(from_node: b, to_node: AwsAccount.where(name: account[:name]).first)
  120. end
  121. end
  122. end
  123. end
  124. ####
  125. def load_security_groups
  126. @cfg.accounts.each do |account|
  127. base_conf = {
  128. provider: 'AWS',
  129. aws_access_key_id: account[:key],
  130. aws_secret_access_key: account[:secret]
  131. }
  132. regions.each do |region|
  133. region_conf = { region: region }
  134. begin
  135. conn = Fog::Compute.new(region_conf.merge(base_conf))
  136. rescue StandardError
  137. puts "Error loading security groups for region #{region}"
  138. next
  139. end
  140. conn.security_groups.all.each do |grp|
  141. if SecurityGroup.where(sg_id: grp.group_id).empty?
  142. g = SecurityGroup.new(
  143. sg_id: grp.group_id,
  144. name: grp.name,
  145. description: grp.description
  146. )
  147. g.save
  148. begin
  149. SecurityGroupOwner.create(from_node: g, to_node: AwsAccount.where(account_id: grp.owner_id).first)
  150. unless grp.vpc_id.nil?
  151. SecurityGroupVpc.create(from_node: g, to_node: Vpc.where(vpc_id: grp.vpc_id).first)
  152. end
  153. rescue
  154. puts "Account #{account[:name]} couldn't load the following security group:"
  155. p grp
  156. end
  157. end
  158. grp.ip_permissions.each do |iprule|
  159. next unless iprule['ipProtocol'] != '-1'
  160. iprule['ipRanges'].each do |r|
  161. to_port = if iprule['toPort'] == -1
  162. 65_535
  163. else
  164. iprule['toPort']
  165. end
  166. from_port = if iprule['fromPort'] == -1
  167. 0
  168. else
  169. iprule['fromPort']
  170. end
  171. if IpRules.where(
  172. cidr_block: r['cidrIp'],
  173. direction: 'ingress',
  174. proto: iprule['ipProtocol'],
  175. to_port: to_port,
  176. from_port: from_port
  177. ).empty?
  178. rl = IpRules.new(
  179. cidr_block: r['cidrIp'],
  180. direction: 'ingress',
  181. proto: iprule['ipProtocol'],
  182. to_port: to_port,
  183. from_port: from_port,
  184. private: RFC_1918.any? { |rfc| rfc.include?(IPAddr.new(r['cidrIp'])) }
  185. )
  186. rl.save
  187. end
  188. # TODO: remove duplicate Relationships
  189. SecurityGroupsIpRules.create(
  190. from_node: SecurityGroup.where(sg_id: grp.group_id).first,
  191. to_node: IpRules.where(
  192. cidr_block: r['cidrIp'],
  193. direction: 'ingress',
  194. proto: iprule['ipProtocol'],
  195. to_port: to_port,
  196. from_port: from_port,
  197. private: RFC_1918.any? { |rfc| rfc.include?(IPAddr.new(r['cidrIp'])) }
  198. ).first
  199. )
  200. end
  201. end
  202. end
  203. end
  204. end
  205. end
  206. def list_lambdas
  207. lambdas = []
  208. Lambda.all.each do |l|
  209. lambdas << {
  210. 'name' => l.name,
  211. 'runtime' => l.runtime,
  212. 'handler' => l.handler,
  213. 'lambda_timeout' => l.lambda_timeout,
  214. 'memorysize' => l.memorysize,
  215. 'last_modified' => l.last_modified,
  216. 'region' => l.region.region,
  217. 'owner' => l.owner.name
  218. }
  219. end
  220. lambdas
  221. end
  222. def list_rds
  223. rds = []
  224. Rds.all.each do |r|
  225. rds << {
  226. 'name' => r.name,
  227. 'size' => r.size,
  228. 'engine' => r.engine,
  229. 'engine_version' => r.engine_version,
  230. 'multi_az' => r.multi_az,
  231. 'endpoint' => r.endpoint,
  232. 'port' => r.port,
  233. 'allocated_storage' => r.allocated_storage,
  234. 'owner' => r.owner.name,
  235. 'az' => r.az.az,
  236. }
  237. end
  238. rds
  239. end
  240. def load_lambda
  241. @cfg.accounts.each do |account|
  242. base_conf = {
  243. aws_access_key_id: account[:key],
  244. aws_secret_access_key: account[:secret]
  245. }
  246. regions.each do |region|
  247. region_conf = { region: region }
  248. begin
  249. lambdas = Fog::AWS::Lambda.new(region_conf.merge(base_conf))
  250. lambdas.list_functions.data[:body]['Functions'].each do |f|
  251. next unless Lambda.where(name: f['FunctionArn']).empty?
  252. l = Lambda.new(
  253. name: f['FunctionName'],
  254. runtime: f['Runtime'],
  255. lambda_timeout: f['Timeout'],
  256. handler: f['Handler'],
  257. memorysize: f['MemorySize'],
  258. arn: f['FunctionArn'],
  259. codesize: f['CodeSize'],
  260. last_modified: f['LastModified']
  261. )
  262. l.save
  263. LambdaAccount.create(from_node: l, to_node: AwsAccount.where(name: account[:name]).first)
  264. LambdaRegion.create(from_node: l, to_node: Region.where(region: region).first)
  265. end
  266. rescue Exception => e
  267. puts "Error with #{region}: #{e.message}"
  268. next
  269. end
  270. end
  271. end
  272. end
  273. def list_dynamos
  274. dynamos = []
  275. Dynamo.all.order('n.sizebytes DESC').each do |d|
  276. dynamos << {
  277. 'name' => d.name,
  278. 'size' => d.sizebytes,
  279. 'itemcount' => d.itemcount,
  280. 'status' => d.status,
  281. 'creation' => d.creation,
  282. 'region' => d.region.region,
  283. 'owner' => d.owner.name
  284. }
  285. end
  286. dynamos
  287. end
  288. def load_dynamo
  289. @cfg.accounts.each do |account|
  290. base_conf = {
  291. aws_access_key_id: account[:key],
  292. aws_secret_access_key: account[:secret]
  293. }
  294. regions.each do |region|
  295. region_conf = { region: region }
  296. begin
  297. dyns = Fog::AWS::DynamoDB.new(region_conf.merge(base_conf))
  298. dyns.list_tables.data[:body]['TableNames'].each do |table|
  299. tb = dyns.describe_table(table).data[:body]['Table']
  300. next unless Dynamo.where(name: table['TableId']).empty?
  301. d = Dynamo.new(
  302. tableid: tb['TableId'],
  303. name: tb['TableName'],
  304. creation: Time.at(tb['CreationDateTime']).to_datetime.strftime('%F %H:%M:%S %Z'),
  305. arn: tb['TableArn'],
  306. itemcount: tb['ItemCount'],
  307. sizebytes: tb['TableSizeBytes'],
  308. status: tb['TableStatus'],
  309. readcap: tb['ProvisionedThroughput']['ReadCapacityUnits'],
  310. writecap: tb['ProvisionedThroughput']['WriteCapacityUnits'],
  311. capdecreases: tb['ProvisionedThroughput']['NumberOfDecreasesToday']
  312. )
  313. d.save
  314. DynamoAccount.create(from_node: d, to_node: AwsAccount.where(name: account[:name]).first)
  315. DynamoRegion.create(from_node: d, to_node: Region.where(region: region).first)
  316. end
  317. rescue Exception => e
  318. puts "Could not list Dynamos for region: #{region}: #{e.message}"
  319. next
  320. end
  321. end
  322. # dyns.list_tables.each do |table|
  323. # p table
  324. # end
  325. end
  326. end
  327. def list_queues
  328. queues = []
  329. SQSQueue.all.order('n.name DESC').each do |d|
  330. queues << {
  331. 'name' => d.name,
  332. 'modified' => d.modified,
  333. 'creation' => d.creation,
  334. 'retention' => d.retention,
  335. 'maxsize' => d.maxsize,
  336. 'region' => d.region.region,
  337. 'owner' => d.owner.name
  338. }
  339. end
  340. queues
  341. end
  342. def load_queues
  343. aws = NeoInfra::Aws.new
  344. cw = NeoInfra::Cloudwatch.new
  345. @cfg.accounts.each do |account|
  346. base_conf = {
  347. aws_access_key_id: account[:key],
  348. aws_secret_access_key: account[:secret]
  349. }
  350. aws.regions.each do |region|
  351. region_conf = { region: region }
  352. q = Fog::AWS::SQS.new(region_conf.merge(base_conf))
  353. q.list_queues.data[:body]['QueueUrls'].each do |x|
  354. next unless SQSQueue.where(url: x).empty?
  355. theAttrs = q.get_queue_attributes(x, "All").data[:body]['Attributes']
  356. z = SQSQueue.new(
  357. url: x,
  358. name: x.split('/')[-1],
  359. modified: theAttrs['LastModifiedTimestamp'],
  360. creation: theAttrs['CreatedTimestamp'],
  361. retention: theAttrs['MessageRetentionPeriod'],
  362. maxsize: theAttrs['MaximumMessageSize'],
  363. )
  364. z.save
  365. SQSQueueRegion.create(from_node: z, to_node: Region.where(region: region).first)
  366. SQSQueueAccount.create(from_node: z, to_node: AwsAccount.where(name: account[:name]).first)
  367. end
  368. end
  369. end
  370. end
  371. def load_rds
  372. @cfg.accounts.each do |account|
  373. base_conf = {
  374. aws_access_key_id: account[:key],
  375. aws_secret_access_key: account[:secret]
  376. }
  377. regions.each do |region|
  378. region_conf = { region: region }
  379. s = Fog::AWS::RDS.new(region_conf.merge(base_conf))
  380. s.servers.each do |rds|
  381. next unless Rds.where(name: rds.id).empty?
  382. r = Rds.new(
  383. name: rds.id,
  384. size: rds.flavor_id,
  385. engine: rds.engine,
  386. engine_version: rds.engine_version,
  387. multi_az: rds.multi_az.to_s,
  388. endpoint: rds.endpoint['Address'],
  389. port: rds.endpoint['Port'],
  390. allocated_storage: rds.allocated_storage
  391. )
  392. r.save
  393. begin
  394. RdsAz.create(from_node: r, to_node: Az.where(az: rds.availability_zone).first)
  395. RdsAccount.create(from_node: r, to_node: AwsAccount.where(name: account[:name]).first)
  396. rescue Exception => e
  397. puts "Account #{account[:name]} couldn't load the following rds: #{e.message}"
  398. p r
  399. next
  400. end
  401. end
  402. end
  403. end
  404. end
  405. end
  406. end