keeper_secrets_manager 17.0.4 → 17.2.0
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/CHANGELOG.md +100 -16
- data/Gemfile +6 -3
- data/README.md +75 -270
- data/Rakefile +1 -1
- data/bin/console +47 -0
- data/keeper_secrets_manager.gemspec +36 -0
- data/lib/keeper_secrets_manager/cache.rb +139 -0
- data/lib/keeper_secrets_manager/config_keys.rb +4 -2
- data/lib/keeper_secrets_manager/core.rb +993 -452
- data/lib/keeper_secrets_manager/crypto.rb +101 -116
- data/lib/keeper_secrets_manager/dto/payload.rb +7 -6
- data/lib/keeper_secrets_manager/dto.rb +374 -38
- data/lib/keeper_secrets_manager/errors.rb +13 -2
- data/lib/keeper_secrets_manager/field_types.rb +3 -3
- data/lib/keeper_secrets_manager/folder_manager.rb +25 -29
- data/lib/keeper_secrets_manager/keeper_globals.rb +11 -17
- data/lib/keeper_secrets_manager/notation.rb +202 -93
- data/lib/keeper_secrets_manager/notation_enhancements.rb +24 -24
- data/lib/keeper_secrets_manager/storage.rb +38 -38
- data/lib/keeper_secrets_manager/totp.rb +27 -27
- data/lib/keeper_secrets_manager/utils.rb +85 -18
- data/lib/keeper_secrets_manager/version.rb +2 -2
- data/lib/keeper_secrets_manager.rb +11 -3
- metadata +39 -22
- data/DEVELOPER_SETUP.md +0 -0
- data/MANUAL_TESTING_GUIDE.md +0 -332
- data/RUBY_SDK_COMPLETE_DOCUMENTATION.md +0 -354
- data/RUBY_SDK_COMPREHENSIVE_SUMMARY.md +0 -192
- data/examples/01_quick_start.rb +0 -45
- data/examples/02_authentication.rb +0 -82
- data/examples/03_retrieve_secrets.rb +0 -81
- data/examples/04_create_update_delete.rb +0 -104
- data/examples/05_field_types.rb +0 -135
- data/examples/06_files.rb +0 -137
- data/examples/07_folders.rb +0 -145
- data/examples/08_notation.rb +0 -103
- data/examples/09_totp.rb +0 -100
- data/examples/README.md +0 -89
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
# Retrieve Secrets Example - Different ways to access your secrets
|
|
4
|
-
|
|
5
|
-
require 'keeper_secrets_manager'
|
|
6
|
-
|
|
7
|
-
# Initialize (use your preferred method)
|
|
8
|
-
config = ENV['KSM_CONFIG'] || 'YOUR_BASE64_CONFIG'
|
|
9
|
-
secrets_manager = KeeperSecretsManager.from_config(config)
|
|
10
|
-
|
|
11
|
-
puts "=== Retrieving Secrets ==="
|
|
12
|
-
|
|
13
|
-
# 1. Get all secrets
|
|
14
|
-
puts "\n1. Get all secrets:"
|
|
15
|
-
secrets = secrets_manager.get_secrets
|
|
16
|
-
secrets.each do |secret|
|
|
17
|
-
puts " - #{secret.title} (UID: #{secret.uid})"
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# 2. Get specific secret by UID
|
|
21
|
-
puts "\n2. Get secret by UID:"
|
|
22
|
-
if secrets.any?
|
|
23
|
-
uid = secrets.first.uid
|
|
24
|
-
secret = secrets_manager.get_secret_by_uid(uid)
|
|
25
|
-
puts " Title: #{secret.title}"
|
|
26
|
-
puts " Type: #{secret.type}"
|
|
27
|
-
puts " Fields: #{secret.fields.keys.join(', ')}"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# 3. Get secret by title
|
|
31
|
-
puts "\n3. Get secret by title:"
|
|
32
|
-
begin
|
|
33
|
-
secret = secrets_manager.get_secret_by_title("My Login")
|
|
34
|
-
puts " Found: #{secret.title}"
|
|
35
|
-
rescue => e
|
|
36
|
-
puts " Not found: #{e.message}"
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# 4. Get multiple secrets by UIDs
|
|
40
|
-
puts "\n4. Get multiple secrets:"
|
|
41
|
-
if secrets.length >= 2
|
|
42
|
-
uids = secrets.first(2).map(&:uid)
|
|
43
|
-
selected_secrets = secrets_manager.get_secrets(uids)
|
|
44
|
-
selected_secrets.each do |secret|
|
|
45
|
-
puts " - #{secret.title}"
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# 5. Access specific fields
|
|
50
|
-
puts "\n5. Access secret fields:"
|
|
51
|
-
if secrets.any?
|
|
52
|
-
secret = secrets.first
|
|
53
|
-
|
|
54
|
-
# Common fields
|
|
55
|
-
puts " Login: #{secret.fields['login']}" if secret.fields['login']
|
|
56
|
-
puts " URL: #{secret.fields['url']}" if secret.fields['url']
|
|
57
|
-
|
|
58
|
-
# Using dynamic field access
|
|
59
|
-
puts " Password: #{secret.password}" if secret.respond_to?(:password)
|
|
60
|
-
|
|
61
|
-
# Custom fields
|
|
62
|
-
secret.custom&.each do |field|
|
|
63
|
-
puts " #{field['label']}: #{field['value']}"
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# 6. Using notation to get specific values
|
|
68
|
-
puts "\n6. Using notation:"
|
|
69
|
-
if secrets.any?
|
|
70
|
-
uid = secrets.first.uid
|
|
71
|
-
|
|
72
|
-
# Get specific field value
|
|
73
|
-
login = secrets_manager.get_notation("keeper://#{uid}/field/login")
|
|
74
|
-
puts " Login via notation: #{login}"
|
|
75
|
-
|
|
76
|
-
# Get by title
|
|
77
|
-
value = secrets_manager.get_notation("keeper://My Login/field/password")
|
|
78
|
-
puts " Password via notation: [hidden]"
|
|
79
|
-
rescue => e
|
|
80
|
-
puts " Notation error: #{e.message}"
|
|
81
|
-
end
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
# CRUD Operations Example - Create, Read, Update, and Delete secrets
|
|
4
|
-
|
|
5
|
-
require 'keeper_secrets_manager'
|
|
6
|
-
require 'securerandom'
|
|
7
|
-
|
|
8
|
-
# Initialize
|
|
9
|
-
config = ENV['KSM_CONFIG'] || 'YOUR_BASE64_CONFIG'
|
|
10
|
-
secrets_manager = KeeperSecretsManager.from_config(config)
|
|
11
|
-
|
|
12
|
-
puts "=== CRUD Operations Example ==="
|
|
13
|
-
|
|
14
|
-
# 1. CREATE - Add a new secret
|
|
15
|
-
puts "\n1. Creating a new secret..."
|
|
16
|
-
begin
|
|
17
|
-
# Create a login record
|
|
18
|
-
new_record = {
|
|
19
|
-
type: 'login',
|
|
20
|
-
title: "Test Login #{Time.now.strftime('%Y%m%d_%H%M%S')}",
|
|
21
|
-
fields: [
|
|
22
|
-
{ type: 'login', value: ['testuser@example.com'] },
|
|
23
|
-
{ type: 'password', value: [SecureRandom.hex(16)] },
|
|
24
|
-
{ type: 'url', value: ['https://example.com'] }
|
|
25
|
-
],
|
|
26
|
-
custom: [
|
|
27
|
-
{ type: 'text', label: 'Environment', value: ['Testing'] }
|
|
28
|
-
],
|
|
29
|
-
notes: 'Created via Ruby SDK example'
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
# Create the record (optionally in a specific folder)
|
|
33
|
-
# record_uid = secrets_manager.create_secret(new_record, folder_uid: 'FOLDER_UID')
|
|
34
|
-
record_uid = secrets_manager.create_secret(new_record)
|
|
35
|
-
|
|
36
|
-
puts "✓ Created record with UID: #{record_uid}"
|
|
37
|
-
|
|
38
|
-
# 2. READ - Retrieve the created secret
|
|
39
|
-
puts "\n2. Reading the secret..."
|
|
40
|
-
secret = secrets_manager.get_secret_by_uid(record_uid)
|
|
41
|
-
puts "✓ Retrieved: #{secret.title}"
|
|
42
|
-
puts " Login: #{secret.login}"
|
|
43
|
-
puts " URL: #{secret.url}"
|
|
44
|
-
puts " Custom field: #{secret.custom.first['value']}" if secret.custom.any?
|
|
45
|
-
|
|
46
|
-
# 3. UPDATE - Modify the secret
|
|
47
|
-
puts "\n3. Updating the secret..."
|
|
48
|
-
|
|
49
|
-
# Update specific fields
|
|
50
|
-
secret.password = SecureRandom.hex(20) # New password
|
|
51
|
-
secret.url = 'https://updated-example.com'
|
|
52
|
-
secret.notes = "Updated on #{Time.now}"
|
|
53
|
-
|
|
54
|
-
# Add a new custom field
|
|
55
|
-
secret.custom ||= []
|
|
56
|
-
secret.custom << {
|
|
57
|
-
'type' => 'text',
|
|
58
|
-
'label' => 'Last Updated',
|
|
59
|
-
'value' => [Time.now.to_s]
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
# Save the updates
|
|
63
|
-
secrets_manager.update_secret(secret)
|
|
64
|
-
puts "✓ Updated successfully"
|
|
65
|
-
|
|
66
|
-
# Verify the update
|
|
67
|
-
updated = secrets_manager.get_secret_by_uid(record_uid)
|
|
68
|
-
puts " New URL: #{updated.url}"
|
|
69
|
-
puts " Notes: #{updated.notes}"
|
|
70
|
-
|
|
71
|
-
# 4. DELETE - Remove the secret
|
|
72
|
-
puts "\n4. Deleting the secret..."
|
|
73
|
-
puts "Press Enter to delete the test record..."
|
|
74
|
-
gets
|
|
75
|
-
|
|
76
|
-
secrets_manager.delete_secret(record_uid)
|
|
77
|
-
puts "✓ Deleted record: #{record_uid}"
|
|
78
|
-
|
|
79
|
-
# Verify deletion
|
|
80
|
-
begin
|
|
81
|
-
secrets_manager.get_secret_by_uid(record_uid)
|
|
82
|
-
puts "✗ Record still exists!"
|
|
83
|
-
rescue
|
|
84
|
-
puts "✓ Confirmed: Record no longer exists"
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
rescue => e
|
|
88
|
-
puts "Error: #{e.message}"
|
|
89
|
-
puts "Make sure you have write permissions in your vault"
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# Batch operations example
|
|
93
|
-
puts "\n=== Batch Operations ==="
|
|
94
|
-
puts "1. Create multiple records at once"
|
|
95
|
-
puts "2. Update multiple records"
|
|
96
|
-
puts "3. Delete multiple records"
|
|
97
|
-
puts "(See documentation for batch operation examples)"
|
|
98
|
-
|
|
99
|
-
# Tips
|
|
100
|
-
puts "\n=== Tips ==="
|
|
101
|
-
puts "- Always handle errors when creating/updating/deleting"
|
|
102
|
-
puts "- Use folder_uid parameter to organize secrets"
|
|
103
|
-
puts "- Check permissions if operations fail"
|
|
104
|
-
puts "- Use batch operations for better performance with multiple records"
|
data/examples/05_field_types.rb
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
# Field Types Example - Working with different field types in Keeper
|
|
4
|
-
|
|
5
|
-
require 'keeper_secrets_manager'
|
|
6
|
-
|
|
7
|
-
# Initialize
|
|
8
|
-
config = ENV['KSM_CONFIG'] || 'YOUR_BASE64_CONFIG'
|
|
9
|
-
secrets_manager = KeeperSecretsManager.from_config(config)
|
|
10
|
-
|
|
11
|
-
puts "=== Field Types Example ==="
|
|
12
|
-
|
|
13
|
-
# Create a record with various field types
|
|
14
|
-
record_data = {
|
|
15
|
-
type: 'login',
|
|
16
|
-
title: 'Field Types Demo',
|
|
17
|
-
fields: [
|
|
18
|
-
# Standard fields
|
|
19
|
-
{ type: 'login', value: ['user@example.com'] },
|
|
20
|
-
{ type: 'password', value: ['SecurePassword123!'] },
|
|
21
|
-
{ type: 'url', value: ['https://example.com'] },
|
|
22
|
-
|
|
23
|
-
# Complex fields
|
|
24
|
-
{ type: 'name', value: [{ first: 'John', middle: 'Q', last: 'Doe' }] },
|
|
25
|
-
{ type: 'phone', value: [{ number: '555-1234', ext: '567', type: 'Work' }] },
|
|
26
|
-
{ type: 'email', value: ['john.doe@example.com'] },
|
|
27
|
-
|
|
28
|
-
# Address field
|
|
29
|
-
{
|
|
30
|
-
type: 'address',
|
|
31
|
-
value: [{
|
|
32
|
-
street1: '123 Main St',
|
|
33
|
-
street2: 'Suite 100',
|
|
34
|
-
city: 'New York',
|
|
35
|
-
state: 'NY',
|
|
36
|
-
zip: '10001',
|
|
37
|
-
country: 'US'
|
|
38
|
-
}]
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
# Host field (for servers)
|
|
42
|
-
{
|
|
43
|
-
type: 'host',
|
|
44
|
-
value: [{
|
|
45
|
-
hostName: '192.168.1.100',
|
|
46
|
-
port: '22'
|
|
47
|
-
}]
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
# Security question
|
|
51
|
-
{
|
|
52
|
-
type: 'securityQuestion',
|
|
53
|
-
value: [{
|
|
54
|
-
question: 'What is your favorite color?',
|
|
55
|
-
answer: 'Blue'
|
|
56
|
-
}]
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
# Bank account
|
|
60
|
-
{
|
|
61
|
-
type: 'bankAccount',
|
|
62
|
-
value: [{
|
|
63
|
-
accountType: 'Checking',
|
|
64
|
-
routingNumber: '021000021',
|
|
65
|
-
accountNumber: '1234567890'
|
|
66
|
-
}]
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
# Payment card
|
|
70
|
-
{
|
|
71
|
-
type: 'paymentCard',
|
|
72
|
-
value: [{
|
|
73
|
-
cardNumber: '4111111111111111',
|
|
74
|
-
cardExpirationDate: '12/25',
|
|
75
|
-
cardSecurityCode: '123'
|
|
76
|
-
}]
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
# Date field
|
|
80
|
-
{ type: 'date', value: [Time.now.to_i * 1000] }, # milliseconds
|
|
81
|
-
|
|
82
|
-
# Multiline field
|
|
83
|
-
{ type: 'multiline', value: ["Line 1\nLine 2\nLine 3"] }
|
|
84
|
-
],
|
|
85
|
-
|
|
86
|
-
# Custom fields
|
|
87
|
-
custom: [
|
|
88
|
-
{ type: 'text', label: 'Department', value: ['Engineering'] },
|
|
89
|
-
{ type: 'text', label: 'Project', value: ['Secret Management'] },
|
|
90
|
-
{ type: 'secret', label: 'API Key', value: ['sk_test_123456789'] },
|
|
91
|
-
{ type: 'url', label: 'Documentation', value: ['https://docs.example.com'] }
|
|
92
|
-
]
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
# Example: Reading different field types
|
|
96
|
-
puts "\n1. Standard Fields:"
|
|
97
|
-
begin
|
|
98
|
-
# If you have a record with these fields
|
|
99
|
-
secret = secrets_manager.get_secrets.first
|
|
100
|
-
|
|
101
|
-
puts " Login: #{secret.login}" if secret.respond_to?(:login)
|
|
102
|
-
puts " Password: [hidden]" if secret.respond_to?(:password)
|
|
103
|
-
puts " URL: #{secret.url}" if secret.respond_to?(:url)
|
|
104
|
-
rescue => e
|
|
105
|
-
puts " (Create a record with the fields above to see this in action)"
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
# Example: Complex field access
|
|
109
|
-
puts "\n2. Complex Fields:"
|
|
110
|
-
puts " Name field: #{record_data[:fields].find { |f| f[:type] == 'name' }[:value].first}"
|
|
111
|
-
puts " Phone field: #{record_data[:fields].find { |f| f[:type] == 'phone' }[:value].first}"
|
|
112
|
-
puts " Address field: #{record_data[:fields].find { |f| f[:type] == 'address' }[:value].first}"
|
|
113
|
-
|
|
114
|
-
# Example: Using field helpers (if available)
|
|
115
|
-
puts "\n3. Field Helpers:"
|
|
116
|
-
puts " The SDK provides dynamic access to fields:"
|
|
117
|
-
puts " - secret.login"
|
|
118
|
-
puts " - secret.password"
|
|
119
|
-
puts " - secret.url"
|
|
120
|
-
puts " - secret.notes"
|
|
121
|
-
puts " - secret.custom"
|
|
122
|
-
|
|
123
|
-
# Example: TOTP field (requires base32 gem)
|
|
124
|
-
puts "\n4. TOTP Fields:"
|
|
125
|
-
puts " TOTP fields store the secret key for 2FA"
|
|
126
|
-
puts " Install 'base32' gem to generate TOTP codes:"
|
|
127
|
-
puts " - { type: 'oneTimeCode', value: ['JBSWY3DPEHPK3PXP'] }"
|
|
128
|
-
|
|
129
|
-
# Tips
|
|
130
|
-
puts "\n=== Field Type Tips ==="
|
|
131
|
-
puts "- Use appropriate field types for better UI experience"
|
|
132
|
-
puts "- Complex fields (name, address, etc.) use structured data"
|
|
133
|
-
puts "- Custom fields are flexible for any additional data"
|
|
134
|
-
puts "- File references use fileRef type"
|
|
135
|
-
puts "- Dates are stored as milliseconds since epoch"
|
data/examples/06_files.rb
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
# Files Example - Upload and download file attachments
|
|
4
|
-
|
|
5
|
-
require 'keeper_secrets_manager'
|
|
6
|
-
require 'tempfile'
|
|
7
|
-
|
|
8
|
-
# Initialize
|
|
9
|
-
config = ENV['KSM_CONFIG'] || 'YOUR_BASE64_CONFIG'
|
|
10
|
-
secrets_manager = KeeperSecretsManager.from_config(config)
|
|
11
|
-
|
|
12
|
-
puts "=== File Operations Example ==="
|
|
13
|
-
|
|
14
|
-
# 1. Find records with files
|
|
15
|
-
puts "\n1. Finding records with files..."
|
|
16
|
-
secrets = secrets_manager.get_secrets
|
|
17
|
-
records_with_files = secrets.select { |s| s.files && s.files.any? }
|
|
18
|
-
|
|
19
|
-
if records_with_files.empty?
|
|
20
|
-
puts "No records with files found. Upload example will create one."
|
|
21
|
-
else
|
|
22
|
-
puts "Found #{records_with_files.length} records with files:"
|
|
23
|
-
records_with_files.each do |record|
|
|
24
|
-
puts " - #{record.title}: #{record.files.length} file(s)"
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# 2. Download files
|
|
29
|
-
if records_with_files.any?
|
|
30
|
-
puts "\n2. Downloading files..."
|
|
31
|
-
record = records_with_files.first
|
|
32
|
-
|
|
33
|
-
record.files.each do |file|
|
|
34
|
-
begin
|
|
35
|
-
# Download the file
|
|
36
|
-
downloaded = secrets_manager.download_file(file)
|
|
37
|
-
|
|
38
|
-
# Save to disk
|
|
39
|
-
filename = downloaded['name'] || 'downloaded_file'
|
|
40
|
-
File.write(filename, downloaded['data'])
|
|
41
|
-
|
|
42
|
-
puts "✓ Downloaded: #{filename} (#{downloaded['size']} bytes)"
|
|
43
|
-
puts " Type: #{downloaded['type']}"
|
|
44
|
-
|
|
45
|
-
# Clean up
|
|
46
|
-
File.delete(filename) if File.exist?(filename)
|
|
47
|
-
|
|
48
|
-
rescue => e
|
|
49
|
-
puts "✗ Download failed: #{e.message}"
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# 3. Upload a file
|
|
55
|
-
puts "\n3. Uploading a file..."
|
|
56
|
-
begin
|
|
57
|
-
# Create a test file
|
|
58
|
-
test_content = "This is a test file created at #{Time.now}\n"
|
|
59
|
-
test_content += "It contains some sample data for demonstration.\n"
|
|
60
|
-
|
|
61
|
-
# Create or find a record to attach the file to
|
|
62
|
-
record = secrets.first || begin
|
|
63
|
-
# Create a new record if none exist
|
|
64
|
-
uid = secrets_manager.create_secret({
|
|
65
|
-
type: 'login',
|
|
66
|
-
title: 'File Upload Test',
|
|
67
|
-
fields: [
|
|
68
|
-
{ type: 'login', value: ['test@example.com'] },
|
|
69
|
-
{ type: 'password', value: ['test123'] }
|
|
70
|
-
]
|
|
71
|
-
})
|
|
72
|
-
secrets_manager.get_secret_by_uid(uid)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
puts "Uploading to record: #{record.title}"
|
|
76
|
-
|
|
77
|
-
# Upload the file
|
|
78
|
-
file_uid = secrets_manager.upload_file(
|
|
79
|
-
owner_record_uid: record.uid,
|
|
80
|
-
file_name: 'test_document.txt',
|
|
81
|
-
file_data: test_content,
|
|
82
|
-
mime_type: 'text/plain'
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
puts "✓ Uploaded file with UID: #{file_uid}"
|
|
86
|
-
|
|
87
|
-
# Verify by downloading
|
|
88
|
-
updated_record = secrets_manager.get_secret_by_uid(record.uid)
|
|
89
|
-
new_file = updated_record.files.find { |f| f['fileUid'] == file_uid }
|
|
90
|
-
|
|
91
|
-
if new_file
|
|
92
|
-
downloaded = secrets_manager.download_file(new_file)
|
|
93
|
-
puts "✓ Verified: #{downloaded['name']}"
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
rescue => e
|
|
97
|
-
puts "✗ Upload failed: #{e.message}"
|
|
98
|
-
puts " Note: File upload requires write permissions"
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# 4. Working with different file types
|
|
102
|
-
puts "\n4. File Type Examples:"
|
|
103
|
-
puts " Text files: .txt, .log, .conf"
|
|
104
|
-
puts " Documents: .pdf, .doc, .docx"
|
|
105
|
-
puts " Images: .jpg, .png, .gif"
|
|
106
|
-
puts " Archives: .zip, .tar.gz"
|
|
107
|
-
puts " Keys/Certs: .pem, .key, .crt"
|
|
108
|
-
|
|
109
|
-
# 5. File size considerations
|
|
110
|
-
puts "\n5. File Size Tips:"
|
|
111
|
-
puts " - Maximum file size depends on your vault settings"
|
|
112
|
-
puts " - Large files may take time to upload/download"
|
|
113
|
-
puts " - Consider compression for large text files"
|
|
114
|
-
puts " - Binary files are handled automatically"
|
|
115
|
-
|
|
116
|
-
# Example: Upload a certificate file
|
|
117
|
-
puts "\n6. Certificate Upload Example:"
|
|
118
|
-
cert_example = <<~CERT
|
|
119
|
-
-----BEGIN CERTIFICATE-----
|
|
120
|
-
MIIDXTCCAkWgAwIBAgIJAKLdQVPy90WJMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
|
121
|
-
... (certificate content) ...
|
|
122
|
-
-----END CERTIFICATE-----
|
|
123
|
-
CERT
|
|
124
|
-
|
|
125
|
-
puts " # Upload a certificate"
|
|
126
|
-
puts " file_uid = secrets_manager.upload_file("
|
|
127
|
-
puts " owner_record_uid: record.uid,"
|
|
128
|
-
puts " file_name: 'server.crt',"
|
|
129
|
-
puts " file_data: cert_content,"
|
|
130
|
-
puts " mime_type: 'application/x-x509-ca-cert'"
|
|
131
|
-
puts " )"
|
|
132
|
-
|
|
133
|
-
puts "\n=== Tips ==="
|
|
134
|
-
puts "- Files are attached to records (you need a record first)"
|
|
135
|
-
puts "- File data is encrypted before upload"
|
|
136
|
-
puts "- Download returns decrypted file content"
|
|
137
|
-
puts "- MIME type helps with file handling but is optional"
|
data/examples/07_folders.rb
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
# Folders Example - Organize secrets in folders
|
|
4
|
-
|
|
5
|
-
require 'keeper_secrets_manager'
|
|
6
|
-
|
|
7
|
-
# Initialize
|
|
8
|
-
config = ENV['KSM_CONFIG'] || 'YOUR_BASE64_CONFIG'
|
|
9
|
-
secrets_manager = KeeperSecretsManager.from_config(config)
|
|
10
|
-
|
|
11
|
-
puts "=== Folder Operations Example ==="
|
|
12
|
-
|
|
13
|
-
# 1. Get all folders
|
|
14
|
-
puts "\n1. Getting all folders..."
|
|
15
|
-
response = secrets_manager.get_secrets(full_response: true)
|
|
16
|
-
folders = response.folders
|
|
17
|
-
|
|
18
|
-
if folders.empty?
|
|
19
|
-
puts "No folders found in vault"
|
|
20
|
-
else
|
|
21
|
-
puts "Found #{folders.length} folders:"
|
|
22
|
-
folders.each do |folder|
|
|
23
|
-
puts " - #{folder.name || folder.uid} (UID: #{folder.uid})"
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# 2. Get folder hierarchy
|
|
28
|
-
puts "\n2. Folder Hierarchy:"
|
|
29
|
-
if folders.any?
|
|
30
|
-
# Build folder tree
|
|
31
|
-
folder_tree = secrets_manager.folder_manager.build_folder_tree
|
|
32
|
-
|
|
33
|
-
# Print tree structure
|
|
34
|
-
secrets_manager.folder_manager.print_tree
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# 3. Create a folder
|
|
38
|
-
puts "\n3. Creating a folder..."
|
|
39
|
-
begin
|
|
40
|
-
folder_name = "Test Folder #{Time.now.strftime('%Y%m%d_%H%M%S')}"
|
|
41
|
-
|
|
42
|
-
# Create at root level
|
|
43
|
-
folder_uid = secrets_manager.create_folder(folder_name)
|
|
44
|
-
puts "✓ Created folder: #{folder_name}"
|
|
45
|
-
puts " UID: #{folder_uid}"
|
|
46
|
-
|
|
47
|
-
# Create a subfolder
|
|
48
|
-
subfolder_name = "Subfolder"
|
|
49
|
-
subfolder_uid = secrets_manager.create_folder(
|
|
50
|
-
name: subfolder_name,
|
|
51
|
-
parent_uid: folder_uid
|
|
52
|
-
)
|
|
53
|
-
puts "✓ Created subfolder: #{subfolder_name}"
|
|
54
|
-
|
|
55
|
-
rescue => e
|
|
56
|
-
puts "✗ Error creating folder: #{e.message}"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# 4. Move records to folders
|
|
60
|
-
puts "\n4. Organizing records in folders..."
|
|
61
|
-
begin
|
|
62
|
-
# Get a record to move
|
|
63
|
-
record = secrets_manager.get_secrets.first
|
|
64
|
-
|
|
65
|
-
if record && defined?(folder_uid)
|
|
66
|
-
# Move record to folder
|
|
67
|
-
record.folder_uid = folder_uid
|
|
68
|
-
secrets_manager.update_secret(record)
|
|
69
|
-
|
|
70
|
-
puts "✓ Moved '#{record.title}' to folder"
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
rescue => e
|
|
74
|
-
puts "✗ Error moving record: #{e.message}"
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# 5. Find folders
|
|
78
|
-
puts "\n5. Finding folders..."
|
|
79
|
-
if folders.any?
|
|
80
|
-
# Find by name
|
|
81
|
-
folder = secrets_manager.find_folder_by_name("Test Folder")
|
|
82
|
-
puts "✓ Found folder by name: #{folder.uid}" if folder
|
|
83
|
-
|
|
84
|
-
# Get folder path
|
|
85
|
-
if folder
|
|
86
|
-
path = secrets_manager.get_folder_path(folder.uid)
|
|
87
|
-
puts "✓ Folder path: #{path}"
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Get folder ancestors
|
|
91
|
-
ancestors = secrets_manager.folder_manager.get_ancestors(folder.uid) if folder
|
|
92
|
-
puts "✓ Ancestors: #{ancestors.map(&:name).join(' > ')}" if ancestors&.any?
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
# 6. List records in a folder
|
|
96
|
-
puts "\n6. Records in folders:"
|
|
97
|
-
response.records.group_by(&:folder_uid).each do |folder_uid, records|
|
|
98
|
-
folder = folders.find { |f| f.uid == folder_uid }
|
|
99
|
-
folder_name = folder&.name || folder_uid || 'Root'
|
|
100
|
-
|
|
101
|
-
puts "\n #{folder_name}:"
|
|
102
|
-
records.each do |record|
|
|
103
|
-
puts " - #{record.title}"
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# 7. Update folder
|
|
108
|
-
puts "\n7. Updating folder..."
|
|
109
|
-
begin
|
|
110
|
-
if defined?(folder_uid)
|
|
111
|
-
secrets_manager.update_folder(
|
|
112
|
-
folder_uid: folder_uid,
|
|
113
|
-
name: "Updated Test Folder"
|
|
114
|
-
)
|
|
115
|
-
puts "✓ Updated folder name"
|
|
116
|
-
end
|
|
117
|
-
rescue => e
|
|
118
|
-
puts "✗ Error updating folder: #{e.message}"
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# 8. Delete folder
|
|
122
|
-
puts "\n8. Cleanup - Delete test folders..."
|
|
123
|
-
puts "Press Enter to delete test folders (or Ctrl+C to keep them)..."
|
|
124
|
-
gets
|
|
125
|
-
|
|
126
|
-
begin
|
|
127
|
-
if defined?(subfolder_uid)
|
|
128
|
-
secrets_manager.delete_folder(subfolder_uid)
|
|
129
|
-
puts "✓ Deleted subfolder"
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
if defined?(folder_uid)
|
|
133
|
-
secrets_manager.delete_folder(folder_uid, force: true)
|
|
134
|
-
puts "✓ Deleted folder"
|
|
135
|
-
end
|
|
136
|
-
rescue => e
|
|
137
|
-
puts "✗ Error deleting folder: #{e.message}"
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
puts "\n=== Folder Tips ==="
|
|
141
|
-
puts "- Folders help organize secrets logically"
|
|
142
|
-
puts "- Use folders for environments (Dev, Test, Prod)"
|
|
143
|
-
puts "- Use folders for teams or projects"
|
|
144
|
-
puts "- Folders can be nested for complex hierarchies"
|
|
145
|
-
puts "- Force delete removes folder even with records"
|
data/examples/08_notation.rb
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
# Notation Example - Using Keeper Notation for quick access
|
|
4
|
-
|
|
5
|
-
require 'keeper_secrets_manager'
|
|
6
|
-
|
|
7
|
-
# Initialize
|
|
8
|
-
config = ENV['KSM_CONFIG'] || 'YOUR_BASE64_CONFIG'
|
|
9
|
-
secrets_manager = KeeperSecretsManager.from_config(config)
|
|
10
|
-
|
|
11
|
-
puts "=== Keeper Notation Example ==="
|
|
12
|
-
|
|
13
|
-
# Keeper Notation provides a URI-style way to access secrets
|
|
14
|
-
# Format: keeper://<uid_or_title>/field/<field_name>
|
|
15
|
-
# keeper://<uid_or_title>/file/<file_name>
|
|
16
|
-
# keeper://<uid_or_title>/custom_field/<label>
|
|
17
|
-
|
|
18
|
-
puts "\n1. Basic field access:"
|
|
19
|
-
begin
|
|
20
|
-
# Get by UID
|
|
21
|
-
secrets = secrets_manager.get_secrets
|
|
22
|
-
if secrets.any?
|
|
23
|
-
uid = secrets.first.uid
|
|
24
|
-
|
|
25
|
-
# Get login field
|
|
26
|
-
login = secrets_manager.get_notation("keeper://#{uid}/field/login")
|
|
27
|
-
puts " Login: #{login}"
|
|
28
|
-
|
|
29
|
-
# Get password field
|
|
30
|
-
password = secrets_manager.get_notation("keeper://#{uid}/field/password")
|
|
31
|
-
puts " Password: [hidden]"
|
|
32
|
-
end
|
|
33
|
-
rescue => e
|
|
34
|
-
puts " Error: #{e.message}"
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
puts "\n2. Access by title:"
|
|
38
|
-
begin
|
|
39
|
-
# Use record title instead of UID
|
|
40
|
-
url = secrets_manager.get_notation("keeper://My Website/field/url")
|
|
41
|
-
puts " URL: #{url}"
|
|
42
|
-
rescue => e
|
|
43
|
-
puts " Note: Create a record titled 'My Website' to see this work"
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
puts "\n3. Custom field access:"
|
|
47
|
-
begin
|
|
48
|
-
# Access custom fields by label
|
|
49
|
-
api_key = secrets_manager.get_notation("keeper://API Server/custom_field/API Key")
|
|
50
|
-
puts " API Key: #{api_key}"
|
|
51
|
-
rescue => e
|
|
52
|
-
puts " Note: Custom fields are accessed by their label"
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
puts "\n4. File access:"
|
|
56
|
-
begin
|
|
57
|
-
# Download file by name
|
|
58
|
-
file_data = secrets_manager.get_notation("keeper://My Certificates/file/server.crt")
|
|
59
|
-
puts " File downloaded: #{file_data.bytesize} bytes"
|
|
60
|
-
rescue => e
|
|
61
|
-
puts " Note: Files are accessed by their filename"
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
puts "\n5. Notation patterns:"
|
|
65
|
-
puts " - keeper://<record>/field/<field_type>"
|
|
66
|
-
puts " - keeper://<record>/custom_field/<label>"
|
|
67
|
-
puts " - keeper://<record>/file/<filename>"
|
|
68
|
-
puts " - keeper://<record> (returns entire record)"
|
|
69
|
-
|
|
70
|
-
puts "\n6. Advanced examples:"
|
|
71
|
-
# You can use notation in templates or configuration
|
|
72
|
-
config_template = <<~CONFIG
|
|
73
|
-
database:
|
|
74
|
-
host: keeper://Database Server/field/host
|
|
75
|
-
port: keeper://Database Server/custom_field/Port
|
|
76
|
-
username: keeper://Database Server/field/login
|
|
77
|
-
password: keeper://Database Server/field/password
|
|
78
|
-
CONFIG
|
|
79
|
-
|
|
80
|
-
puts " Config template example:"
|
|
81
|
-
puts config_template
|
|
82
|
-
|
|
83
|
-
# Process template (example)
|
|
84
|
-
puts "\n7. Processing notation in strings:"
|
|
85
|
-
text = "Connect to keeper://Web Server/field/url with keeper://Web Server/field/login"
|
|
86
|
-
puts " Template: #{text}"
|
|
87
|
-
|
|
88
|
-
# Find and replace notation patterns
|
|
89
|
-
result = text.gsub(/keeper:\/\/[^\/\s]+\/[^\/\s]+\/[^\s]+/) do |notation|
|
|
90
|
-
begin
|
|
91
|
-
secrets_manager.get_notation(notation) || notation
|
|
92
|
-
rescue
|
|
93
|
-
notation
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
puts " Processed: #{result}"
|
|
97
|
-
|
|
98
|
-
puts "\n=== Notation Tips ==="
|
|
99
|
-
puts "- Use UIDs for exact matching (no ambiguity)"
|
|
100
|
-
puts "- Titles are easier to read but must be unique"
|
|
101
|
-
puts "- Notation is great for configuration files"
|
|
102
|
-
puts "- Returns nil if field doesn't exist"
|
|
103
|
-
puts "- Throws exception if record not found"
|