keeper_secrets_manager 17.0.3 → 17.0.4
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/DEVELOPER_SETUP.md +0 -0
- data/MANUAL_TESTING_GUIDE.md +332 -0
- data/RUBY_SDK_COMPLETE_DOCUMENTATION.md +354 -0
- data/RUBY_SDK_COMPREHENSIVE_SUMMARY.md +192 -0
- data/examples/01_quick_start.rb +45 -0
- data/examples/02_authentication.rb +82 -0
- data/examples/03_retrieve_secrets.rb +81 -0
- data/examples/04_create_update_delete.rb +104 -0
- data/examples/05_field_types.rb +135 -0
- data/examples/06_files.rb +137 -0
- data/examples/07_folders.rb +145 -0
- data/examples/08_notation.rb +103 -0
- data/examples/09_totp.rb +100 -0
- data/examples/README.md +89 -0
- data/lib/keeper_secrets_manager/version.rb +1 -1
- metadata +15 -12
- data/examples/basic_usage.rb +0 -139
- data/examples/config_string_example.rb +0 -99
- data/examples/debug_secrets.rb +0 -84
- data/examples/demo_list_secrets.rb +0 -182
- data/examples/download_files.rb +0 -100
- data/examples/flexible_records_example.rb +0 -94
- data/examples/folder_hierarchy_demo.rb +0 -109
- data/examples/full_demo.rb +0 -176
- data/examples/my_test_standalone.rb +0 -176
- data/examples/simple_test.rb +0 -162
- data/examples/storage_examples.rb +0 -126
@@ -0,0 +1,137 @@
|
|
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"
|
@@ -0,0 +1,145 @@
|
|
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"
|
@@ -0,0 +1,103 @@
|
|
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"
|
data/examples/09_totp.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# TOTP Example - Generate Time-based One-Time Passwords
|
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 "=== TOTP (2FA) Example ==="
|
12
|
+
|
13
|
+
# Note: TOTP functionality requires the 'base32' gem
|
14
|
+
# Install with: gem install base32
|
15
|
+
|
16
|
+
begin
|
17
|
+
# Check if TOTP is available
|
18
|
+
unless defined?(KeeperSecretsManager::Totp)
|
19
|
+
puts "\nTOTP functionality requires the 'base32' gem."
|
20
|
+
puts "Install it with: gem install base32"
|
21
|
+
puts "\nWithout TOTP, you can still:"
|
22
|
+
puts "- Store TOTP seeds in oneTimeCode fields"
|
23
|
+
puts "- Use external authenticator apps"
|
24
|
+
puts "- Access the seed for manual setup"
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
|
28
|
+
puts "\n1. Finding records with TOTP:"
|
29
|
+
secrets = secrets_manager.get_secrets
|
30
|
+
totp_records = secrets.select do |s|
|
31
|
+
s.fields.any? { |f| f['type'] == 'oneTimeCode' }
|
32
|
+
end
|
33
|
+
|
34
|
+
if totp_records.empty?
|
35
|
+
puts " No records with TOTP found."
|
36
|
+
|
37
|
+
# Example of creating a record with TOTP
|
38
|
+
puts "\n2. Example: Creating a record with TOTP"
|
39
|
+
puts " record_data = {"
|
40
|
+
puts " type: 'login',"
|
41
|
+
puts " title: '2FA Example',"
|
42
|
+
puts " fields: ["
|
43
|
+
puts " { type: 'login', value: ['user@example.com'] },"
|
44
|
+
puts " { type: 'password', value: ['password123'] },"
|
45
|
+
puts " { type: 'oneTimeCode', value: ['JBSWY3DPEHPK3PXP'] }"
|
46
|
+
puts " ]"
|
47
|
+
puts " }"
|
48
|
+
else
|
49
|
+
puts " Found #{totp_records.length} records with TOTP"
|
50
|
+
|
51
|
+
# Generate TOTP codes
|
52
|
+
puts "\n2. Generating TOTP codes:"
|
53
|
+
totp_records.each do |record|
|
54
|
+
totp_field = record.fields.find { |f| f['type'] == 'oneTimeCode' }
|
55
|
+
if totp_field && totp_field['value']
|
56
|
+
seed = totp_field['value'].first
|
57
|
+
|
58
|
+
# Generate current code
|
59
|
+
code = KeeperSecretsManager::Totp.generate(seed)
|
60
|
+
puts " #{record.title}: #{code}"
|
61
|
+
|
62
|
+
# Show time remaining
|
63
|
+
time_remaining = 30 - (Time.now.to_i % 30)
|
64
|
+
puts " Valid for: #{time_remaining} seconds"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
puts "\n3. Using TOTP via notation:"
|
70
|
+
if totp_records.any?
|
71
|
+
uid = totp_records.first.uid
|
72
|
+
begin
|
73
|
+
totp_url = secrets_manager.get_notation("keeper://#{uid}/field/oneTimeCode")
|
74
|
+
puts " TOTP URL: #{totp_url}"
|
75
|
+
rescue => e
|
76
|
+
puts " Error: #{e.message}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
puts "\n4. TOTP URL format:"
|
81
|
+
puts " Standard TOTP seeds can be imported from URLs:"
|
82
|
+
puts " otpauth://totp/Example:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example"
|
83
|
+
|
84
|
+
puts "\n5. Manual TOTP setup:"
|
85
|
+
puts " If base32 gem is not available:"
|
86
|
+
puts " 1. Store the seed in a oneTimeCode field"
|
87
|
+
puts " 2. Use the seed with Google Authenticator or similar"
|
88
|
+
puts " 3. Or install base32 gem for SDK generation"
|
89
|
+
|
90
|
+
rescue => e
|
91
|
+
puts "Error: #{e.message}"
|
92
|
+
puts "\nMake sure 'base32' gem is installed for TOTP support"
|
93
|
+
end
|
94
|
+
|
95
|
+
puts "\n=== TOTP Tips ==="
|
96
|
+
puts "- TOTP codes change every 30 seconds"
|
97
|
+
puts "- Store TOTP seeds in oneTimeCode fields"
|
98
|
+
puts "- Seeds are typically base32 encoded"
|
99
|
+
puts "- Compatible with Google Authenticator"
|
100
|
+
puts "- Keep TOTP seeds secure like passwords"
|
data/examples/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# Keeper Secrets Manager Ruby SDK Examples
|
2
|
+
|
3
|
+
This directory contains examples demonstrating various features of the Keeper Secrets Manager Ruby SDK.
|
4
|
+
|
5
|
+
## Prerequisites
|
6
|
+
|
7
|
+
1. Set up your configuration using one of these methods:
|
8
|
+
- Token: `export KSM_TOKEN='your_token_here'`
|
9
|
+
- Base64 Config: `export KSM_CONFIG='your_base64_config_here'`
|
10
|
+
|
11
|
+
2. Install the SDK:
|
12
|
+
```bash
|
13
|
+
gem install keeper_secrets_manager
|
14
|
+
```
|
15
|
+
|
16
|
+
## Examples
|
17
|
+
|
18
|
+
### 01_quick_start.rb
|
19
|
+
Basic connection and simple secret retrieval. Start here if you're new to the SDK.
|
20
|
+
|
21
|
+
### 02_authentication.rb
|
22
|
+
Different ways to authenticate with Keeper Secrets Manager:
|
23
|
+
- Using token authentication
|
24
|
+
- Using base64 configuration string
|
25
|
+
|
26
|
+
### 03_retrieve_secrets.rb
|
27
|
+
Various methods to retrieve secrets:
|
28
|
+
- Get all secrets
|
29
|
+
- Get by UID
|
30
|
+
- Get by title
|
31
|
+
- Access specific fields
|
32
|
+
- Using Keeper Notation
|
33
|
+
|
34
|
+
### 04_create_update_delete.rb
|
35
|
+
CRUD operations for managing secrets:
|
36
|
+
- Create new records
|
37
|
+
- Update existing records
|
38
|
+
- Delete records
|
39
|
+
- Batch operations tips
|
40
|
+
|
41
|
+
### 05_field_types.rb
|
42
|
+
Working with different Keeper field types:
|
43
|
+
- Standard fields (login, password, URL)
|
44
|
+
- Complex fields (name, address, phone)
|
45
|
+
- Custom fields
|
46
|
+
- Special fields (payment cards, bank accounts)
|
47
|
+
|
48
|
+
### 06_files.rb
|
49
|
+
File attachment operations:
|
50
|
+
- Download files from records
|
51
|
+
- Upload files to records
|
52
|
+
- Handle different file types
|
53
|
+
|
54
|
+
### 07_folders.rb
|
55
|
+
Folder management:
|
56
|
+
- List folders
|
57
|
+
- Create folders and subfolders
|
58
|
+
- Move records between folders
|
59
|
+
- Get folder hierarchy
|
60
|
+
- Delete folders
|
61
|
+
|
62
|
+
### 08_notation.rb
|
63
|
+
Using Keeper Notation for quick access:
|
64
|
+
- Access fields with URI-style notation
|
65
|
+
- Use in configuration templates
|
66
|
+
- Access custom fields and files
|
67
|
+
|
68
|
+
### 09_totp.rb
|
69
|
+
Time-based One-Time Passwords (2FA):
|
70
|
+
- Generate TOTP codes
|
71
|
+
- Store TOTP seeds
|
72
|
+
- Integration with authenticator apps
|
73
|
+
|
74
|
+
## Running Examples
|
75
|
+
|
76
|
+
Each example can be run directly:
|
77
|
+
|
78
|
+
```bash
|
79
|
+
ruby 01_quick_start.rb
|
80
|
+
```
|
81
|
+
|
82
|
+
Make sure your environment variables are set before running the examples.
|
83
|
+
|
84
|
+
## Security Notes
|
85
|
+
|
86
|
+
- Never hardcode credentials in your code
|
87
|
+
- Use environment variables for configuration
|
88
|
+
- Keep your tokens and configurations secure
|
89
|
+
- Don't commit credentials to version control
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: keeper_secrets_manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 17.0.
|
4
|
+
version: 17.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keeper Security
|
@@ -21,21 +21,24 @@ files:
|
|
21
21
|
- ".rspec"
|
22
22
|
- ".ruby-version"
|
23
23
|
- CHANGELOG.md
|
24
|
+
- DEVELOPER_SETUP.md
|
24
25
|
- Gemfile
|
25
26
|
- LICENSE
|
27
|
+
- MANUAL_TESTING_GUIDE.md
|
26
28
|
- README.md
|
29
|
+
- RUBY_SDK_COMPLETE_DOCUMENTATION.md
|
30
|
+
- RUBY_SDK_COMPREHENSIVE_SUMMARY.md
|
27
31
|
- Rakefile
|
28
|
-
- examples/
|
29
|
-
- examples/
|
30
|
-
- examples/
|
31
|
-
- examples/
|
32
|
-
- examples/
|
33
|
-
- examples/
|
34
|
-
- examples/
|
35
|
-
- examples/
|
36
|
-
- examples/
|
37
|
-
- examples/
|
38
|
-
- examples/storage_examples.rb
|
32
|
+
- examples/01_quick_start.rb
|
33
|
+
- examples/02_authentication.rb
|
34
|
+
- examples/03_retrieve_secrets.rb
|
35
|
+
- examples/04_create_update_delete.rb
|
36
|
+
- examples/05_field_types.rb
|
37
|
+
- examples/06_files.rb
|
38
|
+
- examples/07_folders.rb
|
39
|
+
- examples/08_notation.rb
|
40
|
+
- examples/09_totp.rb
|
41
|
+
- examples/README.md
|
39
42
|
- lib/keeper_secrets_manager.rb
|
40
43
|
- lib/keeper_secrets_manager/config_keys.rb
|
41
44
|
- lib/keeper_secrets_manager/core.rb
|