opensecret 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -0
  3. data/README.md +2 -2
  4. data/bin/opensecret +3 -6
  5. data/lib/opensecret-domain.ini +23 -0
  6. data/lib/opensecret.rb +30 -2
  7. data/lib/opensecret/additions/array.rb +117 -0
  8. data/lib/opensecret/additions/dir.rb +35 -0
  9. data/lib/opensecret/additions/string.rb +312 -0
  10. data/lib/opensecret/commons/eco.cmdline.rb +446 -0
  11. data/lib/opensecret/commons/eco.faculty.rb +364 -0
  12. data/lib/opensecret/commons/eco.system.rb +437 -0
  13. data/lib/opensecret/commons/eco.systems.rb +98 -0
  14. data/lib/opensecret/{safe.rb → delegate.rb} +4 -2
  15. data/lib/opensecret/eco.do.rb +46 -0
  16. data/lib/opensecret/executors/crypt.keys/crypt.keys.ini +79 -0
  17. data/lib/opensecret/executors/crypt.keys/crypt.keys.rb +68 -0
  18. data/lib/opensecret/executors/decrypt/decrypt.ini +64 -0
  19. data/lib/opensecret/executors/decrypt/decrypt.rb +49 -0
  20. data/lib/opensecret/executors/encrypt/encrypt.ini +55 -0
  21. data/lib/opensecret/executors/encrypt/encrypt.rb +82 -0
  22. data/lib/opensecret/factbase/hub-runtime.ini +123 -0
  23. data/lib/opensecret/factbase/known-hosts.ini +75 -0
  24. data/lib/opensecret/factbase/published.facts/blobbolicious-facts.ini +553 -0
  25. data/lib/opensecret/factbase/published.facts/credential-facts.ini +40 -0
  26. data/lib/opensecret/factbase/published.facts/infrastructure-facts.ini +63 -0
  27. data/lib/opensecret/factbase/readme.md +24 -0
  28. data/lib/opensecret/factbase/retired.facts/maven.database.ide.facts.ini +127 -0
  29. data/lib/opensecret/factbase/retired.facts/s3-upload-block-facts.ini +17 -0
  30. data/lib/opensecret/plugins.io/cipher/crypto.rb +174 -0
  31. data/lib/opensecret/plugins.io/error/eco.exceptions.rb +24 -0
  32. data/lib/opensecret/plugins.io/facts/fact.chars.rb +66 -0
  33. data/lib/opensecret/plugins.io/facts/fact.factor.rb +156 -0
  34. data/lib/opensecret/plugins.io/facts/fact.locator.rb +105 -0
  35. data/lib/opensecret/plugins.io/facts/fact.reader.rb +137 -0
  36. data/lib/opensecret/plugins.io/facts/fact.tree.rb +661 -0
  37. data/lib/opensecret/plugins.io/file/file.rb +483 -0
  38. data/lib/opensecret/plugins.io/git/git.flow.rb +388 -0
  39. data/lib/opensecret/plugins.io/logs/log.object.rb +89 -0
  40. data/lib/opensecret/plugins.io/logs/logging.rb +203 -0
  41. data/lib/opensecret/plugins.io/time/time.stamp.rb +425 -0
  42. data/lib/opensecret/version.rb +2 -2
  43. data/opensecret.gemspec +8 -13
  44. metadata +68 -18
