opensecret 0.0.9925 → 0.0.9949
Sign up to get free protection for your applications and to get access to all the features.
- 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
|