opensecret 0.0.9925 → 0.0.9949

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +656 -40
  3. data/lib/configs/README.md +58 -0
  4. data/lib/extension/file.rb +67 -0
  5. data/lib/extension/string.rb +10 -0
  6. data/lib/factbase/facts.opensecret.io.ini +1 -0
  7. data/lib/interprete.rb +334 -61
  8. data/lib/keytools/PRODUCE_RAND_SEQ_USING_DEV_URANDOM.txt +0 -0
  9. data/lib/keytools/kdf.api.rb +9 -15
  10. data/lib/keytools/kdf.bcrypt.rb +69 -19
  11. data/lib/keytools/kdf.pbkdf2.rb +112 -23
  12. data/lib/keytools/key.api.rb +146 -36
  13. data/lib/keytools/key.db.rb +94 -29
  14. data/lib/keytools/key.id.rb +1 -1
  15. data/lib/keytools/key.ident.rb +243 -0
  16. data/lib/keytools/key.local.rb +62 -68
  17. data/lib/keytools/key.pass.rb +2 -2
  18. data/lib/keytools/key.rb +2 -28
  19. data/lib/modules/{cryptology.md → README.md} +0 -0
  20. data/lib/session/fact.finder.rb +65 -428
  21. data/lib/session/time.stamp.rb +1 -28
  22. data/lib/usecase/cmd.rb +127 -54
  23. data/lib/usecase/config/README.md +57 -0
  24. data/lib/usecase/docker/README.md +146 -0
  25. data/lib/usecase/docker/docker.rb +49 -0
  26. data/lib/usecase/edit/README.md +43 -0
  27. data/lib/usecase/edit/delete.rb +46 -0
  28. data/lib/usecase/export.rb +40 -0
  29. data/lib/usecase/files/README.md +37 -0
  30. data/lib/usecase/files/eject.rb +56 -0
  31. data/lib/usecase/files/file_me.rb +78 -0
  32. data/lib/usecase/files/read.rb +169 -0
  33. data/lib/usecase/files/write.rb +89 -0
  34. data/lib/usecase/goto.rb +57 -0
  35. data/lib/usecase/id.rb +1 -1
  36. data/lib/usecase/import.rb +13 -30
  37. data/lib/usecase/init.rb +2 -17
  38. data/lib/usecase/jenkins/README.md +146 -0
  39. data/lib/usecase/jenkins/crazy_ruby_post_attempt.OLD +234 -0
  40. data/lib/usecase/jenkins/jenkins.rb +208 -0
  41. data/lib/usecase/login.rb +6 -5
  42. data/lib/usecase/logout.rb +1 -3
  43. data/lib/usecase/open.rb +11 -66
  44. data/lib/usecase/print.rb +40 -0
  45. data/lib/usecase/put.rb +34 -156
  46. data/lib/usecase/set.rb +2 -4
  47. data/lib/usecase/show.rb +138 -0
  48. data/lib/usecase/terraform/README.md +91 -0
  49. data/lib/usecase/terraform/terraform.rb +121 -0
  50. data/lib/usecase/token.rb +4 -80
  51. data/lib/usecase/update/README.md +55 -0
  52. data/lib/usecase/update/rename.rb +180 -0
  53. data/lib/usecase/use.rb +1 -3
  54. data/lib/usecase/verse.rb +20 -0
  55. data/lib/usecase/view.rb +71 -0
  56. data/lib/usecase/vpn/README.md +150 -0
  57. data/lib/usecase/vpn/vpn.ini +31 -0
  58. data/lib/usecase/vpn/vpn.rb +54 -0
  59. data/lib/version.rb +1 -1
  60. data/opensecret.gemspec +3 -4
  61. metadata +34 -35
  62. data/.travis.yml +0 -5
  63. data/CODE_OF_CONDUCT.md +0 -74
  64. data/LICENSE.txt +0 -21
  65. data/bin/ops +0 -20
  66. data/lib/keytools/binary.map.rb +0 -294
  67. data/lib/keytools/doc.conversion.to.ones.and.zeroes.ruby +0 -179
  68. data/lib/keytools/doc.rsa.radix.binary-mapping.ruby +0 -190
  69. data/lib/keytools/doc.star.schema.strategy.txt +0 -77
  70. data/lib/keytools/doc.using.pbkdf2.kdf.ruby +0 -95
  71. data/lib/keytools/doc.using.pbkdf2.pkcs.ruby +0 -266
  72. data/lib/keytools/key.mach.rb +0 -248
  73. data/lib/keytools/keydebug.txt +0 -295
  74. data/lib/modules/cryptology/open.bcrypt.rb +0 -170
  75. data/lib/usecase/read.rb +0 -89
  76. data/lib/usecase/safe.rb +0 -92