@@ -0,0 +1,40 @@
1
+
2
+ # --
3
+ # -- If a plugin requires AWS IAM user credentials you must
4
+ # -- define the directory the credentials are in within the
5
+ # -- [plugin+platform] fact file.
6
+ # --
7
+ # -- A credentials INI factfile is expected to exist within
8
+ # -- that directory with the name
9
+ # --
10
+ # -- => [:eco][id] + ".aws.credentials.ini"
11
+ # -- => ci.hub.aws.credentials.ini [(if id is ci.hub)]
12
+ # --
13
+ # -- To specify AWS IAM credentials for a plugin, you
14
+ # --
15
+ # -- [1] specify [:aws][:keys_folder] in [plugin+platform]
16
+ # -- [2] put <<eco.id>>.aws.credentials.ini inside folder
17
+ # --
18
+ # -- The format of the credentials file for a plugin ID of
19
+ # -- (ci.hub) named [ci.hub.aws.credentials.ini] would be
20
+ # --
21
+ # -- [ci.hub]
22
+ # -- aws.access.key = AKIA12345
23
+ # -- aws.secret.key = abc123secret
24
+ # -- aws.region.key = us-east-2
25
+ # --
26
+ # -- ----------------------------
27
+ # -- AWS Credentials | Summary
28
+ # -- ----------------------------
29
+ # --
30
+ # -- [One] plugin running on [a] workstation or inside [a]
31
+ # -- container can only use [one] set of IAM user credentials
32
+ # -- located in [an] accessible folder (on a removable drive).
33
+ # --
34
+
35
+ [aws]
36
+ creds.name = e>> @f[:eco][:id] + Do.t + "aws.credentials.ini"
37
+ dir.exists? = e>> !@f[@i[:workstation]][:aws_creds_dir].nil?
38
+ creds.path(if) = { @s[:dir_exists?] } e>> File.join @f[@i[:workstation]][:aws_creds_dir], @s[:creds_name]
39
+ creds.exist? = e>> exists?(@s[:creds_path]) && File.exists?(@s[:creds_path])
40
+
@@ -0,0 +1,63 @@
1
+
2
+ [terraform]
3
+ aws.instance.id = e>> "ec2-" + @f[:stamp][:mini_2]
4
+ aws.sgroup.id = e>> "acl-" + @f[:stamp][:mini_2]
5
+ route53.dns.id = e>> "dns-" + @f[:stamp][:mini_2]
6
+ route53.www.id = e>> "www-" + @f[:stamp][:mini_2]
7
+ route53.ssl.id = e>> "ssl-" + @f[:stamp][:mini_2]
8
+ resource.group = e>> @f[:stamp][:midi]
9
+
10
+ ec2.acl.name = e>> "acl." + @f[:stamp][:midi]
11
+ ec2.tag.name = e>> "ec2." + @f[:stamp][:midi]
12
+ ebs.tag.name = e>> "ebs." + @f[:stamp][:midi]
13
+ ec2.acl.desc = e>> "Rules (acl) for the " + @f[:stamp][:midi] + " tcp/ip traffic."
14
+
15
+ username = ubuntu
16
+ keypair.name = e>> "keypair." + @f[:stamp][:midi]
17
+ private.key = e>> File.join @f[:runtime][:dir], ( @s[:keypair_name] + ".pem" )
18
+
19
+ aws.exe.win = windows_amd64/terraform-provider-aws_v1.7.0_x4.exe
20
+ aws.exe.linux = linux_amd64/terraform-provider-aws_v1.6.0_x4
21
+
22
+ exe.filename(if)= { Gem.win_platform? } e>> @s[:aws_exe_win]
23
+ exe.filename(un)= { Gem.win_platform? } e>> @s[:aws_exe_linux]
24
+ exe.source.dir = e>> File.join @f[:runtime][:dir], ".terraform/plugins"
25
+
26
+ ec2.host = e>> LinuxHost.ec2_using_terraform( \
27
+ @s[:username], \
28
+ @s[:private_key], \
29
+ @f[:runtime][:dir], \
30
+ @s[:keypair_name], \
31
+ @s[:exe_filename], \
32
+ @s[:exe_source_dir], \
33
+ @f[:runtime][:archive] \
34
+ )
35
+
36
+
37
+ [domain]
38
+ has.domain? = e>> exists?( @p[:root_domain] )
39
+ root(if) = { @s[:has_domain?] } e>> @p[:root_domain]
40
+ www(if) = { @s[:has_domain?] } e>> "www" + dot + @s[:root]
41
+ https(if) = { @s[:has_domain?] } e>> "https://" + @s[:www]
42
+ http(if) = { @s[:has_domain?] } e>> "http://" + @s[:www]
43
+
44
+
45
+ [machine]
46
+ suffix = host
47
+ name.known? = e>> exists?(@f[@i[:workstation]][plugin_symbol(@s[:suffix])])
48
+
49
+ fact.name(if) = { @s[:name_known?] } e>> @f[@i[:workstation]][plugin_symbol(@s[:suffix])]
50
+ key.name(if) = { @s[:name_known?] } e>> @s[:fact_name] + ".ssh.key.pem"
51
+ ssh.key(if) = { @s[:name_known?] } e>> File.join @f[@i[:workstation]][:ssh_keydir], @s[:key_name]
52
+ user.name(if) = { @s[:name_known?] } e>> @f[symbol(@s[:fact_name])][:username]
53
+ host.name(if) = { @s[:name_known?] } e>> @f[symbol(@s[:fact_name])][:hostnames].first
54
+ net.bridge(if) = { @s[:name_known?] } e>> @f[symbol(@s[:fact_name])][:net_bridge]
55
+
56
+ host.class(if) = { @s[:name_known?] } e>> LinuxHost.existing_host( \
57
+ @s[:host_name], \
58
+ @s[:user_name], \
59
+ @s[:ssh_key], \
60
+ @s[:net_bridge] \
61
+ )
62
+
63
+ host.class(un) = { @s[:name_known?] } e>> @f[:terraform][:ec2_host]
@@ -0,0 +1,24 @@
1
+
2
+ # Fact File Read Order
3
+
4
+ Fact files are assimilated in a simple yet powerful manner.
5
+
6
+ ## Assimilation Order
7
+
8
+ The fact files are assimilated in this order
9
+
10
+ - first the **core fact files** in the **reusable.facts** folder
11
+ - next is the **plugin's fact file** eg ***gitlab.dev.ini*** in reusable.plugins/gitlab.dev
12
+ - then every fact file in the **reusable.facts/general** directory and subdirectories
13
+ - then it is all the fact files declared for **import via HTTP, SCP, SFTP and Rest APIs**
14
+ - then from **git repositories, key-value stores** (etcd, redis) and **(nosql) databases**
15
+ - finally, **credential fact files on removable media**, in vaults and key pass structures
16
+
17
+ ## Indexing for Large Fact Repositories
18
+
19
+ Once the third reusable.facts/general store becomes **large** we could devise methods of
20
+
21
+ - **indexing** all the **long-lived facts** as and when they are produced
22
+ - **mining fact dependencies** from plugin software, fact files and templates
23
+ - then **importing** just the needful set of facts (and their dependencies)
24
+
@@ -0,0 +1,127 @@
1
+ [database]
2
+ name = app_datastore
3
+ admin.username = e>> "admin.usr." + Stamp.yyjjj_hhmm_sst
4
+ admin.password = e>> Secrets.derive_alphanum
5
+ app.username = e>> "app.usr." + Stamp.yyjjj_hhmm_sst
6
+ app.password = e>> Secrets.derive_alphanum
7
+
8
+ content.url = https://www.eco-platform.co.uk/content/database.git/
9
+ content.name = e>> "db.content." + Stamp.yyjjj_hhmm_sst
10
+ content.zip = e>> @f[:database][:content_name] + ".zip"
11
+ content.files = e>> GitFlow.file_names @f[:database][:content_url]
12
+ content.path = /var/lib/mongodb/content.library
13
+
14
+ import.stmts = e>> MongoFlow.to_inport_stmts( \
15
+ @f[:database][:content_files], \
16
+ @f[:database][:content_path], \
17
+ @f[:database][:database_name], \
18
+ @f[:database][:app_username], \
19
+ @f[:database][:app_password] \
20
+ )
21
+
22
+
23
+ [rest]
24
+ docs.url = https://www.eco-platform.co.uk/content/rest.documents.git/
25
+ docs.offset = application.objects/
26
+ zip.basename = e>> @f[:s3][:upload_prefix] + "application.objects"
27
+ zip.filename = e>> @f[:rest][:zip_basename] + ".zip"
28
+
29
+
30
+ [ide]
31
+ idea.iml.dir = e>> File.join @f[:runtime][:dir], "idea_modules"
32
+ conf.repo.url = https://www.eco-platform.co.uk/content/intellij.conf.git/
33
+ conf.base.dir = e>> File.join @f[:runtime][:dir], "ide_config"
34
+ conf.dir.name = apollo.laundry4j
35
+ conf.home.dir = e>> File.join @f[:ide][:conf_base_dir], @f[:ide][:conf_dir_name]
36
+
37
+ idea.prop.src = e>> File.join @f[:runtime][:dir], "asset.idea.properties"
38
+ idea.prop.dir = C:/Program Files (x86)/JetBrains/IntelliJ IDEA Community Edition 14.0.2/bin
39
+ idea.prop.dst = e>> File.join @f[:ide][:idea_prop_dir], "idea.properties"
40
+
41
+ options.base.dir = e>> File.join @f[:runtime][:dir], "ide_config/apollo.laundry4j/options"
42
+ default.xml.file = project.default.xml
43
+ default.xml.path = e>> File.join @f[:ide][:options_base_dir], @f[:ide][:default_xml_file]
44
+
45
+
46
+ [maven]
47
+ jar.projects = e>> %w[ \
48
+ https://www.eco-platform.co.uk/commons/laundry4j.facility \
49
+ https://www.eco-platform.co.uk/commons/laundry4j.mappable \
50
+ https://www.eco-platform.co.uk/commons/laundry4j.mappers \
51
+ https://www.eco-platform.co.uk/commons/laundry4j.clusters \
52
+ https://www.eco-platform.co.uk/football/footb4ll.net \
53
+ https://www.eco-platform.co.uk/commons/laundry4j.explorer \
54
+ ]
55
+
56
+
57
+ install.dir = C:/Program Files/apache-maven-3.3.9
58
+ settings.xml = C:/Program Files/apache-maven-3.3.9/conf/settings.xml
59
+ version.dev = e>> Stamp.yyjjj_hhmm_sst + "-SNAPSHOT"
60
+ version.push = e>> Stamp.yyjjj_hhmm_sst
61
+
62
+ builds.dir = e>> File.join @f[:runtime][:dir], "maven_builds"
63
+ amalgam.dir = e>> File.join @f[:runtime][:dir], "maven_projects"
64
+ javadocs.dir = e>> File.join @f[:runtime][:dir], "maven_javadocs"
65
+ apidocs.dir = e>> File.join @f[:maven][:javadocs_dir], "site/apidocs"
66
+ pom.xml.src = e>> File.join @f[:runtime][:dir], "asset.amalgam.pom.xml"
67
+ pom.xml.dst = e>> File.join @f[:maven][:amalgam_dir], "pom.xml"
68
+
69
+ css.file.src = e>> File.join @f[:runtime][:dir], "asset.stylesheet.css"
70
+ css.file.dst = e>> File.join @f[:maven][:apidocs_dir], "stylesheet.css"
71
+
72
+ index.html.src = e>> File.join @f[:maven][:apidocs_dir], "overview-summary.html"
73
+ index.html.dst = e>> File.join @f[:maven][:apidocs_dir], "index.html"
74
+
75
+ cmd.prefix = e>> "mvn -f " + @f[:maven][:pom_xml_dst] + " clean "
76
+ cmd.javadocs = e>> @f[:maven][:cmd_prefix] + "javadoc:aggregate source:aggregate"
77
+
78
+ war.project = https://www.eco-platform.co.uk/commons/laundry4j.web
79
+ war.module = e>> Pom.get_module_name @f[:maven][:war_project]
80
+ projects = e>> @f[:maven][:jar_projects].push @f[:maven][:war_project]
81
+ war.prj.dir = e>> File.join @f[:maven][:amalgam_dir], @f[:maven][:war_module]
82
+ war.pom.xml = e>> File.join @f[:maven][:war_prj_dir], "pom.xml"
83
+ war.run.cmd = e>> "mvn -f " + @f[:maven][:war_pom_xml] + " cargo:run -P tomcat8x"
84
+
85
+ module.names = e>> Pom.get_module_names @f[:maven][:projects]
86
+ module.lines = e>> Refactor.sandwich_lines @f[:maven][:module_names], "<module>", "</module>", 16
87
+
88
+ no1.prj.dir = e>> File.join @f[:maven][:amalgam_dir], @f[:maven][:module_names].first
89
+ no1.pom.xml = e>> File.join @f[:maven][:no1_prj_dir], "pom.xml"
90
+ version.cmd = e>> "mvn -f " + @f[:maven][:no1_pom_xml] + " versions:set -DgroupId=com.* -DartifactId=* -DnewVersion=" + @f[:maven][:version_dev] + " -DgenerateBackupPoms=false"
91
+
92
+
93
+ ############ mvn -f facility/pom.xml versions:set -DgroupId=com.* -DartifactId=* -DnewVersion=77.77.00-SNAPSHOT
94
+ ###### http://localhost:8899/explorer-17.263.1858-SNAPSHOT
95
+
96
+ # --
97
+ # -- Create ruby/maven commands that act on one or more projects
98
+ # -- Command examples
99
+ # -- - system "mvn -f maven_projects/customer/pom.xml clean install"
100
+ # --
101
+ install.opts = clean install
102
+ install.cmd = e>> "mvn -f " + @f[:maven][:pom_xml_dst] + " clean install"
103
+
104
+ ## cmd.prefix = e>> "system " + Ch.dq + "mvn -f maven_projects/"
105
+ ## cmd.postfix = /pom.xml
106
+
107
+
108
+ [git]
109
+ base.url = https://www.eco-platform.co.uk
110
+ local.dir = e>> File.dirname Dir.pwd
111
+ dot.git.dir = e>> File.join @f[:git][:local_dir], ".git"
112
+ revision = e>> GitFlow.wc_revision @f[:git][:dot_git_dir]
113
+ ssh.keyfile = e>> File.join Home.dir, "com.laundry4j.drive/library.ssh.access.keys/gitlab.laundry4j.private.key.pem"
114
+
115
+ [git.content]
116
+ url = e>> File.join @f[:git][:base_url], "content"
117
+
118
+
119
+ [git.commons]
120
+ url = e>> File.join @f[:git][:base_url], "commons"
121
+ eco.proj.name = eco-platform
122
+ eco.repo.name = e>> @s[:eco_proj_name] + ".git"
123
+ eco.repo.url = e>> File.join @s[:url], @s[:eco_repo_name]
124
+
125
+
126
+
127
+
@@ -0,0 +1,17 @@
1
+ # --- --------------------------------------------------------------------- --- #
2
+ # --- This fact (INI) file database carries facts for the s3 upload block. --- #
3
+ # --- --------------------------------------------------------------------- --- #
4
+ # --- [DEPENDENCY] => @f[:upload][:src_file_name] --- #
5
+ # --- => This dependency must be set before fact evaluation. --- #
6
+ # --- --------------------------------------------------------------------- --- #
7
+
8
+ [upload]
9
+ src.file.path = e>> File.join @f[:runtime][:dir], @f[:upload][:src_file_name]
10
+ dot.full.extn = e>> File.extname @f[:upload][:src_file_path]
11
+ src.base.name = e>> File.basename @f[:upload][:src_file_name], @f[:upload][:dot_full_extn]
12
+ prefix.less.name = e>> @f[:upload][:src_base_name][ @f[:s3][:upload_prefix].length .. -1 ]
13
+ app.props.base = e>> @f[:upload][:prefix_less_name] + @f[:upload][:dot_full_extn]
14
+ app.props.key = e>> (@f[:upload][:app_props_base] + Ch.p + "url").gsub(".","_").to_sym
15
+ dst.file.base = e>> @f[:upload][:prefix_less_name] + Ch.p + @f[:stamp][:midi]
16
+ dst.file.name = e>> @f[:upload][:dst_file_base] + @f[:upload][:dot_full_extn]
17
+ dst.file.path = e>> File.join @f[:s3][:uploads_dir], @f[:upload][:dst_file_name]
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # --
4
+ # -- Create dynamic secrets of various flavours including
5
+ # --
6
+ # -- - ssh public/private key secrets
7
+ # -- - secret keys for internal database services
8
+ # -- - hashed SHA256 keys for Jenkins user auth
9
+ # --
10
+ class Crypto
11
+
12
+ # --
13
+ # -- Get a viable machine password taking into account the human
14
+ # -- password length and the specified mix_ratio.
15
+ # --
16
+ # -- machine password length = human password length * mix_ratio - 1
17
+ # --
18
+ def self.get_amalgam_password human_password, machine_password, mix_ratio
19
+
20
+ size_error_msg = "Human pass length times mix_ratio must equal machine pass length."
21
+ lengths_are_perfect = human_password.length * mix_ratio == machine_password.length
22
+ raise ArgumentError.new size_error_msg unless lengths_are_perfect
23
+
24
+ machine_passwd_chunk = 0
25
+ amalgam_passwd_index = 0
26
+ amalgamated_password = ""
27
+
28
+ human_password.each_char do |passwd_char|
29
+
30
+ amalgamated_password[amalgam_passwd_index] = passwd_char
31
+ amalgam_passwd_index += 1
32
+
33
+ for i in 0..(mix_ratio-1) do
34
+ machine_pass_index = machine_passwd_chunk * mix_ratio + i
35
+ amalgamated_password[amalgam_passwd_index] = machine_password[machine_pass_index]
36
+ amalgam_passwd_index += 1
37
+ end
38
+
39
+ machine_passwd_chunk += 1
40
+
41
+ end
42
+
43
+ return amalgamated_password
44
+
45
+ end
46
+
47
+ # --
48
+ # -- Get a viable machine password taking into account the human
49
+ # -- password length and the specified mix_ratio.
50
+ # --
51
+ # -- machine password length = human password length * mix_ratio - 1
52
+ # --
53
+ def self.get_machine_password human_password_length, mix_ratio
54
+
55
+ machine_raw_secret = engineer_password( human_password_length * ( mix_ratio + 1) )
56
+ return machine_raw_secret[ 0..( human_password_length * mix_ratio - 1 ) ]
57
+
58
+ end
59
+
60
+
61
+ # --
62
+ # -- Collect a password from the user with a minimum length
63
+ # -- specified in the parameter.
64
+ # --
65
+ # -- An exception is raised if the minimum length is not at
66
+ # -- least 8 characters.
67
+ # --
68
+ def self.collect_secret minimum_size, prompt_1, prompt_2
69
+
70
+ assert_min_size minimum_size
71
+
72
+ sleep(1)
73
+ puts "\n#{prompt_1} : "
74
+ first_secret = STDIN.noecho(&:gets).chomp
75
+
76
+ assert_input_text_size first_secret.length, minimum_size
77
+
78
+ sleep(1)
79
+ puts "\n#{prompt_2} : "
80
+ check_secret = STDIN.noecho(&:gets).chomp
81
+
82
+ assert_same_size_text first_secret, check_secret
83
+
84
+ return first_secret
85
+
86
+ end
87
+
88
+
89
+ # --
90
+ # -- Engineer a raw password that is similar (approximate) in
91
+ # -- length to the integer parameter.
92
+ # --
93
+ def self.engineer_password approx_length
94
+
95
+ non_alphanum = SecureRandom.urlsafe_base64(approx_length);
96
+ return non_alphanum.delete("-_")
97
+
98
+ end
99
+
100
+
101
+ # --
102
+ # -- Raise an exception if asked to collect text that is less
103
+ # -- than 3 characters in length.
104
+ # --
105
+ def self.assert_min_size minimum_size
106
+
107
+ min_length_msg = "\n\nCrypts with 2 (or less) characters open up exploitable holes.\n\n"
108
+ raise ArgumentError.new min_length_msg if minimum_size < 3
109
+
110
+ end
111
+
112
+
113
+ # --
114
+ # -- Output an error message and then exit if the entered input
115
+ # -- text size does not meet the minimum requirements.
116
+ # --
117
+ def self.assert_input_text_size input_size, minimum_size
118
+
119
+ if( input_size < minimum_size )
120
+
121
+ puts
122
+ puts "Input is too short. Please enter at least #{minimum_size} characters."
123
+ puts
124
+
125
+ exit
126
+
127
+ end
128
+
129
+ end
130
+
131
+
132
+ # --
133
+ # -- Assert that the text entered the second time is exactly (case sensitive)
134
+ # -- the same as the text entered the first time.
135
+ # --
136
+ def self.assert_same_size_text first_text, second_text
137
+
138
+ unless( first_text.eql? second_text )
139
+
140
+ puts
141
+ puts "Those two bits of text are not the same (in my book)!"
142
+ puts
143
+
144
+ exit
145
+
146
+ end
147
+
148
+ end
149
+
150
+
151
+ # --
152
+ # -- Print out the machine password that is to be kept as an environment variable
153
+ # -- on any workstation used for material decryption.
154
+ # --
155
+ # -- Remember that neither the human nor machine passwords are required for the
156
+ # -- encryption phase. That is the beauty of assymetric cryptography - you don't
157
+ # -- need a private key to encrypt - just the end user's public key.
158
+ # --
159
+ def self.print_secret_env_var env_var_name, env_var_value
160
+
161
+ machine_to_env_txt = "sudo echo \"#{env_var_name}=#{env_var_value}\" >> /etc/environment"
162
+
163
+ puts
164
+ puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
165
+ puts "@@@ Add as environment variable @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
166
+ puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
167
+ puts machine_to_env_txt
168
+ puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
169
+ puts
170
+
171
+ end
172
+
173
+
174
+ end