cloud-mu 1.9.0.pre.beta

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 (618) hide show
  1. checksums.yaml +7 -0
  2. data/Berksfile +56 -0
  3. data/Berksfile.lock +250 -0
  4. data/Jenkinsfile +184 -0
  5. data/LICENSE.md +37 -0
  6. data/README.md +26 -0
  7. data/bin/mu-aws-setup +376 -0
  8. data/bin/mu-cleanup +68 -0
  9. data/bin/mu-configure +1133 -0
  10. data/bin/mu-deploy +166 -0
  11. data/bin/mu-firewall-allow-clients +30 -0
  12. data/bin/mu-gcp-setup +200 -0
  13. data/bin/mu-gen-docs +34 -0
  14. data/bin/mu-gen-env +42 -0
  15. data/bin/mu-load-config.rb +158 -0
  16. data/bin/mu-node-manage +683 -0
  17. data/bin/mu-self-update +228 -0
  18. data/bin/mu-ssh +23 -0
  19. data/bin/mu-tunnel-nagios +144 -0
  20. data/bin/mu-upload-chef-artifacts +757 -0
  21. data/bin/mu-user-manage +275 -0
  22. data/cookbooks/awscli/LICENSE +37 -0
  23. data/cookbooks/awscli/README.md +58 -0
  24. data/cookbooks/awscli/attributes/default.rb +1 -0
  25. data/cookbooks/awscli/libraries/instance_metadata.rb +21 -0
  26. data/cookbooks/awscli/metadata.rb +20 -0
  27. data/cookbooks/awscli/recipes/default.rb +56 -0
  28. data/cookbooks/awscli/templates/default/config.erb +18 -0
  29. data/cookbooks/mu-activedirectory/CHANGELOG.md +13 -0
  30. data/cookbooks/mu-activedirectory/LICENSE +37 -0
  31. data/cookbooks/mu-activedirectory/README.md +6 -0
  32. data/cookbooks/mu-activedirectory/attributes/default.rb +98 -0
  33. data/cookbooks/mu-activedirectory/files/default/password-auth +32 -0
  34. data/cookbooks/mu-activedirectory/files/default/sshd_pol.pp +0 -0
  35. data/cookbooks/mu-activedirectory/files/default/sshd_pol.te +32 -0
  36. data/cookbooks/mu-activedirectory/files/default/syslogd_oddjobd.pp +0 -0
  37. data/cookbooks/mu-activedirectory/files/default/syslogd_oddjobd.te +10 -0
  38. data/cookbooks/mu-activedirectory/files/default/system-auth +34 -0
  39. data/cookbooks/mu-activedirectory/files/default/winbindpol.pp +0 -0
  40. data/cookbooks/mu-activedirectory/files/default/winbindpol.te +37 -0
  41. data/cookbooks/mu-activedirectory/libraries/config.rb +106 -0
  42. data/cookbooks/mu-activedirectory/libraries/helper.rb +86 -0
  43. data/cookbooks/mu-activedirectory/metadata.rb +17 -0
  44. data/cookbooks/mu-activedirectory/providers/domain.rb +152 -0
  45. data/cookbooks/mu-activedirectory/providers/domain_controller.rb +89 -0
  46. data/cookbooks/mu-activedirectory/providers/domain_node.rb +275 -0
  47. data/cookbooks/mu-activedirectory/recipes/default.rb +8 -0
  48. data/cookbooks/mu-activedirectory/recipes/domain-controller.rb +44 -0
  49. data/cookbooks/mu-activedirectory/recipes/domain-node.rb +50 -0
  50. data/cookbooks/mu-activedirectory/recipes/domain.rb +43 -0
  51. data/cookbooks/mu-activedirectory/recipes/sssd.rb +185 -0
  52. data/cookbooks/mu-activedirectory/resources/domain.rb +25 -0
  53. data/cookbooks/mu-activedirectory/resources/domain_controller.rb +25 -0
  54. data/cookbooks/mu-activedirectory/resources/domain_node.rb +20 -0
  55. data/cookbooks/mu-activedirectory/templates/default/dhclient-eth0.conf.erb +4 -0
  56. data/cookbooks/mu-activedirectory/templates/default/interface +0 -0
  57. data/cookbooks/mu-activedirectory/templates/default/krb5.conf.erb +23 -0
  58. data/cookbooks/mu-activedirectory/templates/default/ntp.conf.erb +56 -0
  59. data/cookbooks/mu-activedirectory/templates/default/smb.conf.erb +33 -0
  60. data/cookbooks/mu-activedirectory/templates/default/sssd.conf.erb +60 -0
  61. data/cookbooks/mu-activedirectory/templates/windows/Backup.xml.erb +20 -0
  62. data/cookbooks/mu-activedirectory/templates/windows/bkupInfo.xml.erb +1 -0
  63. data/cookbooks/mu-activedirectory/templates/windows/gpreprt.xml.erb +198 -0
  64. data/cookbooks/mu-activedirectory/templates/windows/gptmpl.inf.erb +12 -0
  65. data/cookbooks/mu-activedirectory/templates/windows/manifest.xml.erb +1 -0
  66. data/cookbooks/mu-firewall/CHANGELOG.md +11 -0
  67. data/cookbooks/mu-firewall/LICENSE +37 -0
  68. data/cookbooks/mu-firewall/README.md +5 -0
  69. data/cookbooks/mu-firewall/attributes/default.rb +3 -0
  70. data/cookbooks/mu-firewall/metadata.rb +16 -0
  71. data/cookbooks/mu-firewall/recipes/default.rb +10 -0
  72. data/cookbooks/mu-glusterfs/CHANGELOG.md +13 -0
  73. data/cookbooks/mu-glusterfs/LICENSE +37 -0
  74. data/cookbooks/mu-glusterfs/README.md +5 -0
  75. data/cookbooks/mu-glusterfs/attributes/default.rb +34 -0
  76. data/cookbooks/mu-glusterfs/metadata.rb +17 -0
  77. data/cookbooks/mu-glusterfs/recipes/client.rb +62 -0
  78. data/cookbooks/mu-glusterfs/recipes/default.rb +16 -0
  79. data/cookbooks/mu-glusterfs/recipes/samba.rb +57 -0
  80. data/cookbooks/mu-glusterfs/recipes/server.rb +200 -0
  81. data/cookbooks/mu-glusterfs/templates/default/mu-gluster-client.erb +71 -0
  82. data/cookbooks/mu-glusterfs/templates/default/smb.conf.erb +14 -0
  83. data/cookbooks/mu-jenkins/CHANGELOG.md +13 -0
  84. data/cookbooks/mu-jenkins/LICENSE +37 -0
  85. data/cookbooks/mu-jenkins/README.md +105 -0
  86. data/cookbooks/mu-jenkins/attributes/default.rb +42 -0
  87. data/cookbooks/mu-jenkins/files/default/cleanup_deploy_config.xml +73 -0
  88. data/cookbooks/mu-jenkins/files/default/deploy_config.xml +44 -0
  89. data/cookbooks/mu-jenkins/metadata.rb +21 -0
  90. data/cookbooks/mu-jenkins/recipes/default.rb +195 -0
  91. data/cookbooks/mu-jenkins/recipes/node-ssh-config.rb +54 -0
  92. data/cookbooks/mu-jenkins/recipes/public_key.rb +24 -0
  93. data/cookbooks/mu-jenkins/templates/default/example_job.config.xml.erb +24 -0
  94. data/cookbooks/mu-jenkins/templates/default/org.jvnet.hudson.plugins.SSHBuildWrapper.xml.erb +14 -0
  95. data/cookbooks/mu-jenkins/templates/default/ssh_config.erb +6 -0
  96. data/cookbooks/mu-master/CHANGELOG.md +13 -0
  97. data/cookbooks/mu-master/LICENSE +37 -0
  98. data/cookbooks/mu-master/README.md +6 -0
  99. data/cookbooks/mu-master/attributes/default.rb +95 -0
  100. data/cookbooks/mu-master/files/default/0-mu-log-server.conf +19 -0
  101. data/cookbooks/mu-master/files/default/addRSA.ldif +8 -0
  102. data/cookbooks/mu-master/files/default/check_mem.pl +197 -0
  103. data/cookbooks/mu-master/files/default/cloudamatic.png +0 -0
  104. data/cookbooks/mu-master/files/default/dirsrv_admin.pp +0 -0
  105. data/cookbooks/mu-master/files/default/dirsrv_admin.te +13 -0
  106. data/cookbooks/mu-master/files/default/nagios_selinux.pp +0 -0
  107. data/cookbooks/mu-master/files/default/nagios_selinux.te +51 -0
  108. data/cookbooks/mu-master/files/default/nagios_selinux_7.pp +0 -0
  109. data/cookbooks/mu-master/files/default/nagios_selinux_7.te +17 -0
  110. data/cookbooks/mu-master/files/default/pam_sshd +18 -0
  111. data/cookbooks/mu-master/files/default/ssl_enable.ldif +18 -0
  112. data/cookbooks/mu-master/files/default/syslogd_oddjobd.pp +0 -0
  113. data/cookbooks/mu-master/files/default/syslogd_oddjobd.te +10 -0
  114. data/cookbooks/mu-master/files/default/vimrc +19 -0
  115. data/cookbooks/mu-master/libraries/mu.rb +29 -0
  116. data/cookbooks/mu-master/metadata.rb +30 -0
  117. data/cookbooks/mu-master/providers/user.rb +41 -0
  118. data/cookbooks/mu-master/recipes/389ds.rb +164 -0
  119. data/cookbooks/mu-master/recipes/basepackages.rb +58 -0
  120. data/cookbooks/mu-master/recipes/caching_nameserver.rb +37 -0
  121. data/cookbooks/mu-master/recipes/default.rb +451 -0
  122. data/cookbooks/mu-master/recipes/eks-kubectl.rb +41 -0
  123. data/cookbooks/mu-master/recipes/firewall-holes.rb +70 -0
  124. data/cookbooks/mu-master/recipes/init.rb +542 -0
  125. data/cookbooks/mu-master/recipes/ssl-certs.rb +109 -0
  126. data/cookbooks/mu-master/recipes/sssd.rb +89 -0
  127. data/cookbooks/mu-master/recipes/update_nagios_only.rb +242 -0
  128. data/cookbooks/mu-master/recipes/vault.rb +111 -0
  129. data/cookbooks/mu-master/resources/user.rb +19 -0
  130. data/cookbooks/mu-master/templates/default/389-directory-setup.inf.erb +28 -0
  131. data/cookbooks/mu-master/templates/default/chef-server.rb.erb +18 -0
  132. data/cookbooks/mu-master/templates/default/dhclient-eth0.conf.erb +9 -0
  133. data/cookbooks/mu-master/templates/default/mu-momma-cat.erb +149 -0
  134. data/cookbooks/mu-master/templates/default/mu.rc.erb +9 -0
  135. data/cookbooks/mu-master/templates/default/openssl.cnf.erb +354 -0
  136. data/cookbooks/mu-master/templates/default/sssd.conf.erb +44 -0
  137. data/cookbooks/mu-master/templates/default/web_app.conf.erb +90 -0
  138. data/cookbooks/mu-mongo/CHANGELOG.md +13 -0
  139. data/cookbooks/mu-mongo/LICENSE +37 -0
  140. data/cookbooks/mu-mongo/README.md +5 -0
  141. data/cookbooks/mu-mongo/attributes/default.rb +22 -0
  142. data/cookbooks/mu-mongo/files/default/keyfile +16 -0
  143. data/cookbooks/mu-mongo/files/default/remove_nodes.js +5 -0
  144. data/cookbooks/mu-mongo/metadata.rb +17 -0
  145. data/cookbooks/mu-mongo/recipes/default.rb +149 -0
  146. data/cookbooks/mu-mongo/recipes/yum-update-rule.rb +18 -0
  147. data/cookbooks/mu-mongo/templates/default/mongo_create_openfema_db.js.erb +2 -0
  148. data/cookbooks/mu-mongo/templates/default/mongo_init.js.erb +1 -0
  149. data/cookbooks/mu-mongo/templates/default/mongo_logrotate.erb +14 -0
  150. data/cookbooks/mu-mongo/templates/default/mongo_replset_addnodes.js.erb +6 -0
  151. data/cookbooks/mu-mongo/templates/default/replset_init.js.erb +2 -0
  152. data/cookbooks/mu-openvpn/CHANGELOG.md +13 -0
  153. data/cookbooks/mu-openvpn/LICENSE +37 -0
  154. data/cookbooks/mu-openvpn/README.md +6 -0
  155. data/cookbooks/mu-openvpn/attributes/default.rb +119 -0
  156. data/cookbooks/mu-openvpn/metadata.rb +18 -0
  157. data/cookbooks/mu-openvpn/recipes/default.rb +108 -0
  158. data/cookbooks/mu-openvpn/templates/default/users.json.erb +42 -0
  159. data/cookbooks/mu-php54/CHANGELOG.md +12 -0
  160. data/cookbooks/mu-php54/LICENSE +37 -0
  161. data/cookbooks/mu-php54/README.md +0 -0
  162. data/cookbooks/mu-php54/files/centos/php.ini +1802 -0
  163. data/cookbooks/mu-php54/files/ubuntu/php.ini +1870 -0
  164. data/cookbooks/mu-php54/metadata.rb +21 -0
  165. data/cookbooks/mu-php54/recipes/default.rb +97 -0
  166. data/cookbooks/mu-splunk/CHANGELOG.md +37 -0
  167. data/cookbooks/mu-splunk/LICENSE +37 -0
  168. data/cookbooks/mu-splunk/README.md +451 -0
  169. data/cookbooks/mu-splunk/attributes/default.rb +95 -0
  170. data/cookbooks/mu-splunk/attributes/upgrade.rb +49 -0
  171. data/cookbooks/mu-splunk/definitions/splunk_installer.rb +103 -0
  172. data/cookbooks/mu-splunk/files/default/splunk-nocheck +10 -0
  173. data/cookbooks/mu-splunk/libraries/helpers.rb +72 -0
  174. data/cookbooks/mu-splunk/libraries/splunk_app_provider.rb +156 -0
  175. data/cookbooks/mu-splunk/libraries/splunk_app_resource.rb +43 -0
  176. data/cookbooks/mu-splunk/metadata.json +30 -0
  177. data/cookbooks/mu-splunk/metadata.rb +17 -0
  178. data/cookbooks/mu-splunk/recipes/client.rb +143 -0
  179. data/cookbooks/mu-splunk/recipes/default.rb +31 -0
  180. data/cookbooks/mu-splunk/recipes/disabled.rb +41 -0
  181. data/cookbooks/mu-splunk/recipes/install_forwarder.rb +23 -0
  182. data/cookbooks/mu-splunk/recipes/install_server.rb +23 -0
  183. data/cookbooks/mu-splunk/recipes/server.rb +53 -0
  184. data/cookbooks/mu-splunk/recipes/service.rb +95 -0
  185. data/cookbooks/mu-splunk/recipes/setup_auth.rb +49 -0
  186. data/cookbooks/mu-splunk/recipes/setup_ssl.rb +63 -0
  187. data/cookbooks/mu-splunk/recipes/upgrade.rb +94 -0
  188. data/cookbooks/mu-splunk/recipes/user.rb +34 -0
  189. data/cookbooks/mu-splunk/templates/default/base_logs_unix_inputs.conf.erb +26 -0
  190. data/cookbooks/mu-splunk/templates/default/inputs.conf.erb +13 -0
  191. data/cookbooks/mu-splunk/templates/default/outputs.conf.erb +9 -0
  192. data/cookbooks/mu-splunk/templates/default/splunk-init.erb +74 -0
  193. data/cookbooks/mu-splunk/templates/default/system-web.conf.erb +7 -0
  194. data/cookbooks/mu-tools/CHANGELOG.md +12 -0
  195. data/cookbooks/mu-tools/LICENSE +37 -0
  196. data/cookbooks/mu-tools/README.md +188 -0
  197. data/cookbooks/mu-tools/attributes/default.rb +142 -0
  198. data/cookbooks/mu-tools/attributes/ebs_rolling_snapshots.rb +3 -0
  199. data/cookbooks/mu-tools/files/amazon/etc/freshclam.conf +235 -0
  200. data/cookbooks/mu-tools/files/centos/CentOS-Base.repo +52 -0
  201. data/cookbooks/mu-tools/files/centos/etc/bashrc +93 -0
  202. data/cookbooks/mu-tools/files/centos/etc/freshclam.conf +235 -0
  203. data/cookbooks/mu-tools/files/centos/etc/login.defs +72 -0
  204. data/cookbooks/mu-tools/files/centos/etc/profile +77 -0
  205. data/cookbooks/mu-tools/files/centos/etc/security/limits.conf +57 -0
  206. data/cookbooks/mu-tools/files/centos/etc/sysconfig/init +19 -0
  207. data/cookbooks/mu-tools/files/centos/etc/sysctl.conf +82 -0
  208. data/cookbooks/mu-tools/files/centos-6/README_MU +0 -0
  209. data/cookbooks/mu-tools/files/centos-6/etc/audit/stig.rules +173 -0
  210. data/cookbooks/mu-tools/files/centos-6/etc/bashrc +90 -0
  211. data/cookbooks/mu-tools/files/centos-6/etc/login.defs +70 -0
  212. data/cookbooks/mu-tools/files/centos-6/etc/pam.d/su +12 -0
  213. data/cookbooks/mu-tools/files/centos-6/etc/profile +83 -0
  214. data/cookbooks/mu-tools/files/centos-6/etc/securetty +12 -0
  215. data/cookbooks/mu-tools/files/centos-6/etc/sysconfig/init +30 -0
  216. data/cookbooks/mu-tools/files/centos-6/etc/sysctl.conf +40 -0
  217. data/cookbooks/mu-tools/files/default/Mu_CA.pem +34 -0
  218. data/cookbooks/mu-tools/files/default/PSWindowsUpdate.zip +0 -0
  219. data/cookbooks/mu-tools/files/default/ebs_snapshots.py +123 -0
  220. data/cookbooks/mu-tools/files/default/etc/BANNER +0 -0
  221. data/cookbooks/mu-tools/files/default/etc/BANNER-FEDERAL +19 -0
  222. data/cookbooks/mu-tools/files/default/gpo_no_uac.zip +0 -0
  223. data/cookbooks/mu-tools/files/default/mypol.pp +0 -0
  224. data/cookbooks/mu-tools/files/default/mypol.te +37 -0
  225. data/cookbooks/mu-tools/files/default/nrpe_c7.pp +0 -0
  226. data/cookbooks/mu-tools/files/default/nrpe_c7.te +31 -0
  227. data/cookbooks/mu-tools/files/default/nrpe_check_disk.pp +0 -0
  228. data/cookbooks/mu-tools/files/default/nrpe_check_disk.te +11 -0
  229. data/cookbooks/mu-tools/files/default/nrpe_disk.pp +0 -0
  230. data/cookbooks/mu-tools/files/default/nrpe_disk.te +10 -0
  231. data/cookbooks/mu-tools/files/default/nrpe_file.pp +0 -0
  232. data/cookbooks/mu-tools/files/default/nrpe_file.te +31 -0
  233. data/cookbooks/mu-tools/files/default/ntrights +0 -0
  234. data/cookbooks/mu-tools/files/default/serverclass.conf +18 -0
  235. data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_unix/local/app.conf +1 -0
  236. data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_unix/local/inputs.conf +13 -0
  237. data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_windows/local/app.conf +1 -0
  238. data/cookbooks/mu-tools/files/default/splunk-apps/base_logs_windows/local/inputs.conf +8 -0
  239. data/cookbooks/mu-tools/files/default/sshd_pol.pp +0 -0
  240. data/cookbooks/mu-tools/files/default/sshd_pol.te +32 -0
  241. data/cookbooks/mu-tools/files/redhat/etc/bashrc +93 -0
  242. data/cookbooks/mu-tools/files/redhat/etc/freshclam.conf +235 -0
  243. data/cookbooks/mu-tools/files/redhat/etc/login.defs +72 -0
  244. data/cookbooks/mu-tools/files/redhat/etc/profile +77 -0
  245. data/cookbooks/mu-tools/files/redhat/etc/security/limits.conf +57 -0
  246. data/cookbooks/mu-tools/files/redhat/etc/sysconfig/init +19 -0
  247. data/cookbooks/mu-tools/files/redhat/etc/sysctl.conf +82 -0
  248. data/cookbooks/mu-tools/files/redhat-6/README_MU +0 -0
  249. data/cookbooks/mu-tools/files/redhat-6/etc/audit/stig.rules +173 -0
  250. data/cookbooks/mu-tools/files/redhat-6/etc/bashrc +90 -0
  251. data/cookbooks/mu-tools/files/redhat-6/etc/login.defs +70 -0
  252. data/cookbooks/mu-tools/files/redhat-6/etc/pam.d/su +12 -0
  253. data/cookbooks/mu-tools/files/redhat-6/etc/profile +83 -0
  254. data/cookbooks/mu-tools/files/redhat-6/etc/securetty +12 -0
  255. data/cookbooks/mu-tools/files/redhat-6/etc/sysconfig/init +30 -0
  256. data/cookbooks/mu-tools/files/redhat-6/etc/sysctl.conf +40 -0
  257. data/cookbooks/mu-tools/files/redhat-7.1/etc/freshclam.conf +235 -0
  258. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/bash.bashrc +64 -0
  259. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/common-session +30 -0
  260. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/login.defs +338 -0
  261. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/profile +30 -0
  262. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/security/limits.conf +56 -0
  263. data/cookbooks/mu-tools/files/ubuntu-12.04/etc/sysctl.conf +60 -0
  264. data/cookbooks/mu-tools/libraries/helper.rb +292 -0
  265. data/cookbooks/mu-tools/metadata.rb +28 -0
  266. data/cookbooks/mu-tools/recipes/add_admin_ssh_keys.rb +35 -0
  267. data/cookbooks/mu-tools/recipes/apply_security.rb +440 -0
  268. data/cookbooks/mu-tools/recipes/aws_api.rb +23 -0
  269. data/cookbooks/mu-tools/recipes/base_repositories.rb +31 -0
  270. data/cookbooks/mu-tools/recipes/cisbenchmark.rb +59 -0
  271. data/cookbooks/mu-tools/recipes/clamav.rb +53 -0
  272. data/cookbooks/mu-tools/recipes/cloudinit.rb +58 -0
  273. data/cookbooks/mu-tools/recipes/configure_oracle_tools.rb +81 -0
  274. data/cookbooks/mu-tools/recipes/disable-requiretty.rb +22 -0
  275. data/cookbooks/mu-tools/recipes/ebs_rolling_snapshots.rb +75 -0
  276. data/cookbooks/mu-tools/recipes/efs.rb +70 -0
  277. data/cookbooks/mu-tools/recipes/eks.rb +160 -0
  278. data/cookbooks/mu-tools/recipes/gcloud.rb +98 -0
  279. data/cookbooks/mu-tools/recipes/google_api.rb +25 -0
  280. data/cookbooks/mu-tools/recipes/maldet.rb +67 -0
  281. data/cookbooks/mu-tools/recipes/nagios.rb +19 -0
  282. data/cookbooks/mu-tools/recipes/newclient.rb +23 -0
  283. data/cookbooks/mu-tools/recipes/nrpe.rb +115 -0
  284. data/cookbooks/mu-tools/recipes/python_pip.rb +35 -0
  285. data/cookbooks/mu-tools/recipes/retrieve_application.rb +51 -0
  286. data/cookbooks/mu-tools/recipes/rsyslog.rb +65 -0
  287. data/cookbooks/mu-tools/recipes/set_local_fw.rb +57 -0
  288. data/cookbooks/mu-tools/recipes/set_mu_hostname.rb +81 -0
  289. data/cookbooks/mu-tools/recipes/split_var_partitions.rb +86 -0
  290. data/cookbooks/mu-tools/recipes/splunk-client.rb +69 -0
  291. data/cookbooks/mu-tools/recipes/splunk-server.rb +104 -0
  292. data/cookbooks/mu-tools/recipes/store_inspec_attr.rb +8 -0
  293. data/cookbooks/mu-tools/recipes/updates.rb +96 -0
  294. data/cookbooks/mu-tools/recipes/windows-client.rb +202 -0
  295. data/cookbooks/mu-tools/resources/aws_windows.rb +33 -0
  296. data/cookbooks/mu-tools/resources/disk.rb +88 -0
  297. data/cookbooks/mu-tools/resources/mommacat_request.rb +11 -0
  298. data/cookbooks/mu-tools/resources/scheduled_tasks.rb +29 -0
  299. data/cookbooks/mu-tools/resources/sshd_service.rb +45 -0
  300. data/cookbooks/mu-tools/resources/windows_users.rb +242 -0
  301. data/cookbooks/mu-tools/templates/amazon/sshd_config.erb +168 -0
  302. data/cookbooks/mu-tools/templates/centos-6/sshd_config.erb +212 -0
  303. data/cookbooks/mu-tools/templates/centos-7/sshd_config.erb +215 -0
  304. data/cookbooks/mu-tools/templates/default/0-mu-log-client.conf.erb +13 -0
  305. data/cookbooks/mu-tools/templates/default/conf.maldet.erb +137 -0
  306. data/cookbooks/mu-tools/templates/default/etc_hosts.erb +30 -0
  307. data/cookbooks/mu-tools/templates/default/etc_pamd_password-auth.erb +14 -0
  308. data/cookbooks/mu-tools/templates/default/etc_pamd_system-auth.erb +14 -0
  309. data/cookbooks/mu-tools/templates/default/etc_sysconfig_network.erb +12 -0
  310. data/cookbooks/mu-tools/templates/default/kubeconfig.erb +29 -0
  311. data/cookbooks/mu-tools/templates/default/kubelet.service.erb +35 -0
  312. data/cookbooks/mu-tools/templates/default/maldet_scanall.sh.erb +15 -0
  313. data/cookbooks/mu-tools/templates/default/nrpe.cfg.erb +233 -0
  314. data/cookbooks/mu-tools/templates/redhat-6/sshd_config.erb +213 -0
  315. data/cookbooks/mu-tools/templates/redhat-7/sshd_config.erb +215 -0
  316. data/cookbooks/mu-tools/templates/ubuntu-12.04/sshd_config.erb +146 -0
  317. data/cookbooks/mu-tools/templates/ubuntu-14.04/sshd_config.erb +145 -0
  318. data/cookbooks/mu-tools/templates/windows/Backup.xml.erb +20 -0
  319. data/cookbooks/mu-tools/templates/windows/bkupInfo.xml.erb +1 -0
  320. data/cookbooks/mu-tools/templates/windows/gpreprt.xml.erb +214 -0
  321. data/cookbooks/mu-tools/templates/windows/gptmpl.inf.erb +12 -0
  322. data/cookbooks/mu-tools/templates/windows/manifest.xml.erb +1 -0
  323. data/cookbooks/mu-tools/templates/windows/set_ad_dns_scheduled_task.ps1.erb +6 -0
  324. data/cookbooks/mu-tools/templates/windows/sshd_config.erb +136 -0
  325. data/cookbooks/mu-utility/CHANGELOG.md +12 -0
  326. data/cookbooks/mu-utility/LICENSE +37 -0
  327. data/cookbooks/mu-utility/README.md +6 -0
  328. data/cookbooks/mu-utility/attributes/default.rb +1 -0
  329. data/cookbooks/mu-utility/libraries/matchers.rb +21 -0
  330. data/cookbooks/mu-utility/metadata.rb +16 -0
  331. data/cookbooks/mu-utility/recipes/apt.rb +23 -0
  332. data/cookbooks/mu-utility/recipes/cleanup_image_helper.rb +118 -0
  333. data/cookbooks/mu-utility/recipes/iptables.rb +26 -0
  334. data/cookbooks/mu-utility/recipes/luks.rb +18 -0
  335. data/cookbooks/mu-utility/recipes/nat.rb +104 -0
  336. data/cookbooks/mu-utility/recipes/php.rb +33 -0
  337. data/cookbooks/mu-utility/recipes/rdp_gateway.rb +83 -0
  338. data/cookbooks/mu-utility/recipes/remi.rb +44 -0
  339. data/cookbooks/mu-utility/recipes/vim.rb +26 -0
  340. data/cookbooks/mu-utility/recipes/windows_basics.rb +37 -0
  341. data/cookbooks/mu-utility/recipes/zip.rb +26 -0
  342. data/cookbooks/mu-utility/templates/default/BundleConfig.xml.erb +34 -0
  343. data/cookbooks/mu-utility/templates/default/config.xml.erb +60 -0
  344. data/cookbooks/nagios/Berksfile +8 -0
  345. data/cookbooks/nagios/CHANGELOG.md +589 -0
  346. data/cookbooks/nagios/CONTRIBUTING.md +11 -0
  347. data/cookbooks/nagios/LICENSE +37 -0
  348. data/cookbooks/nagios/README.md +328 -0
  349. data/cookbooks/nagios/TESTING.md +2 -0
  350. data/cookbooks/nagios/attributes/config.rb +171 -0
  351. data/cookbooks/nagios/attributes/default.rb +228 -0
  352. data/cookbooks/nagios/chefignore +102 -0
  353. data/cookbooks/nagios/definitions/command.rb +33 -0
  354. data/cookbooks/nagios/definitions/contact.rb +33 -0
  355. data/cookbooks/nagios/definitions/contactgroup.rb +33 -0
  356. data/cookbooks/nagios/definitions/host.rb +33 -0
  357. data/cookbooks/nagios/definitions/hostdependency.rb +33 -0
  358. data/cookbooks/nagios/definitions/hostescalation.rb +34 -0
  359. data/cookbooks/nagios/definitions/hostgroup.rb +33 -0
  360. data/cookbooks/nagios/definitions/nagios_conf.rb +38 -0
  361. data/cookbooks/nagios/definitions/resource.rb +33 -0
  362. data/cookbooks/nagios/definitions/service.rb +33 -0
  363. data/cookbooks/nagios/definitions/servicedependency.rb +33 -0
  364. data/cookbooks/nagios/definitions/serviceescalation.rb +34 -0
  365. data/cookbooks/nagios/definitions/servicegroup.rb +33 -0
  366. data/cookbooks/nagios/definitions/timeperiod.rb +33 -0
  367. data/cookbooks/nagios/libraries/base.rb +314 -0
  368. data/cookbooks/nagios/libraries/command.rb +91 -0
  369. data/cookbooks/nagios/libraries/contact.rb +230 -0
  370. data/cookbooks/nagios/libraries/contactgroup.rb +112 -0
  371. data/cookbooks/nagios/libraries/custom_option.rb +36 -0
  372. data/cookbooks/nagios/libraries/data_bag_helper.rb +23 -0
  373. data/cookbooks/nagios/libraries/default.rb +90 -0
  374. data/cookbooks/nagios/libraries/host.rb +412 -0
  375. data/cookbooks/nagios/libraries/hostdependency.rb +181 -0
  376. data/cookbooks/nagios/libraries/hostescalation.rb +173 -0
  377. data/cookbooks/nagios/libraries/hostgroup.rb +119 -0
  378. data/cookbooks/nagios/libraries/nagios.rb +282 -0
  379. data/cookbooks/nagios/libraries/resource.rb +59 -0
  380. data/cookbooks/nagios/libraries/service.rb +455 -0
  381. data/cookbooks/nagios/libraries/servicedependency.rb +215 -0
  382. data/cookbooks/nagios/libraries/serviceescalation.rb +195 -0
  383. data/cookbooks/nagios/libraries/servicegroup.rb +144 -0
  384. data/cookbooks/nagios/libraries/timeperiod.rb +160 -0
  385. data/cookbooks/nagios/libraries/users_helper.rb +54 -0
  386. data/cookbooks/nagios/metadata.rb +25 -0
  387. data/cookbooks/nagios/recipes/_load_databag_config.rb +153 -0
  388. data/cookbooks/nagios/recipes/_load_default_config.rb +241 -0
  389. data/cookbooks/nagios/recipes/apache.rb +48 -0
  390. data/cookbooks/nagios/recipes/default.rb +204 -0
  391. data/cookbooks/nagios/recipes/nginx.rb +82 -0
  392. data/cookbooks/nagios/recipes/pagerduty.rb +143 -0
  393. data/cookbooks/nagios/recipes/server_package.rb +40 -0
  394. data/cookbooks/nagios/recipes/server_source.rb +164 -0
  395. data/cookbooks/nagios/templates/default/apache2.conf.erb +96 -0
  396. data/cookbooks/nagios/templates/default/cgi.cfg.erb +266 -0
  397. data/cookbooks/nagios/templates/default/commands.cfg.erb +13 -0
  398. data/cookbooks/nagios/templates/default/contacts.cfg.erb +37 -0
  399. data/cookbooks/nagios/templates/default/hostgroups.cfg.erb +25 -0
  400. data/cookbooks/nagios/templates/default/hosts.cfg.erb +15 -0
  401. data/cookbooks/nagios/templates/default/htpasswd.users.erb +6 -0
  402. data/cookbooks/nagios/templates/default/nagios.cfg.erb +22 -0
  403. data/cookbooks/nagios/templates/default/nginx.conf.erb +62 -0
  404. data/cookbooks/nagios/templates/default/pagerduty.cgi.erb +185 -0
  405. data/cookbooks/nagios/templates/default/resource.cfg.erb +27 -0
  406. data/cookbooks/nagios/templates/default/servicedependencies.cfg.erb +15 -0
  407. data/cookbooks/nagios/templates/default/servicegroups.cfg.erb +14 -0
  408. data/cookbooks/nagios/templates/default/services.cfg.erb +14 -0
  409. data/cookbooks/nagios/templates/default/templates.cfg.erb +31 -0
  410. data/cookbooks/nagios/templates/default/timeperiods.cfg.erb +13 -0
  411. data/cookbooks/s3fs/CHANGELOG.md +13 -0
  412. data/cookbooks/s3fs/LICENSE +37 -0
  413. data/cookbooks/s3fs/README.md +6 -0
  414. data/cookbooks/s3fs/attributes/default.rb +15 -0
  415. data/cookbooks/s3fs/files/default/fuse-2.9.3.zip +0 -0
  416. data/cookbooks/s3fs/metadata.rb +16 -0
  417. data/cookbooks/s3fs/recipes/default.rb +91 -0
  418. data/data_bags/demo/app.json +7 -0
  419. data/data_bags/nagios_services/chef.json +6 -0
  420. data/data_bags/nagios_services/linux_diskspace.json +5 -0
  421. data/data_bags/nagios_services/momma_cat.json +6 -0
  422. data/data_bags/nagios_services/mu-master-memory.json +5 -0
  423. data/data_bags/nagios_services/nagios_ui.json +6 -0
  424. data/data_bags/nagios_services/node_ssh.json +6 -0
  425. data/data_bags/nagios_services/ssh.json +6 -0
  426. data/demo/lambda_test.yaml +29 -0
  427. data/environments/DEV.json +8 -0
  428. data/environments/PROD.json +8 -0
  429. data/environments/dev.json +8 -0
  430. data/environments/development.json +8 -0
  431. data/environments/prod.json +8 -0
  432. data/extras/README.md +1 -0
  433. data/extras/admin-role-binding.yaml +16 -0
  434. data/extras/admin-user.yaml +6 -0
  435. data/extras/aws-auth-cm.yaml.erb +12 -0
  436. data/extras/clean-stock-amis +48 -0
  437. data/extras/git-fix-permissions-hook +12 -0
  438. data/extras/gitlab-eks-helper.sh.erb +20 -0
  439. data/extras/image-generators/README.md +2 -0
  440. data/extras/image-generators/aws/centos6.yaml +18 -0
  441. data/extras/image-generators/aws/centos7-govcloud.yaml +24 -0
  442. data/extras/image-generators/aws/centos7.yaml +17 -0
  443. data/extras/image-generators/aws/rhel7.yaml +17 -0
  444. data/extras/image-generators/aws/win2k12.yaml +16 -0
  445. data/extras/image-generators/aws/win2k16.yaml +16 -0
  446. data/extras/image-generators/aws/windows.yaml +18 -0
  447. data/extras/image-generators/gcp/centos6.yaml +17 -0
  448. data/extras/lambda_waf_domain_blacklist.py +103 -0
  449. data/extras/platform_berksfile_base +50 -0
  450. data/extras/ruby_rpm/build.sh +17 -0
  451. data/extras/ruby_rpm/muby.spec +44 -0
  452. data/extras/vault_tools/README.md +6 -0
  453. data/extras/vault_tools/export_vaults.sh +3 -0
  454. data/extras/vault_tools/recreate_vaults.sh +5 -0
  455. data/extras/vault_tools/test_vaults.sh +5 -0
  456. data/install/README.md +8 -0
  457. data/install/cfn_create_mu_master.json +1034 -0
  458. data/install/chef-server.rb.erb +19 -0
  459. data/install/deprecated-bash-library.sh +1891 -0
  460. data/install/images/Usage.png +0 -0
  461. data/install/installer +71 -0
  462. data/install/jenkinskeys.rb +8 -0
  463. data/install/user-dot-murc.erb +14 -0
  464. data/modules/html.erb +19 -0
  465. data/modules/mommacat.ru +426 -0
  466. data/modules/mu/cleanup.rb +339 -0
  467. data/modules/mu/cloud.rb +1446 -0
  468. data/modules/mu/clouds/README.md +201 -0
  469. data/modules/mu/clouds/aws/alarm.rb +319 -0
  470. data/modules/mu/clouds/aws/cache_cluster.rb +1010 -0
  471. data/modules/mu/clouds/aws/collection.rb +373 -0
  472. data/modules/mu/clouds/aws/container_cluster.rb +667 -0
  473. data/modules/mu/clouds/aws/database.rb +1836 -0
  474. data/modules/mu/clouds/aws/dnszone.rb +911 -0
  475. data/modules/mu/clouds/aws/firewall_rule.rb +641 -0
  476. data/modules/mu/clouds/aws/folder.rb +92 -0
  477. data/modules/mu/clouds/aws/function.rb +349 -0
  478. data/modules/mu/clouds/aws/group.rb +251 -0
  479. data/modules/mu/clouds/aws/loadbalancer.rb +888 -0
  480. data/modules/mu/clouds/aws/log.rb +363 -0
  481. data/modules/mu/clouds/aws/msg_queue.rb +480 -0
  482. data/modules/mu/clouds/aws/notification.rb +139 -0
  483. data/modules/mu/clouds/aws/role.rb +656 -0
  484. data/modules/mu/clouds/aws/search_domain.rb +646 -0
  485. data/modules/mu/clouds/aws/server.rb +2294 -0
  486. data/modules/mu/clouds/aws/server_pool.rb +1388 -0
  487. data/modules/mu/clouds/aws/storage_pool.rb +495 -0
  488. data/modules/mu/clouds/aws/user.rb +382 -0
  489. data/modules/mu/clouds/aws/userdata/README.md +4 -0
  490. data/modules/mu/clouds/aws/userdata/linux.erb +179 -0
  491. data/modules/mu/clouds/aws/userdata/windows.erb +278 -0
  492. data/modules/mu/clouds/aws/vpc.rb +1943 -0
  493. data/modules/mu/clouds/aws.rb +1009 -0
  494. data/modules/mu/clouds/cloudformation/alarm.rb +146 -0
  495. data/modules/mu/clouds/cloudformation/cache_cluster.rb +167 -0
  496. data/modules/mu/clouds/cloudformation/collection.rb +117 -0
  497. data/modules/mu/clouds/cloudformation/database.rb +278 -0
  498. data/modules/mu/clouds/cloudformation/dnszone.rb +274 -0
  499. data/modules/mu/clouds/cloudformation/firewall_rule.rb +308 -0
  500. data/modules/mu/clouds/cloudformation/loadbalancer.rb +193 -0
  501. data/modules/mu/clouds/cloudformation/log.rb +170 -0
  502. data/modules/mu/clouds/cloudformation/server.rb +370 -0
  503. data/modules/mu/clouds/cloudformation/server_pool.rb +279 -0
  504. data/modules/mu/clouds/cloudformation/vpc.rb +322 -0
  505. data/modules/mu/clouds/cloudformation.rb +733 -0
  506. data/modules/mu/clouds/docker.rb +30 -0
  507. data/modules/mu/clouds/google/container_cluster.rb +290 -0
  508. data/modules/mu/clouds/google/database.rb +152 -0
  509. data/modules/mu/clouds/google/firewall_rule.rb +267 -0
  510. data/modules/mu/clouds/google/group.rb +164 -0
  511. data/modules/mu/clouds/google/loadbalancer.rb +479 -0
  512. data/modules/mu/clouds/google/server.rb +1510 -0
  513. data/modules/mu/clouds/google/server_pool.rb +274 -0
  514. data/modules/mu/clouds/google/user.rb +266 -0
  515. data/modules/mu/clouds/google/userdata/README.md +4 -0
  516. data/modules/mu/clouds/google/userdata/linux.erb +137 -0
  517. data/modules/mu/clouds/google/userdata/windows.erb +275 -0
  518. data/modules/mu/clouds/google/vpc.rb +890 -0
  519. data/modules/mu/clouds/google.rb +811 -0
  520. data/modules/mu/config/README.md +11 -0
  521. data/modules/mu/config/alarm.rb +271 -0
  522. data/modules/mu/config/cache_cluster.rb +172 -0
  523. data/modules/mu/config/collection.rb +87 -0
  524. data/modules/mu/config/container_cluster.rb +103 -0
  525. data/modules/mu/config/container_cluster.yml +36 -0
  526. data/modules/mu/config/database.rb +458 -0
  527. data/modules/mu/config/database.yml +26 -0
  528. data/modules/mu/config/dnszone.rb +327 -0
  529. data/modules/mu/config/firewall_rule.rb +118 -0
  530. data/modules/mu/config/folder.rb +70 -0
  531. data/modules/mu/config/function.rb +140 -0
  532. data/modules/mu/config/group.rb +64 -0
  533. data/modules/mu/config/loadbalancer.rb +482 -0
  534. data/modules/mu/config/log.rb +47 -0
  535. data/modules/mu/config/log.yml +6 -0
  536. data/modules/mu/config/msg_queue.rb +47 -0
  537. data/modules/mu/config/msg_queue.yml +9 -0
  538. data/modules/mu/config/notification.rb +44 -0
  539. data/modules/mu/config/project.rb +71 -0
  540. data/modules/mu/config/role.rb +102 -0
  541. data/modules/mu/config/search_domain.rb +61 -0
  542. data/modules/mu/config/search_domain.yml +25 -0
  543. data/modules/mu/config/server.rb +587 -0
  544. data/modules/mu/config/server.yml +8 -0
  545. data/modules/mu/config/server_pool.rb +216 -0
  546. data/modules/mu/config/server_pool.yml +71 -0
  547. data/modules/mu/config/storage_pool.rb +145 -0
  548. data/modules/mu/config/user.rb +78 -0
  549. data/modules/mu/config/vpc.rb +743 -0
  550. data/modules/mu/config/vpc.yml +6 -0
  551. data/modules/mu/config.rb +2000 -0
  552. data/modules/mu/defaults/README.md +2 -0
  553. data/modules/mu/defaults/amazon_images.yaml +121 -0
  554. data/modules/mu/defaults/google_images.yaml +16 -0
  555. data/modules/mu/deploy.rb +686 -0
  556. data/modules/mu/groomer.rb +123 -0
  557. data/modules/mu/groomers/README.md +58 -0
  558. data/modules/mu/groomers/chef.rb +1024 -0
  559. data/modules/mu/kittens.rb +11319 -0
  560. data/modules/mu/logger.rb +208 -0
  561. data/modules/mu/master/README.md +27 -0
  562. data/modules/mu/master/chef.rb +471 -0
  563. data/modules/mu/master/ldap.rb +1005 -0
  564. data/modules/mu/master.rb +415 -0
  565. data/modules/mu/mommacat.rb +2703 -0
  566. data/modules/mu-load-config.rb +1 -0
  567. data/modules/mu.rb +724 -0
  568. data/modules/scratchpad.erb +1 -0
  569. data/modules/tests/super_complex_bok.yml +41 -0
  570. data/modules/tests/super_simple_bok.yml +40 -0
  571. data/mu.gemspec +62 -0
  572. data/roles/demo-dbservice-configure.json +19 -0
  573. data/roles/demo-portal-configure.json +19 -0
  574. data/roles/mu-master-jenkins.json +24 -0
  575. data/roles/mu-master-nagios-only.json +13 -0
  576. data/roles/mu-master.json +12 -0
  577. data/roles/mu-node.json +19 -0
  578. data/roles/mu-splunk-server.json +13 -0
  579. data/roles/mu-splunk.json +13 -0
  580. data/test/clean_up.py +25 -0
  581. data/test/demo-test-profile/README.md +3 -0
  582. data/test/demo-test-profile/controls/flask.rb +84 -0
  583. data/test/demo-test-profile/inspec.lock +7 -0
  584. data/test/demo-test-profile/inspec.yml +11 -0
  585. data/test/etco-test-profile/README.md +3 -0
  586. data/test/etco-test-profile/controls/all-in-one.rb +182 -0
  587. data/test/etco-test-profile/inspec.lock +7 -0
  588. data/test/etco-test-profile/inspec.yml +11 -0
  589. data/test/exec_inspec.py +246 -0
  590. data/test/exec_mu_install.py +241 -0
  591. data/test/exec_retry.py +44 -0
  592. data/test/mu-master-test/README.md +3 -0
  593. data/test/mu-master-test/controls/all_in_one.rb +557 -0
  594. data/test/mu-master-test/inspec.lock +3 -0
  595. data/test/mu-master-test/inspec.yml +11 -0
  596. data/test/mu-tools-test/README.md +3 -0
  597. data/test/mu-tools-test/controls/base.rb +265 -0
  598. data/test/mu-tools-test/inspec.lock +3 -0
  599. data/test/mu-tools-test/inspec.yml +8 -0
  600. data/test/simple-server-php-test/README.md +3 -0
  601. data/test/simple-server-php-test/controls/apachephp.rb +25 -0
  602. data/test/simple-server-php-test/controls/example.rb +19 -0
  603. data/test/simple-server-php-test/inspec.lock +7 -0
  604. data/test/simple-server-php-test/inspec.yml +12 -0
  605. data/test/simple-server-rails-test/README.md +3 -0
  606. data/test/simple-server-rails-test/controls/rails.rb +188 -0
  607. data/test/simple-server-rails-test/inspec.lock +7 -0
  608. data/test/simple-server-rails-test/inspec.yml +11 -0
  609. data/test/simple-windows-test/README.md +3 -0
  610. data/test/simple-windows-test/controls/windows.rb +20 -0
  611. data/test/simple-windows-test/inspec.lock +7 -0
  612. data/test/simple-windows-test/inspec.yml +11 -0
  613. data/test/smoke_test.rb +75 -0
  614. data/test/wordpress-test/README.md +3 -0
  615. data/test/wordpress-test/controls/wordpress.rb +97 -0
  616. data/test/wordpress-test/inspec.lock +7 -0
  617. data/test/wordpress-test/inspec.yml +11 -0
  618. metadata +979 -0
