L’objectif de ce blog est de vous montrer comment créer/modifier/supprimer des feuilles Google via des programmes d’arrière-plan de SAP.
Comme il s’agit de tâches d’arrière-plan exécutées par le système SAP, ce n’est pas à l’utilisateur de s’authentifier auprès de Google puisqu’il n’y a pas d’action humaine. Nous ne pouvons donc pas choisir les méthodes où l’utilisateur s’authentifie directement pour effectuer l’extraction vers Google, comme ceci par exemple :

Pour utiliser cette méthode, vous devez consulter la documentation ici :
https://www.sap.com/documents/2018/07/56e0dd6d-0f7d-0010-87a3-c30de2ffd8ff.html
Dans le cas d’une connexion de serveur à serveur, nous travaillerons de cette manière :

Développement
Le contenu suivant est inspiré de cet article : https://blogs.sap.com/2019/11/10/connect-from-as-abap-to-google-cloud-platform-app-engine-resource-secured-with-google-identity-aware-proxy/?fbclid=IwAR2H4FpeB_HMuSw6yF9NFTpBFxKmQfTnwJwrEpKbAVxEfQdxh1P_Ae_Tm1U
- Créer un projet Google Cloud Platform :

- Dans le projet, créez un compte de service
Naviguez vers IAM&Admin -> Comptes de service et créez un nouveau compte de service. Saisissez un nom et une description et cliquez sur créer. Sur l’écran suivant, vous devez sélectionner un rôle.

Tapez IAP dans la recherche et sélectionnez le rôle IAP-secured Web App User.

- Et obtenir la clé au format P12
Après la création de votre compte de service, vous pouvez créer votre clé au format P12.


Le téléchargement du fichier P12 devrait commencer sur votre machine locale. Le compte de service permet d’accéder aux ressources du nuage, il faut donc le conserver en toute sécurité. Notez le secret indiqué pour une utilisation ultérieure.
- Importer le certificat du compte de service dans STRUST
Avant de pouvoir écrire du code ABAP et utiliser l’API Google, nous devons nous assurer de deux choses : Premièrement, nous devons importer le fichier P12 dans le système AS ABAP, deuxièmement, nous devons nous assurer que Google est une source de confiance pour la communication.
- Créer une nouvelle application SSF
Nous devons créer une nouvelle entrée dans la table SSFAPPLIC. Allez à la transaction SE16 et ouvrez la table. Créez une nouvelle entrée.

Utilisez JWR_SI pour APPLIC et sélectionnez tout sauf B_INCCERTS, B_DETACHED, B_ASKPWD. En tant que Description, nous définissons la Signature JWT. Cette entrée sera plus tard un nouveau noeud dans la transaction STRUST où nous pourrons importer des certificats. Sauvegardez la nouvelle entrée.
Ouvrez ensuite la transaction SSFA. Appuyez sur « New Entries ». Créez une nouvelle entrée comme indiqué ci-dessous

Nous avons maintenant un nouveau nœud dans la transaction STRUST.
- Importer des certificats dans STRUST
Ouvrez la transaction STRUST et un nouveau noeud devrait être disponible avec le nom « SSF JWT Signature ».

Passez en mode « Edition », faites un clic droit sur le nouveau nœud et sélectionnez « Créer ».
Dans la fenêtre suivante, réglez l’algorithme sur « RSA », la force de la clé sur « 2048 » et l’algorithme de signature sur « SHA256 ».
Confirmez la sélection et le nouveau nœud sera maintenant disponible pour les importations. Dans le menu du haut, sélectionnez « PSE->Import » et sélectionnez le fichier P12 du compte de service que vous avez téléchargé. Il se peut que vous deviez entrer le secret qui a été affiché lors du téléchargement du fichier P12 depuis GCP.
Le fichier P12 est maintenant chargé dans le nœud « File » de STRUST. Ensuite, nous devons le déplacer du nœud « File » vers la bonne application SSF. Dans le menu supérieur, sélectionnez « PSE->Save as ». Dans la fenêtre suivante, sélectionnez « SSF Application » et sélectionnez l’application SSF que nous avons créée dans les étapes précédentes (JWR_SI).
Confirmez la sélection et appuyez sur « Enregistrer ». Nous avons ainsi importé le fichier Service Account P12 dans l’ABAP AS et pouvons l’utiliser pour signer notre JWT pour les demandes adressées à GCP. Avec STRUST, nous disposons d’un endroit sûr pour stocker la clé privée du compte de service et les informations relatives au certificat.

