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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +100 -16
  3. data/Gemfile +6 -3
  4. data/README.md +75 -270
  5. data/Rakefile +1 -1
  6. data/bin/console +47 -0
  7. data/keeper_secrets_manager.gemspec +36 -0
  8. data/lib/keeper_secrets_manager/cache.rb +139 -0
  9. data/lib/keeper_secrets_manager/config_keys.rb +4 -2
  10. data/lib/keeper_secrets_manager/core.rb +993 -452
  11. data/lib/keeper_secrets_manager/crypto.rb +101 -116
  12. data/lib/keeper_secrets_manager/dto/payload.rb +7 -6
  13. data/lib/keeper_secrets_manager/dto.rb +374 -38
  14. data/lib/keeper_secrets_manager/errors.rb +13 -2
  15. data/lib/keeper_secrets_manager/field_types.rb +3 -3
  16. data/lib/keeper_secrets_manager/folder_manager.rb +25 -29
  17. data/lib/keeper_secrets_manager/keeper_globals.rb +11 -17
  18. data/lib/keeper_secrets_manager/notation.rb +202 -93
  19. data/lib/keeper_secrets_manager/notation_enhancements.rb +24 -24
  20. data/lib/keeper_secrets_manager/storage.rb +38 -38
  21. data/lib/keeper_secrets_manager/totp.rb +27 -27
  22. data/lib/keeper_secrets_manager/utils.rb +85 -18
  23. data/lib/keeper_secrets_manager/version.rb +2 -2
  24. data/lib/keeper_secrets_manager.rb +11 -3
  25. metadata +39 -22
  26. data/DEVELOPER_SETUP.md +0 -0
  27. data/MANUAL_TESTING_GUIDE.md +0 -332
  28. data/RUBY_SDK_COMPLETE_DOCUMENTATION.md +0 -354
  29. data/RUBY_SDK_COMPREHENSIVE_SUMMARY.md +0 -192
  30. data/examples/01_quick_start.rb +0 -45
  31. data/examples/02_authentication.rb +0 -82
  32. data/examples/03_retrieve_secrets.rb +0 -81
  33. data/examples/04_create_update_delete.rb +0 -104
  34. data/examples/05_field_types.rb +0 -135
  35. data/examples/06_files.rb +0 -137
  36. data/examples/07_folders.rb +0 -145
  37. data/examples/08_notation.rb +0 -103
  38. data/examples/09_totp.rb +0 -100
  39. 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"
@@ -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"
@@ -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"
@@ -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"