edurange 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/bin/edurange +8 -0
- data/edurange.gemspec +19 -0
- data/final.yml +41 -0
- data/lib/edurange/edu_machine.rb +49 -0
- data/lib/edurange/parser.rb +73 -0
- data/lib/edurange/puppet_master.rb +86 -0
- data/lib/edurange/version.rb +3 -0
- data/lib/edurange.rb +13 -0
- data/parser.rb +57 -0
- data/site.pp +20 -0
- metadata +61 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Stefan Boesen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Edurange
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'edurange'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install edurange
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/edurange
ADDED
data/edurange.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'edurange/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "edurange"
|
8
|
+
gem.version = Edurange::VERSION
|
9
|
+
gem.authors = ["Stefan Boesen"]
|
10
|
+
gem.email = ["stefan.boesen@gmail.com"]
|
11
|
+
gem.description = %q{EDURange Project}
|
12
|
+
gem.summary = %q{Automatic warspace simulations}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
end
|
data/final.yml
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
Nodes:
|
2
|
+
# Main_Box: # attacking box
|
3
|
+
# AMI_ID: ami-e720ad8e
|
4
|
+
# Users:
|
5
|
+
# - Team_1
|
6
|
+
# - Instructor
|
7
|
+
# Software:
|
8
|
+
# - Attacker_CTF
|
9
|
+
|
10
|
+
Victim: # victim host
|
11
|
+
AMI_ID: ami-e720ad8e
|
12
|
+
Users:
|
13
|
+
- Instructor
|
14
|
+
Software:
|
15
|
+
- Victim_CTF
|
16
|
+
|
17
|
+
Groups:
|
18
|
+
Team_1:
|
19
|
+
- { login: sboesen, pass: password }
|
20
|
+
Instructor:
|
21
|
+
- { login: weissr, pass: pass2 }
|
22
|
+
|
23
|
+
Software:
|
24
|
+
Victim_CTF:
|
25
|
+
IPTables:
|
26
|
+
# Ports open
|
27
|
+
20:
|
28
|
+
Protocol: tcp
|
29
|
+
Hosts:
|
30
|
+
- 127.0.0.1
|
31
|
+
- All
|
32
|
+
80:
|
33
|
+
Protocol: tcp
|
34
|
+
Hosts:
|
35
|
+
- 127.0.0.1
|
36
|
+
- All
|
37
|
+
|
38
|
+
Packages: # References to puppet modules so we can support different OS options. Otherwise we need to know what OS we're on...
|
39
|
+
- iptables
|
40
|
+
- apache
|
41
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Edurange
|
2
|
+
class EduMachine
|
3
|
+
attr_reader :uuid, :ami_id, :key_name, :vm_size, :ip_address
|
4
|
+
|
5
|
+
EC2_UTILS_PATH = "/home/ubuntu/.ec2/bin/"
|
6
|
+
|
7
|
+
def initialize(uuid, key_name, ami_id, vm_size="t1.micro")
|
8
|
+
# generate uuid
|
9
|
+
@uuid = uuid
|
10
|
+
@instance_id = nil
|
11
|
+
@key_name = key_name
|
12
|
+
@vm_size = vm_size
|
13
|
+
@ami_id = ami_id
|
14
|
+
end
|
15
|
+
def run(command)
|
16
|
+
# runs an ec2 command with full path.
|
17
|
+
command = EC2_UTILS_PATH + command
|
18
|
+
`#{command}`
|
19
|
+
end
|
20
|
+
|
21
|
+
def spin_up
|
22
|
+
# Pref user-data-file for ourselves
|
23
|
+
|
24
|
+
# Create & run instance, setting instance_id and IP to match the newly created ami
|
25
|
+
command = "ec2-run-instances #{@ami_id} -t #{@vm_size} --region us-east-1 --key #{@key_name} --user-data-file my-user-script.sh"
|
26
|
+
puts "Would run: #{command}"
|
27
|
+
self.run(command)
|
28
|
+
@instance_id = self.get_last_instance_id()
|
29
|
+
puts "Waiting for instance #{@instance_id} to spin up..."
|
30
|
+
sleep(40)
|
31
|
+
self.update_ec2_info()
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def update_ec2_info
|
36
|
+
command = "ec2-describe-instances | grep INSTANCE | grep '#{@instance_id}'"
|
37
|
+
vm = self.run(command).split("\t")
|
38
|
+
p vm
|
39
|
+
@ip_address = vm[17] # public ip
|
40
|
+
@hostname = vm[3] # ec2 hostname
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_last_instance_id
|
44
|
+
command = 'ec2-describe-instances | grep INSTANCE | tail -n 1'
|
45
|
+
vm = self.run(command)
|
46
|
+
return vm.split("\t")[1]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Edurange
|
2
|
+
class Parser
|
3
|
+
def self.facter_facts(uuid)
|
4
|
+
facter_conf = <<conf
|
5
|
+
uuid=#{uuid}
|
6
|
+
services=apache2,vsftpd,iptables
|
7
|
+
conf
|
8
|
+
end
|
9
|
+
def self.parse_yaml(filename)
|
10
|
+
nodes = []
|
11
|
+
file = YAML.load_file(filename)
|
12
|
+
|
13
|
+
softwares = {}
|
14
|
+
file["Software"].each do |software|
|
15
|
+
softwares[software[0]] = software[1]
|
16
|
+
end
|
17
|
+
|
18
|
+
groups = {}
|
19
|
+
file["Groups"].each do |group|
|
20
|
+
groups[group[0]] = group[1]
|
21
|
+
end
|
22
|
+
|
23
|
+
file["Nodes"].each do |node|
|
24
|
+
node_name = node[0]
|
25
|
+
ami_id = node[1]["AMI_ID"]
|
26
|
+
|
27
|
+
users = []
|
28
|
+
users_groups = node[1]["Users"]
|
29
|
+
users_groups.each do |user_group|
|
30
|
+
users.push groups[user_group]
|
31
|
+
end
|
32
|
+
users.flatten!
|
33
|
+
|
34
|
+
software = []
|
35
|
+
software_groups = node[1]["Software"]
|
36
|
+
software_groups.each do |software_group|
|
37
|
+
software.push softwares[software_group]
|
38
|
+
end
|
39
|
+
software.flatten!
|
40
|
+
|
41
|
+
iptables_rules = []
|
42
|
+
packages = []
|
43
|
+
software.each do |sw|
|
44
|
+
if !sw["IPTables"].nil?
|
45
|
+
sw["IPTables"].each do |iptable_rule|
|
46
|
+
port = iptable_rule[0]
|
47
|
+
protocol = iptable_rule[1]["Protocol"]
|
48
|
+
hosts = iptable_rule[1]["Hosts"]
|
49
|
+
hosts.each do |host|
|
50
|
+
iptables_rules.push [protocol, port, host]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
if !sw["Packages"].nil?
|
55
|
+
sw["Packages"].each do |package|
|
56
|
+
packages.push package
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
nodes.push [
|
61
|
+
ami_id,
|
62
|
+
users,
|
63
|
+
iptables_rules,
|
64
|
+
packages
|
65
|
+
]
|
66
|
+
p ami_id
|
67
|
+
p users
|
68
|
+
p iptables_rules
|
69
|
+
p packages
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Edurange
|
2
|
+
class PuppetMaster
|
3
|
+
def self.puppetmaster_ip
|
4
|
+
`curl http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null`
|
5
|
+
end
|
6
|
+
def self.get_our_ssh_key
|
7
|
+
# make some ssh keys
|
8
|
+
`ssh-keygen -t rsa -f /home/ubuntu/.ssh/id_rsa -N '' -q` unless File.exists?("/home/ubuntu/.ssh/id_rsa")
|
9
|
+
# return our public key
|
10
|
+
file = File.open("/home/ubuntu/.ssh/id_rsa.pub", "rb")
|
11
|
+
contents = file.read
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.gen_client_ssl_cert
|
15
|
+
# We need to:
|
16
|
+
# Generate unique name (UUIDgen)
|
17
|
+
uuid = `uuidgen`.chomp
|
18
|
+
# Create cert for name on puppetmaster
|
19
|
+
`sudo puppet cert --generate #{uuid}`
|
20
|
+
ssl_cert = `sudo cat /var/lib/puppet/ssl/certs/#{uuid}.pem`.chomp
|
21
|
+
ca_cert = `sudo cat /var/lib/puppet/ssl/certs/ca.pem`.chomp
|
22
|
+
private_key = `sudo cat /var/lib/puppet/ssl/private_keys/#{uuid}.pem`.chomp
|
23
|
+
return [uuid, ssl_cert, ca_cert, private_key]
|
24
|
+
end
|
25
|
+
def self.write_shell_config_file(ssh_key, puppetmaster_ip, certs, puppet_conf, facter_facts)
|
26
|
+
File.open("my-user-script.sh", 'w') do |file|
|
27
|
+
file_contents = <<contents
|
28
|
+
#!/bin/sh
|
29
|
+
set -e
|
30
|
+
set -x
|
31
|
+
echo "Hello World. The time is now $(date -R)!" | tee /root/output.txt
|
32
|
+
apt-get update; apt-get upgrade -y
|
33
|
+
|
34
|
+
key='#{ssh_key.chomp}'
|
35
|
+
echo $key >> /home/ubuntu/.ssh/authorized_keys
|
36
|
+
|
37
|
+
echo #{puppetmaster_ip} puppet >> /etc/hosts
|
38
|
+
apt-get -y install puppet
|
39
|
+
|
40
|
+
mkdir -p /var/lib/puppet/ssl/certs
|
41
|
+
mkdir -p /var/lib/puppet/ssl/private_keys
|
42
|
+
mkdir -p /etc/puppet
|
43
|
+
|
44
|
+
mkdir -p /etc/facter/facts.d
|
45
|
+
echo '#{facter_facts}' >> "/etc/facter/facts.d/facts.txt"
|
46
|
+
|
47
|
+
echo '#{certs[1]}' >> "/var/lib/puppet/ssl/certs/#{certs[0]}.pem"
|
48
|
+
echo '#{certs[2]}' >> "/var/lib/puppet/ssl/certs/ca.pem"
|
49
|
+
echo '#{certs[3]}' >> "/var/lib/puppet/ssl/private_keys/#{certs[0]}.pem"
|
50
|
+
|
51
|
+
echo '#{puppet_conf.chomp}' > /etc/puppet/puppet.conf
|
52
|
+
|
53
|
+
sed -i /etc/default/puppet -e 's/START=no/START=yes/'
|
54
|
+
service puppet restart
|
55
|
+
|
56
|
+
echo "Goodbye World. The time is now $(date -R)!" | tee /root/output.txt
|
57
|
+
contents
|
58
|
+
file.write(file_contents)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
def self.generate_puppet_conf(uuid)
|
62
|
+
conf_file = <<conf
|
63
|
+
[main]
|
64
|
+
logdir=/var/log/puppet
|
65
|
+
vardir=/var/lib/puppet
|
66
|
+
ssldir=/var/lib/puppet/ssl
|
67
|
+
rundir=/var/run/puppet
|
68
|
+
factpath=$vardir/lib/facter
|
69
|
+
templatedir=$confdir/templates
|
70
|
+
prerun_command=/etc/puppet/etckeeper-commit-pre
|
71
|
+
postrun_command=/etc/puppet/etckeeper-commit-post
|
72
|
+
runinterval=60 # run every minute for debug TODO REMOVE
|
73
|
+
pluginsync=true
|
74
|
+
|
75
|
+
[master]
|
76
|
+
# These are needed when the puppetmaster is run by passenger
|
77
|
+
# and can safely be removed if webrick is used.
|
78
|
+
ssl_client_header = SSL_CLIENT_S_DN
|
79
|
+
ssl_client_verify_header = SSL_CLIENT_VERIFY
|
80
|
+
|
81
|
+
[agent]
|
82
|
+
certname=#{uuid}
|
83
|
+
conf
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/edurange.rb
ADDED
data/parser.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
file = YAML.load_file('final.yml')
|
4
|
+
|
5
|
+
softwares = {}
|
6
|
+
file["Software"].each do |software|
|
7
|
+
softwares[software[0]] = software[1]
|
8
|
+
end
|
9
|
+
|
10
|
+
groups = {}
|
11
|
+
file["Groups"].each do |group|
|
12
|
+
groups[group[0]] = group[1]
|
13
|
+
end
|
14
|
+
|
15
|
+
file["Nodes"].each do |node|
|
16
|
+
node_name = node[0]
|
17
|
+
ami_id = node[1]["AMI_ID"]
|
18
|
+
|
19
|
+
users = []
|
20
|
+
users_groups = node[1]["Users"]
|
21
|
+
users_groups.each do |user_group|
|
22
|
+
users.push groups[user_group]
|
23
|
+
end
|
24
|
+
users.flatten!
|
25
|
+
|
26
|
+
software = []
|
27
|
+
software_groups = node[1]["Software"]
|
28
|
+
software_groups.each do |software_group|
|
29
|
+
software.push softwares[software_group]
|
30
|
+
end
|
31
|
+
software.flatten!
|
32
|
+
|
33
|
+
iptables_rules = []
|
34
|
+
packages = []
|
35
|
+
software.each do |sw|
|
36
|
+
if !sw["IPTables"].nil?
|
37
|
+
sw["IPTables"].each do |iptable_rule|
|
38
|
+
port = iptable_rule[0]
|
39
|
+
protocol = iptable_rule[1]["Protocol"]
|
40
|
+
hosts = iptable_rule[1]["Hosts"]
|
41
|
+
hosts.each do |host|
|
42
|
+
iptables_rules.push [protocol, port, host]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
if !sw["Packages"].nil?
|
47
|
+
sw["Packages"].each do |package|
|
48
|
+
packages.push package
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
p ami_id
|
53
|
+
p users
|
54
|
+
p iptables_rules
|
55
|
+
p packages
|
56
|
+
end
|
57
|
+
|
data/site.pp
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
node default {
|
2
|
+
include stdlib
|
3
|
+
|
4
|
+
file { "/tmp/test1":
|
5
|
+
ensure => present
|
6
|
+
}
|
7
|
+
file { "/tmp/derp":
|
8
|
+
ensure => present,
|
9
|
+
content => $aaaaaafact
|
10
|
+
}
|
11
|
+
}
|
12
|
+
define install_software {
|
13
|
+
$package = $name
|
14
|
+
package { $name:
|
15
|
+
name => $name,
|
16
|
+
ensure => latest,
|
17
|
+
}
|
18
|
+
}
|
19
|
+
$packages = split($services,',')
|
20
|
+
install_software{ $packages:; }
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: edurange
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Stefan Boesen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-15 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: EDURange Project
|
15
|
+
email:
|
16
|
+
- stefan.boesen@gmail.com
|
17
|
+
executables:
|
18
|
+
- edurange
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE.txt
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- bin/edurange
|
28
|
+
- edurange.gemspec
|
29
|
+
- final.yml
|
30
|
+
- lib/edurange.rb
|
31
|
+
- lib/edurange/edu_machine.rb
|
32
|
+
- lib/edurange/parser.rb
|
33
|
+
- lib/edurange/puppet_master.rb
|
34
|
+
- lib/edurange/version.rb
|
35
|
+
- parser.rb
|
36
|
+
- site.pp
|
37
|
+
homepage: ''
|
38
|
+
licenses: []
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.8.24
|
58
|
+
signing_key:
|
59
|
+
specification_version: 3
|
60
|
+
summary: Automatic warspace simulations
|
61
|
+
test_files: []
|