SAP ABAP Ortamında Güvenli API Entegrasyonları için RSA SHA256 ile JWT Oluşturma Rehberi
Modern API entegrasyonlarında güvenlik, özellikle bankacılık gibi hassas verilerin paylaşıldığı senaryolarda kritik bir öneme sahiptir. Bu bağlamda, JWT (JSON Web Token) ve RSA SHA256 kombinasyonu, hem kimlik doğrulama hem de veri bütünlüğünü sağlamak için yaygın olarak tercih edilen bir yöntemdir.
Çoğu zaman SAP CPI gibi harici araçlarla yönetilen bu süreç, aslında SAP ABAP içerisinde doğrudan da uygulanabilir. Bu makale, ABAP'ın yerel kütüphane eksikliklerine rağmen, güvenli ve bağımsız bir JWT oluşturma mekanizmasının nasıl kurulacağını adım adım açıklamaktadır.
⁉️ Neden JWT ve RSA SHA256?
JWT (JSON Web Token): Taraflar arasında bilgi alışverişi için güvenli, kompakt ve URL-güvenli bir yöntem sunar. Üç ana bileşenden oluşur:
- 🎩 Başlık (Header): Token'ın tipini (`"typ": "JWT"`) ve imzalama algoritmasını (`"alg": "RS256"`) belirtir.
- 🚚 Yük (Payload): Token ile taşınan talep edilen verileri (claims) içerir; örneğin, `iss` (düzenleyen), `aud` (hedef kitle), `exp` (son kullanma süresi) gibi bilgiler.
- ✍️ İmza (Signature): Başlık ve yükün bütünlüğünü doğrular. İmza, özel anahtar kullanılarak oluşturulur ve ilgili açık anahtarla doğrulanabilir.
Bu güçlü kriptografik algoritma ikilisi, JWT'nin kurcalanamazlığını garanti eder.
RSA: Asimetrik şifreleme prensiplerine dayanır; bir açık anahtar ve bir özel anahtar çifti kullanır.
SHA256: Güvenli bir hashing algoritmasıdır ve imzalanacak veriden benzersiz bir mesaj özeti (hash) oluşturur.
Birlikte kullanıldığında, imza yalnızca ilgili özel anahtarla oluşturulabilir ve açık anahtarla doğrulanabilir, bu da yüksek güvenlik seviyesi sağlar.
⚠️ SAP ABAP Ortamındaki Zorluklar
SAP ABAP, yerleşik bir JWT kütüphanesine sahip olmadığı için bu süreci doğrudan uygulamak bazı zorluklar içerir:
- JWT Kütüphanesi Eksikliği: ABAP'ta JWT token oluşturmak için hazır bir fonksiyon veya sınıf bulunmamaktadır.
- RSA SHA256 İmzalama: Karmaşık kriptografik imzalama işlemlerinin ABAP içinde yönetimi özel yaklaşımlar gerektirir.
- Anahtar Yönetimi: Asimetrik anahtar çiftlerinin güvenli bir şekilde depolanması ve kullanılması için uygun bir mekanizma gereklidir.
🚶♂️🚶♀️ Adım Adım ABAP ile
JWT Oluşturma
Bu zorluklara rağmen, SAP'nin kendi araçları ve temel fonksiyon modülleri kullanılarak ABAP içinde tam teşekküllü bir JWT oluşturmak mümkündür:
- RSA Anahtar Çifti Oluşturma ve STRUST'a Aktarma: Öncelikle, OpenSSL gibi harici bir araç kullanarak bir açık/özel anahtar çifti oluşturulur. Oluşturulan özel anahtar, SAP sisteminde `STRUST` işlem kodu aracılığıyla `JWT_PK` gibi özel bir PSE (Personal Security Environment) dosyasına güvenli bir şekilde aktarılır. Bu adım, anahtar yönetimi sorununu çözer. Gerekli kök, ara ve imzalı sertifikaların da yüklendiğinden emin olunmalıdır.
- JWT Başlık ve Yükünü ABAP'ta Oluşturma:
Başlık (Header): ABAP içinde, aşağıdaki gibi bir JSON dizesi oluşturulur.
{
"alg":"RS256",
"typ":"JWT"
}Yük (Payload): Aşağıdaki gibi gerekli tüm talepleri (claims) içeren bir JSON dizesi oluşturulur. Bu JSON objeleri, ABAP'ın `/UI2/CL_JSON` gibi sınıfları kullanılarak kolayca seri hale getirilebilir.
{
"iss": "Test-Bank",
"jti": "b98f361e",
"aud": "Banking",
"iat": lv_iat,
"exp": lv_exp,
"sub": "Act",
"payload": {
"clientReferenceId": "Test"
}
}- Başlık ve Yükü Base64URL ile Kodlama: Oluşturulan JSON başlık ve yük metinleri, `SCMS_BASE64_ENCODE_STR` fonksiyon modülü kullanılarak önce standart Base64 formatına kodlanır. Ardından, Base64URL uyumluluğu için kodlanmış metinlerdeki `+` karakterleri `-` ile, `/` karakterleri `_` ile değiştirilir ve `=` karakterleri tamamen kaldırılır. Bu iki Base64URL kodlu parça, `.` ile birleştirilerek imza için temel girdi (örneğin, `lv_jwt_input = |{ lv_header_b64 }.{ lv_payload_b64 }|`) oluşturulur.
CALL FUNCTION 'SCMS_BASE64_ENCODE_STR'
EXPORTING
input = lv_header_x
IMPORTING
output = lv_header_b64.
CALL FUNCTION 'SCMS_BASE64_ENCODE_STR'
EXPORTING
input = lv_payload_x
IMPORTING
output = lv_payload_b64.
REPLACE ALL OCCURRENCES OF '+' IN lv_header_b64 WITH '-'.
REPLACE ALL OCCURRENCES OF '/' IN lv_header_b64 WITH '_'.
REPLACE ALL OCCURRENCES OF '=' IN lv_header_b64 WITH ''.
REPLACE ALL OCCURRENCES OF '+' IN lv_payload_b64 WITH '-'.
REPLACE ALL OCCURRENCES OF '/' IN lv_payload_b64 WITH '_'.
REPLACE ALL OCCURRENCES OF '=' IN lv_payload_b64 WITH ''.
lv_jwt_input = |{ lv_header_b64 }.{ lv_payload_b64 }|.- RSA SHA256 ile İmzalama: ABAP'ın yerel bir JWT imzalama metodu olmadığı için, SAP Secure Store and Forward (SSF) çekirdek fonksiyon modülü `SSFW_KRN_SIGN` kullanılır. *Bu fonksiyon modülü, `STRUST`'ta saklanan özel anahtarı (PSE dosyası aracılığıyla) kullanarak, `PKCS1-V1.5` formatında ve `SHA256` hash algoritmasıyla Base64URL kodlu başlık, yük (`lv_jwt_input_x` değişkeni) verisini imzalar. Elde edilen ikili imza verisi (`lv_signature_x`), yine `SCMS_BASE64_ENCODE_STR` ve Base64URL dönüşüm adımları kullanılarak Base64URL formatına getirilir.
*--------------------------------------------------------------------*
* Fetch PSE details
*--------------------------------------------------------------------*
SELECT SINGLE *
FROM ssf_pse_h INTO (ls_ssf_pse)
WHERE filename EQ 'SAPJWT_PK100.pse'. "PSE filename stored in strust
ls_signer-id = ls_ssf_pse-id.
ls_signer-profile = ls_ssf_pse-filename.
APPEND ls_signer TO lt_signer.
*--------------------------------------------------------------------*
* Sign header.payload using RSA SHA256
*--------------------------------------------------------------------*
CALL FUNCTION 'SSFW_KRN_SIGN'
EXPORTING
str_format = 'PKCS1-V1.5'
str_hashalg = 'SHA256'
str_chainfmt = 'X509v3'
ostr_input_data = lv_jwt_input_x
IMPORTING
ostr_signed_data = lv_signature_x
str_signer_name = lv_signer_name
ostr_chain_data = lv_chain_data
crc = lv_crc
TABLES
signer = lt_signer
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
WRITE: / 'Error signing JWT.'.
EXIT.
ENDIF.
*--------------------------------------------------------------------*
* Base64URL encode the signature
*--------------------------------------------------------------------*
CALL FUNCTION 'SCMS_BASE64_ENCODE_STR'
EXPORTING
input = lv_signature_x
IMPORTING
output = lv_signature_b64.
REPLACE ALL OCCURRENCES OF '+' IN lv_signature_b64 WITH '-'.
REPLACE ALL OCCURRENCES OF '/' IN lv_signature_b64 WITH '_'.
REPLACE ALL OCCURRENCES OF '=' IN lv_signature_b64 WITH ''.- Tüm Parçaları Birleştirme: Son adımda, Base64URL kodlu başlık, yük ve imza, `.` karakterleri ile birleştirilerek nihai JWT token oluşturulur:
Base64URL(header) + '.' + Base64URL(payload) + '.' + Base64URL(signature)
Kaynak