A Ruby client library for the SPIFFE Workload API, enabling Ruby applications to obtain and use SPIFFE identities from a SPIRE agent.
This project aims to be part of the SPIFFE ecosystem. See the SPIFFE GitHub for more information about the SPIFFE project.
This gem allows Ruby applications (including Puppet) to:
- Fetch X.509 SVIDs (certificates) from SPIRE for mTLS
- Generate JWT SVIDs for API authentication
- Access trust bundles for verification
- Handle automatic credential rotation
It communicates directly with the SPIRE agent over Unix domain sockets, enabling proper process-based attestation (unlike subprocess-based CLI tools).
gem install spiffe-workloadFor Puppet:
/opt/puppetlabs/puppet/bin/gem install spiffe-workload- SPIRE Agent running with workload API socket accessible
- Workload entry registered for your application
# Verify SPIRE agent is running
ls -la /run/spire/sockets/agent.sock
# Register your application
spire-server entry create \
-parentID spiffe://example.org/agent/myhost \
-spiffeID spiffe://example.org/myapp \
-selector unix:uid:$(id -u) \
-selector unix:path:/path/to/your/apprequire 'spiffe'
client = Spiffe.workload_api_client
svid = client.x509_svid
puts "My identity: #{svid.spiffe_id}"
puts "Expires: #{svid.leaf_certificate.not_after}"
client.shutdownrequire 'spiffe'
client = Spiffe.workload_api_client
jwt = client.jwt_svid(audience: 'my-service')
puts "Token: #{jwt.token}"
puts "Expires: #{jwt.expiration}"
client.shutdownrequire 'spiffe'
require 'net/http'
client = Spiffe.workload_api_client
uri = URI('https://api.example.com/data')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.ssl_context = client.tls_context
response = http.get(uri.path)
puts response.body
client.shutdownAuto-detected from:
socket_pathparameterSPIFFE_ENDPOINT_SOCKETenvironment variable- Default:
/run/spire/sockets/agent.sock
client = Spiffe.workload_api_client(
socket_path: '/var/run/spire/agent.sock'
)client = Spiffe.workload_api_client(timeout: 10)# modules/spiffe/lib/puppet/functions/spiffe_jwt.rb
Puppet::Functions.create_function(:spiffe_jwt) do
def spiffe_jwt(audience)
require 'spiffe'
client = Spiffe.workload_api_client
jwt = client.jwt_svid(audience: audience)
jwt.token
ensure
client&.shutdown
end
endUse in Puppet manifest:
$token = Deferred('spiffe_jwt', ['vault.example.com'])
file { '/etc/app/token':
content => $token,
mode => '0600',
}# Puppet agent workload entry
selectors:
- "unix:uid:0" # Root user
- "unix:path:/opt/puppetlabs/puppet/bin/ruby" # Puppet Ruby binaryCreates a new Workload API client.
Parameters:
socket_path(String, optional): Path to SPIRE agent sockettimeout(Integer, optional): Request timeout in seconds
Returns: Spiffe::Workload::Client
Fetches X.509 SVID.
Returns: Spiffe::Workload::X509SVIDWrapper
Properties:
spiffe_id- SPIFFE ID stringleaf_certificate- OpenSSL::X509::Certificatecertificate_chain- Array of certificatesprivate_key- OpenSSL::PKey::RSAttl- Time to live in seconds
Fetches JWT SVID.
Parameters:
audience(String|Array): Target audience(s)spiffe_id(String, optional): Specific SPIFFE ID
Returns: Spiffe::Workload::JWTSVIDWrapper
Properties:
spiffe_id- SPIFFE ID stringtoken- JWT token stringexpiration- Expiration timeclaims- Decoded JWT claims
Creates OpenSSL context with current SVID.
Returns: OpenSSL::SSL::SSLContext
Registers callback for SVID rotation.
Cleanly shuts down the client.
# Check SPIRE agent status
systemctl status spire-agent
# Verify socket location
sudo find /run /var/run -name "agent.sock" 2>/dev/null# Check workload registration
spire-server entry show
# Verify selectors match your process
ps aux | grep your-app# Check socket permissions
ls -la /run/spire/sockets/agent.sock
# Add user to spire group
sudo usermod -a -G spire $USERThis gem implements a client-side library for the SPIFFE Workload API:
┌────────────────┐
│ Ruby App │
│ (this gem) │
└───────┬────────┘
│ gRPC over Unix socket
▼
┌────────────────┐
│ SPIRE Agent │
│ (attests app) │
└───────┬────────┘
│ mTLS
▼
┌────────────────┐
│ SPIRE Server │
└────────────────┘
Key points:
- No subprocess attestation issues (unlike CLI tools)
- Direct process attestation by SPIRE
- Thread-safe credential caching
- Automatic rotation support
We welcome contributions! This project follows the SPIFFE contribution guidelines.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Ensure tests pass (
bundle exec rspec) - Ensure code style passes (
bundle exec rubocop) - Commit with DCO sign-off (
git commit -s -m 'Add amazing feature') - Push to your fork (
git push origin feature/amazing-feature) - Open a Pull Request
All commits must include a Signed-off-by line to certify the Developer Certificate of Origin (DCO):
git commit -s -m "Your commit message"- go-spiffe - Go implementation
- java-spiffe - Java implementation
- py-spiffe - Python implementation
See SPIFFE CONTRIBUTING.md for more details on contributing to SPIFFE projects.
git clone https://github.com/halradaideh/spiffe-rubygem.git
cd spiffe-rubygem
bundle install
gem build spiffe-workload.gemspec
gem install spiffe-workload-*.gembundle exec rspecgem install grpc-tools
rake generate_protosApache License 2.0 - see LICENSE file
- Issues: GitHub Issues
- SPIFFE Slack: slack.spiffe.io
- SPIFFE Docs: spiffe.io/docs
Current version: 1.0.0
See CHANGELOG.md for version history.