ConfigLMM 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.yardopts +4 -0
  4. data/CHANGELOG.md +5 -0
  5. data/Examples/Android.mm.yaml +8 -0
  6. data/Examples/Apps/Blog.mm.yaml +7 -0
  7. data/Examples/Apps/Jellyfin.mm.yaml +3 -0
  8. data/Examples/Implemented.mm.yaml +155 -0
  9. data/Examples/Keys.ini +7 -0
  10. data/Examples/Linux.mm.yaml +16 -0
  11. data/Examples/Windows.mm.yaml +11 -0
  12. data/Examples/configlmmAuth.sh +26 -0
  13. data/Plugins/Apps/ArchiSteamFarm/ArchiSteamFarm.conf.erb +38 -0
  14. data/Plugins/Apps/ArchiSteamFarm/ArchiSteamFarm.lmm.rb +19 -0
  15. data/Plugins/Apps/IPFS/IPFS.conf.erb +44 -0
  16. data/Plugins/Apps/IPFS/IPFS.lmm.rb +23 -0
  17. data/Plugins/Apps/InfluxDB/InfluxDB.conf.erb +34 -0
  18. data/Plugins/Apps/InfluxDB/InfluxDB.lmm.rb +19 -0
  19. data/Plugins/Apps/Jackett/Jackett.conf.erb +38 -0
  20. data/Plugins/Apps/Jackett/Jackett.lmm.rb +19 -0
  21. data/Plugins/Apps/Jellyfin/Jellyfin.conf.erb +59 -0
  22. data/Plugins/Apps/Jellyfin/Jellyfin.lmm.rb +23 -0
  23. data/Plugins/Apps/Mastodon/Mastodon.conf.erb +81 -0
  24. data/Plugins/Apps/Mastodon/Mastodon.lmm.rb +23 -0
  25. data/Plugins/Apps/Matrix/Matrix.conf.erb +36 -0
  26. data/Plugins/Apps/Matrix/Matrix.lmm.rb +23 -0
  27. data/Plugins/Apps/Netdata/Netdata.conf.erb +37 -0
  28. data/Plugins/Apps/Netdata/Netdata.lmm.rb +23 -0
  29. data/Plugins/Apps/Nextcloud/Nextcloud.conf.erb +165 -0
  30. data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +23 -0
  31. data/Plugins/Apps/Nginx/config-lmm/errors.conf +31 -0
  32. data/Plugins/Apps/Nginx/config-lmm/private.conf +6 -0
  33. data/Plugins/Apps/Nginx/config-lmm/proxy.conf +15 -0
  34. data/Plugins/Apps/Nginx/config-lmm/public.conf +3 -0
  35. data/Plugins/Apps/Nginx/config-lmm/ssl.conf +18 -0
  36. data/Plugins/Apps/Nginx/main.conf +30 -0
  37. data/Plugins/Apps/Nginx/nginx.conf +90 -0
  38. data/Plugins/Apps/Nginx/nginx.lmm.rb +62 -0
  39. data/Plugins/Apps/Nginx/proxy.conf.erb +31 -0
  40. data/Plugins/Apps/Odoo/Odoo.conf.erb +44 -0
  41. data/Plugins/Apps/Odoo/Odoo.lmm.rb +23 -0
  42. data/Plugins/Apps/Pterodactyl/Pterodactyl.conf.erb +50 -0
  43. data/Plugins/Apps/Pterodactyl/Pterodactyl.lmm.rb +30 -0
  44. data/Plugins/Apps/Pterodactyl/Wings.conf.erb +38 -0
  45. data/Plugins/Apps/Sunshine/Sunshine.conf.erb +31 -0
  46. data/Plugins/Apps/Sunshine/Sunshine.lmm.rb +21 -0
  47. data/Plugins/Apps/Vaultwarden/Vaultwarden.conf.erb +48 -0
  48. data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +25 -0
  49. data/Plugins/Apps/bitmagnet/bitmagnet.conf.erb +35 -0
  50. data/Plugins/Apps/bitmagnet/bitmagnet.lmm.rb +19 -0
  51. data/Plugins/Apps/gollum/config.ru +11 -0
  52. data/Plugins/Apps/gollum/gollum.conf.erb +41 -0
  53. data/Plugins/Apps/gollum/gollum.lmm.rb +52 -0
  54. data/Plugins/OS/Linux.lmm.rb +64 -0
  55. data/Plugins/OS/Routers/Aruba/ArubaInstant.lmm.rb +144 -0
  56. data/Plugins/Platforms/GitHub.lmm.rb +57 -0
  57. data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +83 -0
  58. data/Plugins/Platforms/GoDaddy/zone.txt.erb +13 -0
  59. data/Plugins/Platforms/porkbun.lmm.rb +129 -0
  60. data/Plugins/Platforms/porkbun_spec.rb +110 -0
  61. data/Plugins/Services/DNS/AmberBit.lmm.rb +14 -0
  62. data/Plugins/Services/DNS/ArubaItDNS.lmm.rb +14 -0
  63. data/Plugins/Services/DNS/NICLV.lmm.rb +18 -0
  64. data/Plugins/Services/DNS/PowerDNS.lmm.rb +261 -0
  65. data/Plugins/Services/DNS/tonic.lmm.rb +126 -0
  66. data/README.md +337 -0
  67. data/Rakefile +15 -0
  68. data/UNLICENSE +24 -0
  69. data/bin/configlmm +7 -0
  70. data/bin/console +11 -0
  71. data/bin/setup +8 -0
  72. data/lib/ConfigLMM/Framework/plugins/dns.rb +63 -0
  73. data/lib/ConfigLMM/Framework/plugins/errors.rb +23 -0
  74. data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +55 -0
  75. data/lib/ConfigLMM/Framework/plugins/plugin.rb +167 -0
  76. data/lib/ConfigLMM/Framework/plugins/ssh.rb +37 -0
  77. data/lib/ConfigLMM/Framework/plugins/store.rb +57 -0
  78. data/lib/ConfigLMM/Framework/plugins.rb +5 -0
  79. data/lib/ConfigLMM/Framework/registrator.rb +32 -0
  80. data/lib/ConfigLMM/Framework.rb +9 -0
  81. data/lib/ConfigLMM/LMM/plugins.rb +5 -0
  82. data/lib/ConfigLMM/LMM.rb +8 -0
  83. data/lib/ConfigLMM/cli.rb +161 -0
  84. data/lib/ConfigLMM/command.rb +53 -0
  85. data/lib/ConfigLMM/commands/build.rb +41 -0
  86. data/lib/ConfigLMM/commands/cleanup.rb +30 -0
  87. data/lib/ConfigLMM/commands/configsCommand.rb +167 -0
  88. data/lib/ConfigLMM/commands/deploy.rb +39 -0
  89. data/lib/ConfigLMM/commands/diff.rb +45 -0
  90. data/lib/ConfigLMM/commands/list.rb +15 -0
  91. data/lib/ConfigLMM/commands/refresh.rb +46 -0
  92. data/lib/ConfigLMM/commands/types.rb +35 -0
  93. data/lib/ConfigLMM/commands/validate.rb +49 -0
  94. data/lib/ConfigLMM/context.rb +52 -0
  95. data/lib/ConfigLMM/io/configList.rb +98 -0
  96. data/lib/ConfigLMM/io/path.rb +48 -0
  97. data/lib/ConfigLMM/io/source.rb +47 -0
  98. data/lib/ConfigLMM/io.rb +2 -0
  99. data/lib/ConfigLMM/state.rb +78 -0
  100. data/lib/ConfigLMM/utils/filters.rb +126 -0
  101. data/lib/ConfigLMM/version.rb +5 -0
  102. data/lib/ConfigLMM.rb +6 -0
  103. data/sig/ConfigLMM.rbs +4 -0
  104. metadata +485 -0
