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.
@@ -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"
@@ -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"
@@ -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
@@ -1,3 +1,3 @@
1
1
  module KeeperSecretsManager
2
- VERSION = '17.0.3'.freeze
2
+ VERSION = '17.0.4'.freeze
3
3
  end
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.3
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/basic_usage.rb
29
- - examples/config_string_example.rb
30
- - examples/debug_secrets.rb
31
- - examples/demo_list_secrets.rb
32
- - examples/download_files.rb
33
- - examples/flexible_records_example.rb
34
- - examples/folder_hierarchy_demo.rb
35
- - examples/full_demo.rb
36
- - examples/my_test_standalone.rb
37
- - examples/simple_test.rb
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