@@ -0,0 +1,146 @@
1
+
2
+ # safe jenkins <command>
3
+
4
+
5
+ ### safe jenkins post [aws|docker|git] <<jenkins-host-url>> | introduction
6
+
7
+ Use **`safe jenkins post`** to inject both your **AWS IAM User** and **docker login/password** credentials into your Jenkins 2.0 continuous integration portal reachable by the **jenkins host url** given in the 4th parameter of the safe command.
8
+
9
+ ---
10
+
11
+ ## safe jenkins post | prerequisite
12
+
13
+ Before you can inject credentials into jenkins using **`safe jenkins post`** you must
14
+
15
+ - be logged into your safe
16
+ - have opened the appropriate chapter/verse
17
+ - have put the required credential key/value pairs into the safe
18
+ - have the jenkins service up and running
19
+
20
+ After the post (to jenkins), your continuous integration jobs will be able to access the credential values via their IDs as stated in the below table.
21
+
22
+ ---
23
+
24
+ ## safe jenkins post aws | key names table
25
+
26
+ As credentials are WORO (write once, read often), safe makes the reading part very very easy (and secure) so your effort is frontloaded.
27
+
28
+ | Safe Key | Jenkins Credential IDs | Environment Variable | Description |
29
+ |:-----------:|:----------------------:|:--------------------- |:-------------------------------------------------------- |
30
+ | @access.key | safe.aws.access.key | AWS_ACCESS_KEY_ID | The AWS IAM user's access key credential. |
31
+ | @secret.key | safe.aws.secret.key | AWS_SECRET_ACCESS_KEY | The AWS IAM user's secret key credential. |
32
+ | region.key | safe.aws.region.key | AWS_REGION | The AWS region key that your Jenkins service points to. |
33
+
34
+ So you can see that by convention, safe expects the credential keys in the safe to be named a particular way, and likewise, you can be assured of the IDs it gives those credentials when posted to Jenkins.
35
+
36
+
37
+ ## safe jenkins post | credentials lifecycle
38
+
39
+ The life of the credentials begins when you create an IAM user and record its access and secret keys. Then
40
+
41
+ - you login to safe and store the 3 keys and their values
42
+ - safe jenkins post will read the values and post them to Jenkins
43
+ - Jenkins stores the values in conjunction with the Jenkins Credential IDs
44
+ - pipeline jobs ask Jenkins to put the Credential ID values against environment variables
45
+ - tools like Terraform and AwsCli use the environment variables to work in the cloud
46
+
47
+
48
+ ## Jenkinsfile | Usage in Pipeline Jobs
49
+
50
+ Here is a pipeline declaration within a Jenkinsfile that asks Jenkins to put the credential values in its secrets store into the stated environment variables.
51
+
52
+ environment
53
+ {
54
+ AWS_ACCESS_KEY_ID = credentials( 'safe.aws.access.key' )
55
+ AWS_SECRET_ACCESS_KEY = credentials( 'safe.aws.secret.key' )
56
+ AWS_REGION = credentials( 'safe.aws.region.key' )
57
+ }
58
+
59
+ After **`safe jenkins post aws`** you can **click into the Credentials item in the Jenkins main menu** to assure yourself that the credentials have indeed been properly injected.
60
+
61
+ ---
62
+
63
+ ## How to Write AWS Credentials into your Safe
64
+
65
+ In order to **`safe terraform apply`** or **`safe jenkins post aws <<jenkins-host-url>>`** or `safe visit` you must first put those ubiquitous IAM programmatic user credentials into your safe.
66
+
67
+ $ safe login joebloggs.com # open the book
68
+
69
+ $ safe open iam dev.s3.reader # open chapter and verse
70
+ $ safe put @access.key ABCD1234EFGH5678 # Put IAM access key in safe
71
+ $ safe put @secret.key xyzabcd1234efgh5678 # Put IAM secret key in safe
72
+ $ safe put region.key eu-west-3 # infrastructure in Paris
73
+
74
+ $ safe open iam canary.admin # open chapter and verse
75
+ $ safe put @access.key 4321DCBA8765WXYZ # Put IAM access key in safe
76
+ $ safe put @secret.key 5678uvwx4321abcd9876 # Put IAM secret key in safe
77
+ $ safe put region.key eu-west-1 # infrastructure in Dublin
78
+
79
+ $ safe logout
80
+
81
+
82
+ ---
83
+
84
+
85
+ ## How to write DockerHub Credentials into your Safe
86
+
87
+ #### safe jenkins post docker https://jenkins.example.com
88
+
89
+ Before you can issue a **`safe jenkins post docker http://localhost:8080`** you must insert your docker login credentials in the form of a username and @password into your safe. Remember that any key starting with the `@ sign` tells the safe to keep it a secret like when you issue a **`safe show`** command.
90
+
91
+ $ safe login joebloggs.com # open the book
92
+ $ safe open docker production # at the docker (for production) chapter and verse
93
+ $ safe put username admin # Put the Docker repository login username into the safe
94
+ $ safe put @password secret12345 # Put the Docker repository login @password into the safe
95
+ $ safe logout
96
+
97
+ When docker credentials are injected into a Jenkins service the safe will expect to find a key at the open chapter and verse called username and another one called password.
98
+
99
+ The safe promises to inject credentials with an ID of **safe.docker.login.id** so any jenkins jobs that need to use the docker login username and password must specify this ID when talking to the Jenkins credentials service.
100
+
101
+
102
+ ### DockerHub Credentials Inject Response
103
+
104
+ Here is an example of posting dockerhub credentials into a Jenkins service running on the local machine.
105
+
106
+ ``` bash
107
+ safe jenkins post docker http://localhost:8080
108
+ ```
109
+
110
+ If successful safe provides a polite response detailing what just happened.
111
+
112
+ ```
113
+ - Jenkins Host Url : http://localhost:8080/credentials/store/system/domain/_/createCredentials
114
+ - Credentials ID : safe.docker.login.id
115
+ - Inject Username : devops4me
116
+ - So what is this? : The docker repository login credentials in the shape of a username and password.
117
+
118
+ % Total % Received % Xferd Average Speed Time Time Time Current
119
+ Dload Upload Total Spent Left Speed
120
+ 100 428 0 0 100 428 0 47555 --:--:-- --:--:-- --:--:-- 47555
121
+ ```
122
+
123
+ ---
124
+
125
+
126
+ ## safe integrations | we need your help
127
+
128
+ **You can help to extend safe's integrations.**
129
+
130
+ By design - safe integrations are simple to write. They primarily integrate with producers and consumers. To deliver efficacy to devops engineers safe will endeavour to
131
+
132
+ - **send** credentials to **downstream consumers** and
133
+ - **receive** credentials from **upstream producers**
134
+
135
+ safe needs pull requests from the devops community and it promises to always strive to keep the task of writing an integration extremely simple.
136
+
137
+ ### integrations | what giving takes?
138
+
139
+ Currently, writing an integration entails delivering 3 or 4 artifacts which are
140
+
141
+ - 1 simple Ruby class
142
+ - 1 README.md documenting the command structure, the prerequisites and the expected outcome
143
+ - 1 class containing unit tests
144
+ - (optionaly) an INI file if many configuration and facts are involved
145
+
146
+ Giving doesn't take much so roll up your sleeves (or frocks) and get writing.
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module OpenSecret
4
+
5
+ # This Jenkins use case handles the to and fro integration of secrets and sensitive information
6
+ # between the safe database under management and a Jenkins service pinpointed by an incoming
7
+ # host url parameter.
8
+ #
9
+ # This Jenkins use case injects for example the AWS IAM user access key, secret key and region key
10
+ # into a running Jenkins CI (Continuous Integration) service at the specified (url) location.
11
+ #
12
+ # safe jenkins post <<[ aws | docker | git ]>> <<jenkins-host-url>>
13
+
14
+ class Jenkins < UseCase
15
+
16
+ attr_writer :command, :service, :url
17
+
18
+ JENKINS_URL_POSTFIX = "credentials/store/system/domain/_/createCredentials"
19
+ JENKINS_URL_PATH = "/credentials/store/system/domain/_/createCredentials"
20
+ REQUEST_CONTENT_TYPE = 'application/json;charset=UTF-8'
21
+
22
+ DATA_DICTIONARY = {
23
+ "scope" => "GLOBAL",
24
+ "id" => "safe.aws.region.key",
25
+ "secret" => "blahblahblah",
26
+ "description" => "The AWS region key for example eu-west-1 for Dublin in Ireland.",
27
+ "$class" => "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl"
28
+ }
29
+
30
+ ### DICTIONARY_TO_POST = { "" => "0", "credentials" => DATA_DICTIONARY }
31
+ DICTIONARY_TO_POST = { "credentials" => DATA_DICTIONARY }
32
+
33
+ def json_api_post_request_2
34
+
35
+ require 'net/http'
36
+ require 'json'
37
+
38
+ http = Net::HTTP.new( "localhost", "8080" )
39
+
40
+ ########### service_url = File.join( @url, JENKINS_URL_POSTFIX )
41
+
42
+ request = Net::HTTP::Post.new( JENKINS_URL_PATH )
43
+ uri_encoded_json = URI::encode( DICTIONARY_TO_POST.to_json )
44
+ request.body = uri_encoded_json
45
+ request.content_type = REQUEST_CONTENT_TYPE
46
+
47
+ response = http.request( request )
48
+
49
+ ### uri = URI.parse( "#{service_url}" )
50
+ ### req = Net::HTTP::Post.new(uri)
51
+ ### req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31')
52
+
53
+ ### res = Net::HTTP.start(uri.hostname, uri.port) do |http|
54
+ ### http.request(req)
55
+ ### end
56
+
57
+ puts response.body
58
+
59
+ end
60
+
61
+
62
+ def json_api_post_request_1
63
+
64
+ require 'net/http'
65
+ require 'json'
66
+
67
+ begin
68
+ service_url = File.join( @url, JENKINS_URL_POSTFIX )
69
+
70
+ puts ""
71
+ puts "The service_url is #{service_url}"
72
+
73
+ uri = URI( service_url )
74
+
75
+ puts "The simple URI hostname is #{uri.host}"
76
+ puts "Data will be sent via the URI port numbered [#{uri.port}]"
77
+ puts "The URI path string is #{uri.path}"
78
+
79
+ http = Net::HTTP.new(uri.host, uri.port)
80
+ #### req = Net::HTTP::Post.new(uri.path, {'Content-Type' =>'application/json',
81
+ #### 'Authorization' => 'XXXXXXXXXXXXXXXX'})
82
+
83
+
84
+ ### our_request = Net::HTTP::Post.new( uri.path, { 'Content-Type' =>'application/json' } )
85
+ ############## our_request.body = {"pizza_type" => "Margherita", "pizza_no" => "2"}.to_json
86
+
87
+ jenkins_inner_dictionary = {
88
+ "scope" => "GLOBAL",
89
+ "id" => "safe.aws.region.key",
90
+ "secret" => "blahblahblah",
91
+ "description" => "The AWS region key for example eu-west-1 for Dublin in Ireland.",
92
+ "$class" => "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl"
93
+ }
94
+
95
+ jenkins_outer_dictionary = { "" => "0", "credentials" => jenkins_inner_dictionary }
96
+
97
+ our_request = Net::HTTP::Post.new( uri.path )
98
+ our_request.set_form_data( jenkins_outer_dictionary.to_json )
99
+ ##### our_request.set_form_data( jenkins_inner_dictionary )
100
+
101
+
102
+
103
+ #### jenkins_jason_dictionary = jenkins_outer_dictionary.to_json
104
+ #### our_request.body = jenkins_jason_dictionary
105
+
106
+
107
+
108
+ ## http = Net::HTTP.new("api.restsite.com")
109
+
110
+ ## request = Net::HTTP::Post.new("/users")
111
+ ## request.set_form_data({"users[login]" => "quentin"})
112
+ ## response = http.request(request)
113
+
114
+
115
+
116
+ ## DELETE ME
117
+ ## DELETE ME
118
+ ## DELETE ME
119
+ puts "The [[[ SENSITIVE ]] JSON request body is this.\n\n #{our_request.body}"
120
+ puts ""
121
+
122
+ res = http.request( our_request )
123
+
124
+ puts res.body
125
+ ##### puts JSON.parse(res.body)
126
+
127
+ rescue => e
128
+
129
+ puts "failed #{e}"
130
+
131
+ end
132
+
133
+ end
134
+
135
+ def execute
136
+
137
+ return unless ops_key_exists?
138
+ master_db = get_master_database()
139
+ return if unopened_envelope?( master_db )
140
+
141
+ # Get the open chapter identifier (id).
142
+ # Decide whether chapter already exists.
143
+ # Then get (or instantiate) the chapter's hash data structure
144
+ chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
145
+ verse_id = master_db[ KEY_PATH ]
146
+ chapter_exists = OpenKey::KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
147
+
148
+ # Unlock the chapter data structure by supplying
149
+ # key/value mini-dictionary breadcrumbs sitting
150
+ # within the master database at the section labelled
151
+ # envelope@<<actual_chapter_id>>.
152
+ chapter_data = OpenKey::KeyDb.from_json( OpenKey::KeyApi.content_unlock( master_db[ chapter_id ] ) )
153
+
154
+ # Now read the three AWS IAM credentials @access.key, @secret.key and region.key
155
+ # into the 3 environment variables terraform expects to find.
156
+
157
+ # ----------------------------------------------------------------------------------------------------- #
158
+ # ----------------------------------------------------------------------------------------------------- #
159
+
160
+ # --
161
+ # -- Reading material for CUrl like activities using net/http core ruby library
162
+ # --
163
+ # -- ssl/https/rest => http://www.rubyinside.com/nethttp-cheat-sheet-2940.html
164
+ # -- official docs => https://ruby-doc.org/stdlib-2.4.1/libdoc/net/http/rdoc/Net/HTTP.html
165
+ # -- =>
166
+ # -- =>
167
+ # -- =>
168
+ # -- =>
169
+ # --
170
+
171
+ # ----------------------------------------------------------------------------------------------------- #
172
+ # ----------------------------------------------------------------------------------------------------- #
173
+
174
+
175
+ json_api_post_request_2
176
+
177
+ puts ""
178
+ puts "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
179
+ puts "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
180
+ puts ""
181
+
182
+ =begin
183
+ ENV[ "AWS_ACCESS_KEY_ID" ] = chapter_data[ verse_id ][ "@access.key" ]
184
+ ENV[ "AWS_SECRET_ACCESS_KEY" ] = chapter_data[ verse_id ][ "@secret.key" ]
185
+ ENV[ "AWS_DEFAULT_REGION" ] = chapter_data[ verse_id ][ "region.key" ]
186
+
187
+ auto_approve = @command && @command.eql?( "plan" ) ? "" : "-auto-approve"
188
+ command_name = @command ? @command : "apply"
189
+
190
+ puts ""
191
+ puts "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
192
+ puts ""
193
+
194
+ system "terraform #{command_name} #{auto_approve}"
195
+
196
+ puts ""
197
+ puts "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
198
+ puts ""
199
+ =end
200
+
201
+ # ############## | ############################################################
202
+ # @todo refactor | ############################################################
203
+ # -------------- | 000000000000000000000000000000000000000000000000000000000000
204
+ # export-then-execute
205
+ # -------------------
206
+ # Refactor all this code into a generic export-then-execute use case
207
+ # Then you pass in a Key/Value Dictionary
208
+ #
209
+ # { "AWS_ACCESS_KEY_ID" => "@access_key",
210
+ # "AWS_SECRET_ACCESS_KEY" => "@secret_key",
211
+ # "AWS_DEFAULT_REGION" => "region_key"
212
+ # }
213
+ #
214
+ # And pass in a command array [ "terraform #{command_name} #{auto_approve}", "terraform graph ..." ]
215
+ #
216
+ # Validation is done by the generic use case (which loops checking that every value exists
217
+ # as a key at the opened location.
218
+ #
219
+ # If all good the generic use case exports the ENV vars and runs each command in the list.
220
+ # PS - configure map in INI not code file
221
+ #
222
+ # The extra power will speed up generation of environment variable use cases including
223
+ # ansible, s3 bucket operations, git interactions and more.
224
+ #
225
+ # ############## | ############################################################
226
+ # ############## | ############################################################
227
+
228
+ end
229
+
230
+
231
+ end
232
+
233
+
234
+ end
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module OpenSecret
4
+
5
+ # This Jenkins use case handles the to and fro integration of secrets and sensitive information
6
+ # between the safe database under management and a Jenkins service pinpointed by an incoming
7
+ # host url parameter.
8
+ #
9
+ # This Jenkins use case injects for example the AWS IAM user access key, secret key and region key
10
+ # into a running Jenkins CI (Continuous Integration) service at the specified (url) location.
11
+ #
12
+ # safe jenkins post <<[ aws | docker | git ]>> <<jenkins-host-url>>
13
+
14
+ class Jenkins < UseCase
15
+
16
+ # The three instance variables provided through the command line like
17
+ # for example $ safe jenkins post aws http://localhost:8080
18
+ # For more info visit the documentation in the command interpreter class.
19
+ attr_writer :command, :service, :url
20
+
21
+ # If string variables EXPLODE throughout (and come to dominate) this class
22
+ # we should consider introducing an INI factfile like the [vpn] use case.
23
+ JENKINS_URI_PATH = "credentials/store/system/domain/_/createCredentials"
24
+
25
+ # If string variables EXPLODE throughout (and come to dominate) this class
26
+ # we should consider introducing an INI factfile like the [vpn] use case.
27
+ SECRET_KEY_VALUE_PAIR_DICTIONARY =
28
+ {
29
+ "scope" => "GLOBAL",
30
+ "$class" => "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl"
31
+ }
32
+
33
+ # If string variables EXPLODE throughout (and come to dominate) this class
34
+ # we should consider introducing an INI factfile like the [vpn] use case.
35
+ SECRET_KEY_VALUE_PAIR_TO_POST = { "" => "0", "credentials" => SECRET_KEY_VALUE_PAIR_DICTIONARY }
36
+
37
+
38
+ # If string variables EXPLODE throughout (and come to dominate) this class
39
+ # we should consider introducing an INI factfile like the [vpn] use case.
40
+ USERNAME_AND_PASSWORD_DICTIONARY =
41
+ {
42
+ "scope" => "GLOBAL",
43
+ "$class" => "com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl"
44
+ }
45
+
46
+ # If string variables EXPLODE throughout (and come to dominate) this class
47
+ # we should consider introducing an INI factfile like the [vpn] use case.
48
+ USERNAME_AND_PASSWORD_TO_POST = { "" => "0", "credentials" => USERNAME_AND_PASSWORD_DICTIONARY }
49
+
50
+
51
+
52
+ # Inject a Jenkins credential key-value pair that is secret and/or sensitive and
53
+ # needs to be referenced by executing continuous integration jobs.
54
+ #
55
+ # @param jenkins_base_url [String]
56
+ #
57
+ # This base url includes the scheme (protocol) which can be either http
58
+ # or https. It can include the port if it is not either 80 or 443. A common
59
+ # example is http://localhost:8080 but can also be https://jenkins.example.com
60
+ # It pays not to provide a trailing backslash on this url.
61
+ #
62
+ # @param credentials_id [String]
63
+ #
64
+ # The ID that Jenkins jobs will use to reference this credential's value.
65
+ #
66
+ # @param secret_value [String]
67
+ #
68
+ # The value of this credential (secret) that will be injected for SafeKeeping
69
+ # to the Jenkins service at the provided URL.
70
+ #
71
+ # @param description [String]
72
+ #
73
+ # Description of the credential that will be posted and can be viewed via
74
+ # the Jenkins user interface.
75
+ def inject_secret_key_value_pair( jenkins_base_url, credentials_id, secret_value, description )
76
+
77
+ jenkins_url = File.join( jenkins_base_url, JENKINS_URI_PATH )
78
+
79
+ credentials_dictionary = SECRET_KEY_VALUE_PAIR_DICTIONARY
80
+ credentials_dictionary.store( "id", credentials_id )
81
+ credentials_dictionary.store( "secret", secret_value )
82
+ credentials_dictionary.store( "description", description )
83
+
84
+ curl_cmd = "curl -X POST '#{jenkins_url}' --data-urlencode 'json=#{SECRET_KEY_VALUE_PAIR_TO_POST.to_json}'"
85
+
86
+ puts ""
87
+ puts " - Jenkins Host Url : #{jenkins_url}"
88
+ puts " - Credentials ID : #{credentials_id}"
89
+ puts " - So what is this? : #{description}"
90
+ puts ""
91
+
92
+ %x[ #{curl_cmd} ]
93
+
94
+ puts ""
95
+
96
+ end
97
+
98
+
99
+
100
+ # Inject into Jenkins a username and password pairing against an ID key that the
101
+ # continuous integration jobs know and can use to access the credentials pair.
102
+ #
103
+ # @param jenkins_base_url [String]
104
+ #
105
+ # This base url includes the scheme (protocol) which can be either http
106
+ # or https. It can include the port if it is not either 80 or 443. A common
107
+ # example is http://localhost:8080 but can also be https://jenkins.example.com
108
+ # It pays not to provide a trailing backslash on this url.
109
+ #
110
+ # @param credentials_id [String]
111
+ #
112
+ # The ID that Jenkins jobs will use to reference this credential's value.
113
+ #
114
+ # @param username [String]
115
+ #
116
+ # The value of this username (secret) that will be injected for SafeKeeping
117
+ # to the Jenkins service at the provided URL.
118
+ #
119
+ # @param password [String]
120
+ #
121
+ # The value of this password (secret) that will be injected for SafeKeeping
122
+ # to the Jenkins service at the provided URL.
123
+ #
124
+ # @param description [String]
125
+ #
126
+ # Description of the username and password pairing that will be posted and
127
+ # can be viewed via the Jenkins user interface.
128
+ def inject_username_and_password( jenkins_base_url, credentials_id, username, password, description )
129
+
130
+ jenkins_url = File.join( jenkins_base_url, JENKINS_URI_PATH )
131
+
132
+ credentials_dictionary = USERNAME_AND_PASSWORD_DICTIONARY
133
+ credentials_dictionary.store( "id", credentials_id )
134
+ credentials_dictionary.store( "username", username )
135
+ credentials_dictionary.store( "password", password )
136
+ credentials_dictionary.store( "description", description )
137
+
138
+ curl_cmd = "curl -X POST '#{jenkins_url}' --data-urlencode 'json=#{USERNAME_AND_PASSWORD_TO_POST.to_json}'"
139
+
140
+ puts ""
141
+ puts " - Jenkins Host Url : #{jenkins_url}"
142
+ puts " - Credentials ID : #{credentials_id}"
143
+ puts " - Inject Username : #{username}"
144
+ puts " - So what is this? : #{description}"
145
+ puts ""
146
+
147
+ %x[ #{curl_cmd} ]
148
+
149
+ puts ""
150
+
151
+ end
152
+
153
+
154
+
155
+ def execute
156
+
157
+ return unless ops_key_exists?
158
+ master_db = get_master_database()
159
+ return if unopened_envelope?( master_db )
160
+
161
+ # Get the open chapter identifier (id).
162
+ # Decide whether chapter already exists.
163
+ # Then get (or instantiate) the chapter's hash data structure
164
+ chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
165
+ verse_id = master_db[ KEY_PATH ]
166
+ chapter_exists = OpenKey::KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
167
+
168
+ # Unlock the chapter data structure by supplying
169
+ # key/value mini-dictionary breadcrumbs sitting
170
+ # within the master database at the section labelled
171
+ # envelope@<<actual_chapter_id>>.
172
+ chapter_data = OpenKey::KeyDb.from_json( OpenKey::KeyApi.content_unlock( master_db[ chapter_id ] ) )
173
+
174
+ key_value_dictionary = chapter_data[ verse_id ]
175
+
176
+ inject_aws_credentials( key_value_dictionary ) if @service.eql?( "aws" )
177
+ inject_docker_credentials( key_value_dictionary ) if @service.eql?( "docker" )
178
+
179
+ end
180
+
181
+
182
+
183
+ def inject_aws_credentials( mini_dictionary )
184
+
185
+ access_key_desc = "The access key of the AWS IAM (programmatic) user credentials."
186
+ secret_key_desc = "The secret key of the AWS IAM (programmatic) user credentials."
187
+ region_key_desc = "The AWS region key for example eu-west-1 for Dublin in Ireland."
188
+
189
+ inject_secret_key_value_pair( @url, "safe.aws.access.key", mini_dictionary[ "@access.key" ], access_key_desc )
190
+ inject_secret_key_value_pair( @url, "safe.aws.secret.key", mini_dictionary[ "@secret.key" ], secret_key_desc )
191
+ inject_secret_key_value_pair( @url, "safe.aws.region.key", mini_dictionary[ "region.key" ], region_key_desc )
192
+
193
+ end
194
+
195
+
196
+ def inject_docker_credentials( mini_dictionary )
197
+
198
+ docker_desc = "The docker repository login credentials in the shape of a username and password."
199
+
200
+ inject_username_and_password( @url, "safe.docker.login.id", mini_dictionary[ "docker.username" ], mini_dictionary[ "@docker.password" ], docker_desc )
201
+
202
+ end
203
+
204
+
205
+ end
206
+
207
+
208
+ end