La clé privée et le certificat du compte de service GCP ont été importés dans le système.
- Créer la connexion dans SAP



Ensuite, nous devons faire de Google une source de confiance pour la communication. Cela peut être réalisé en important l’autorité de certification racine de Google dans STRUST.
Téléchargez le certificat Google nécessaire à partir du navigateur (voir avec votre équipe SAP BASIS). Dans la transaction STRUST sur le client SSL Client SSL (Anonyme).

Google est maintenant une source de confiance pour la communication et nous avons créé les connexions HTTP qui seront utilisées pour la communication dans notre code ABAP plus tard.
Note : Vous pouvez tester votre connexion en cliquant sur « Connection test » :

Vous devriez obtenir une erreur 404 (c’est normal).
Si vous avez un message d’erreur SSL, vous avez un problème avec vos certificats Google.
Essayez de voir avec votre équipe SAP BASIS les erreurs dans les journaux ICM (TCODE SMICM).

- Créer les méthodes ABAP qui vont :
Créer et signer un jeton JWT dans SAP
L’envoyer à Google pour l’échanger contre un jeton d’authentification à placer dans l’en-tête de chaque appel API vers les ressources Google (drive, sheets, docs, etc…).
- Créer la classe ZCL_GCP_API_HANDLER

|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 |
CLASS zcl_gcp_api_handler DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF zgcp_response, content TYPE string, cookies TYPE tihttpcki, code type i, reason type string, END OF zgcp_response. CLASS-METHODS create_rs256_signed_jwt IMPORTING iv_jwt_header TYPE zgcp_jwt_header iv_jwt_payload TYPE zgcp_jwt_payload iv_ssf_profilename TYPE string iv_ssf_id TYPE string iv_ssf_result TYPE i RETURNING VALUE(rv_signed_jwt_base64) TYPE string. * RAISING zcx_gcp_api_handler. CLASS-METHODS exchange_jwt_with_oidc_token IMPORTING iv_exchange_destination TYPE c iv_jwt_token TYPE string RETURNING VALUE(rv_oidc_base64) TYPE string. * RAISING zcx_gcp_api_handler. CLASS-METHODS do_api_request IMPORTING iv_destination TYPE c iv_oidc_token TYPE string iv_method TYPE string iv_xcontent TYPE xstring OPTIONAL iv_content TYPE string OPTIONAL iv_sub_uri TYPE string OPTIONAL it_header_fields TYPE tihttpnvp OPTIONAL it_cookies TYPE tihttpcki OPTIONAL iv_content_type TYPE string DEFAULT 'application/json' RETURNING VALUE(rs_response) TYPE zgcp_response. * RAISING zcx_gcp_api_handler. CLASS-METHODS get_iat_unixtime RETURNING VALUE(rv_iat) TYPE int4. PROTECTED SECTION. PRIVATE SECTION. TYPES: ltty_tssfbin TYPE STANDARD TABLE OF ssfbin WITH KEY table_line WITHOUT FURTHER SECONDARY KEYS, BEGIN OF oidc_token_json, access_token TYPE string, END OF oidc_token_json. CLASS-METHODS string_to_binary_tab IMPORTING iv_string TYPE string RETURNING VALUE(rt_bin_tab) TYPE ltty_tssfbin. * RAISING zcx_gcp_api_handler. CLASS-METHODS binary_tab_to_string IMPORTING it_bin_tab TYPE ltty_tssfbin iv_length TYPE ssflen RETURNING VALUE(rv_string) TYPE string. * RAISING zcx_gcp_api_handler. CLASS-METHODS base64_url_encode CHANGING iv_base64 TYPE string. ENDCLASS. CLASS ZCL_GCP_API_HANDLER IMPLEMENTATION. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_GCP_API_HANDLER=>BASE64_URL_ENCODE * +-------------------------------------------------------------------------------------------------+ * | [<-->] IV_BASE64 TYPE STRING * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD base64_url_encode. REPLACE ALL OCCURRENCES OF '=' IN iv_base64 WITH ''. REPLACE ALL OCCURRENCES OF '+' IN iv_base64 WITH '-'. REPLACE ALL OCCURRENCES OF '/' IN iv_base64 WITH '_'. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_GCP_API_HANDLER=>BINARY_TAB_TO_STRING * +-------------------------------------------------------------------------------------------------+ * | [--->] IT_BIN_TAB TYPE LTTY_TSSFBIN * | [--->] IV_LENGTH TYPE SSFLEN * | [<-()] RV_STRING TYPE STRING * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD binary_tab_to_string. CALL FUNCTION 'SCMS_BINARY_TO_STRING' EXPORTING input_length = iv_length encoding = '4110' IMPORTING text_buffer = rv_string TABLES binary_tab = it_bin_tab EXCEPTIONS failed = 1 OTHERS = 2. * IF sy-subrc <> 0. * RAISE EXCEPTION TYPE zcx_gcp_api_handler * EXPORTING * textid = zcx_gcp_api_handler=>zcx_bintostr_conversion_failed. * ENDIF. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Static Public Method ZCL_GCP_API_HANDLER=>CREATE_RS256_SIGNED_JWT * +-------------------------------------------------------------------------------------------------+ * | [--->] IV_JWT_HEADER TYPE ZGCP_JWT_HEADER * | [--->] IV_JWT_PAYLOAD TYPE ZGCP_JWT_PAYLOAD * | [--->] IV_SSF_PROFILENAME TYPE STRING * | [--->] IV_SSF_ID TYPE STRING * | [--->] IV_SSF_RESULT TYPE I * | [<-()] RV_SIGNED_JWT_BASE64 TYPE STRING * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD create_rs256_signed_jwt. DATA lt_input_bin TYPE STANDARD TABLE OF ssfbin. DATA lt_output_bin TYPE STANDARD TABLE OF ssfbin. DATA lv_input_length TYPE ssflen. DATA lv_output_length TYPE ssflen. DATA lv_output_crc TYPE ssfreturn. DATA lt_signer TYPE STANDARD TABLE OF ssfinfo. DATA lv_unix_iat TYPE string. DATA(lv_jwt_payload) = /ui2/cl_json=>serialize( data = iv_jwt_payload pretty_name = /ui2/cl_json=>pretty_mode-low_case ). DATA(lv_jwt_header) = /ui2/cl_json=>serialize( data = iv_jwt_header pretty_name = /ui2/cl_json=>pretty_mode-low_case ). DATA(lv_jwt_header_base64) = cl_http_utility=>encode_base64( unencoded = lv_jwt_header ). DATA(lv_jwt_payload_base64) = cl_http_utility=>encode_base64( unencoded = lv_jwt_payload ). DATA(lv_data_base64) = |{ lv_jwt_header_base64 }.{ lv_jwt_payload_base64 }|. base64_url_encode( CHANGING iv_base64 = lv_data_base64 ). TRY. lt_input_bin = string_to_binary_tab( iv_string = lv_data_base64 ). * CATCH zcx_gcp_api_handler INTO DATA(lo_cx). * RAISE EXCEPTION TYPE zcx_gcp_api_handler * EXPORTING * textid = lo_cx->textid. ENDTRY. lt_signer = VALUE #( ( id = iv_ssf_id profile = iv_ssf_profilename result = iv_ssf_result ) ). lv_input_length = strlen( lv_data_base64 ). CALL FUNCTION 'SSF_KRN_SIGN' EXPORTING str_format = 'PKCS1-V1.5' b_inc_certs = abap_false b_detached = abap_false b_inenc = abap_false ostr_input_data_l = lv_input_length str_hashalg = 'SHA256' IMPORTING ostr_signed_data_l = lv_output_length crc = lv_output_crc " SSF Return code TABLES ostr_input_data = lt_input_bin signer = lt_signer ostr_signed_data = lt_output_bin EXCEPTIONS ssf_krn_error = 1 ssf_krn_noop = 2 ssf_krn_nomemory = 3 ssf_krn_opinv = 4 ssf_krn_nossflib = 5 ssf_krn_signer_list_error = 6 ssf_krn_input_data_error = 7 ssf_krn_invalid_par = 8 ssf_krn_invalid_parlen = 9 ssf_fb_input_parameter_error = 10. * IF sy-subrc <> 0. * RAISE EXCEPTION TYPE zcx_gcp_api_handler * EXPORTING * textid = zcx_gcp_api_handler=>zcx_signature_failed. * ENDIF. TRY. DATA(lv_signature) = binary_tab_to_string( it_bin_tab = lt_output_bin iv_length = lv_output_length ). * CATCH zcx_gcp_api_handler INTO DATA(lo_zcx). * RAISE EXCEPTION TYPE zcx_gcp_api_handler * EXPORTING * textid = lo_zcx->textid. ENDTRY. DATA(lv_jwt) = |{ lv_data_base64 }.{ cl_http_utility=>encode_base64( unencoded = lv_signature ) }|. base64_url_encode( CHANGING iv_base64 = lv_jwt ). rv_signed_jwt_base64 = lv_jwt. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Static Public Method ZCL_GCP_API_HANDLER=>DO_API_REQUEST * +-------------------------------------------------------------------------------------------------+ * | [--->] IV_DESTINATION TYPE C * | [--->] IV_OIDC_TOKEN TYPE STRING * | [--->] IV_METHOD TYPE STRING * | [--->] IV_XCONTENT TYPE XSTRING(optional) * | [--->] IV_CONTENT TYPE STRING(optional) * | [--->] IV_SUB_URI TYPE STRING(optional) * | [--->] IT_HEADER_FIELDS TYPE TIHTTPNVP(optional) * | [--->] IT_COOKIES TYPE TIHTTPCKI(optional) * | [--->] IV_CONTENT_TYPE TYPE STRING (default ='application/json') * | [<-()] RS_RESPONSE TYPE ZGCP_RESPONSE * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD do_api_request. DATA lo_client_api TYPE REF TO if_http_client. DATA lv_response TYPE string. DATA lv_oidc TYPE string. CALL METHOD cl_http_client=>create_by_destination EXPORTING destination = iv_destination IMPORTING client = lo_client_api EXCEPTIONS argument_not_found = 1 destination_not_found = 2 destination_no_authority = 3 plugin_not_active = 4 internal_error = 5 OTHERS = 6. * IF sy-subrc <> 0. * RAISE EXCEPTION TYPE zcx_gcp_api_handler * EXPORTING * textid = zcx_gcp_api_handler=>zcx_api_dest_not_found. * ENDIF. IF lo_client_api IS BOUND. lv_oidc = |Bearer { iv_oidc_token }|. lo_client_api->request->set_header_fields( fields = it_header_fields ). lo_client_api->request->set_content_type( content_type = iv_content_type ). lo_client_api->request->set_method( method = iv_method ). * set jwt token auth lo_client_api->request->set_header_field( name = 'Authorization' ##NO_TEXT value = lv_oidc ). lo_client_api->request->set_header_field( name = 'content-type' value = iv_content_type ). IF iv_sub_uri IS NOT INITIAL. cl_http_utility=>set_request_uri( request = lo_client_api->request uri = iv_sub_uri ). ENDIF. IF iv_xcontent IS NOT INITIAL. lo_client_api->request->set_data( data = iv_xcontent ). ENDIF. IF iv_content IS NOT INITIAL. lo_client_api->request->set_cdata( data = iv_content ). ENDIF. LOOP AT it_cookies ASSIGNING FIELD-SYMBOL(<cookie>). lo_client_api->request->set_cookie( EXPORTING name = <cookie>-name " Name of cookie path = <cookie>-path " Path of Cookie value = <cookie>-value " Cookie value domain = <cookie>-xdomain " Domain Name of Cookie expires = <cookie>-expires " Cookie expiry date secure = <cookie>-secure " 0: unsaved; 1:saved ). ENDLOOP. lo_client_api->send( ). lo_client_api->receive( EXCEPTIONS http_communication_failure = 1 http_invalid_state = 2 http_processing_failed = 3 ). * IF sy-subrc <> 0. * RAISE EXCEPTION TYPE zcx_gcp_api_handler * EXPORTING * textid = zcx_gcp_api_handler=>zcx_api_receive_failed. * ENDIF. rs_response-content = lo_client_api->response->get_data( ). lo_client_api->response->get_status( IMPORTING code = rs_response-code reason = rs_response-reason ). lo_client_api->response->get_cookies( CHANGING cookies = rs_response-cookies ). ENDIF. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Static Public Method ZCL_GCP_API_HANDLER=>EXCHANGE_JWT_WITH_OIDC_TOKEN * +-------------------------------------------------------------------------------------------------+ * | [--->] IV_EXCHANGE_DESTINATION TYPE C * | [--->] IV_JWT_TOKEN TYPE STRING * | [<-()] RV_OIDC_BASE64 TYPE STRING * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD exchange_jwt_with_oidc_token. DATA lo_client TYPE REF TO if_http_client. DATA ls_response TYPE oidc_token_json. CALL METHOD cl_http_client=>create_by_destination EXPORTING destination = iv_exchange_destination IMPORTING client = lo_client EXCEPTIONS argument_not_found = 1 destination_not_found = 2 destination_no_authority = 3 plugin_not_active = 4 internal_error = 5 OTHERS = 6. * IF sy-subrc <> 0. * RAISE EXCEPTION TYPE zcx_gcp_api_handler * EXPORTING * textid = zcx_gcp_api_handler=>zcx_oauth_dest_not_found. * ENDIF. IF lo_client IS BOUND. lo_client->request->set_method( if_http_request=>co_request_method_post ). lo_client->request->set_formfield_encoding( formfield_encoding = if_http_entity=>co_formfield_encoding_encoded ). lo_client->request->set_form_field( EXPORTING name = 'grant_type' value = 'urn:ietf:params:oauth:grant-type:jwt-bearer' ). lo_client->request->set_form_field( EXPORTING name = 'assertion' value = iv_jwt_token ). lo_client->send( ). lo_client->receive( EXCEPTIONS http_communication_failure = 1 http_invalid_state = 2 http_processing_failed = 3 ). * IF sy-subrc <> 0. * RAISE EXCEPTION TYPE zcx_gcp_api_handler * EXPORTING * textid = zcx_gcp_api_handler=>zcx_oauth_token_receive_fail. * ENDIF. DATA(lv_response_json) = lo_client->response->get_cdata( ). /ui2/cl_json=>deserialize( EXPORTING json = lv_response_json pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ). * IF ls_response-id_token IS INITIAL. * RAISE EXCEPTION TYPE zcx_gcp_api_handler * EXPORTING * textid = zcx_gcp_api_handler=>zcx_oauth_token_receive_fail. * ENDIF. rv_oidc_base64 = ls_response-access_token. ENDIF. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Static Public Method ZCL_GCP_API_HANDLER=>GET_IAT_UNIXTIME * +-------------------------------------------------------------------------------------------------+ * | [<-()] RV_IAT TYPE INT4 * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD get_iat_unixtime. DATA lv_unix_iat TYPE string. GET TIME STAMP FIELD DATA(lv_timestamp). CONVERT TIME STAMP lv_timestamp TIME ZONE 'UTC' INTO DATE DATA(lv_date) TIME DATA(lv_time). cl_pco_utility=>convert_abap_timestamp_to_java( EXPORTING iv_date = lv_date iv_time = lv_time iv_msec = 0 IMPORTING ev_timestamp = lv_unix_iat ). rv_iat = substring( val = lv_unix_iat off = 0 len = strlen( lv_unix_iat ) - 3 ). ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_GCP_API_HANDLER=>STRING_TO_BINARY_TAB * +-------------------------------------------------------------------------------------------------+ * | [--->] IV_STRING TYPE STRING * | [<-()] RT_BIN_TAB TYPE LTTY_TSSFBIN * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD string_to_binary_tab. DATA lv_xstring TYPE xstring. CALL FUNCTION 'SCMS_STRING_TO_XSTRING' EXPORTING text = iv_string encoding = '4110' IMPORTING buffer = lv_xstring EXCEPTIONS failed = 1 OTHERS = 2. * IF sy-subrc <> 0. * RAISE EXCEPTION TYPE zcx_gcp_api_handler * EXPORTING * textid = zcx_gcp_api_handler=>zcx_strtobin_conversion_failed. * ENDIF. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING buffer = lv_xstring TABLES binary_tab = rt_bin_tab. ENDMETHOD. ENDCLASS. |
- Créer 2 structures zgcp_jwt_header et zgcp_jwt_payload.