@@ -0,0 +1,23 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Odoo < Framework::NginxApp
5
+
6
+ def actionOdooBuild(id, target, state, context, options)
7
+ writeNginxConfig(__dir__, 'Odoo', id, target, state, context, options)
8
+ end
9
+
10
+ def actionOdooDiff(id, target, activeState, context, options)
11
+ # TODO
12
+ end
13
+
14
+ def actionOdooDeploy(id, target, activeState, context, options)
15
+ if !target['Location'] || target['Location'] == '@me'
16
+ deployNginxConfig(id, target, activeState, context, options)
17
+ activeState['Location'] = '@me'
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,50 @@
1
+
2
+
3
+ server {
4
+
5
+ <% if !config['TLS'] %>
6
+ listen <%= config['Port'] %>;
7
+ listen [::]:<%= config['Port'] %>;
8
+ <% else %>
9
+ listen <%= config['Port'] %> ssl;
10
+ listen [::]:<%= config['Port'] %> ssl;
11
+ http2 on;
12
+ include config-lmm/ssl.conf;
13
+ <% end %>
14
+
15
+ server_name <%= config['Domain'] %>;
16
+
17
+ access_log /var/log/nginx/pterodactyl.access.log;
18
+ error_log /var/log/nginx/pterodactyl.error.log;
19
+
20
+ include config-lmm/private.conf;
21
+ include config-lmm/errors.conf;
22
+
23
+ root /usr/share/webapps/pterodactyl/public/;
24
+ index index.php;
25
+
26
+ # allow larger file uploads and longer script runtimes
27
+ client_max_body_size 100m;
28
+ client_body_timeout 120s;
29
+
30
+ sendfile off;
31
+
32
+ location / {
33
+ try_files $uri $uri/ /index.php?$query_string;
34
+ }
35
+
36
+ location ~ \.php$ {
37
+ fastcgi_pass unix:/run/php-fpm/php-fpm-pterodactyl.sock;
38
+ include fastcgi.conf;
39
+ fastcgi_param HTTP_PROXY "";
40
+ fastcgi_buffer_size 16k;
41
+ fastcgi_buffers 4 16k;
42
+
43
+ fastcgi_send_timeout 300;
44
+ fastcgi_read_timeout 300;
45
+ }
46
+
47
+ location ~ /\.ht {
48
+ include config-lmm/private.conf;
49
+ }
50
+ }
@@ -0,0 +1,30 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Pterodactyl < Framework::NginxApp
5
+
6
+ def actionPterodactylBuild(id, target, state, context, options)
7
+ writeNginxConfig(__dir__, 'Pterodactyl', id, target, state, context, options)
8
+ end
9
+
10
+ def actionPterodactylDeploy(id, target, activeState, context, options)
11
+ if !target['Location'] || target['Location'] == '@me'
12
+ deployNginxConfig(id, target, activeState, context, options)
13
+ activeState['Location'] = '@me'
14
+ end
15
+ end
16
+
17
+ def actionWingsBuild(id, target, state, context, options)
18
+ writeNginxConfig(__dir__, 'Wings', id, target, state, context, options)
19
+ end
20
+
21
+ def actionWingsDeploy(id, target, activeState, context, options)
22
+ if !target['Location'] || target['Location'] == '@me'
23
+ deployNginxConfig(id, target, activeState, context, options)
24
+ activeState['Location'] = '@me'
25
+ end
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,38 @@
1
+
2
+ upstream wings {
3
+ server 127.0.0.1:1200;
4
+ }
5
+
6
+ server {
7
+
8
+ <% if !config['TLS'] %>
9
+ listen <%= config['Port'] %>;
10
+ listen [::]:<%= config['Port'] %>;
11
+ <% else %>
12
+ listen <%= config['Port'] %> ssl;
13
+ listen [::]:<%= config['Port'] %> ssl;
14
+ http2 on;
15
+ include config-lmm/ssl.conf;
16
+ <% end %>
17
+
18
+ server_name <%= config['Domain'] %>;
19
+
20
+ access_log /var/log/nginx/wings.access.log;
21
+ error_log /var/log/nginx/wings.error.log;
22
+
23
+ include config-lmm/private.conf;
24
+ include config-lmm/errors.conf;
25
+
26
+ location / {
27
+ proxy_pass http://wings;
28
+
29
+ include config/proxy.conf;
30
+ }
31
+
32
+ location ~ \/ws$ {
33
+ proxy_pass http://wings;
34
+
35
+ include config/proxy.conf;
36
+ }
37
+
38
+ }
@@ -0,0 +1,31 @@
1
+
2
+ upstream sunshine {
3
+ server 127.0.0.1:47990 fail_timeout=0;
4
+ }
5
+
6
+ server {
7
+
8
+ <% if !config['TLS'] %>
9
+ listen <%= config['Port'] %>;
10
+ listen [::]:<%= config['Port'] %>;
11
+ <% else %>
12
+ listen <%= config['Port'] %> ssl;
13
+ listen [::]:<%= config['Port'] %> ssl;
14
+ http2 on;
15
+ include config-lmm/ssl.conf;
16
+ <% end %>
17
+
18
+ server_name <%= config['Domain'] %>;
19
+
20
+ access_log /var/log/nginx/sunshine.access.log;
21
+ error_log /var/log/nginx/sunshine.error.log;
22
+
23
+ include config-lmm/private.conf;
24
+ include config-lmm/errors.conf;
25
+
26
+ location / {
27
+ proxy_pass https://sunshine;
28
+ include config-lmm/proxy.conf;
29
+ }
30
+
31
+ }
@@ -0,0 +1,21 @@
1
+
2
+ require 'fileutils'
3
+
4
+ module ConfigLMM
5
+ module LMM
6
+ class Sunshine < Framework::NginxApp
7
+
8
+ def actionSunshineBuild(id, target, state, context, options)
9
+ writeNginxConfig(__dir__, 'Sunshine', id, target, state, context, options)
10
+ end
11
+
12
+ def actionSunshineDeploy(id, target, activeState, context, options)
13
+ if !target['Location'] || target['Location'] == '@me'
14
+ deployNginxConfig(id, target, activeState, context, options)
15
+ activeState['Location'] = '@me'
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+
2
+ upstream vaultwarden {
3
+ server 127.0.0.1:8000;
4
+ }
5
+
6
+ upstream vaultwarden-websocket {
7
+ server 127.0.0.1:3012;
8
+ }
9
+
10
+ server {
11
+
12
+ <% if !config['TLS'] %>
13
+ listen <%= config['Port'] %>;
14
+ listen [::]:<%= config['Port'] %>;
15
+ <% else %>
16
+ listen <%= config['Port'] %> ssl;
17
+ listen [::]:<%= config['Port'] %> ssl;
18
+ http2 on;
19
+ include config-lmm/ssl.conf;
20
+ <% end %>
21
+
22
+ server_name <%= config['Domain'] %>;
23
+
24
+ <% if config['Private'] %>
25
+ include config-lmm/private.conf;
26
+ <% end %>
27
+
28
+ access_log /var/log/nginx/vaultwarden.access.log;
29
+ error_log /var/log/nginx/vaultwarden.error.log;
30
+
31
+ client_max_body_size 200M;
32
+
33
+ include config-lmm/errors.conf;
34
+
35
+ location / {
36
+ proxy_pass http://vaultwarden;
37
+ include config-lmm/proxy.conf;
38
+ }
39
+
40
+ location /notifications/ {
41
+ proxy_pass http://vaultwarden-websocket/;
42
+
43
+ proxy_set_header Upgrade $http_upgrade;
44
+ proxy_set_header Connection "upgrade";
45
+ include config-lmm/proxy.conf;
46
+ }
47
+
48
+ }
@@ -0,0 +1,25 @@
1
+
2
+ require 'fileutils'
3
+
4
+ module ConfigLMM
5
+ module LMM
6
+ class Vaultwarden < Framework::NginxApp
7
+
8
+ def actionVaultwardenBuild(id, target, state, context, options)
9
+ writeNginxConfig(__dir__, 'Vaultwarden', id, target, state, context, options)
10
+ end
11
+
12
+ def actionVaultwardenDiff(id, target, activeState, context, options)
13
+ # TODO
14
+ end
15
+
16
+ def actionVaultwardenDeploy(id, target, activeState, context, options)
17
+ if !target['Location'] || target['Location'] == '@me'
18
+ deployNginxConfig(id, target, activeState, context, options)
19
+ activeState['Location'] = '@me'
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+
2
+ upstream bitmagnet {
3
+ server 127.0.0.1:3333;
4
+ }
5
+
6
+ server {
7
+ <% if !config['TLS'] %>
8
+ listen <%= config['Port'] %>;
9
+ listen [::]:<%= config['Port'] %>;
10
+ <% else %>
11
+ listen <%= config['Port'] %> ssl;
12
+ listen [::]:<%= config['Port'] %> ssl;
13
+ http2 on;
14
+ include config-lmm/ssl.conf;
15
+ <% end %>
16
+
17
+ server_name <%= config['Domain'] %>;
18
+
19
+ access_log /var/log/nginx/bitmagnet.access.log;
20
+ error_log /var/log/nginx/bitmagnet.error.log;
21
+
22
+ include config-lmm/private.conf;
23
+ include config-lmm/errors.conf;
24
+
25
+ location / {
26
+ proxy_pass http://bitmagnet;
27
+ include config-lmm/proxy.conf;
28
+ }
29
+
30
+ location = /graphql {
31
+ proxy_read_timeout 10m;
32
+ proxy_pass http://bitmagnet;
33
+ include config-lmm/proxy.conf;
34
+ }
35
+ }
@@ -0,0 +1,19 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Bitmagnet < Framework::NginxApp
5
+
6
+ def actionBitmagnetBuild(id, target, state, context, options)
7
+ writeNginxConfig(__dir__, 'bitmagnet', id, target, state, context, options)
8
+ end
9
+
10
+ def actionBitmagnetDeploy(id, target, activeState, context, options)
11
+ if !target['Location'] || target['Location'] == '@me'
12
+ deployNginxConfig(id, target, activeState, context, options)
13
+ activeState['Location'] = '@me'
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'gollum/app'
4
+
5
+ gollum_path = File.expand_path(File.dirname(__FILE__)) + '/repo'
6
+
7
+ wiki_options = {:universal_toc => false}
8
+ Precious::App.set(:gollum_path, gollum_path)
9
+ Precious::App.set(:default_markup, :markdown) # set your favorite markup language
10
+ Precious::App.set(:wiki_options, wiki_options)
11
+ run Precious::App
@@ -0,0 +1,41 @@
1
+
2
+ server {
3
+
4
+ <% if !config['TLS'] %>
5
+ listen <%= config['Port'] %>;
6
+ listen [::]:<%= config['Port'] %>;
7
+ <% else %>
8
+ listen <%= config['Port'] %> ssl;
9
+ listen [::]:<%= config['Port'] %> ssl;
10
+ http2 on;
11
+ include config-lmm/ssl.conf;
12
+ <% end %>
13
+
14
+ server_name <%= config['Domain'] %>;
15
+
16
+ root <%= config['Root'] %>;
17
+ passenger_app_root /srv/gollum;
18
+
19
+ try_files $uri @Passenger;
20
+
21
+ access_log /var/log/nginx/gollum.access.log;
22
+ error_log /var/log/nginx/gollum.error.log;
23
+
24
+ include config-lmm/private.conf;
25
+ include config-lmm/errors.conf;
26
+
27
+ <% if config['CertName'] %>
28
+ ssl_certificate "/etc/letsencrypt/live/<%= config['CertName'] %>/fullchain.pem";
29
+ ssl_certificate_key "/etc/letsencrypt/live/<%= config['CertName'] %>/privkey.pem";
30
+ ssl_trusted_certificate "/etc/letsencrypt/live/<%= config['CertName'] %>/chain.pem";
31
+ <% end %>
32
+
33
+ location @Passenger {
34
+ passenger_enabled on;
35
+ passenger_min_instances 1;
36
+ rails_env production;
37
+
38
+ #passenger_set_cgi_param HTTP_X_FORWARDED_PROTO https;
39
+ #limit_req zone=one burst=5;
40
+ }
41
+ }
@@ -0,0 +1,52 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Gollum < Framework::NginxApp
5
+
6
+ NAME = 'gollum'
7
+ GOLLUM_PATH = '/srv/gollum'
8
+
9
+ def actionGollumBuild(id, target, activeState, context, options)
10
+ if !target['Root'] && (!target['Location'] || target['Location'] == '@me')
11
+ target['Root'] = File.dirname(`gem which gollum`.strip) + '/gollum/public'
12
+ end
13
+ writeNginxConfig(__dir__, NAME, id, target, activeState, context, options)
14
+ targetDir = options['output'] + GOLLUM_PATH
15
+ mkdir(targetDir, options['dry'])
16
+ copy(__dir__ + '/config.ru', targetDir, options['dry'])
17
+ `git init #{targetDir}/repo`
18
+ end
19
+
20
+ def actionGollumRefresh(id, target, activeState, context, options)
21
+ # Would need to parse deployed config to implement
22
+ end
23
+
24
+ def actionGollumDeploy(id, target, activeState, context, options)
25
+ if !target['Location'] || target['Location'] == '@me'
26
+ targetDir = GOLLUM_PATH
27
+ mkdir(targetDir, options['dry'])
28
+ deployNginxConfig(id, target, activeState, context, options)
29
+ copy(options['output'] + GOLLUM_PATH + '/config.ru', GOLLUM_PATH, options['dry'])
30
+ copyNotPresent(options['output'] + GOLLUM_PATH + '/repo', GOLLUM_PATH, options['dry'])
31
+ chown('http', 'http', GOLLUM_PATH, options['dry'])
32
+ activeState['Location'] = '@me'
33
+ else
34
+ # TODO
35
+ end
36
+ end
37
+
38
+ def cleanup(configs, state, context, options)
39
+ items = state.selectType(:Gollum)
40
+ items.each do |id, item|
41
+ if !configs.key?(id)
42
+ if item['Location'] == '@me'
43
+ cleanupNginxConfig(NAME, id, state, context, options)
44
+ else
45
+ # TODO
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,64 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Linux < Framework::Plugin
5
+
6
+ HOSTS_FILE = '/etc/hosts'
7
+ HOSTS_SECTION_BEGIN = "# -----BEGIN CONFIGLMM-----\n"
8
+ HOSTS_SECTION_END = "# -----END CONFIGLMM-----\n"
9
+
10
+ def actionLinuxBuild(id, target, activeState, context, options)
11
+ if target['Hosts']
12
+ hosts = "#\n"
13
+ hosts += "# /etc/hosts: static lookup table for host names\n"
14
+ hosts += "#\n\n"
15
+ hosts += "#<ip-address> <hostname.domain.org> <hostname>\n"
16
+ hosts += "127.0.0.1 localhost\n"
17
+ hosts += "::1 localhost\n\n"
18
+ hosts += HOSTS_SECTION_BEGIN
19
+ target['Hosts'].each do |ip, entries|
20
+ hosts += ip.ljust(16) + entries.join(' ') + "\n"
21
+ end
22
+ hosts += HOSTS_SECTION_END
23
+
24
+ mkdir(options['output'] + '/etc', options[:dry])
25
+ fileWrite(options['output'] + HOSTS_FILE, hosts, options[:dry])
26
+ end
27
+ end
28
+
29
+ def actionLinuxDeploy(id, target, activeState, context, options)
30
+ if !target['Location'] || target['Location'] == '@me'
31
+ if target['Hosts']
32
+ hostsLines = File.read(HOSTS_FILE).lines
33
+ sectionBeginIndex = hostsLines.index(HOSTS_SECTION_BEGIN)
34
+ sectionEndIndex = hostsLines.index(HOSTS_SECTION_END)
35
+ if sectionBeginIndex.nil?
36
+ linesBefore = hostsLines
37
+ linesBefore << "\n"
38
+ linesBefore << HOSTS_SECTION_BEGIN
39
+ linesAfter = [HOSTS_SECTION_END]
40
+ linesAfter << "\n"
41
+ else
42
+ linesBefore = hostsLines[0..sectionBeginIndex]
43
+ if sectionEndIndex.nil?
44
+ linesAfter = [HOSTS_SECTION_END]
45
+ linesAfter << "\n"
46
+ else
47
+ linesAfter = hostsLines[sectionEndIndex..hostsLines.length]
48
+ end
49
+ end
50
+
51
+ hostsLines = linesBefore
52
+ target['Hosts'].each do |ip, entries|
53
+ hostsLines << ip.ljust(16) + entries.join(' ') + "\n"
54
+ end
55
+ hostsLines += linesAfter
56
+
57
+ fileWrite(HOSTS_FILE, hostsLines.join(), options[:dry])
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,144 @@
1
+
2
+ require 'expect'
3
+ require 'securerandom'
4
+ require 'socket'
5
+ require 'pty'
6
+ require 'tty-which'
7
+ require 'webrick'
8
+
9
+ module ConfigLMM
10
+ module LMM
11
+ class ArubaInstant < Framework::SSH
12
+
13
+ CERT_BASE = '/etc/letsencrypt/live/'
14
+ HTTP_PORT = 6582
15
+
16
+ def actionArubaInstantDeploy(id, target, activeState, context, options)
17
+ if !target['Location']
18
+ raise Framework::PluginProcessError.new(id + ': Location must be provided!')
19
+ end
20
+ if target['CertificateName']
21
+ fullchain = CERT_BASE + target['CertificateName'] + '/fullchain.pem'
22
+ privkey = CERT_BASE + target['CertificateName'] + '/privkey.pem'
23
+ if !File.exist?(fullchain) || !File.exist?(privkey)
24
+ prompt.error('Couldn\'t find certificate!')
25
+ prompt.error("Looked at #{fullchain} and #{privkey}")
26
+ raise Framework::PluginProcessError.new(id + ': Certificate not found!')
27
+ end
28
+ certData = File.read(fullchain)
29
+ certData += File.read(privkey)
30
+ certFileName = SecureRandom.hex(10)
31
+ File.write(options['output'] + '/' + certFileName, certData)
32
+
33
+ httpThread = Thread.new do
34
+ server = WEBrick::HTTPServer.new(Port: HTTP_PORT,
35
+ DocumentRoot: options['output'],
36
+ Logger: WEBrick::Log.new("/dev/null"),
37
+ AccessLog: [])
38
+ server.start
39
+ end
40
+
41
+ ourIP = Socket.ip_address_list.select { |addr| addr.ipv4_private? }.first.ip_address
42
+
43
+ firewallcmd = TTY::Which.which("firewall-cmd")
44
+ if firewallcmd
45
+ `#{firewallcmd} --add-port #{HTTP_PORT}/tcp >/dev/null 2>&1`
46
+ end
47
+
48
+ creds = parseLocation(target['Location'])
49
+ password = ENV['ARUBA_INSTANT_PASSWORD']
50
+
51
+ # Couldn't get it working with net-ssh gem so using `ssh` as workaround
52
+ # Net::SSH.start(creds[:hostname], creds[:user], password: password, port: creds[:port]) do |ssh|
53
+ PTY.spawn("ssh -o NumberOfPasswordPrompts=1 -o HostKeyAlgorithms=ssh-rsa #{creds[:user]}@#{creds[:hostname]}") do |reader, writer, pid|
54
+ reader.expect(/password:/) do |result|
55
+ writer.puts(password)
56
+ end
57
+
58
+ output = ''
59
+ lastWrite = nil
60
+ error = nil
61
+ thread = Thread.new do
62
+ reader.each do |line|
63
+ output += line
64
+ lastWrite = Time.now.to_f
65
+ end
66
+ rescue SystemCallError => err
67
+ # Most likely wrong password
68
+ error = err
69
+ end
70
+ while lastWrite.nil? || Time.now.to_f - lastWrite < 5 # It takes while to respond
71
+ sleep(0.2)
72
+ if error
73
+ raise Framework::PluginProcessError.new(id + ': ' + error.message)
74
+ end
75
+ end
76
+ output = ''
77
+ lastWrite = nil
78
+ writer.puts('show version')
79
+ while lastWrite.nil? || Time.now.to_f - lastWrite < 2
80
+ sleep(0.2)
81
+ end
82
+ thread.terminate
83
+ if output.include?('ArubaOS')
84
+ result = output.match(/MODEL: (\d+)., Version ([\d\.]+)/)
85
+ prompt.say("ArubaOS Version: #{result[2]}")
86
+ prompt.say("MODEL: #{result[1]}")
87
+ if result[1] == '275'
88
+ output = ''
89
+ lastWrite = nil
90
+ # See Aruba Instant 8.x Command-Line Interface Reference Guide
91
+ # download-cert ui <url> format pem [psk <psk>]
92
+ writer.puts("download-cert ui http://#{ourIP}:#{HTTP_PORT}/#{certFileName}")
93
+ thread = Thread.new do
94
+ reader.each do |line|
95
+ output += line
96
+ lastWrite = Time.now.to_f
97
+ prompt.say(line)
98
+ end
99
+ end
100
+ while lastWrite.nil? || Time.now.to_f - lastWrite < 4
101
+ sleep(0.2)
102
+ end
103
+ thread.terminate
104
+ if output.include?('error')
105
+ message = 'Something went wrong! :('
106
+ prompt.error(message)
107
+ raise Framework::PluginProcessError.new(id + ': ' + message)
108
+ end
109
+ else
110
+ message = 'Not risking with untested device! Please test and submit PR! :)'
111
+ prompt.error(message)
112
+ raise Framework::PluginProcessError.new(id + ': ' + message)
113
+ end
114
+ else
115
+ message = 'This is not Aruba device!'
116
+ prompt.error(message)
117
+ raise Framework::PluginProcessError.new(id + ': ' + message)
118
+ end
119
+ reader.close
120
+ writer.close
121
+ rescue Framework::PluginProcessError => error
122
+ `#{firewallcmd} --remove-port #{HTTP_PORT}/tcp` if firewallcmd
123
+ raise error
124
+ end
125
+ httpThread.terminate
126
+ `#{firewallcmd} --remove-port #{HTTP_PORT}/tcp` if firewallcmd
127
+ end
128
+ end
129
+
130
+ def authenticate(actionMethod, target, activeState, context, options)
131
+ if ENV['ARUBA_INSTANT_PASSWORD'].to_s.empty? || ENV['ARUBA_INSTANT_PASSWORD'].to_s.empty?
132
+ prompt.error('Set your Aruba Instant SSH password to ARUBA_INSTANT_PASSWORD as Environment Variable')
133
+ raise Framework::PluginPrerequisite.new('Need ARUBA_INSTANT_PASSWORD')
134
+ else
135
+ if !target['Location']
136
+ raise Framework::PluginProcessError.new('Location must be provided!')
137
+ end
138
+ checkSSHAuth!(target['Location'], ENV['ARUBA_INSTANT_PASSWORD'])
139
+ end
140
+ true
141
+ end
142
+ end
143
+ end
144
+ end