aws.rb 11 KB

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