ALG signifie Algorithme et comprendra l’algorithme utilisé pour le cryptage, à savoir RS256.
TYP signifie « token type » (type de jeton) et sera JWT.

ISS signifie émetteur et sera le nom de notre compte de service Google.
AUD signifie audience, c’est-à-dire le consommateur du jeton.
TARGET_AUDIENCE est l’identifiant de notre client OAUTH chez Google.
IAT signifie issued at time (émis à l’heure) et correspond à l’heure UNIX à laquelle nous avons créé le jeton.
EXP signifie expires et correspond à la date d’expiration du jeton en heure UNIX.
- Créez un programme qui appellera les méthodes ci-dessus pour s’identifier.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
*&---------------------------------------------------------------------* *& Report ZCL_GCP_JWT_AUTH_TEST *&---------------------------------------------------------------------* *& *&---------------------------------------------------------------------* REPORT ZCL_GCP_JWT_AUTH_TEST. *1 DATA(lv_iat) = zcl_gcp_api_handler=>get_iat_unixtime( ). DATA(ls_jwt_payload) = VALUE zgcp_jwt_payload( iss = 'your email google service account' * aud = 'https://www.googleapis.com/oauth2/v4/token' scope = 'https://www.googleapis.com/auth/drive' aud = 'https://oauth2.googleapis.com/token' * target_audience = '110934787806204234349' iat = lv_iat exp = lv_iat + 30 ). DATA(ls_jwt_header) = VALUE zgcp_jwt_header( typ = 'JWT' alg = 'RS256' ). *2 TRY. DATA(lv_signed_jwt) = zcl_gcp_api_handler=>create_rs256_signed_jwt( EXPORTING iv_jwt_header = ls_jwt_header iv_jwt_payload = ls_jwt_payload iv_ssf_profilename = 'SAPJWR_SI400.pse' iv_ssf_id = '<implicit>' iv_ssf_result = 28 ). * CATCH zcx_gcp_api_handler. ENDTRY. *3 TRY. DATA(lv_oidc) = zcl_gcp_api_handler=>exchange_jwt_with_oidc_token( iv_exchange_destination = 'GCP_OAUTH2_TOKEN' iv_jwt_token = lv_signed_jwt ). * CATCH zcx_gcp_api_handler. ENDTRY. |
- Nous spécifions toutes les variables nécessaires à la création du JWT et à sa signature
- Lancement du programme pour générer et signer le JWT.
- Lancer la classe pour générer le jeton d’authentification en envoyant le JWT signé à Google qui renvoie un jeton. Le jeton Google se trouve dans la variable lv_oidc.
With this token, it is now possible to call google APIs by specifying the token in the call header.
Now we can create a test program calling the google sheets APIs with our authentication token
You can test your calls here :
https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/update
By inspecting, it is possible to find the url to specify in the call to have this operation:

Pour voir des exemples d’appels dans SAP, j’ai créé un programme de test :
Exemple pour créer une feuille blanche :

Exemple d’ajout de valeurs dans la feuille de calcul :

Conclusion
Vous pouvez maintenant créer/modifier/supprimer des feuilles Google. En utilisant cette technique vous pouvez interagir avec toutes les API de google (drive, doc, sheet, etc…).
