Class: Gem::CredentialStore::LinuxBackend
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | lib/rubygems/credential_store/native/linux.rb |
Overview
Stores credentials in the Secret Service API (GNOME Keyring, KWallet,
...) via the secret-tool command line tool from libsecret.
Constant Summary
-
ACCOUNT_ATTRIBUTE =
# File 'lib/rubygems/credential_store/native/linux.rb', line 13
secret-tool prints an item's attributes to stderr, one per line.
/^attribute\.account = (.*)$/
Class Attribute Summary
- .available? ⇒ Boolean readonly
Class Method Summary
- .delete(service, account)
- .delete_all(service)
- .get(service, account)
-
.list(service)
secret-tool writes attributes to stderr and secrets to stdout, so accounts are read from stderr.
-
.reset!
Clears the memoized #available? result.
- .set(service, account, secret)
-
.cleared?(service, account = nil) ⇒ Boolean
private
libsecret clears only unlocked items and reports no error for the ones it skipped, so a locked keyring answers a clear with success while keeping every secret.
Class Attribute Details
.available? ⇒ Boolean (readonly)
[ GitHub ]
Class Method Details
.cleared?(service, account = nil) ⇒ Boolean (private)
libsecret clears only unlocked items and reports no error for the ones it skipped, so a locked keyring answers a clear with success while keeping every secret. search exits zero either way, so its output is the answer.
# File 'lib/rubygems/credential_store/native/linux.rb', line 87
def self.cleared?(service, account = nil) _out, err, status = Open3.capture3( "secret-tool", "search", "--all", "service", service ) return false unless status.success? remaining = err.scan(ACCOUNT_ATTRIBUTE).flatten account ? !remaining.include?(account) : remaining.empty? end
.delete(service, account)
[ GitHub ]# File 'lib/rubygems/credential_store/native/linux.rb', line 65
def self.delete(service, account) _out, err, status = Open3.capture3( "secret-tool", "clear", "service", service, "account", account ) return cleared?(service, account) if status.success? # secret-tool clear exits 1 with no stderr when nothing matched. status.exitstatus == 1 && err.to_s.strip.empty? end
.delete_all(service)
[ GitHub ]# File 'lib/rubygems/credential_store/native/linux.rb', line 75
def self.delete_all(service) _out, err, status = Open3.capture3( "secret-tool", "clear", "service", service ) return cleared?(service) if status.success? status.exitstatus == 1 && err.to_s.strip.empty? end
.get(service, account)
[ GitHub ]# File 'lib/rubygems/credential_store/native/linux.rb', line 29
def self.get(service, account) out, err, status = Open3.capture3( "secret-tool", "lookup", "service", service, "account", account ) # secret-tool exits 1 with nothing on stderr when the entry is simply # absent. Anything else is a real failure. unless status.success? return nil if status.exitstatus == 1 && err.to_s.strip.empty? raise "secret-tool exited with #{status.exitstatus}: #{err.strip}" end secret = out.chomp secret.empty? ? nil : secret end
.list(service)
secret-tool writes attributes to stderr and secrets to stdout, so accounts are read from stderr. Discarding stdout also keeps a secret containing a newline from being mistaken for an attribute line.
# File 'lib/rubygems/credential_store/native/linux.rb', line 56
def self.list(service) _out, err, status = Open3.capture3( "secret-tool", "search", "--all", "service", service ) return [] unless status.success? err.scan(ACCOUNT_ATTRIBUTE).flatten.uniq end
.reset!
Clears the memoized Gem::CredentialStore#available? result. Intended for tests only.
# File 'lib/rubygems/credential_store/native/linux.rb', line 25
def self.reset! remove_instance_variable(:@available) if defined?(@available) end
.set(service, account, secret)
[ GitHub ]# File 'lib/rubygems/credential_store/native/linux.rb', line 45
def self.set(service, account, secret) _out, status = Open3.capture2( "secret-tool", "store", "--label=RubyGems", "service", service, "account", account, stdin_data: secret ) status.success? end