keeper_secrets_manager 17.1.0 → 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 +83 -10
- data/Gemfile +3 -0
- data/README.md +75 -270
- 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 +2 -0
- data/lib/keeper_secrets_manager/core.rb +455 -114
- data/lib/keeper_secrets_manager/crypto.rb +3 -11
- data/lib/keeper_secrets_manager/dto/payload.rb +3 -2
- data/lib/keeper_secrets_manager/dto.rb +326 -8
- data/lib/keeper_secrets_manager/keeper_globals.rb +6 -6
- data/lib/keeper_secrets_manager/notation.rb +105 -3
- data/lib/keeper_secrets_manager/notation_enhancements.rb +2 -0
- data/lib/keeper_secrets_manager/storage.rb +3 -2
- data/lib/keeper_secrets_manager/utils.rb +2 -1
- data/lib/keeper_secrets_manager/version.rb +1 -1
- data/lib/keeper_secrets_manager.rb +8 -0
- metadata +34 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a4bd6d345590ff9f958814a482c10cb18dff351be76d9068f477183baf707d2e
|
|
4
|
+
data.tar.gz: 452a1bfcf84c267a3e9e6b5eee53f791ea14a2ad276f2fc2ba8b42a763f48e3b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 772bfaed3f3376b4e5aad8214fc99685c6168a92391865b83faac03a69d4e44bfd26d7a03d2052cc251fa2b70f1fb0e72a313e250678ddb6ba539dd666b3dfa2
|
|
7
|
+
data.tar.gz: ddf197159f9d56b79ad8eecf7ae74f2ccc8ccfb5642cc8f4d9dff57046a2f6c753f7cc8bd0e48d659819251fe89852573791aa69894a4bb0741a2dc6ce86fe59
|
data/CHANGELOG.md
CHANGED
|
@@ -1,16 +1,79 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [17.2.0]
|
|
4
4
|
|
|
5
5
|
### Fixed
|
|
6
|
-
- `update_secret` now
|
|
7
|
-
- `update_secret`
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
- Fixed AES-CBC
|
|
6
|
+
- **KSM-1095**: `update_secret` now calls `complete_transaction` after staging the update, so changes are committed to the server rather than remaining in a staged state indefinitely; works for both `KeeperRecord` objects and plain hash inputs
|
|
7
|
+
- **KSM-1094**: `update_secret` no longer raises `NameError: undefined local variable 'record_uid'` when called with a `KeeperRecord` object; the revision refresh now correctly references `record.uid`
|
|
8
|
+
- **KSM-1096**: `download_thumbnail` no longer raises `NoMethodError` when passed a `KeeperFile` object; `KeeperFile` now exposes a `file_key` attribute and the method dispatches on type before attempting hash access
|
|
9
|
+
- **KSM-824**: `to_h` now always includes `custom` in the V3 API payload, even when the array is empty, matching Commander and Vault behavior
|
|
10
|
+
- **KSM-906**: Added IL5 region mapping (`IL5` → `il5.keepersecurity.us`) to `KEEPER_SERVERS`
|
|
11
|
+
- **KSM-987**: `url_safe_str_to_bytes` and `base64_to_bytes` in `Utils` now raise `Error` when passed `nil`; all Base64 decoding in `core.rb` routes through `Utils`
|
|
12
|
+
- **KSM-1090**: `base64` and `logger` are now declared as explicit runtime dependencies in the gemspec; Ruby 4.0 removed these from the default standard library, so any clean install on Ruby 4.0+ previously raised `LoadError` on `require 'keeper_secrets_manager'`. Also removed a dead `require 'ostruct'` from `dto.rb`.
|
|
13
|
+
- **KSM-1070**: Fixed silent AES-CBC fallback in `decrypt_aes_gcm`: an AES-GCM authentication-tag failure now raises `DecryptionError` immediately rather than retrying decryption as AES-CBC; tampered or wrong-key ciphertext previously could produce output without any error.
|
|
14
|
+
- **KSM-685**: `CreateOptions.subfolder_uid` parameter is now correctly sent to the API when creating records
|
|
15
|
+
- **KSM-686**: Disaster recovery caching with `CachingPostFunction` is now implemented to match other SDKs; API response caching works for both `get_secret` and `get_folders` endpoints, and unused `@cache` and `@cache_expiry` instance variables are removed from `SecretsManager`
|
|
16
|
+
- **KSM-696**: Config storage file is now written with `0600` permissions (owner read/write only), preventing other local users from reading stored credentials
|
|
17
|
+
- **KSM-734**: Fixed notation lookup to deduplicate record shortcuts via `uniq { |r| r.uid }` before the ambiguity check; preserves genuine duplicate-title detection while preventing false ambiguity errors when both an original record and its shortcut are in scope
|
|
18
|
+
- **KSM-1088**: `delete_secret` and `delete_folder` now log an error for each record/folder whose `responseCode` is not `"ok"`, surfacing partial-failure details that were previously silently discarded
|
|
19
|
+
- **KSM-1091**: Invalid `proxy_url` now raises `ArgumentError` at initialization with a descriptive message; a URL with no host previously silently bypassed the proxy, and a fully malformed URL raised `NetworkError` at request time instead
|
|
20
|
+
- **KSM-1098**: `get_value`, `get_totp_code`, and `download_file` in `notation_enhancements` no longer raise `NoMethodError` when passed `nil`, an empty string, or a non-String value; `parse` itself now checks `is_a?(String)` before `empty?` to avoid `NoMethodError` for non-String inputs. `notation_enhancements` is now properly required from the main entry point.
|
|
21
|
+
- Fixed example files to use correct SDK APIs: `09_totp.rb` corrects `Totp` to `TOTP` and `generate()` to `generate_code()`; `01_quick_start.rb` uses the `secret.login` dynamic getter instead of hash access; `10_custom_caching.rb` uses `Utils.bytes_to_base64`
|
|
22
|
+
- Fixed badly anchored regular expression in `test/integration/test_totp.rb` that could cause false positives in test validation
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- **KSM-906**: `SecretsManager` now accepts the 4-part IL5 one-time token `IL5:clientKey:serverPublicKeyId:serverPublicKey`, registering the supplied EC P-256 server public key (keyId 20, outside the built-in 1–18 table) for ECIES transmission-key wrapping, and persists it as `serverPublicKey` in config so it survives restarts. Adds `server_public_key` / `server_public_key_id` constructor options (precedence: programmatic > token > config), a new `ConfigKeys::KEY_SERVER_PUBLIC_KEY`, malformed-OTT validation, and an actionable error when the backend rejects a configured custom key. Non-IL5 tokens are unchanged.
|
|
26
|
+
- **KSM-1013**: `KeeperRecordLink` (via `KeeperRecord#get_links`) wraps each raw `links` entry with never-raising typed accessors: permission booleans with an `allowedSettings` fallback (top-level wins), AES-256-GCM `get_decrypted_data`/`get_link_data`, and `meta`/`ai_settings`/`jit_settings` settings accessors. Adds a `request_links:` keyword to `get_secrets`. Purely additive; the raw `record.links` list is unchanged.
|
|
27
|
+
- **KSM-883**: On HTTP 403 `{"error":"throttled"}`, `post_query` now retries up to 5 times with exponentially increasing delays (11s, 22s, 44s, 88s, 176s) plus 0–25% jitter (one-sided), honoring `retry_after` from the response when present, and raises `ThrottledError` once retries are exhausted. Replaces the previous fixed 60-second sleep with no backoff, jitter, or retry cap.
|
|
28
|
+
- **KSM-1102**: Added `save(record, transaction_type: nil, links_to_remove: nil)` and `save_with_options(record, update_options)`: non-finalizing update aliases that use the stored record key without re-fetching and do not call `complete_transaction`
|
|
29
|
+
- **KSM-1101**: Added `inflate_field_value(uids, replace_fields)` and `get_inflate_ref_types(field_type)` for field-reference resolution; `addressRef` resolves to address fields, `cardRef` resolves to paymentCard/text/pinCode/address fields with recursive inflate
|
|
30
|
+
- **KSM-1100**: Added `get_notation_results` and `try_get_notation_results`: list-returning notation lookup that always returns `Array[String]`, returns all field values by default (no first-element shortcut), and JSON-serializes complex values
|
|
31
|
+
- **KSM-1099**: Added `create_secret_with_options(create_options, record_data, folders: nil)`: explicit options-based creation that accepts a pre-fetched folders list to avoid an extra `get_folders` network call; `create_secret` is unchanged
|
|
32
|
+
- **KSM-743**: Added transmission public key #18 for Gov Cloud Dev environment support
|
|
33
|
+
- **KSM-687**: Added DTO fields and PAM transaction support for complete SDK parity:
|
|
34
|
+
- `links` field to `KeeperRecord` for linked records support
|
|
35
|
+
- `is_editable` field to `KeeperRecord` to check edit permissions
|
|
36
|
+
- `inner_folder_uid` field to `KeeperRecord` for folder location tracking
|
|
37
|
+
- `thumbnail_url` and `last_modified` fields to `KeeperFile`
|
|
38
|
+
- `UpdateOptions` class with `transaction_type` and `links_to_remove` support
|
|
39
|
+
- `update_secret_with_options` method to support removing file links
|
|
40
|
+
- `request_links` option to `QueryOptions` for fetching linked records
|
|
41
|
+
- `download_thumbnail` method for downloading file thumbnails
|
|
42
|
+
- `expires_on` field to `SecretsManagerResponse`
|
|
43
|
+
- `complete_transaction(record_uid, rollback: false)` method for PAM rotation workflows
|
|
44
|
+
- `CompleteTransactionPayload` DTO class for transaction completion
|
|
45
|
+
- **KSM-692**: HTTP proxy support for enterprise environments:
|
|
46
|
+
- `proxy_url` initialization parameter for explicit proxy configuration
|
|
47
|
+
- `HTTPS_PROXY` / `https_proxy` environment variable support (automatic detection)
|
|
48
|
+
- Authenticated proxy support (username:password in URL)
|
|
49
|
+
- Proxy applies to all HTTP operations (API calls, file downloads, file uploads)
|
|
50
|
+
- **KSM-694**: Convenience methods for improved developer experience:
|
|
51
|
+
- `upload_file_from_path(owner_record_uid, file_path, file_title: nil)`: upload files directly from disk
|
|
52
|
+
- `try_get_notation(notation_uri)`: error-safe notation access (returns empty array on error)
|
|
53
|
+
- `KeeperSecretsManager.from_config(config_base64, options = {})`: convenience method for initializing from a base64 config string; complements `from_token()` and `from_file()` and provides parity with the .NET SDK's `GetVaultConfigFromConfigString()` pattern
|
|
54
|
+
- `KeeperSecretsManager::CachingPostFunction`: built-in disaster recovery caching
|
|
55
|
+
- `KeeperSecretsManager::Cache`: file-based cache management (save, load, clear); location configurable via `KSM_CACHE_DIR` environment variable
|
|
56
|
+
- Development console script (`bin/console`) for interactive SDK exploration using Pry REPL
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
- Documentation: Added Ruby SDK to root repository SDK comparison table
|
|
60
|
+
- **Test Coverage:**
|
|
61
|
+
- Added 5 new integration test files (test_pam_rotation.rb, test_proxy.rb, test_pam_linked_records.rb, test_caching.rb)
|
|
62
|
+
- Added 17 unit tests for caching functionality and 27 for new features (CompleteTransactionPayload, QueryOptions, proxy configuration, convenience methods)
|
|
63
|
+
- Enhanced test_file_operations.rb with thumbnail download and file link removal tests
|
|
64
|
+
- **Mock Infrastructure:** Implemented proper AES-256-GCM encryption in `mock_helper.rb`:
|
|
65
|
+
- Records now use proper AES-GCM encryption (was Base64 only)
|
|
66
|
+
- Folders use correct AES-CBC encryption for data
|
|
67
|
+
- Added transmission key encryption/decryption
|
|
68
|
+
- Added mock endpoints for transaction completion (finalize_secret_update, rollback_secret_update)
|
|
69
|
+
- Enabled complete offline testing without config.base64
|
|
70
|
+
- **Example Files:**
|
|
71
|
+
- Added `11_pam_linked_records.rb`: PAM resources with linked credentials and transaction workflow
|
|
72
|
+
- Added `12_proxy_usage.rb`: HTTP proxy configuration examples
|
|
73
|
+
- Updated `06_files.rb`: added `upload_file_from_path` convenience method example
|
|
74
|
+
- Updated `08_notation.rb`: added `try_get_notation` error-safe notation example
|
|
75
|
+
- Removed emojis from all example files for professional appearance
|
|
76
|
+
- **Dependencies:** Added base32 gem to test dependencies for TOTP support
|
|
14
77
|
|
|
15
78
|
## [17.1.0] - 2025-01-06
|
|
16
79
|
|
|
@@ -22,6 +85,14 @@
|
|
|
22
85
|
- ECC key generation now correctly returns 32-byte raw private keys (was returning 121-byte DER format)
|
|
23
86
|
- Client version now dynamically uses VERSION constant instead of hardcoded value
|
|
24
87
|
- Fixed Tests
|
|
88
|
+
- `update_secret` now correctly encrypts record data before sending to server
|
|
89
|
+
- `update_secret` now calls `finalize_secret_update` endpoint to persist changes
|
|
90
|
+
- Local record's revision number is automatically refreshed after successful update
|
|
91
|
+
- Consecutive updates on the same record object now work without manual refetching
|
|
92
|
+
- `download_file` now properly respects SSL certificate verification settings and disables CRL checking
|
|
93
|
+
- `upload_file` now uses correct `add_file` endpoint and includes required `ownerRecordRevision` in payload
|
|
94
|
+
- `create_folder` now properly encrypts folder key with AES-CBC and sets correct parent_uid (nil for root-level folders)
|
|
95
|
+
- Fixed AES-CBC encryption to not double-pad data (OpenSSL handles padding automatically)
|
|
25
96
|
|
|
26
97
|
## [17.0.4] - 2025-10-20
|
|
27
98
|
|
|
@@ -57,4 +128,6 @@
|
|
|
57
128
|
|
|
58
129
|
### Notes
|
|
59
130
|
- Version 17.0.0 to align with other Keeper SDKs
|
|
60
|
-
- No runtime dependencies (base32 is optional)
|
|
131
|
+
- No runtime dependencies (base32 is optional)
|
|
132
|
+
|
|
133
|
+
[17.2.0]: https://github.com/Keeper-Security/secrets-manager/compare/ruby-sdk-v17.1.0...ruby-sdk-v17.2.0
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,305 +1,110 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
1
|
+
## Keeper Secrets Manager Ruby SDK
|
|
2
|
+
|
|
3
|
+
For more information see our official documentation page https://docs.keeper.io/secrets-manager/secrets-manager/developer-sdk-library/ruby-sdk
|
|
4
|
+
|
|
5
|
+
# Change Log
|
|
6
|
+
|
|
7
|
+
## 17.2.0 - 2025-11-14
|
|
8
|
+
- KSM-685 - Fixed `CreateOptions.subfolder_uid` parameter API transmission
|
|
9
|
+
- KSM-686 - Implemented disaster recovery caching with `CachingPostFunction`
|
|
10
|
+
- KSM-687 - Added missing DTO fields for complete SDK parity (links, is_editable, inner_folder_uid, thumbnail_url, last_modified, expires_on)
|
|
11
|
+
- KSM-1013 - Added typed linked-credential accessors (`KeeperRecordLink` via `record.get_links`) and a `request_links:` option on `get_secrets`
|
|
12
|
+
- KSM-692 - Added HTTP proxy support for enterprise environments
|
|
13
|
+
- KSM-694 - Added convenience methods (`upload_file_from_path`, `try_get_notation`)
|
|
14
|
+
- KSM-696 - Fixed file permissions for Ruby SDK config files
|
|
15
|
+
- KSM-697 - Comprehensive unit test coverage improvements (+358 tests, 63.3% coverage)
|
|
16
|
+
- KSM-734 - Fixed notation lookup to handle duplicate UIDs from record shortcuts
|
|
17
|
+
- KSM-743 - Added transmission public key #18 for Gov Cloud Dev environment support
|
|
18
|
+
- Added `from_config()` convenience method for base64 config initialization
|
|
19
|
+
- Added `update_secret_with_options()` method for removing file links
|
|
20
|
+
- Added `download_thumbnail()` method for file thumbnails
|
|
21
|
+
- Added development console (`bin/console`) for interactive SDK exploration
|
|
22
|
+
- Fixed example files to use correct SDK APIs
|
|
23
|
+
- Improved mock infrastructure with proper AES-256-GCM encryption
|
|
24
|
+
|
|
25
|
+
## 17.1.0 - 2025-01-06
|
|
26
|
+
- **BREAKING**: Minimum Ruby version increased to 3.1.0 (from 2.6.0)
|
|
27
|
+
- Fixed ECC key generation to return 32-byte raw private keys
|
|
28
|
+
- Fixed `update_secret` to correctly encrypt and persist changes
|
|
29
|
+
- Fixed `download_file` SSL certificate verification
|
|
30
|
+
- Fixed `upload_file` to use correct endpoint
|
|
31
|
+
- Fixed `create_folder` encryption and parent_uid handling
|
|
32
|
+
|
|
33
|
+
For full version history, see [CHANGELOG.md](CHANGELOG.md)
|
|
34
|
+
|
|
35
|
+
# Quick Start
|
|
14
36
|
|
|
15
37
|
## Installation
|
|
16
38
|
|
|
17
|
-
Add this line to your application's Gemfile:
|
|
18
|
-
|
|
19
|
-
```ruby
|
|
20
|
-
gem 'keeper_secrets_manager'
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
And then execute:
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
$ bundle install
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Or install it yourself as:
|
|
30
|
-
|
|
31
39
|
```bash
|
|
32
|
-
|
|
40
|
+
gem install keeper_secrets_manager
|
|
33
41
|
```
|
|
34
42
|
|
|
35
|
-
##
|
|
36
|
-
|
|
37
|
-
### Initialize with One-Time Token
|
|
43
|
+
## Basic Usage
|
|
38
44
|
|
|
39
45
|
```ruby
|
|
40
46
|
require 'keeper_secrets_manager'
|
|
41
47
|
|
|
42
|
-
# Initialize
|
|
43
|
-
token = "US:ONE_TIME_TOKEN_HERE"
|
|
44
|
-
secrets_manager = KeeperSecretsManager.from_token(token)
|
|
45
|
-
|
|
46
|
-
# Retrieve secrets
|
|
47
|
-
records = secrets_manager.get_secrets
|
|
48
|
-
records.each do |record|
|
|
49
|
-
puts "#{record.title}: #{record.get_field_value_single('login')}"
|
|
50
|
-
end
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Initialize with Existing Configuration
|
|
54
|
-
|
|
55
|
-
```ruby
|
|
56
|
-
# From config file
|
|
48
|
+
# Initialize from config file
|
|
57
49
|
secrets_manager = KeeperSecretsManager.from_file('keeper_config.json')
|
|
58
50
|
|
|
59
|
-
#
|
|
60
|
-
|
|
61
|
-
secrets_manager = KeeperSecretsManager.new(config: config)
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Dynamic Record Creation
|
|
65
|
-
|
|
66
|
-
The Ruby SDK uses a flexible, JavaScript-style approach to records:
|
|
67
|
-
|
|
68
|
-
```ruby
|
|
69
|
-
# Create record with hash syntax
|
|
70
|
-
record = KeeperSecretsManager::Dto::KeeperRecord.new(
|
|
71
|
-
title: 'My Server',
|
|
72
|
-
type: 'login',
|
|
73
|
-
fields: [
|
|
74
|
-
{ 'type' => 'login', 'value' => ['admin'] },
|
|
75
|
-
{ 'type' => 'password', 'value' => ['SecurePass123!'] },
|
|
76
|
-
{ 'type' => 'url', 'value' => ['https://example.com'] },
|
|
77
|
-
{
|
|
78
|
-
'type' => 'host',
|
|
79
|
-
'value' => [{ 'hostName' => '192.168.1.1', 'port' => '22' }],
|
|
80
|
-
'label' => 'SSH Server'
|
|
81
|
-
}
|
|
82
|
-
],
|
|
83
|
-
custom: [
|
|
84
|
-
{ 'type' => 'text', 'label' => 'Environment', 'value' => ['Production'] }
|
|
85
|
-
]
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
# Dynamic field access
|
|
89
|
-
puts record.login # => "admin"
|
|
90
|
-
record.password = 'NewPassword123!'
|
|
51
|
+
# Get all secrets
|
|
52
|
+
records = secrets_manager.get_secrets
|
|
91
53
|
|
|
92
|
-
#
|
|
93
|
-
record.
|
|
94
|
-
|
|
95
|
-
'city' => 'New York',
|
|
96
|
-
'state' => 'NY',
|
|
97
|
-
'zip' => '10001'
|
|
98
|
-
})
|
|
54
|
+
# Access secret fields
|
|
55
|
+
record = records.first
|
|
56
|
+
puts "Password: #{record.password}"
|
|
99
57
|
```
|
|
100
58
|
|
|
101
|
-
##
|
|
59
|
+
## Linked Credentials (PAM)
|
|
102
60
|
|
|
103
|
-
|
|
61
|
+
PAM records can carry linked credentials. Request them with `request_links: true`, then use the typed `KeeperRecordLink` accessors returned by `record.get_links` (the raw entries remain available on `record.links`):
|
|
104
62
|
|
|
105
63
|
```ruby
|
|
106
|
-
|
|
107
|
-
password = secrets_manager.get_notation("keeper://RECORD_UID/field/password")
|
|
108
|
-
|
|
109
|
-
# Get specific property from complex field
|
|
110
|
-
hostname = secrets_manager.get_notation("keeper://RECORD_UID/field/host[hostName]")
|
|
111
|
-
port = secrets_manager.get_notation("keeper://RECORD_UID/field/host[port]")
|
|
64
|
+
records = secrets_manager.get_secrets(request_links: true)
|
|
112
65
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
# Access by record title
|
|
117
|
-
url = secrets_manager.get_notation("keeper://My Login/field/url")
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Field Type Helpers
|
|
121
|
-
|
|
122
|
-
Optional convenience methods for creating typed fields:
|
|
66
|
+
records.each do |record|
|
|
67
|
+
record.get_links.each do |link|
|
|
68
|
+
puts "-> #{link.record_uid} (path: #{link.path.inspect})"
|
|
123
69
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
KeeperSecretsManager::FieldTypes::Helpers.login('username'),
|
|
128
|
-
KeeperSecretsManager::FieldTypes::Helpers.password('SecurePass123!'),
|
|
129
|
-
KeeperSecretsManager::FieldTypes::Helpers.host(
|
|
130
|
-
hostname: '192.168.1.100',
|
|
131
|
-
port: 22
|
|
132
|
-
),
|
|
133
|
-
KeeperSecretsManager::FieldTypes::Helpers.name(
|
|
134
|
-
first: 'John',
|
|
135
|
-
last: 'Doe',
|
|
136
|
-
middle: 'Q'
|
|
137
|
-
)
|
|
138
|
-
]
|
|
70
|
+
# Permission booleans read allowedSettings when nested (e.g. on "meta" links)
|
|
71
|
+
puts " rotation allowed: #{link.allows_rotation?}"
|
|
72
|
+
puts " admin user: #{link.admin_user?}"
|
|
139
73
|
|
|
140
|
-
record
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
74
|
+
# Encrypted ai_settings / jit_settings decrypt with the owning record's key
|
|
75
|
+
ai = link.get_ai_settings_data(record.record_key)
|
|
76
|
+
puts " ai settings: #{ai.inspect}" if ai
|
|
77
|
+
end
|
|
78
|
+
end
|
|
145
79
|
```
|
|
146
80
|
|
|
147
|
-
|
|
81
|
+
Accessors never raise — decode or decryption failures return `nil`/`false`.
|
|
148
82
|
|
|
149
|
-
|
|
150
|
-
```ruby
|
|
151
|
-
storage = KeeperSecretsManager::Storage::InMemoryStorage.new
|
|
152
|
-
```
|
|
83
|
+
## Proxy Support
|
|
153
84
|
|
|
154
|
-
|
|
155
|
-
```ruby
|
|
156
|
-
storage = KeeperSecretsManager::Storage::FileStorage.new('keeper_config.json')
|
|
157
|
-
```
|
|
85
|
+
For enterprise environments behind HTTP proxies:
|
|
158
86
|
|
|
159
|
-
### Environment Variables
|
|
160
87
|
```ruby
|
|
161
|
-
#
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
### Caching Storage
|
|
166
|
-
```ruby
|
|
167
|
-
# Wrap any storage with caching (600 second TTL)
|
|
168
|
-
base_storage = KeeperSecretsManager::Storage::FileStorage.new('config.json')
|
|
169
|
-
storage = KeeperSecretsManager::Storage::CachingStorage.new(base_storage, 600)
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
## CRUD Operations
|
|
173
|
-
|
|
174
|
-
### Create Record
|
|
175
|
-
```ruby
|
|
176
|
-
record = KeeperSecretsManager::Dto::KeeperRecord.new(
|
|
177
|
-
title: 'New Record',
|
|
178
|
-
type: 'login',
|
|
179
|
-
fields: [
|
|
180
|
-
{ 'type' => 'login', 'value' => ['user'] },
|
|
181
|
-
{ 'type' => 'password', 'value' => ['pass'] }
|
|
182
|
-
]
|
|
88
|
+
# Method 1: Explicit proxy_url parameter
|
|
89
|
+
secrets_manager = KeeperSecretsManager.from_file(
|
|
90
|
+
'keeper_config.json',
|
|
91
|
+
proxy_url: 'http://proxy.company.com:8080'
|
|
183
92
|
)
|
|
184
93
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
```ruby
|
|
190
|
-
# Get existing record
|
|
191
|
-
record = secrets_manager.get_secret_by_title("My Record")
|
|
192
|
-
|
|
193
|
-
# Update fields
|
|
194
|
-
record.set_field('password', 'NewPassword123!')
|
|
195
|
-
record.notes = "Updated on #{Time.now}"
|
|
196
|
-
|
|
197
|
-
# Save changes
|
|
198
|
-
secrets_manager.update_secret(record)
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
### Delete Records
|
|
202
|
-
```ruby
|
|
203
|
-
# Delete single record
|
|
204
|
-
secrets_manager.delete_secret('RECORD_UID')
|
|
205
|
-
|
|
206
|
-
# Delete multiple records
|
|
207
|
-
secrets_manager.delete_secret(['UID1', 'UID2', 'UID3'])
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
### Folder Operations
|
|
211
|
-
```ruby
|
|
212
|
-
# Get all folders
|
|
213
|
-
folders = secrets_manager.get_folders
|
|
214
|
-
|
|
215
|
-
# Create folder
|
|
216
|
-
folder_uid = secrets_manager.create_folder('New Folder', parent_uid: 'PARENT_UID')
|
|
217
|
-
|
|
218
|
-
# Update folder
|
|
219
|
-
secrets_manager.update_folder(folder_uid, 'Renamed Folder')
|
|
220
|
-
|
|
221
|
-
# Delete folder
|
|
222
|
-
secrets_manager.delete_folder(folder_uid, force: true)
|
|
223
|
-
|
|
224
|
-
# Folder hierarchy features
|
|
225
|
-
fm = secrets_manager.folder_manager
|
|
226
|
-
|
|
227
|
-
# Build folder tree structure
|
|
228
|
-
tree = fm.build_folder_tree
|
|
229
|
-
|
|
230
|
-
# Get folder path from root
|
|
231
|
-
path = secrets_manager.get_folder_path(folder_uid) # "Parent/Child/Grandchild"
|
|
232
|
-
|
|
233
|
-
# Find folder by name
|
|
234
|
-
folder = secrets_manager.find_folder_by_name("Finance")
|
|
235
|
-
folder = secrets_manager.find_folder_by_name("Finance", parent_uid: "parent_uid")
|
|
236
|
-
|
|
237
|
-
# Get folder relationships
|
|
238
|
-
ancestors = fm.get_ancestors(folder_uid) # [parent, grandparent, ...]
|
|
239
|
-
descendants = fm.get_descendants(folder_uid) # [children, grandchildren, ...]
|
|
240
|
-
|
|
241
|
-
# Print folder tree to console
|
|
242
|
-
fm.print_tree
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
## Error Handling
|
|
246
|
-
|
|
247
|
-
```ruby
|
|
248
|
-
begin
|
|
249
|
-
records = secrets_manager.get_secrets
|
|
250
|
-
rescue KeeperSecretsManager::AuthenticationError => e
|
|
251
|
-
puts "Authentication failed: #{e.message}"
|
|
252
|
-
rescue KeeperSecretsManager::NetworkError => e
|
|
253
|
-
puts "Network error: #{e.message}"
|
|
254
|
-
rescue KeeperSecretsManager::Error => e
|
|
255
|
-
puts "General error: #{e.message}"
|
|
256
|
-
end
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
## Configuration
|
|
260
|
-
|
|
261
|
-
The SDK can be configured through various options:
|
|
262
|
-
|
|
263
|
-
```ruby
|
|
264
|
-
secrets_manager = KeeperSecretsManager.new(
|
|
265
|
-
config: storage,
|
|
266
|
-
hostname: 'keepersecurity.eu', # EU datacenter
|
|
267
|
-
verify_ssl_certs: true, # Verify SSL certificates
|
|
268
|
-
logger: Logger.new(STDOUT), # Custom logger
|
|
269
|
-
log_level: Logger::DEBUG # Log level
|
|
94
|
+
# Method 2: Authenticated proxy
|
|
95
|
+
secrets_manager = KeeperSecretsManager.from_file(
|
|
96
|
+
'keeper_config.json',
|
|
97
|
+
proxy_url: 'http://username:password@proxy.company.com:8080'
|
|
270
98
|
)
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
## Development
|
|
274
99
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
## Testing
|
|
280
|
-
|
|
281
|
-
```bash
|
|
282
|
-
# Run all tests
|
|
283
|
-
bundle exec rake spec
|
|
284
|
-
|
|
285
|
-
# Run unit tests only
|
|
286
|
-
bundle exec rake unit
|
|
287
|
-
|
|
288
|
-
# Run with coverage
|
|
289
|
-
bundle exec rake coverage
|
|
290
|
-
|
|
291
|
-
# Run linter
|
|
292
|
-
bundle exec rubocop
|
|
100
|
+
# Method 3: HTTPS_PROXY environment variable (recommended)
|
|
101
|
+
# export HTTPS_PROXY=http://proxy.company.com:8080
|
|
102
|
+
secrets_manager = KeeperSecretsManager.from_file('keeper_config.json')
|
|
103
|
+
# Proxy auto-detected from environment
|
|
293
104
|
```
|
|
294
105
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/Keeper-Security/secrets-manager.
|
|
298
|
-
|
|
299
|
-
## License
|
|
300
|
-
|
|
301
|
-
The gem is available as open source under the terms of the MIT License.
|
|
106
|
+
See `examples/ruby/12_proxy_usage.rb` for complete examples.
|
|
302
107
|
|
|
303
|
-
|
|
108
|
+
# Documentation
|
|
304
109
|
|
|
305
|
-
For
|
|
110
|
+
For complete documentation, see: https://docs.keeper.io/secrets-manager/secrets-manager/developer-sdk-library/ruby-sdk
|
data/bin/console
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Interactive console for Keeper Secrets Manager Ruby SDK development
|
|
5
|
+
|
|
6
|
+
require 'bundler/setup'
|
|
7
|
+
require 'pry'
|
|
8
|
+
|
|
9
|
+
# Load the SDK from local source
|
|
10
|
+
require_relative '../lib/keeper_secrets_manager'
|
|
11
|
+
|
|
12
|
+
# Load environment variables if .env exists
|
|
13
|
+
begin
|
|
14
|
+
require 'dotenv/load'
|
|
15
|
+
puts "✓ Loaded environment variables from .env"
|
|
16
|
+
rescue LoadError
|
|
17
|
+
# dotenv not available, skip
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Helper message
|
|
21
|
+
puts "Keeper Secrets Manager Ruby SDK Console"
|
|
22
|
+
puts "=" * 60
|
|
23
|
+
puts "SDK loaded from: #{File.expand_path('../lib/keeper_secrets_manager.rb', __dir__)}"
|
|
24
|
+
puts "Version: #{KeeperSecretsManager::VERSION}"
|
|
25
|
+
puts
|
|
26
|
+
|
|
27
|
+
if ENV['KSM_CONFIG']
|
|
28
|
+
puts "Quick start:"
|
|
29
|
+
puts " storage = KeeperSecretsManager::Storage::InMemoryStorage.new(ENV['KSM_CONFIG'])"
|
|
30
|
+
puts " sm = KeeperSecretsManager.new(config: storage)"
|
|
31
|
+
puts " secrets = sm.get_secrets"
|
|
32
|
+
puts
|
|
33
|
+
puts "With caching:"
|
|
34
|
+
puts " sm = KeeperSecretsManager.new(config: storage, custom_post_function: KeeperSecretsManager::CachingPostFunction)"
|
|
35
|
+
puts
|
|
36
|
+
else
|
|
37
|
+
puts "No KSM_CONFIG found in environment"
|
|
38
|
+
puts "Set it in .env or export it before running"
|
|
39
|
+
puts
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
puts "Type 'ls KeeperSecretsManager' to explore the SDK"
|
|
43
|
+
puts "=" * 60
|
|
44
|
+
puts
|
|
45
|
+
|
|
46
|
+
# Start Pry REPL
|
|
47
|
+
Pry.start
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require_relative 'lib/keeper_secrets_manager/version'
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |spec|
|
|
4
|
+
spec.name = 'keeper_secrets_manager'
|
|
5
|
+
spec.version = KeeperSecretsManager::VERSION
|
|
6
|
+
spec.authors = ['Keeper Security']
|
|
7
|
+
spec.email = ['sm@keepersecurity.com']
|
|
8
|
+
|
|
9
|
+
spec.summary = 'Keeper Secrets Manager SDK for Ruby'
|
|
10
|
+
spec.description = 'Ruby SDK for Keeper Secrets Manager - A zero-knowledge platform for managing and protecting infrastructure secrets'
|
|
11
|
+
spec.homepage = 'https://github.com/Keeper-Security/secrets-manager'
|
|
12
|
+
spec.license = 'MIT'
|
|
13
|
+
spec.required_ruby_version = '>= 3.1.0'
|
|
14
|
+
|
|
15
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
16
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
17
|
+
spec.metadata['source_code_uri'] = 'https://github.com/Keeper-Security/secrets-manager'
|
|
18
|
+
spec.metadata['changelog_uri'] = 'https://github.com/Keeper-Security/secrets-manager/blob/master/CHANGELOG.md'
|
|
19
|
+
|
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
23
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
spec.bindir = 'exe'
|
|
27
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
28
|
+
spec.require_paths = ['lib']
|
|
29
|
+
|
|
30
|
+
# base64 and logger were default gems through Ruby 3.x; Ruby 4.0 unbundled them.
|
|
31
|
+
# Both are maintained by the Ruby core team — declaring them makes the implicit explicit.
|
|
32
|
+
spec.add_runtime_dependency 'base64'
|
|
33
|
+
spec.add_runtime_dependency 'logger'
|
|
34
|
+
|
|
35
|
+
# All development dependencies are in Gemfile
|
|
36
|
+
end
|