rma-payment-gateway 1.0.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.
data/docs/SECURITY.md ADDED
@@ -0,0 +1,506 @@
1
+ # Security Guide
2
+
3
+ This document outlines security best practices for integrating the RMA Payment Gateway into your application.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Overview](#overview)
8
+ - [Configuration Security](#configuration-security)
9
+ - [Data Protection](#data-protection)
10
+ - [Network Security](#network-security)
11
+ - [Application Security](#application-security)
12
+ - [Compliance](#compliance)
13
+ - [Incident Response](#incident-response)
14
+
15
+ ## Overview
16
+
17
+ Payment processing requires strict security measures to protect sensitive customer data and prevent fraud. This guide covers essential security practices for the RMA Payment Gateway integration.
18
+
19
+ ## Configuration Security
20
+
21
+ ### 1. RSA Private Key Management
22
+
23
+ **DO:**
24
+ - ✅ Store RSA private keys outside the application directory
25
+ - ✅ Use file permissions to restrict access (chmod 600)
26
+ - ✅ Use environment variables for key paths
27
+ - ✅ Rotate keys periodically
28
+ - ✅ Keep backup keys in secure storage
29
+
30
+ **DON'T:**
31
+ - ❌ Commit private keys to version control
32
+ - ❌ Store keys in the application directory
33
+ - ❌ Share keys via email or chat
34
+ - ❌ Use the same key across environments
35
+
36
+ **Example:**
37
+
38
+ ```bash
39
+ # Set proper permissions
40
+ chmod 600 /secure/path/rma_private_key.pem
41
+ chown app_user:app_group /secure/path/rma_private_key.pem
42
+
43
+ # Verify permissions
44
+ ls -la /secure/path/rma_private_key.pem
45
+ # Should show: -rw------- 1 app_user app_group
46
+ ```
47
+
48
+ ### 2. Environment Variables
49
+
50
+ **DO:**
51
+ - ✅ Use `.env` files for local development
52
+ - ✅ Use secure secret management in production (e.g., AWS Secrets Manager, HashiCorp Vault)
53
+ - ✅ Add `.env` to `.gitignore`
54
+ - ✅ Use different credentials for each environment
55
+
56
+ **Example `.gitignore`:**
57
+
58
+ ```
59
+ .env
60
+ .env.local
61
+ .env.*.local
62
+ config/rma_private_key.pem
63
+ *.pem
64
+ ```
65
+
66
+ **Example Production Setup (Rails):**
67
+
68
+ ```ruby
69
+ # config/initializers/rma_payment_gateway.rb
70
+ Rma::Payment::Gateway.configure do |config|
71
+ # Use Rails credentials or environment variables
72
+ config.base_url = Rails.application.credentials.dig(:rma, :base_url) || ENV['RMA_BASE_URL']
73
+ config.rsa_key_path = Rails.application.credentials.dig(:rma, :key_path) || ENV['RMA_RSA_KEY_PATH']
74
+ config.beneficiary_id = Rails.application.credentials.dig(:rma, :beneficiary_id) || ENV['RMA_BENEFICIARY_ID']
75
+ config.payment_description = ENV['RMA_PAYMENT_DESCRIPTION']
76
+ end
77
+ ```
78
+
79
+ ### 3. Configuration Validation
80
+
81
+ Always validate configuration on application startup:
82
+
83
+ ```ruby
84
+ # config/initializers/rma_payment_gateway.rb
85
+ config = Rma::Payment::Gateway.configuration
86
+
87
+ unless config.valid?
88
+ raise "RMA Payment Gateway configuration is invalid: #{config.missing_fields.join(', ')}"
89
+ end
90
+
91
+ # Verify RSA key file exists and is readable
92
+ unless File.exist?(config.rsa_key_path)
93
+ raise "RMA RSA key file not found: #{config.rsa_key_path}"
94
+ end
95
+
96
+ unless File.readable?(config.rsa_key_path)
97
+ raise "RMA RSA key file is not readable: #{config.rsa_key_path}"
98
+ end
99
+ ```
100
+
101
+ ## Data Protection
102
+
103
+ ### 1. Sensitive Data Handling
104
+
105
+ **Never log or store:**
106
+ - OTP codes
107
+ - Full account numbers (mask if needed)
108
+ - RSA private keys
109
+ - Customer passwords
110
+
111
+ **Example - Masked Logging:**
112
+
113
+ ```ruby
114
+ def log_payment_attempt(transaction_id, account_number)
115
+ Rails.logger.info({
116
+ event: 'payment_attempt',
117
+ transaction_id: transaction_id,
118
+ account_number: Rma::Payment::Gateway::Utils.mask_sensitive(account_number, 2),
119
+ timestamp: Time.current
120
+ }.to_json)
121
+ end
122
+ ```
123
+
124
+ ### 2. Database Security
125
+
126
+ **Encrypt sensitive data at rest:**
127
+
128
+ ```ruby
129
+ # Using Rails encrypted attributes
130
+ class Payment < ApplicationRecord
131
+ encrypts :customer_account_number
132
+ encrypts :rma_transaction_id
133
+
134
+ # Don't store OTP - it's single-use
135
+ end
136
+ ```
137
+
138
+ ### 3. Data Retention
139
+
140
+ **Implement data retention policies:**
141
+
142
+ ```ruby
143
+ class Payment < ApplicationRecord
144
+ # Delete old payment records after retention period
145
+ scope :expired, -> { where('created_at < ?', 7.years.ago) }
146
+
147
+ def self.cleanup_old_records
148
+ expired.find_each do |payment|
149
+ payment.anonymize! # Remove PII
150
+ payment.destroy if payment.can_be_deleted?
151
+ end
152
+ end
153
+ end
154
+ ```
155
+
156
+ ### 4. PII Protection
157
+
158
+ **Minimize PII collection:**
159
+
160
+ ```ruby
161
+ # Only collect what's necessary
162
+ def create_payment(order)
163
+ client.authorization.call(
164
+ order.number,
165
+ order.total,
166
+ order.customer_email # Only email, not full customer details
167
+ )
168
+ end
169
+ ```
170
+
171
+ ## Network Security
172
+
173
+ ### 1. HTTPS Only
174
+
175
+ **Always use HTTPS:**
176
+
177
+ ```ruby
178
+ # Verify base URL uses HTTPS
179
+ config = Rma::Payment::Gateway.configuration
180
+
181
+ unless config.base_url.start_with?('https://')
182
+ raise "RMA base URL must use HTTPS: #{config.base_url}"
183
+ end
184
+ ```
185
+
186
+ ### 2. SSL/TLS Configuration
187
+
188
+ **Use strong SSL/TLS settings:**
189
+
190
+ ```ruby
191
+ # In production, verify SSL certificates
192
+ Rma::Payment::Gateway.configure do |config|
193
+ config.base_url = ENV['RMA_BASE_URL']
194
+ # Faraday will verify SSL by default
195
+ end
196
+ ```
197
+
198
+ ### 3. Network Timeouts
199
+
200
+ **Set appropriate timeouts to prevent hanging:**
201
+
202
+ ```ruby
203
+ Rma::Payment::Gateway.configure do |config|
204
+ config.timeout = 30 # Request timeout
205
+ config.open_timeout = 10 # Connection timeout
206
+ end
207
+ ```
208
+
209
+ ### 4. IP Whitelisting
210
+
211
+ **Restrict API access by IP (if supported):**
212
+
213
+ ```ruby
214
+ # Configure firewall rules to only allow outbound connections
215
+ # to RMA Payment Gateway IP addresses
216
+ ```
217
+
218
+ ## Application Security
219
+
220
+ ### 1. Input Validation
221
+
222
+ **Always validate user inputs:**
223
+
224
+ ```ruby
225
+ class PaymentController < ApplicationController
226
+ def create
227
+ # Validate before processing
228
+ validate_payment_params!
229
+
230
+ # Process payment
231
+ process_payment
232
+ end
233
+
234
+ private
235
+
236
+ def validate_payment_params!
237
+ unless Rma::Payment::Gateway::Utils.valid_amount?(params[:amount])
238
+ raise ActionController::BadRequest, "Invalid amount"
239
+ end
240
+
241
+ unless Rma::Payment::Gateway::Utils.valid_email?(params[:email])
242
+ raise ActionController::BadRequest, "Invalid email"
243
+ end
244
+
245
+ unless Rma::Payment::Gateway::Utils.valid_bank_code?(params[:bank_id])
246
+ raise ActionController::BadRequest, "Invalid bank code"
247
+ end
248
+ end
249
+ end
250
+ ```
251
+
252
+ ### 2. CSRF Protection
253
+
254
+ **Enable CSRF protection:**
255
+
256
+ ```ruby
257
+ # Rails - enabled by default
258
+ class ApplicationController < ActionController::Base
259
+ protect_from_forgery with: :exception
260
+ end
261
+ ```
262
+
263
+ ### 3. Rate Limiting
264
+
265
+ **Implement rate limiting:**
266
+
267
+ ```ruby
268
+ # Using Rack::Attack
269
+ class Rack::Attack
270
+ # Limit payment attempts per IP
271
+ throttle('payments/ip', limit: 5, period: 1.hour) do |req|
272
+ req.ip if req.path.start_with?('/payments') && req.post?
273
+ end
274
+
275
+ # Limit payment attempts per user
276
+ throttle('payments/user', limit: 10, period: 1.hour) do |req|
277
+ req.session[:user_id] if req.path.start_with?('/payments') && req.post?
278
+ end
279
+ end
280
+ ```
281
+
282
+ ### 4. Session Security
283
+
284
+ **Secure session management:**
285
+
286
+ ```ruby
287
+ # Rails session configuration
288
+ Rails.application.config.session_store :cookie_store,
289
+ key: '_app_session',
290
+ secure: Rails.env.production?, # HTTPS only in production
291
+ httponly: true, # Not accessible via JavaScript
292
+ same_site: :lax # CSRF protection
293
+ ```
294
+
295
+ ### 5. Authorization
296
+
297
+ **Verify user authorization:**
298
+
299
+ ```ruby
300
+ class PaymentsController < ApplicationController
301
+ before_action :authenticate_user!
302
+ before_action :authorize_payment!
303
+
304
+ def complete
305
+ # User can only complete their own payments
306
+ @payment = current_user.payments.find(params[:id])
307
+ # Process payment
308
+ end
309
+
310
+ private
311
+
312
+ def authorize_payment!
313
+ unless current_user.can_make_payment?
314
+ redirect_to root_path, alert: 'Not authorized'
315
+ end
316
+ end
317
+ end
318
+ ```
319
+
320
+ ### 6. Idempotency
321
+
322
+ **Prevent duplicate payments:**
323
+
324
+ ```ruby
325
+ class Payment < ApplicationRecord
326
+ validates :order_number, uniqueness: { scope: :status }
327
+
328
+ def self.create_or_find_by_order(order_number)
329
+ # Atomic operation to prevent race conditions
330
+ transaction do
331
+ find_or_create_by!(order_number: order_number) do |payment|
332
+ payment.status = 'pending'
333
+ end
334
+ end
335
+ end
336
+ end
337
+ ```
338
+
339
+ ## Compliance
340
+
341
+ ### 1. PCI DSS Compliance
342
+
343
+ **Key requirements:**
344
+ - Don't store card data (RMA handles this)
345
+ - Use HTTPS for all communications
346
+ - Implement access controls
347
+ - Maintain audit logs
348
+ - Regular security testing
349
+
350
+ ### 2. Data Privacy Regulations
351
+
352
+ **GDPR/Privacy compliance:**
353
+
354
+ ```ruby
355
+ class Customer < ApplicationRecord
356
+ # Right to be forgotten
357
+ def anonymize!
358
+ update!(
359
+ email: "deleted_#{id}@example.com",
360
+ name: "Deleted User",
361
+ phone: nil
362
+ )
363
+ end
364
+
365
+ # Data export
366
+ def export_data
367
+ {
368
+ personal_info: attributes.slice('name', 'email', 'phone'),
369
+ payments: payments.map(&:export_data)
370
+ }
371
+ end
372
+ end
373
+ ```
374
+
375
+ ### 3. Audit Logging
376
+
377
+ **Maintain comprehensive audit logs:**
378
+
379
+ ```ruby
380
+ class AuditLog < ApplicationRecord
381
+ def self.log_payment_event(event_type, user, details)
382
+ create!(
383
+ event_type: event_type,
384
+ user_id: user&.id,
385
+ ip_address: details[:ip],
386
+ user_agent: details[:user_agent],
387
+ details: details.to_json,
388
+ created_at: Time.current
389
+ )
390
+ end
391
+ end
392
+
393
+ # Usage
394
+ AuditLog.log_payment_event('payment_authorized', current_user, {
395
+ transaction_id: response["bfs_bfsTxnId"],
396
+ amount: amount,
397
+ ip: request.remote_ip,
398
+ user_agent: request.user_agent
399
+ })
400
+ ```
401
+
402
+ ## Incident Response
403
+
404
+ ### 1. Security Monitoring
405
+
406
+ **Monitor for suspicious activity:**
407
+
408
+ ```ruby
409
+ class SecurityMonitor
410
+ def self.check_suspicious_payment(payment)
411
+ alerts = []
412
+
413
+ # Multiple failed attempts
414
+ if payment.user.failed_payments.last_hour.count > 5
415
+ alerts << "Multiple failed payments"
416
+ end
417
+
418
+ # Unusual amount
419
+ if payment.amount > payment.user.average_payment_amount * 10
420
+ alerts << "Unusually large payment"
421
+ end
422
+
423
+ # Different location
424
+ if payment.ip_country != payment.user.usual_country
425
+ alerts << "Payment from unusual location"
426
+ end
427
+
428
+ notify_security_team(alerts) if alerts.any?
429
+ end
430
+ end
431
+ ```
432
+
433
+ ### 2. Incident Response Plan
434
+
435
+ **Steps to take if security incident occurs:**
436
+
437
+ 1. **Immediate Actions:**
438
+ - Disable affected accounts
439
+ - Revoke compromised credentials
440
+ - Block suspicious IP addresses
441
+
442
+ 2. **Investigation:**
443
+ - Review audit logs
444
+ - Identify scope of breach
445
+ - Document findings
446
+
447
+ 3. **Remediation:**
448
+ - Patch vulnerabilities
449
+ - Reset credentials
450
+ - Notify affected users
451
+
452
+ 4. **Prevention:**
453
+ - Update security measures
454
+ - Conduct security training
455
+ - Review and update policies
456
+
457
+ ### 3. Emergency Contacts
458
+
459
+ **Maintain emergency contact list:**
460
+
461
+ ```ruby
462
+ # config/security_contacts.yml
463
+ security_team:
464
+ primary: security@example.com
465
+ phone: +975-XXXXXXXX
466
+
467
+ rma_support:
468
+ email: support@rma.org.bt
469
+ phone: +975-XXXXXXXX
470
+
471
+ incident_response:
472
+ email: incidents@example.com
473
+ escalation: cto@example.com
474
+ ```
475
+
476
+ ## Security Checklist
477
+
478
+ Before going to production:
479
+
480
+ - [ ] RSA private keys stored securely
481
+ - [ ] Environment variables configured
482
+ - [ ] HTTPS enforced
483
+ - [ ] Input validation implemented
484
+ - [ ] CSRF protection enabled
485
+ - [ ] Rate limiting configured
486
+ - [ ] Session security configured
487
+ - [ ] Audit logging implemented
488
+ - [ ] Error handling doesn't leak sensitive info
489
+ - [ ] Security monitoring in place
490
+ - [ ] Incident response plan documented
491
+ - [ ] Team trained on security practices
492
+ - [ ] Regular security audits scheduled
493
+ - [ ] Backup and recovery procedures tested
494
+
495
+ ## Resources
496
+
497
+ - [OWASP Top 10](https://owasp.org/www-project-top-ten/)
498
+ - [PCI DSS Requirements](https://www.pcisecuritystandards.org/)
499
+ - [Rails Security Guide](https://guides.rubyonrails.org/security.html)
500
+
501
+ ## Support
502
+
503
+ For security concerns:
504
+ - Email: tashii.dendupp@gmail.com
505
+ - GitHub Security Advisories: https://github.com/dcplbt/rma-payment-gateway/security
506
+