aws.rb 12 KB

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