aws.rb 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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. base_conf = {
  48. provider: 'AWS',
  49. aws_access_key_id: account[:key],
  50. aws_secret_access_key: account[:secret],
  51. region: region
  52. }
  53. begin
  54. conn = Fog::Compute.new(base_conf)
  55. p conn.describe_availability_zones.data[:body]['availabilityZoneInfo'].collect { |x| x['zoneName'] }
  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. cw = NeoInfra::Cloudwatch.new
  96. @cfg.accounts.each do |account|
  97. base_conf = {
  98. provider: 'AWS',
  99. aws_access_key_id: account[:key],
  100. aws_secret_access_key: account[:secret]
  101. }
  102. s = Fog::Storage.new(base_conf)
  103. s.directories.each do |bucket|
  104. next unless Bucket.where(name: bucket.key).empty?
  105. begin
  106. vers = bucket.versioning?.to_s
  107. crea = bucket.creation_date.to_s
  108. rescue StandardError
  109. vers = 'unknown'
  110. crea = 'unknown'
  111. end
  112. b = Bucket.new(
  113. name: bucket.key,
  114. versioning: vers,
  115. creation: crea,
  116. size: cw.get_bucket_size(account[:key], account[:secret], bucket.location, bucket.key)
  117. )
  118. b.save
  119. BucketRegion.create(from_node: b, to_node: Region.where(region: bucket.location).first)
  120. BucketAccount.create(from_node: b, to_node: AwsAccount.where(name: account[:name]).first)
  121. end
  122. end
  123. end
  124. def load_security_groups
  125. @cfg.accounts.each do |account|
  126. base_conf = {
  127. provider: 'AWS',
  128. aws_access_key_id: account[:key],
  129. aws_secret_access_key: account[:secret]
  130. }
  131. regions.each do |region|
  132. region_conf = { region: region }
  133. begin
  134. conn = Fog::Compute.new(region_conf.merge(base_conf))
  135. rescue StandardError
  136. puts "Error loading security groups for region #{region}"
  137. next
  138. end
  139. conn.security_groups.all.each do |grp|
  140. if SecurityGroup.where(sg_id: grp.group_id).empty?
  141. g = SecurityGroup.new(
  142. sg_id: grp.group_id,
  143. name: grp.name,
  144. description: grp.description
  145. )
  146. g.save
  147. begin
  148. SecurityGroupOwner.create(from_node: g, to_node: AwsAccount.where(account_id: grp.owner_id).first)
  149. unless grp.vpc_id.nil?
  150. SecurityGroupVpc.create(from_node: g, to_node: Vpc.where(vpc_id: grp.vpc_id).first)
  151. end
  152. rescue
  153. puts "Account #{account[:name]} couldn't load the following security group:"
  154. p grp
  155. end
  156. end
  157. grp.ip_permissions.each do |iprule|
  158. next unless iprule['ipProtocol'] != '-1'
  159. iprule['ipRanges'].each do |r|
  160. to_port = if iprule['toPort'] == -1
  161. 65_535
  162. else
  163. iprule['toPort']
  164. end
  165. from_port = if iprule['fromPort'] == -1
  166. 0
  167. else
  168. iprule['fromPort']
  169. end
  170. if IpRules.where(
  171. cidr_block: r['cidrIp'],
  172. direction: 'ingress',
  173. proto: iprule['ipProtocol'],
  174. to_port: to_port,
  175. from_port: from_port
  176. ).empty?
  177. rl = IpRules.new(
  178. cidr_block: r['cidrIp'],
  179. direction: 'ingress',
  180. proto: iprule['ipProtocol'],
  181. to_port: to_port,
  182. from_port: from_port,
  183. private: RFC_1918.any? { |rfc| rfc.include?(IPAddr.new(r['cidrIp'])) }
  184. )
  185. rl.save
  186. end
  187. # TODO: remove duplicate Relationships
  188. SecurityGroupsIpRules.create(
  189. from_node: SecurityGroup.where(sg_id: grp.group_id).first,
  190. to_node: IpRules.where(
  191. cidr_block: r['cidrIp'],
  192. direction: 'ingress',
  193. proto: iprule['ipProtocol'],
  194. to_port: to_port,
  195. from_port: from_port,
  196. private: RFC_1918.any? { |rfc| rfc.include?(IPAddr.new(r['cidrIp'])) }
  197. ).first
  198. )
  199. end
  200. end
  201. end
  202. end
  203. end
  204. end
  205. def list_lambdas
  206. lambdas = []
  207. Lambda.all.each do |l|
  208. lambdas << {
  209. 'name' => l.name,
  210. 'runtime' => l.runtime,
  211. 'handler' => l.handler,
  212. 'lambda_timeout' => l.lambda_timeout,
  213. 'memorysize' => l.memorysize,
  214. 'last_modified' => l.last_modified,
  215. 'region' => l.region.region,
  216. 'owner' => l.owner.name
  217. }
  218. end
  219. lambdas
  220. end
  221. def list_rds
  222. rds = []
  223. Rds.all.each do |r|
  224. rds << {
  225. 'name' => r.name,
  226. 'size' => r.size,
  227. 'engine' => r.engine,
  228. 'engine_version' => r.engine_version,
  229. 'multi_az' => r.multi_az,
  230. 'endpoint' => r.endpoint,
  231. 'port' => r.port,
  232. 'allocated_storage' => r.allocated_storage,
  233. 'owner' => r.owner.name,
  234. 'az' => r.az.az,
  235. }
  236. end
  237. rds
  238. end
  239. def load_lambda
  240. @cfg.accounts.each do |account|
  241. base_conf = {
  242. aws_access_key_id: account[:key],
  243. aws_secret_access_key: account[:secret]
  244. }
  245. regions.each do |region|
  246. region_conf = { region: region }
  247. begin
  248. lambdas = Fog::AWS::Lambda.new(region_conf.merge(base_conf))
  249. lambdas.list_functions.data[:body]['Functions'].each do |f|
  250. next unless Lambda.where(name: f['FunctionArn']).empty?
  251. l = Lambda.new(
  252. name: f['FunctionName'],
  253. runtime: f['Runtime'],
  254. lambda_timeout: f['Timeout'],
  255. handler: f['Handler'],
  256. memorysize: f['MemorySize'],
  257. arn: f['FunctionArn'],
  258. codesize: f['CodeSize'],
  259. last_modified: f['LastModified']
  260. )
  261. l.save
  262. LambdaAccount.create(from_node: l, to_node: AwsAccount.where(name: account[:name]).first)
  263. LambdaRegion.create(from_node: l, to_node: Region.where(region: region).first)
  264. end
  265. rescue Exception => e
  266. puts "Error with #{region}: #{e.message}"
  267. next
  268. end
  269. end
  270. end
  271. end
  272. def list_dynamos
  273. dynamos = []
  274. Dynamo.all.order('n.sizebytes DESC').each do |d|
  275. dynamos << {
  276. 'name' => d.name,
  277. 'size' => d.sizebytes,
  278. 'itemcount' => d.itemcount,
  279. 'status' => d.status,
  280. 'creation' => d.creation,
  281. 'region' => d.region.region,
  282. 'owner' => d.owner.name
  283. }
  284. end
  285. dynamos
  286. end
  287. def load_dynamo
  288. @cfg.accounts.each do |account|
  289. base_conf = {
  290. aws_access_key_id: account[:key],
  291. aws_secret_access_key: account[:secret]
  292. }
  293. regions.each do |region|
  294. region_conf = { region: region }
  295. begin
  296. dyns = Fog::AWS::DynamoDB.new(region_conf.merge(base_conf))
  297. dyns.list_tables.data[:body]['TableNames'].each do |table|
  298. tb = dyns.describe_table(table).data[:body]['Table']
  299. next unless Dynamo.where(name: table['TableId']).empty?
  300. d = Dynamo.new(
  301. tableid: tb['TableId'],
  302. name: tb['TableName'],
  303. creation: Time.at(tb['CreationDateTime']).to_datetime.strftime('%F %H:%M:%S %Z'),
  304. arn: tb['TableArn'],
  305. itemcount: tb['ItemCount'],
  306. sizebytes: tb['TableSizeBytes'],
  307. status: tb['TableStatus'],
  308. readcap: tb['ProvisionedThroughput']['ReadCapacityUnits'],
  309. writecap: tb['ProvisionedThroughput']['WriteCapacityUnits'],
  310. capdecreases: tb['ProvisionedThroughput']['NumberOfDecreasesToday']
  311. )
  312. d.save
  313. DynamoAccount.create(from_node: d, to_node: AwsAccount.where(name: account[:name]).first)
  314. DynamoRegion.create(from_node: d, to_node: Region.where(region: region).first)
  315. end
  316. rescue Exception => e
  317. puts "Could not list Dynamos for region: #{region}: #{e.message}"
  318. next
  319. end
  320. end
  321. # dyns.list_tables.each do |table|
  322. # p table
  323. # end
  324. end
  325. end
  326. def load_rds
  327. @cfg.accounts.each do |account|
  328. base_conf = {
  329. aws_access_key_id: account[:key],
  330. aws_secret_access_key: account[:secret]
  331. }
  332. regions.each do |region|
  333. region_conf = { region: region }
  334. s = Fog::AWS::RDS.new(region_conf.merge(base_conf))
  335. s.servers.each do |rds|
  336. next unless Rds.where(name: rds.id).empty?
  337. r = Rds.new(
  338. name: rds.id,
  339. size: rds.flavor_id,
  340. engine: rds.engine,
  341. engine_version: rds.engine_version,
  342. multi_az: rds.multi_az.to_s,
  343. endpoint: rds.endpoint['Address'],
  344. port: rds.endpoint['Port'],
  345. allocated_storage: rds.allocated_storage
  346. )
  347. r.save
  348. begin
  349. RdsAz.create(from_node: r, to_node: Az.where(az: rds.availability_zone).first)
  350. RdsAccount.create(from_node: r, to_node: AwsAccount.where(name: account[:name]).first)
  351. rescue Exception => e
  352. puts "Account #{account[:name]} couldn't load the following rds: #{e.message}"
  353. p r
  354. next
  355. end
  356. end
  357. end
  358. end
  359. end
  360. end
  361. end