Class: Spiffe::Workload::Client
- Inherits:
-
Object
- Object
- Spiffe::Workload::Client
- Defined in:
- lib/spiffe/workload/client.rb
Overview
Client for SPIFFE Workload API Connects to SPIRE Agent via Unix domain socket and fetches SVIDs
Constant Summary collapse
- DEFAULT_SOCKET_PATH =
'/run/spire/sockets/agent.sock'- DEFAULT_TIMEOUT =
seconds
5
Instance Attribute Summary collapse
-
#socket_path ⇒ Object
readonly
Returns the value of attribute socket_path.
Instance Method Summary collapse
-
#current_x509_svid ⇒ X509SVIDWrapper?
Get the current X.509 SVID without blocking.
-
#initialize(socket_path: nil, timeout: DEFAULT_TIMEOUT) ⇒ Client
constructor
A new instance of Client.
-
#jwt_bundles ⇒ Hash<String, String>
Fetch JWT bundles.
-
#jwt_svid(audience:, spiffe_id: nil) ⇒ JWTSVIDWrapper
Fetch JWT SVID for the given audience.
-
#on_x509_svid_update {|X509SVID| ... } ⇒ Object
Register a callback to be called when X.509 SVID is updated.
-
#shutdown ⇒ Object
Shutdown the client and stop all background threads.
-
#tls_context ⇒ OpenSSL::SSL::SSLContext
Create an OpenSSL context configured with the current SVID.
-
#x509_bundles ⇒ Hash<String, OpenSSL::X509::Store>
Fetch X.509 trust bundles.
-
#x509_svid ⇒ X509SVIDWrapper
Fetch X.509 SVID (blocking call, returns first response).
-
#x509_svids ⇒ Array<X509SVIDWrapper>
Fetch all X.509 SVIDs.
Constructor Details
#initialize(socket_path: nil, timeout: DEFAULT_TIMEOUT) ⇒ Client
Returns a new instance of Client.
22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/spiffe/workload/client.rb', line 22 def initialize(socket_path: nil, timeout: DEFAULT_TIMEOUT) @socket_path = socket_path || ENV['SPIFFE_ENDPOINT_SOCKET']&.sub('unix://', '') || DEFAULT_SOCKET_PATH @timeout = timeout @mutex = Mutex.new @x509_svid_cache = nil @x509_bundles_cache = nil @jwt_bundles_cache = nil @rotation_thread = nil @shutdown = false validate_socket! end |
Instance Attribute Details
#socket_path ⇒ Object (readonly)
Returns the value of attribute socket_path.
18 19 20 |
# File 'lib/spiffe/workload/client.rb', line 18 def socket_path @socket_path end |
Instance Method Details
#current_x509_svid ⇒ X509SVIDWrapper?
Get the current X.509 SVID without blocking
49 50 51 |
# File 'lib/spiffe/workload/client.rb', line 49 def current_x509_svid @mutex.synchronize { @x509_svid_cache } end |
#jwt_bundles ⇒ Hash<String, String>
Fetch JWT bundles
99 100 101 102 103 104 105 |
# File 'lib/spiffe/workload/client.rb', line 99 def jwt_bundles ensure_jwt_bundles_stream_started @mutex.synchronize do @jwt_bundles_cache || {} end end |
#jwt_svid(audience:, spiffe_id: nil) ⇒ JWTSVIDWrapper
Fetch JWT SVID for the given audience
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/spiffe/workload/client.rb', line 68 def jwt_svid(audience:, spiffe_id: nil) audiences = audience.is_a?(Array) ? audience : [audience] request = Spiffe::Workload::JWTSVIDRequest.new( audience: audiences, spiffe_id: spiffe_id || '' ) # SPIRE requires this security header for workload API calls = { 'workload.spiffe.io' => 'true' } response = stub.fetch_jwtsvid(request, metadata: ) raise Spiffe::Error, 'No JWT SVID returned' if response.svids.empty? JWTSVIDWrapper.from_proto(response.svids.first) rescue GRPC::BadStatus => e raise Spiffe::Error, "Failed to fetch JWT SVID: #{e.message}" end |
#on_x509_svid_update {|X509SVID| ... } ⇒ Object
Register a callback to be called when X.509 SVID is updated
123 124 125 126 127 128 |
# File 'lib/spiffe/workload/client.rb', line 123 def on_x509_svid_update(&block) @mutex.synchronize do @x509_update_callbacks ||= [] @x509_update_callbacks << block end end |
#shutdown ⇒ Object
Shutdown the client and stop all background threads
131 132 133 134 135 136 137 |
# File 'lib/spiffe/workload/client.rb', line 131 def shutdown @shutdown = true @rotation_thread&.kill @x509_stream_thread&.kill @x509_bundles_stream_thread&.kill @jwt_bundles_stream_thread&.kill end |
#tls_context ⇒ OpenSSL::SSL::SSLContext
Create an OpenSSL context configured with the current SVID
109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/spiffe/workload/client.rb', line 109 def tls_context svid = x509_svid context = OpenSSL::SSL::SSLContext.new context.cert = svid.leaf_certificate context.key = svid.private_key context.extra_chain_cert = svid.cert_chain[1..-1] if svid.cert_chain.length > 1 context.cert_store = svid.trust_bundle context.verify_mode = OpenSSL::SSL::VERIFY_PEER context end |
#x509_bundles ⇒ Hash<String, OpenSSL::X509::Store>
Fetch X.509 trust bundles
89 90 91 92 93 94 95 |
# File 'lib/spiffe/workload/client.rb', line 89 def x509_bundles ensure_x509_bundles_stream_started @mutex.synchronize do @x509_bundles_cache || {} end end |
#x509_svid ⇒ X509SVIDWrapper
Fetch X.509 SVID (blocking call, returns first response)
38 39 40 41 42 43 44 45 |
# File 'lib/spiffe/workload/client.rb', line 38 def x509_svid ensure_x509_svid_stream_started @mutex.synchronize do raise Spiffe::Error, 'No X.509 SVID available' unless @x509_svid_cache @x509_svid_cache end end |
#x509_svids ⇒ Array<X509SVIDWrapper>
Fetch all X.509 SVIDs
55 56 57 58 59 60 61 |
# File 'lib/spiffe/workload/client.rb', line 55 def x509_svids ensure_x509_svid_stream_started @mutex.synchronize do @x509_svids_cache || [] end end |