@@ -0,0 +1,811 @@
1
+ # Copyright:: Copyright (c) 2017 eGlobalTech, Inc., all rights reserved
2
+ #
3
+ # Licensed under the BSD-3 license (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License in the root of the project or at
6
+ #
7
+ # http://egt-labs.com/mu/LICENSE.html
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'googleauth'
16
+ require "net/http"
17
+ require 'net/https'
18
+ require 'multi_json'
19
+ require 'stringio'
20
+
21
+ module MU
22
+ class Cloud
23
+ # Support for Google Cloud Platform as a provisioning layer.
24
+ class Google
25
+ @@authtoken = nil
26
+ @@default_project = nil
27
+ @@myRegion_var = nil
28
+ @@authorizers = {}
29
+
30
+ # Any cloud-specific instance methods we require our resource
31
+ # implementations to have, above and beyond the ones specified by
32
+ # {MU::Cloud}
33
+ # @return [Array<Symbol>]
34
+ def self.required_instance_methods
35
+ []
36
+ end
37
+
38
+ # If we're running this cloud, return the $MU_CFG blob we'd use to
39
+ # describe this environment as our target one.
40
+ def self.hosted_config
41
+ return nil if !hosted?
42
+ getGoogleMetaData("instance/zone").match(/^projects\/[^\/]+\/zones\/([^\/]+)$/)
43
+ zone = Regexp.last_match[1]
44
+ {
45
+ "project" => MU::Cloud::Google.getGoogleMetaData("project/project-id"),
46
+ "region" => zone.sub(/-[a-z]$/, "")
47
+ }
48
+ end
49
+
50
+ # A non-working example configuration
51
+ def self.config_example
52
+ sample = hosted_config
53
+ sample ||= {
54
+ "project" => "my-project",
55
+ "region" => "us-east4"
56
+ }
57
+ sample["credentials_file"] = "#{Etc.getpwuid(Process.uid).dir}/gcp_serviceacct.json"
58
+ sample["log_bucket_name"] = "my-mu-cloud-storage-bucket"
59
+ sample
60
+ end
61
+
62
+ # If we've configured Google as a provider, or are simply hosted in GCP,
63
+ # decide what our default region is.
64
+ def self.myRegion
65
+ if $MU_CFG['google'] and $MU_CFG['google']['region']
66
+ @@myRegion_var = $MU_CFG['google']['region']
67
+ elsif MU::Cloud::Google.hosted?
68
+ zone = MU::Cloud::Google.getGoogleMetaData("instance/zone")
69
+ @@myRegion_var = zone.gsub(/^.*?\/|\-\d+$/, "")
70
+ end
71
+ @@myRegion_var
72
+ end
73
+
74
+ # Plant a Mu deploy secret into a storage bucket somewhere for so our kittens can consume it
75
+ # @param deploy_id [String]: The deploy for which we're writing the secret
76
+ # @param value [String]: The contents of the secret
77
+ def self.writeDeploySecret(deploy_id, value)
78
+ name = deploy_id+"-secret"
79
+ begin
80
+ MU.log "Writing #{name} to Cloud Storage bucket #{$MU_CFG['google']['log_bucket_name']}"
81
+ f = Tempfile.new(name) # XXX this is insecure and stupid
82
+ f.write value
83
+ f.close
84
+ objectobj = MU::Cloud::Google.storage(:Object).new(
85
+ bucket: $MU_CFG['google']['log_bucket_name'],
86
+ name: name
87
+ )
88
+ ebs_key = MU::Cloud::Google.storage.insert_object(
89
+ $MU_CFG['google']['log_bucket_name'],
90
+ objectobj,
91
+ upload_source: f.path
92
+ )
93
+ f.unlink
94
+ rescue ::Google::Apis::ClientError => e
95
+ # XXX comment for NCBI tests
96
+ # raise MU::MommaCat::DeployInitializeError, "Got #{e.inspect} trying to write #{name} to #{$MU_CFG['google']['log_bucket_name']}"
97
+ end
98
+ end
99
+
100
+ # Remove the service account and various deploy secrets associated with a deployment. Intended for invocation from MU::Cleanup.
101
+ # @param deploy_id [String]: The deploy for which we're granting the secret
102
+ # @param noop [Boolean]: If true, will only print what would be done
103
+ def self.removeDeploySecretsAndRoles(deploy_id = MU.deploy_id, flags: {}, noop: false)
104
+ return if !$MU_CFG['google'] or !$MU_CFG['google']['project']
105
+ flags["project"] ||= MU::Cloud::Google.defaultProject
106
+ name = deploy_id+"-secret"
107
+
108
+ end
109
+
110
+ # Grant access to appropriate Cloud Storage objects in our log/secret bucket for a deploy member.
111
+ # @param acct [String]: The service account (by email addr) to which we'll grant access
112
+ # @param deploy_id [String]: The deploy for which we're granting the secret
113
+ # XXX add equivalent for AWS and call agnostically
114
+ def self.grantDeploySecretAccess(acct, deploy_id = MU.deploy_id)
115
+ name = deploy_id+"-secret"
116
+ begin
117
+ MU.log "Granting #{acct} access to list Cloud Storage bucket #{$MU_CFG['google']['log_bucket_name']}"
118
+ MU::Cloud::Google.storage.insert_bucket_access_control(
119
+ $MU_CFG['google']['log_bucket_name'],
120
+ MU::Cloud::Google.storage(:BucketAccessControl).new(
121
+ bucket: $MU_CFG['google']['log_bucket_name'],
122
+ role: "READER",
123
+ entity: "user-"+acct
124
+ )
125
+ )
126
+
127
+ aclobj = MU::Cloud::Google.storage(:ObjectAccessControl).new(
128
+ bucket: $MU_CFG['google']['log_bucket_name'],
129
+ role: "READER",
130
+ entity: "user-"+acct
131
+ )
132
+
133
+ [name, "log_vol_ebs_key"].each { |obj|
134
+ MU.log "Granting #{acct} access to #{obj} in Cloud Storage bucket #{$MU_CFG['google']['log_bucket_name']}"
135
+ MU::Cloud::Google.storage.insert_object_access_control(
136
+ $MU_CFG['google']['log_bucket_name'],
137
+ obj,
138
+ aclobj
139
+ )
140
+ }
141
+ rescue ::Google::Apis::ClientError => e
142
+ raise MuError, "Got #{e.inspect} trying to set ACLs for #{deploy_id} in #{$MU_CFG['google']['log_bucket_name']}"
143
+ end
144
+ end
145
+
146
+ @@is_in_gcp = nil
147
+
148
+ # Alias for #{MU::Cloud::Google.hosted?}
149
+ def self.hosted
150
+ MU::Cloud::Google.hosted?
151
+ end
152
+
153
+ # Determine whether we (the Mu master, presumably) are hosted in this
154
+ # cloud.
155
+ # @return [Boolean]
156
+ def self.hosted?
157
+ if !@@is_in_gcp.nil?
158
+ return @@is_in_gcp
159
+ end
160
+
161
+ if getGoogleMetaData("instance/name")
162
+ @@is_in_gcp = true
163
+ return true
164
+ end
165
+ @@is_in_gcp = false
166
+ false
167
+ end
168
+
169
+ # Fetch a Google instance metadata parameter (example: instance/id).
170
+ # @param param [String]: The parameter name to fetch
171
+ # @return [String, nil]
172
+ def self.getGoogleMetaData(param)
173
+ base_url = "http://metadata.google.internal/computeMetadata/v1"
174
+ begin
175
+ Timeout.timeout(2) do
176
+ response = open(
177
+ "#{base_url}/#{param}",
178
+ "Metadata-Flavor" => "Google"
179
+ ).read
180
+ return response
181
+ end
182
+ rescue Net::HTTPServerException, OpenURI::HTTPError, Timeout::Error, SocketError, Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
183
+ # This is fairly normal, just handle it gracefully
184
+ logger = MU::Logger.new
185
+ logger.log "Failed metadata request #{base_url}/#{param}: #{e.inspect}", MU::DEBUG
186
+ end
187
+
188
+ nil
189
+ end
190
+
191
+ # Create an SSL Certificate resource from some local x509 cert files.
192
+ # @param name [String]: A resource name for the certificate
193
+ # @param cert [String,OpenSSL::X509::Certificate]: An x509 certificate
194
+ # @param key [String,OpenSSL::PKey]: An x509 private key
195
+ # @return [Google::Apis::ComputeBeta::SslCertificate]
196
+ def self.createSSLCertificate(name, cert, key, flags = {})
197
+ flags["project"] ||= MU::Cloud::Google.defaultProject
198
+ flags["description"] ||= MU.deploy_id
199
+ certobj = ::Google::Apis::ComputeBeta::SslCertificate.new(
200
+ name: name,
201
+ certificate: cert.to_s,
202
+ private_key: key.to_s,
203
+ description: flags["description"]
204
+ )
205
+ MU::Cloud::Google.compute.insert_ssl_certificate(flags["project"], certobj)
206
+ end
207
+
208
+ @@svc_account_name = nil
209
+ # Fetch the name of the service account we were using last time we loaded
210
+ # GCP credentials.
211
+ # @return [String]
212
+ def self.svc_account_name
213
+ @@svc_account_name
214
+ end
215
+ # Pull our global Google Cloud Platform credentials out of their secure
216
+ # vault, feed them to the googleauth gem, and stash the results on hand
217
+ # for consumption by the various GCP APIs.
218
+ # @param scopes [Array<String>]: One or more scopes for which to authorizer the caller. Will vary depending on the API you're calling.
219
+ def self.loadCredentials(scopes = nil)
220
+ return @@authorizers[scopes.to_s] if @@authorizers[scopes.to_s]
221
+
222
+ if $MU_CFG.has_key?("google")
223
+ data = nil
224
+
225
+ def self.get_machine_credentials(scopes)
226
+ @@svc_account_name = MU::Cloud::Google.getGoogleMetaData("instance/service-accounts/default/email")
227
+ MU.log "We are hosted in GCP, so I will attempt to use the service account #{@@svc_account_name} to make API requests.", MU::DEBUG
228
+
229
+ @@authorizers[scopes.to_s] = ::Google::Auth.get_application_default(scopes)
230
+ @@authorizers[scopes.to_s].fetch_access_token!
231
+ @@default_project ||= MU::Cloud::Google.getGoogleMetaData("project/project-id")
232
+ @@authorizers[scopes.to_s]
233
+ end
234
+
235
+ if $MU_CFG["google"]["credentials_file"]
236
+ begin
237
+ data = JSON.parse(File.read($MU_CFG["google"]["credentials_file"]))
238
+ @@default_project ||= data["project_id"]
239
+ creds = {
240
+ :json_key_io => StringIO.new(MultiJson.dump(data)),
241
+ :scope => scopes
242
+ }
243
+ @@svc_account_name = data["client_email"]
244
+ @@authorizers[scopes.to_s] = ::Google::Auth::ServiceAccountCredentials.make_creds(creds)
245
+ return @@authorizers[scopes.to_s]
246
+ rescue JSON::ParserError, Errno::ENOENT, Errno::EACCES => e
247
+ if !MU::Cloud::Google.hosted?
248
+ raise MuError, "Google Cloud credentials file #{$MU_CFG["google"]["credentials_file"]} is missing or invalid (#{e.message})"
249
+ end
250
+ MU.log "Google Cloud credentials file #{$MU_CFG["google"]["credentials_file"]} is missing or invalid", MU::WARN, details: e.message
251
+ return get_machine_credentials(scopes)
252
+ end
253
+ elsif $MU_CFG["google"]["credentials"]
254
+ begin
255
+ vault, item = $MU_CFG["google"]["credentials"].split(/:/)
256
+ data = MU::Groomer::Chef.getSecret(vault: vault, item: item).to_h
257
+ rescue MU::Groomer::Chef::MuNoSuchSecret
258
+ if !MU::Cloud::Google.hosted?
259
+ raise MuError, "Google Cloud credentials not found in Vault #{vault}:#{item}"
260
+ end
261
+ MU.log "Google Cloud credentials not found in Vault #{vault}:#{item}", MU::WARN
262
+ return get_machine_credentials(scopes)
263
+ end
264
+
265
+ @@default_project ||= data["project_id"]
266
+ creds = {
267
+ :json_key_io => StringIO.new(MultiJson.dump(data)),
268
+ :scope => scopes
269
+ }
270
+ @@svc_account_name = data["client_email"]
271
+ @@authorizers[scopes.to_s] = ::Google::Auth::ServiceAccountCredentials.make_creds(creds)
272
+ return @@authorizers[scopes.to_s]
273
+ elsif MU::Cloud::Google.hosted?
274
+ return get_machine_credentials(scopes)
275
+ else
276
+ raise MuError, "Google Cloud credentials not configured"
277
+ end
278
+
279
+ end
280
+ nil
281
+ end
282
+
283
+ # Fetch a URL
284
+ def self.get(url)
285
+ uri = URI url
286
+ resp = nil
287
+
288
+ Net::HTTP.start(uri.host, uri.port) do |http|
289
+ resp = http.get(uri)
290
+ end
291
+
292
+ unless resp.code == "200"
293
+ puts resp.code, resp.body
294
+ exit
295
+ end
296
+ resp.body
297
+ end
298
+
299
+ # If this Mu master resides in the Google Cloud Platform, return the
300
+ # project id in which we reside. Nil if we're not in GCP.
301
+ def self.myProject
302
+ if MU::Cloud::Google.hosted?
303
+ return MU::Cloud::Google.getGoogleMetaData("project/project-id")
304
+ end
305
+ nil
306
+ end
307
+
308
+ # If this Mu master resides in the Google Cloud Platform, return the
309
+ # default service account associated with its metadata.
310
+ def self.myServiceAccount
311
+ if MU::Cloud::Google.hosted?
312
+ MU::Cloud::Google.getGoogleMetaData("instance/service-accounts/default/email")
313
+ else
314
+ nil
315
+ end
316
+ end
317
+
318
+ # Our credentials map to a project, an organizational structure in Google
319
+ # Cloud. This fetches the identifier of the project associated with our
320
+ # default credentials.
321
+ def self.defaultProject
322
+ return myProject if !$MU_CFG['google'] or !$MU_CFG['google']['project']
323
+ loadCredentials if !@@default_project
324
+ @@default_project
325
+ end
326
+
327
+ # List all Google Cloud Platform projects available to our credentials
328
+ def self.listProjects
329
+ return [] if !$MU_CFG['google'] or !$MU_CFG['google']['project']
330
+ result = MU::Cloud::Google.resource_manager.list_projects
331
+ result.projects.reject! { |p| p.lifecycle_state == "DELETE_REQUESTED" }
332
+ result.projects.map { |p| p.project_id }
333
+ end
334
+
335
+ @@regions = {}
336
+ # List all known Google Cloud Platform regions
337
+ # @param us_only [Boolean]: Restrict results to United States only
338
+ def self.listRegions(us_only = false)
339
+ if !MU::Cloud::Google.defaultProject
340
+ return []
341
+ end
342
+ if @@regions.size == 0
343
+ begin
344
+ result = MU::Cloud::Google.compute.list_regions(MU::Cloud::Google.defaultProject)
345
+ rescue ::Google::Apis::ClientError => e
346
+ if e.message.match(/forbidden/)
347
+ raise MuError, "Insufficient permissions to list Google Cloud region. The service account #{myServiceAccount} should probably have the project owner role."
348
+ end
349
+ raise e
350
+ end
351
+
352
+ regions = []
353
+ result.items.each { |region|
354
+ @@regions[region.name] = []
355
+ region.zones.each { |az|
356
+ @@regions[region.name] << az.sub(/^.*?\/([^\/]+)$/, '\1')
357
+ }
358
+ }
359
+ end
360
+ if us_only
361
+ @@regions.keys.delete_if { |r| !r.match(/^us/) }
362
+ else
363
+ @@regions.keys
364
+ end
365
+ end
366
+
367
+
368
+ @@instance_types = nil
369
+ # Query the GCP API for the list of valid EC2 instance types and some of
370
+ # their attributes. We can use this in config validation and to help
371
+ # "translate" machine types across cloud providers.
372
+ # @param region [String]: Supported machine types can vary from region to region, so we look for the set we're interested in specifically
373
+ # @return [Hash]
374
+ def self.listInstanceTypes(region = myRegion)
375
+ return @@instance_types if @@instance_types and @@instance_types[region]
376
+ if !MU::Cloud::Google.defaultProject
377
+ return {}
378
+ end
379
+
380
+ @@instance_types ||= {}
381
+ @@instance_types[region] ||= {}
382
+ result = MU::Cloud::Google.compute.list_machine_types(MU::Cloud::Google.defaultProject, listAZs(region).first)
383
+ result.items.each { |type|
384
+ @@instance_types[region][type.name] ||= {}
385
+ @@instance_types[region][type.name]["memory"] = sprintf("%.1f", type.memory_mb/1024.0).to_f
386
+ @@instance_types[region][type.name]["vcpu"] = type.guest_cpus.to_f
387
+ if type.is_shared_cpu
388
+ @@instance_types[region][type.name]["ecu"] = "Variable"
389
+ else
390
+ @@instance_types[region][type.name]["ecu"] = type.guest_cpus
391
+ end
392
+ }
393
+ @@instance_types
394
+ end
395
+
396
+ # Google has fairly strict naming conventions (all lowercase, no
397
+ # underscores, etc). Provide a wrapper to our standard names to handle it.
398
+ def self.nameStr(name)
399
+ name.downcase.gsub(/[^a-z0-9\-]/, "-")
400
+ end
401
+
402
+ # List the Availability Zones associated with a given Google Cloud
403
+ # region. If no region is given, search the one in which this MU master
404
+ # server resides (if it resides in this cloud provider's ecosystem).
405
+ # @param region [String]: The region to search.
406
+ # @return [Array<String>]: The Availability Zones in this region.
407
+ def self.listAZs(region = MU.curRegion)
408
+ MU::Cloud::Google.listRegions if !@@regions.has_key?(region)
409
+ raise MuError, "No such Google Cloud region '#{region}'" if !@@regions.has_key?(region)
410
+ @@regions[region]
411
+ end
412
+
413
+ # Google's Compute Service API
414
+ # @param subclass [<Google::Apis::ComputeBeta>]: If specified, will return the class ::Google::Apis::ComputeBeta::subclass instead of an API client instance
415
+ def self.compute(subclass = nil)
416
+ require 'google/apis/compute_beta'
417
+
418
+ if subclass.nil?
419
+ @@compute_api ||= MU::Cloud::Google::Endpoint.new(api: "ComputeBeta::ComputeService", scopes: ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/compute.readonly'])
420
+ return @@compute_api
421
+ elsif subclass.is_a?(Symbol)
422
+ return Object.const_get("::Google").const_get("Apis").const_get("ComputeBeta").const_get(subclass)
423
+ end
424
+ end
425
+
426
+ # Google's Storage Service API
427
+ # @param subclass [<Google::Apis::StorageV1>]: If specified, will return the class ::Google::Apis::StorageV1::subclass instead of an API client instance
428
+ def self.storage(subclass = nil)
429
+ require 'google/apis/storage_v1'
430
+
431
+ if subclass.nil?
432
+ @@storage_api ||= MU::Cloud::Google::Endpoint.new(api: "StorageV1::StorageService", scopes: ['https://www.googleapis.com/auth/cloud-platform'])
433
+ return @@storage_api
434
+ elsif subclass.is_a?(Symbol)
435
+ return Object.const_get("::Google").const_get("Apis").const_get("StorageV1").const_get(subclass)
436
+ end
437
+ end
438
+
439
+ # Google's IAM Service API
440
+ # @param subclass [<Google::Apis::IamV1>]: If specified, will return the class ::Google::Apis::IamV1::subclass instead of an API client instance
441
+ def self.iam(subclass = nil)
442
+ require 'google/apis/iam_v1'
443
+
444
+ if subclass.nil?
445
+ @@iam_api ||= MU::Cloud::Google::Endpoint.new(api: "IamV1::IamService", scopes: ['https://www.googleapis.com/auth/cloud-platform'])
446
+ return @@iam_api
447
+ elsif subclass.is_a?(Symbol)
448
+ return Object.const_get("::Google").const_get("Apis").const_get("IamV1").const_get(subclass)
449
+ end
450
+ end
451
+
452
+ # GCP's AdminDirectory Service API
453
+ # @param subclass [<Google::Apis::AdminDirectoryV1>]: If specified, will return the class ::Google::Apis::AdminDirectoryV1::subclass instead of an API client instance
454
+ def self.admin_directory(subclass = nil)
455
+ require 'google/apis/admin_directory_v1'
456
+
457
+ if subclass.nil?
458
+ begin
459
+ @@admin_directory_api ||= MU::Cloud::Google::Endpoint.new(api: "AdminDirectoryV1::DirectoryService", scopes: ['https://www.googleapis.com/auth/admin.directory.group.member.readonly', 'https://www.googleapis.com/auth/admin.directory.group.readonly'], masquerade: $MU_CFG['google']['masquerade_as'])
460
+ rescue Signet::AuthorizationError => e
461
+ MU.log "Cannot masquerade as #{$MU_CFG['google']['masquerade_as']}", MU::ERROR, details: "You can only use masquerade_as with GSuite. For more information on delegating GSuite authority to a service account, see:\nhttps://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority"
462
+ raise e
463
+ end
464
+ return @@admin_directory_api
465
+ elsif subclass.is_a?(Symbol)
466
+ return Object.const_get("::Google").const_get("Apis").const_get("AdminDirectoryV1").const_get(subclass)
467
+ end
468
+ end
469
+
470
+ # Google's Cloud Resource Manager API
471
+ # @param subclass [<Google::Apis::CloudresourcemanagerV1>]: If specified, will return the class ::Google::Apis::CloudresourcemanagerV1::subclass instead of an API client instance
472
+ def self.resource_manager(subclass = nil)
473
+ require 'google/apis/cloudresourcemanager_v1'
474
+
475
+ if subclass.nil?
476
+ @@resource_api ||= MU::Cloud::Google::Endpoint.new(api: "CloudresourcemanagerV1::CloudResourceManagerService", scopes: ['https://www.googleapis.com/auth/cloud-platform'])
477
+ return @@resource_api
478
+ elsif subclass.is_a?(Symbol)
479
+ return Object.const_get("::Google").const_get("Apis").const_get("CloudresourcemanagerV1").const_get(subclass)
480
+ end
481
+ end
482
+
483
+ # Google's Container API
484
+ # @param subclass [<Google::Apis::ContainerV1>]: If specified, will return the class ::Google::Apis::ContainerV1::subclass instead of an API client instance
485
+ def self.container(subclass = nil)
486
+ require 'google/apis/container_v1'
487
+
488
+ if subclass.nil?
489
+ @@container_api ||= MU::Cloud::Google::Endpoint.new(api: "ContainerV1::ContainerService", scopes: ['https://www.googleapis.com/auth/cloud-platform'])
490
+ return @@container_api
491
+ elsif subclass.is_a?(Symbol)
492
+ return Object.const_get("::Google").const_get("Apis").const_get("ContainerV1").const_get(subclass)
493
+ end
494
+ end
495
+
496
+ # Google's Service Manager API (the one you use to enable pre-project APIs)
497
+ # @param subclass [<Google::Apis::ServicemanagementV1>]: If specified, will return the class ::Google::Apis::ServicemanagementV1::subclass instead of an API client instance
498
+ def self.service_manager(subclass = nil)
499
+ require 'google/apis/servicemanagement_v1'
500
+
501
+ if subclass.nil?
502
+ @@service_api ||= MU::Cloud::Google::Endpoint.new(api: "ServicemanagementV1::ServiceManagementService", scopes: ['https://www.googleapis.com/auth/cloud-platform'])
503
+ return @@service_api
504
+ elsif subclass.is_a?(Symbol)
505
+ return Object.const_get("::Google").const_get("Apis").const_get("ServicemanagementV1").const_get(subclass)
506
+ end
507
+ end
508
+
509
+ # Google's SQL Service API
510
+ # @param subclass [<Google::Apis::SqladminV1beta4>]: If specified, will return the class ::Google::Apis::SqladminV1beta4::subclass instead of an API client instance
511
+ def self.sql(subclass = nil)
512
+ require 'google/apis/sqladmin_v1beta4'
513
+
514
+ if subclass.nil?
515
+ @@sql_api ||= MU::Cloud::Google::Endpoint.new(api: "SqladminV1beta4::SQLAdminService", scopes: ['https://www.googleapis.com/auth/cloud-platform'])
516
+ return @@sql_api
517
+ elsif subclass.is_a?(Symbol)
518
+ return Object.const_get("::Google").const_get("Apis").const_get("SqladminV1beta4").const_get(subclass)
519
+ end
520
+ end
521
+
522
+ # Google's StackDriver Logging Service API
523
+ # @param subclass [<Google::Apis::LoggingV2>]: If specified, will return the class ::Google::Apis::LoggingV2::subclass instead of an API client instance
524
+ def self.logging(subclass = nil)
525
+ require 'google/apis/logging_v2'
526
+
527
+ if subclass.nil?
528
+ @@logging_api ||= MU::Cloud::Google::Endpoint.new(api: "LoggingV2::LoggingService", scopes: ['https://www.googleapis.com/auth/cloud-platform'])
529
+ return @@logging_api
530
+ elsif subclass.is_a?(Symbol)
531
+ return Object.const_get("::Google").const_get("Apis").const_get("LoggingV2").const_get(subclass)
532
+ end
533
+ end
534
+
535
+
536
+ private
537
+
538
+ # Wrapper class for Google APIs, so that we can catch some common
539
+ # transient endpoint errors without having to spray rescues all over the
540
+ # codebase.
541
+ class Endpoint
542
+ @api = nil
543
+
544
+ # Create a Google Cloud Platform API client
545
+ # @param api [String]: Which API are we wrapping?
546
+ # @param scopes [Array<String>]: Google auth scopes applicable to this API
547
+ def initialize(api: "ComputeBeta::ComputeService", scopes: ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/compute.readonly'], masquerade: nil)
548
+ @api = Object.const_get("Google::Apis::#{api}").new
549
+ @api.authorization = MU::Cloud::Google.loadCredentials(scopes)
550
+ if masquerade
551
+ @api.authorization.sub = masquerade
552
+ @api.authorization.fetch_access_token!
553
+ end
554
+ end
555
+
556
+ # Generic wrapper for deleting Compute resources
557
+ # @param type [String]: The type of resource, typically the string you'll find in all of the API calls referring to it
558
+ # @param project [String]: The project in which we should look for the resources
559
+ # @param region [String]: The region in which to loop for the resources
560
+ # @param noop [Boolean]: If true, will only log messages about resources to be deleted, without actually deleting them
561
+ # @param filter [String]: The Compute API filter string to use to isolate appropriate resources
562
+ def delete(type, project, region = nil, noop = false, filter = "description eq #{MU.deploy_id}")
563
+ list_sym = "list_#{type.sub(/y$/, "ie")}s".to_sym
564
+ resp = nil
565
+ begin
566
+ if region
567
+ resp = MU::Cloud::Google.compute.send(list_sym, project, region, filter: filter)
568
+ else
569
+ resp = MU::Cloud::Google.compute.send(list_sym, project, filter: filter)
570
+ end
571
+ rescue ::Google::Apis::ClientError => e
572
+ return if e.message.match(/^notFound: /)
573
+ end
574
+
575
+ if !resp.nil? and !resp.items.nil?
576
+ threads = []
577
+ parent_thread_id = Thread.current.object_id
578
+ resp.items.each { |obj|
579
+ threads << Thread.new {
580
+ MU.dupGlobals(parent_thread_id)
581
+ MU.log "Removing #{type.gsub(/_/, " ")} #{obj.name}"
582
+ delete_sym = "delete_#{type}".to_sym
583
+ if !noop
584
+ retries = 0
585
+ failed = false
586
+ begin
587
+ resp = nil
588
+ failed = false
589
+ if region
590
+ resp = MU::Cloud::Google.compute.send(delete_sym, project, region, obj.name)
591
+ else
592
+ resp = MU::Cloud::Google.compute.send(delete_sym, project, obj.name)
593
+ end
594
+ if resp.error and resp.error.errors and resp.error.errors.size > 0
595
+ failed = true
596
+ retries += 1
597
+ if resp.error.errors.first.code == "RESOURCE_IN_USE_BY_ANOTHER_RESOURCE" and retries < 3
598
+ sleep 10
599
+ else
600
+ MU.log "Error deleting #{type.gsub(/_/, " ")} #{obj.name}", MU::ERR, details: resp.error.errors
601
+ raise MuError, "Failed to delete #{type.gsub(/_/, " ")} #{obj.name}"
602
+ end
603
+ else
604
+ # TODO validate that the resource actually went away, because it seems not to do so very reliably
605
+ end
606
+ failed = false
607
+ rescue ::Google::Apis::ClientError => e
608
+ raise e if !e.message.match(/^notFound: /)
609
+ end while failed and retries < 3
610
+ end
611
+ }
612
+ }
613
+ threads.each do |t|
614
+ t.join
615
+ end
616
+
617
+ end
618
+ end
619
+
620
+ @instance_cache = {}
621
+ # Catch-all for AWS client methods. Essentially a pass-through with some
622
+ # rescues for known silly endpoint behavior.
623
+ def method_missing(method_sym, *arguments)
624
+ retries = 0
625
+ actual_resource = nil
626
+ begin
627
+ MU.log "Calling #{method_sym}", MU::DEBUG, details: arguments
628
+ retval = nil
629
+ retries = 0
630
+ begin
631
+ if !arguments.nil? and arguments.size == 1
632
+ retval = @api.method(method_sym).call(arguments[0])
633
+ elsif !arguments.nil? and arguments.size > 0
634
+ retval = @api.method(method_sym).call(*arguments)
635
+ else
636
+ retval = @api.method(method_sym).call
637
+ end
638
+ rescue ::Google::Apis::AuthorizationError => e
639
+ if arguments.size > 0
640
+ raise MU::MuError, "Service account #{MU::Cloud::Google.svc_account_name} has insufficient privileges to call #{method_sym} in project #{arguments.first}"
641
+ else
642
+ raise MU::MuError, "Service account #{MU::Cloud::Google.svc_account_name} has insufficient privileges to call #{method_sym}"
643
+ end
644
+ rescue ::Google::Apis::ClientError => e
645
+ if e.message.match(/^invalidParameter:/)
646
+ MU.log "#{method_sym.to_s}: "+e.message, MU::ERR, details: arguments
647
+ end
648
+ if retries <= 1 and e.message.match(/^accessNotConfigured/)
649
+ enable_obj = nil
650
+ project = arguments.size > 0 ? arguments.first.to_s : MU::Cloud::Google.defaultProject
651
+ enable_obj = MU::Cloud::Google.service_manager(:EnableServiceRequest).new(
652
+ consumer_id: "project:"+project
653
+ )
654
+ # XXX dumbass way to get this string
655
+ e.message.match(/Enable it by visiting https:\/\/console\.developers\.google\.com\/apis\/api\/(.+?)\//)
656
+ svc_name = Regexp.last_match[1]
657
+ save_verbosity = MU.verbosity
658
+ if svc_name != "servicemanagement.googleapis.com"
659
+ MU.setLogging(MU::Logger::NORMAL)
660
+ MU.log "Attempting to enable #{svc_name} in project #{project}, then waiting for 30s", MU::WARN
661
+ MU.setLogging(save_verbosity)
662
+ MU::Cloud::Google.service_manager.enable_service(svc_name, enable_obj)
663
+ sleep 30
664
+ retries += 1
665
+ retry
666
+ else
667
+ MU.setLogging(MU::Logger::NORMAL)
668
+ MU.log "Google Cloud's Service Management API must be enabled manually by visiting #{e.message.gsub(/.*?(https?:\/\/[^\s]+)(?:$|\s).*/, '\1')}", MU::ERR
669
+ MU.setLogging(save_verbosity)
670
+ raise MU::MuError, "Service Management API not yet enabled for this account/project"
671
+ end
672
+ elsif retries <= 10 and
673
+ e.message.match(/^resourceNotReady:/) or
674
+ (e.message.match(/^resourceInUseByAnotherResource:/) and method_sym.to_s.match(/^delete_/))
675
+ if retries > 0 and retries % 3 == 0
676
+ MU.log "Will retry #{method_sym} after #{e.message} (retry #{retries})", MU::NOTICE, details: arguments
677
+ else
678
+ MU.log "Will retry #{method_sym} after #{e.message} (retry #{retries})", MU::DEBUG, details: arguments
679
+ end
680
+ retries = retries + 1
681
+ sleep retries*10
682
+ retry
683
+ else
684
+ raise e
685
+ end
686
+ end
687
+
688
+ if retval.class == ::Google::Apis::ComputeBeta::Operation
689
+ retries = 0
690
+ orig_target = retval.name
691
+ begin
692
+ if retries > 0 and retries % 3 == 0
693
+ MU.log "Waiting for #{method_sym} to be done (retry #{retries})", MU::NOTICE
694
+ else
695
+ MU.log "Waiting for #{method_sym} to be done (retry #{retries})", MU::DEBUG, details: retval
696
+ end
697
+
698
+ if retval.status != "DONE"
699
+ sleep 7
700
+ begin
701
+ resp = MU::Cloud::Google.compute.get_global_operation(
702
+ arguments.first, # there's always a project id
703
+ retval.name
704
+ )
705
+ retval = resp
706
+ rescue ::Google::Apis::ClientError => e
707
+ # this is ok; just means the operation is done and went away
708
+ if e.message.match(/^notFound:/)
709
+ break
710
+ else
711
+ raise e
712
+ end
713
+ end
714
+ retries = retries + 1
715
+ end
716
+ end while retval.status != "DONE"
717
+
718
+ # Most insert methods have a predictable get_* counterpart. Let's
719
+ # take advantage.
720
+ # XXX might want to do something similar for delete ops? just the
721
+ # but where we wait for the operation to definitely be done
722
+ had_been_found = false
723
+ if method_sym.to_s.match(/^(insert|create)_/) and retval.target_link
724
+ # service["#MU_CLOUDCLASS"].instance_methods(false).include?(:groom)
725
+ get_method = method_sym.to_s.gsub(/^(insert|create_disk|create)_/, "get_").to_sym
726
+ cloud_id = retval.target_link.sub(/^.*?\/([^\/]+)$/, '\1')
727
+ faked_args = arguments.dup
728
+ faked_args.pop
729
+ if get_method == :get_snapshot
730
+ faked_args.pop
731
+ faked_args.pop
732
+ end
733
+ faked_args.push(cloud_id)
734
+ actual_resource = @api.method(get_method).call(*faked_args)
735
+ #if method_sym == :insert_instance
736
+ #MU.log "actual_resource", MU::WARN, details: actual_resource
737
+ #end
738
+ had_been_found = true
739
+ if actual_resource.respond_to?(:status) and
740
+ ["PROVISIONING", "STAGING", "PENDING", "CREATING", "RESTORING"].include?(actual_resource.status)
741
+ retries = 0
742
+ begin
743
+ if retries > 0 and retries % 3 == 0
744
+ MU.log "Waiting for #{cloud_id} to get past #{actual_resource.status} (retry #{retries})", MU::NOTICE
745
+ else
746
+ MU.log "Waiting for #{cloud_id} to get past #{actual_resource.status} (retry #{retries})", MU::DEBUG, details: actual_resource
747
+ end
748
+ sleep 10
749
+ actual_resource = @api.method(get_method).call(*faked_args)
750
+ retries = retries + 1
751
+ end while ["PROVISIONING", "STAGING", "PENDING", "CREATING", "RESTORING"].include?(actual_resource.status)
752
+ end
753
+ return actual_resource
754
+ end
755
+ end
756
+ return retval
757
+ rescue ::Google::Apis::ServerError, ::Google::Apis::ClientError => e
758
+ if e.class.name == "Google::Apis::ClientError" and
759
+ (!method_sym.to_s.match(/^insert_/) or !e.message.match(/^notFound: /) or
760
+ (e.message.match(/^notFound: /) and method_sym.to_s.match(/^insert_/))
761
+ )
762
+ if e.message.match(/^notFound: /) and method_sym.to_s.match(/^insert_/)
763
+ logreq = MU::Cloud::Google.logging(:ListLogEntriesRequest).new(
764
+ resource_names: ["projects/"+arguments.first],
765
+ filter: %Q{labels."compute.googleapis.com/resource_id"="#{retval.target_id}" OR labels."ssl_certificate_id"="#{retval.target_id}"} # XXX I guess we need to cover all of the possible keys, ugh
766
+ )
767
+ logs = MU::Cloud::Google.logging.list_entry_log_entries(logreq)
768
+ details = nil
769
+ if logs.entries
770
+ details = logs.entries.map { |e| e.json_payload }
771
+ details.reject! { |e| e["error"].nil? or e["error"].size == 0 }
772
+ end
773
+
774
+ raise MuError, "#{method_sym.to_s} of #{retval.target_id} appeared to succeed, but then the resource disappeared! #{details.to_s}"
775
+ end
776
+ raise e
777
+ end
778
+ retries = retries + 1
779
+ debuglevel = MU::DEBUG
780
+ interval = 5 + Random.rand(4) - 2
781
+ if retries < 10 and retries > 2
782
+ debuglevel = MU::NOTICE
783
+ interval = 20 + Random.rand(10) - 3
784
+ # elsif retries >= 10 and retries <= 100
785
+ elsif retries >= 10
786
+ debuglevel = MU::WARN
787
+ interval = 40 + Random.rand(15) - 5
788
+ # elsif retries > 100
789
+ # raise MuError, "Exhausted retries after #{retries} attempts while calling EC2's #{method_sym} in #{@region}. Args were: #{arguments}"
790
+ end
791
+
792
+ MU.log "Got #{e.inspect} calling Google's #{method_sym}, waiting #{interval.to_s}s and retrying. Called from: #{caller[1]}", debuglevel, details: arguments
793
+ sleep interval
794
+ MU.log method_sym.to_s.bold+" "+e.inspect, MU::WARN, details: arguments
795
+ retry
796
+ end
797
+ end
798
+ end
799
+
800
+ @@compute_api = nil
801
+ @@container_api = nil
802
+ @@storage_api = nil
803
+ @@sql_api = nil
804
+ @@iam_api = nil
805
+ @@logging_api = nil
806
+ @@resource_api = nil
807
+ @@service_api = nil
808
+ @@admin_directory_api = nil
809
+ end
810
+ end
811
+ end