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.
- checksums.yaml +4 -4
- data/README.md +656 -40
- data/lib/configs/README.md +58 -0
- data/lib/extension/file.rb +67 -0
- data/lib/extension/string.rb +10 -0
- data/lib/factbase/facts.opensecret.io.ini +1 -0
- data/lib/interprete.rb +334 -61
- data/lib/keytools/PRODUCE_RAND_SEQ_USING_DEV_URANDOM.txt +0 -0
- data/lib/keytools/kdf.api.rb +9 -15
- data/lib/keytools/kdf.bcrypt.rb +69 -19
- data/lib/keytools/kdf.pbkdf2.rb +112 -23
- data/lib/keytools/key.api.rb +146 -36
- data/lib/keytools/key.db.rb +94 -29
- data/lib/keytools/key.id.rb +1 -1
- data/lib/keytools/key.ident.rb +243 -0
- data/lib/keytools/key.local.rb +62 -68
- data/lib/keytools/key.pass.rb +2 -2
- data/lib/keytools/key.rb +2 -28
- data/lib/modules/{cryptology.md → README.md} +0 -0
- data/lib/session/fact.finder.rb +65 -428
- data/lib/session/time.stamp.rb +1 -28
- data/lib/usecase/cmd.rb +127 -54
- data/lib/usecase/config/README.md +57 -0
- data/lib/usecase/docker/README.md +146 -0
- data/lib/usecase/docker/docker.rb +49 -0
- data/lib/usecase/edit/README.md +43 -0
- data/lib/usecase/edit/delete.rb +46 -0
- data/lib/usecase/export.rb +40 -0
- data/lib/usecase/files/README.md +37 -0
- data/lib/usecase/files/eject.rb +56 -0
- data/lib/usecase/files/file_me.rb +78 -0
- data/lib/usecase/files/read.rb +169 -0
- data/lib/usecase/files/write.rb +89 -0
- data/lib/usecase/goto.rb +57 -0
- data/lib/usecase/id.rb +1 -1
- data/lib/usecase/import.rb +13 -30
- data/lib/usecase/init.rb +2 -17
- data/lib/usecase/jenkins/README.md +146 -0
- data/lib/usecase/jenkins/crazy_ruby_post_attempt.OLD +234 -0
- data/lib/usecase/jenkins/jenkins.rb +208 -0
- data/lib/usecase/login.rb +6 -5
- data/lib/usecase/logout.rb +1 -3
- data/lib/usecase/open.rb +11 -66
- data/lib/usecase/print.rb +40 -0
- data/lib/usecase/put.rb +34 -156
- data/lib/usecase/set.rb +2 -4
- data/lib/usecase/show.rb +138 -0
- data/lib/usecase/terraform/README.md +91 -0
- data/lib/usecase/terraform/terraform.rb +121 -0
- data/lib/usecase/token.rb +4 -80
- data/lib/usecase/update/README.md +55 -0
- data/lib/usecase/update/rename.rb +180 -0
- data/lib/usecase/use.rb +1 -3
- data/lib/usecase/verse.rb +20 -0
- data/lib/usecase/view.rb +71 -0
- data/lib/usecase/vpn/README.md +150 -0
- data/lib/usecase/vpn/vpn.ini +31 -0
- data/lib/usecase/vpn/vpn.rb +54 -0
- data/lib/version.rb +1 -1
- data/opensecret.gemspec +3 -4
- metadata +34 -35
- data/.travis.yml +0 -5
- data/CODE_OF_CONDUCT.md +0 -74
- data/LICENSE.txt +0 -21
- data/bin/ops +0 -20
- data/lib/keytools/binary.map.rb +0 -294
- data/lib/keytools/doc.conversion.to.ones.and.zeroes.ruby +0 -179
- data/lib/keytools/doc.rsa.radix.binary-mapping.ruby +0 -190
- data/lib/keytools/doc.star.schema.strategy.txt +0 -77
- data/lib/keytools/doc.using.pbkdf2.kdf.ruby +0 -95
- data/lib/keytools/doc.using.pbkdf2.pkcs.ruby +0 -266
- data/lib/keytools/key.mach.rb +0 -248
- data/lib/keytools/keydebug.txt +0 -295
- data/lib/modules/cryptology/open.bcrypt.rb +0 -170
- data/lib/usecase/read.rb +0 -89
- 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 docker.username and @docker.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 docker.username admin # Put the Docker repository login docker.username into the safe
|
94
|
+
$ safe put @docker.password s3cr3t # Put the Docker repository login @docker.password into the safe
|
95
|
+
$ safe logout
|
96
|
+
|
97
|
+
When docker credentials are injected into a Jenkins service the safe will expect to find **lines** at the open chapter and verse location with key names **`docker.username`** and **`@docker.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 docker.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,49 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module OpenSecret
|
4
|
+
|
5
|
+
# This docker use case handles the ...
|
6
|
+
#
|
7
|
+
# safe docker login
|
8
|
+
# safe docker logout
|
9
|
+
|
10
|
+
class Docker < UseCase
|
11
|
+
|
12
|
+
# The command which currently must be login, logout or
|
13
|
+
# an empty string.
|
14
|
+
attr_writer :command
|
15
|
+
|
16
|
+
def execute
|
17
|
+
|
18
|
+
return unless ops_key_exists?
|
19
|
+
master_db = get_master_database()
|
20
|
+
return if unopened_envelope?( master_db )
|
21
|
+
|
22
|
+
# Get the open chapter identifier (id).
|
23
|
+
# Decide whether chapter already exists.
|
24
|
+
# Then get (or instantiate) the chapter's hash data structure
|
25
|
+
chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
|
26
|
+
verse_id = master_db[ KEY_PATH ]
|
27
|
+
chapter_exists = OpenKey::KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
|
28
|
+
|
29
|
+
# Unlock the chapter data structure by supplying
|
30
|
+
# key/value mini-dictionary breadcrumbs sitting
|
31
|
+
# within the master database at the section labelled
|
32
|
+
# envelope@<<actual_chapter_id>>.
|
33
|
+
chapter_data = OpenKey::KeyDb.from_json( OpenKey::KeyApi.content_unlock( master_db[ chapter_id ] ) )
|
34
|
+
|
35
|
+
key_value_dictionary = chapter_data[ verse_id ]
|
36
|
+
docker_username = key_value_dictionary[ "docker.username" ]
|
37
|
+
docker_password = key_value_dictionary[ "@docker.password" ]
|
38
|
+
docker_login_cmd = "docker login --username #{docker_username} --password #{docker_password} 2>/dev/null"
|
39
|
+
docker_logout_cmd = "docker logout"
|
40
|
+
docker_cmd = @command.eql?( "logout" ) ? docker_logout_cmd : docker_login_cmd
|
41
|
+
system docker_cmd
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
### safe put | safe delete | safe copy | safe paste
|
3
|
+
|
4
|
+
# edit use cases | copy | paste | delete
|
5
|
+
|
6
|
+
The edit use cases create, delete and update the credentials and configuration inside your safe.
|
7
|
+
|
8
|
+
## Common Usage
|
9
|
+
|
10
|
+
Typically you login to a book, open a chapter and verse, then you put **`key/value`** pairs, known as **lines**.
|
11
|
+
|
12
|
+
```
|
13
|
+
safe login joe@home
|
14
|
+
|
15
|
+
# -- -------------------------------------------------- -- #
|
16
|
+
# -- Create chapter (email) and verse <<email-address>> -- #
|
17
|
+
# -- -------------------------------------------------- -- #
|
18
|
+
safe open email joebloggs@gmail.com
|
19
|
+
|
20
|
+
# -- ---------------------------- -- #
|
21
|
+
# -- Populate it with credentials -- #
|
22
|
+
# -- ---------------------------- -- #
|
23
|
+
safe put gmail.id joebloggs
|
24
|
+
safe put @password s3cr3et
|
25
|
+
safe put recovery.phone 07500875278
|
26
|
+
|
27
|
+
# -- ----------------------------------------------- -- #
|
28
|
+
# -- Now copy and then paste a line (key/value pair) -- #
|
29
|
+
# -- ----------------------------------------------- -- #
|
30
|
+
safe copy recovery.phone
|
31
|
+
safe open email joe@ywork.com
|
32
|
+
safe paste
|
33
|
+
```
|
34
|
+
|
35
|
+
## editing behaviour
|
36
|
+
|
37
|
+
**These use cases are intuitive and behave almost like what you would expect.** The safe ethos is for commands to behave according to which of the 5 levels you are at.
|
38
|
+
|
39
|
+
|
40
|
+
| Command | Verse | Chapter | Book |
|
41
|
+
|:---------------- |:----------------------------- |:-------------------------------- |:------------------------------- |
|
42
|
+
| safe copy <<id>> | Copy one of the verse's lines | Copy one of the chapter's verses | Copy one of the book's chapters |
|
43
|
+
| safe copy | Copy all of the verse's lines | Copy all of the chapter's verses | Copy all of the book's chapters |
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module OpenSecret
|
4
|
+
|
5
|
+
# The <b>delete use case</b> delete's one or more of the safe's entities.
|
6
|
+
#
|
7
|
+
# - at <tt>verse</tt> level - it can delete one or more lines
|
8
|
+
# - at <tt>chapter</tt> level - it can delete one or more verses
|
9
|
+
# - at <tt>book</tt> level - it can delete one or more chapters
|
10
|
+
# - at <tt>safe</tt> level - it can delete one book
|
11
|
+
#
|
12
|
+
class DeleteMe < UseCase
|
13
|
+
|
14
|
+
attr_writer :entity_id
|
15
|
+
|
16
|
+
# Deletion that currently expects an open chapter and verse and always
|
17
|
+
# wants to delete only one line (key/value pair).
|
18
|
+
def execute
|
19
|
+
|
20
|
+
return unless ops_key_exists?
|
21
|
+
master_db = OpenKey::KeyApi.read_master_db()
|
22
|
+
return if unopened_envelope?( master_db )
|
23
|
+
|
24
|
+
chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
|
25
|
+
chapter_exists = OpenKey::KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
|
26
|
+
chapter_data = OpenKey::KeyDb.from_json( OpenKey::KeyApi.content_unlock( master_db[ chapter_id ] ) ) if chapter_exists
|
27
|
+
chapter_data = OpenKey::KeyDb.new() unless chapter_exists
|
28
|
+
|
29
|
+
content_hdr = create_header()
|
30
|
+
master_db[ chapter_id ] = {} unless chapter_exists
|
31
|
+
verse_id = master_db[ KEY_PATH ]
|
32
|
+
|
33
|
+
chapter_data.delete_entry( verse_id, @entity_id )
|
34
|
+
chapter_data.delete_entry( verse_id, "#{FILE_KEY_PREFIX}#{@entity_id}" )
|
35
|
+
|
36
|
+
OpenKey::KeyApi.content_lock( master_db[ chapter_id ], chapter_data.to_json, content_hdr )
|
37
|
+
OpenKey::KeyApi.write_master_db( content_hdr, master_db )
|
38
|
+
Show.new.flow_of_events
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module OpenSecret
|
4
|
+
|
5
|
+
# Export the entire book if no chapter and verse is specified (achieved with a safe close),
|
6
|
+
# or the chapter if only the chapter is open (safe shut or safe open <<chapter>>, or the
|
7
|
+
# mini-dictionary at the verse if both chapter and verse are open.
|
8
|
+
class Export < UseCase
|
9
|
+
|
10
|
+
def get_chapter_data( chapter_key )
|
11
|
+
return OpenKey::KeyDb.from_json( OpenKey::KeyApi.content_unlock( chapter_key ) )
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute
|
15
|
+
|
16
|
+
return unless ops_key_exists?
|
17
|
+
master_db = OpenKey::KeyApi.read_master_db()
|
18
|
+
|
19
|
+
return if unopened_envelope?( master_db )
|
20
|
+
|
21
|
+
chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
|
22
|
+
has_chapter = OpenKey::KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
|
23
|
+
|
24
|
+
unless has_chapter
|
25
|
+
puts "{}"
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
chapter_data = get_chapter_data( master_db[ chapter_id ] )
|
30
|
+
puts JSON.pretty_generate( chapter_data )
|
31
|
+
|
32
|
+
return
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
# safe file | ingest and eject files
|
3
|
+
|
4
|
+
You ingest a file with **safe file** and then **safe eject** will output that file into the present working directory.
|
5
|
+
|
6
|
+
If safe detects during an eject, that a file already exists with the same name - it backs it up with a timestamp before ejecting and clobbering the existing file.
|
7
|
+
|
8
|
+
```bash
|
9
|
+
safe open <<chapter-name>> <<verse-name>>
|
10
|
+
safe file <<keyname>> <</path/to/private-key.pem>>
|
11
|
+
safe eject <<keyname>>
|
12
|
+
safe show
|
13
|
+
```
|
14
|
+
|
15
|
+
To pull in 3 certificate oriented files for Kubernetes one could use these commands.
|
16
|
+
|
17
|
+
```bash
|
18
|
+
safe open production kubernetes
|
19
|
+
safe file kubernetes.cert ~/.kubectl/kube.prod.cert.pem
|
20
|
+
safe file kubernetes.ca.cert ~/.kubectl/kube.prod.ca.cert.pem
|
21
|
+
safe file kubernetes.key ~/.kubectl/kube.prod.key.pem
|
22
|
+
cd /tmp
|
23
|
+
safe eject
|
24
|
+
```
|
25
|
+
|
26
|
+
The safe ingests the files and spits them out whenever you so desire.
|
27
|
+
**Binary files** are supported and can be safely pulled in with <tt>safe file</tt> and ejected at any point in the future.
|
28
|
+
|
29
|
+
## remote (external) files
|
30
|
+
|
31
|
+
The **local filesystem** is the most common, but by no means the only file storage location. You can read from and write to
|
32
|
+
|
33
|
+
- a zip file **`zip://`**
|
34
|
+
- an S3 filesystem **`s3://`**
|
35
|
+
- SSH locations **`<<user>>@<<hostname>>:/path/to/file`**
|
36
|
+
- a git repository **`git@github.com`**
|
37
|
+
- a **google drive** store
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module OpenSecret
|
4
|
+
|
5
|
+
# The <b>eject use case</b> writes (or overwrites) a file or files.
|
6
|
+
# Files are always ejected into the present working directory. If an
|
7
|
+
# overwrite is detected a backup is taken of the about to be clobbered
|
8
|
+
# file.
|
9
|
+
#
|
10
|
+
# If a keyname is provided then only the file against that key is ejected.
|
11
|
+
# No keyname will eject every file in the opened chapter and verse.
|
12
|
+
class Eject < UseCase
|
13
|
+
|
14
|
+
attr_writer :file_key
|
15
|
+
|
16
|
+
# Files are always ejected into the present working directory and any
|
17
|
+
# about to be clobbered files are backed up with a timestamp.
|
18
|
+
#
|
19
|
+
# If a keyname is provided then only the file against that key is ejected.
|
20
|
+
# No keyname will eject every file in the opened chapter and verse.
|
21
|
+
def execute
|
22
|
+
|
23
|
+
return unless ops_key_exists?
|
24
|
+
master_db = get_master_database()
|
25
|
+
return if unopened_envelope?( master_db )
|
26
|
+
chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
|
27
|
+
verse_id = master_db[ KEY_PATH ]
|
28
|
+
chapter_data = OpenKey::KeyDb.from_json( OpenKey::KeyApi.content_unlock( master_db[ chapter_id ] ) )
|
29
|
+
|
30
|
+
base64_content = chapter_data[ verse_id ][ "#{FILE_KEY_PREFIX}#{@file_key}" ][ FILE_CONTENT_KEY ]
|
31
|
+
simple_filename = chapter_data[ verse_id ][ "#{FILE_KEY_PREFIX}#{@file_key}" ][ FILE_NAME_KEY ]
|
32
|
+
file_full_path = File.join( Dir.pwd, simple_filename )
|
33
|
+
backup_filename = OpenKey::KeyNow.yyjjj_hhmm_sst() + "-" + simple_filename
|
34
|
+
backup_file_path = File.join( Dir.pwd, backup_filename )
|
35
|
+
will_clobber = File.file?( file_full_path )
|
36
|
+
|
37
|
+
File.write( backup_file_path, File.read( file_full_path ) ) if will_clobber
|
38
|
+
::File.write( file_full_path, Base64.urlsafe_decode64( base64_content ) )
|
39
|
+
|
40
|
+
puts ""
|
41
|
+
puts "File successfully ejected from safe into current directory."
|
42
|
+
puts ""
|
43
|
+
puts "Clobbered File = #{backup_filename}" if will_clobber
|
44
|
+
puts "Current Directory = #{Dir.pwd}"
|
45
|
+
puts "Ejected Filename = #{simple_filename}"
|
46
|
+
puts "Chapter and Verse = #{master_db[ENV_PATH]}:#{verse_id}"
|
47
|
+
puts "Ejected File Key = #{@file_key}"
|
48
|
+
puts ""
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module OpenSecret
|
4
|
+
|
5
|
+
# The <b>file use case</b> pulls a file in from either an accessible filesystem
|
6
|
+
# or from a remote http, https, git, S3, GoogleDrive and/or ssh source.
|
7
|
+
#
|
8
|
+
# The @file_url is the most common parameter given to this use case.
|
9
|
+
class FileMe < UseCase
|
10
|
+
|
11
|
+
attr_writer :file_key, :file_url
|
12
|
+
|
13
|
+
# There are 3 maps involved in the implementation and they are all (or in part) retrieved and/or
|
14
|
+
# created as necessary. They are
|
15
|
+
#
|
16
|
+
# - the current chapter as a map
|
17
|
+
# - the current verse as a map
|
18
|
+
# - the file's keyname as a map
|
19
|
+
#
|
20
|
+
# Once the maps have been found and/or created if necessary the file's keyname map is either
|
21
|
+
# populated or amended with the following data.
|
22
|
+
#
|
23
|
+
# - filename | {UseCase::FILE_NAME_KEY} | the file's simple name
|
24
|
+
# - content64 | {UseCase::FILE_CONTENT_KEY} | the file's base64 content
|
25
|
+
def execute
|
26
|
+
|
27
|
+
return unless ops_key_exists?
|
28
|
+
master_db = OpenKey::KeyApi.read_master_db()
|
29
|
+
return if unopened_envelope?( master_db )
|
30
|
+
|
31
|
+
chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
|
32
|
+
chapter_exists = OpenKey::KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
|
33
|
+
chapter_data = OpenKey::KeyDb.from_json( OpenKey::KeyApi.content_unlock( master_db[ chapter_id ] ) ) if chapter_exists
|
34
|
+
chapter_data = OpenKey::KeyDb.new() unless chapter_exists
|
35
|
+
|
36
|
+
content_hdr = create_header()
|
37
|
+
master_db[ chapter_id ] = {} unless chapter_exists
|
38
|
+
verse_id = master_db[ KEY_PATH ]
|
39
|
+
|
40
|
+
file_full_path = ::File.absolute_path( @file_url )
|
41
|
+
file_base_name = ::File.basename( file_full_path )
|
42
|
+
file_content64 = Base64.urlsafe_encode64( ::File.read( file_full_path ) )
|
43
|
+
|
44
|
+
log.info(x) { "Key name of the file to ingest => #{@file_key}" }
|
45
|
+
log.info(x) { "Ingesting file at path => #{file_full_path}" }
|
46
|
+
log.info(x) { "The name of the file to ingest is => #{file_base_name}" }
|
47
|
+
log.info(x) { "Size of base64 file content => [#{file_content64.length}]" }
|
48
|
+
|
49
|
+
chapter_data.create_map_entry( verse_id, "#{FILE_KEY_PREFIX}#{@file_key}", FILE_NAME_KEY, file_base_name )
|
50
|
+
chapter_data.create_map_entry( verse_id, "#{FILE_KEY_PREFIX}#{@file_key}", FILE_CONTENT_KEY, file_content64 )
|
51
|
+
|
52
|
+
OpenKey::KeyApi.content_lock( master_db[ chapter_id ], chapter_data.to_json, content_hdr )
|
53
|
+
OpenKey::KeyApi.write_master_db( content_hdr, master_db )
|
54
|
+
|
55
|
+
Show.new.flow_of_events
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
|
63
|
+
# Perform pre-conditional validations in preparation to executing the main flow
|
64
|
+
# of events for this use case. This method may throw the below exceptions.
|
65
|
+
#
|
66
|
+
# @raise [SafeDirNotConfigured] if the safe's url has not been configured
|
67
|
+
# @raise [EmailAddrNotConfigured] if the email address has not been configured
|
68
|
+
# @raise [StoreUrlNotConfigured] if the crypt store url is not configured
|
69
|
+
def pre_validation
|
70
|
+
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
end
|