← Todos los artículos

Enviar archivos de AL11 a un servidor SFTP con SAP Cloud Integration

Una guía completa — probar la conexión SSH, añadir la clave de host del socio a known_hosts, construir el iFlow y enviar los archivos de AL11 con un pequeño report ABAP.

Cloud IntegrationSFTPSSHAL11ABAP

Un requisito muy habitual: S/4HANA escribe un archivo en el servidor de aplicaciones (AL11) — facturas, pagos, listas de stock — y un socio lo quiere en su servidor SFTP. En este artículo montamos ese flujo con SAP Cloud Integration (parte de Integration Suite), desde la primera prueba de conexión hasta que el archivo llega al otro lado.

El flujo completo: AL11 → report ABAP → iFlow → SFTP del socio
El flujo completo: AL11 → report ABAP → iFlow → SFTP del socio

La idea

Cloud Integration se ejecuta en la nube y no ve el sistema de archivos de tu servidor de aplicaciones on-premise. Por eso invertimos el sentido:

  1. Un pequeño report ABAP lee el archivo de AL11 y lo envía al endpoint HTTPS de un iFlow.
  2. El iFlow lo escribe en el servidor del socio con el adaptador SFTP receiver.
  3. El report mueve el archivo original a una carpeta de archivo.

Otra opción es un adaptador SFTP sender que consulta un servidor SFTP de tu red a través del Cloud Connector. Para eso necesitas un servidor SFTP propio; el enfoque anterior no necesita nada adicional.

Qué pedirle al socio

Información Ejemplo
Host y puerto sftp.partner-example.com:22
Usuario s4_upload
Autenticación Contraseña o clave pública
Directorio destino /inbound/
¿Lista blanca de IP? Si es así, envíale las IP de salida de tu región de Cloud Integration

1. Probar la conexión y obtener la clave de host

Abre Monitor → Integrations and APIs → Manage Security → Connectivity Tests y ve a la pestaña SSH.

  • Host / Port: el servidor del socio
  • Proxy Type: Internet
  • Authentication: None en el primer intento
  • Deja Check Host Key sin marcar — aún no conocemos la clave

Pulsa Send. Si el servidor responde, verás su clave de host. Pulsa Copy Host Key.

Prueba de conexión SSH: el servidor responde con su clave de host
Prueba de conexión SSH: el servidor responde con su clave de host

Si la prueba termina en timeout, casi siempre es un firewall: el socio todavía no ha permitido tus IP de Cloud Integration.

2. Añadir la clave de host a known_hosts

El adaptador SFTP solo se conecta a servidores que conoce. Esa lista es un material de seguridad llamado known_hosts. Esta comprobación es la que te protege de que alguien se haga pasar por el servidor del socio.

Ve a Manage Security → Security Material:

  • Si known_hosts ya existe, descárgalo primero y añade la nueva línea al final. Nunca subas un archivo que solo contenga la clave nueva: se perderían los hosts de todas las demás integraciones.
  • Después elige Upload → Known Hosts (SSH), mantén el nombre known_hosts y despliega.
known_hosts.txt
# one line per host:  <host> <key type> <base64 public key>
sftp.old-partner.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7v...
sftp.partner-example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM8wq2xYkRb4Tq3Vn0e7HhGfPz1cL5uXo9Ks2dWm4AaQe
Subida del archivo known_hosts ampliado
Subida del archivo known_hosts ampliado

3. Guardar las credenciales

  • Contraseña: Security Material → Create → User Credentials, por ejemplo SFTP_PARTNER_USER.
  • Clave pública: Keystore → Create → SSH Key. Descarga la clave OpenSSH pública y envíasela al socio; la clave privada nunca sale del tenant. En el adaptador la indicas con Private Key Alias.

4. Probar de nuevo — esta vez completo

De vuelta en la prueba SSH:

  • Authentication: User Credentials con SFTP_PARTNER_USER (o Public Key)
  • Check Host Key: ✓
  • Check Directory Access: ✓ con /inbound/

Cuando esta prueba sale en verde, la parte de Cloud Integration está lista. Cualquier error posterior estará en el iFlow o en ABAP, lo que facilita mucho el análisis.

5. Construir el iFlow

El iFlow y la configuración del SFTP receiver
El iFlow y la configuración del SFTP receiver

Adaptador HTTPS sender

  • Address: /al11/sftp-out
  • User Role: ESBMessaging.send
  • CSRF Protected: sin marcar — nuestro report ABAP no obtiene token

En la Runtime Configuration del iFlow, añade FileName en Allowed Header(s). Si no, Cloud Integration descarta la cabecera y se pierde el nombre del archivo.

Content Modifier — definir el nombre del archivo destino:

content-modifier.txt
Message Header
  Name:        TargetFile
  Source Type: Expression
  Source Value: ${header.FileName}

Optional – add a timestamp to avoid overwriting:
  Source Value: ${date:now:yyyyMMdd_HHmmss}_${header.FileName}

Adaptador SFTP receiver

Campo Valor
Address sftp.partner-example.com:22
Proxy Type Internet
Authentication User Name/Password
Credential Name SFTP_PARTNER_USER
Directory /inbound/
File Name ${header.TargetFile}
Handling for Existing Files Fail — más seguro que sobrescribir

Despliega el iFlow y copia su endpoint desde Monitor → Manage Integration Content.

6. El lado ABAP: SM59 y el report

Crea en SM59 un destino HTTP de tipo G:

  • Target Host: el host runtime de tu tenant (...-rt.cfapps.<región>.hana.ondemand.com)
  • Port: 443, SSL: activo
  • Path Prefix: /http/al11/sftp-out
  • Logon: autenticación básica con clientid / clientsecret de una clave de servicio de Process Integration Runtime (plan integration-flow), o un certificado de cliente

Importa la cadena de certificados del servidor en STRUST (identidad SSL cliente) para que funcione el handshake TLS.

Los archivos pendientes en AL11:

Archivos pendientes en el directorio de salida (AL11)
Archivos pendientes en el directorio de salida (AL11)

Y el report:

zal11_to_cpi_sftp.prog.abap
REPORT zal11_to_cpi_sftp.

" Reads a file from the application server (AL11), posts it to a
" Cloud Integration iFlow and moves it to an archive folder.
" Classic ABAP (on-premise): OPEN DATASET is not available in ABAP Cloud.

PARAMETERS: p_dir  TYPE c LENGTH 200 LOWER CASE DEFAULT '/interface/sftp_out/',
            p_file TYPE c LENGTH 120 LOWER CASE OBLIGATORY,
            p_arch TYPE c LENGTH 200 LOWER CASE DEFAULT '/interface/sftp_out/archive/'.

CONSTANTS c_destination TYPE rfcdest VALUE 'ZCPI_SFTP_OUT'.

START-OF-SELECTION.
  DATA(path)    = |{ p_dir }{ p_file }|.
  DATA(archive) = |{ p_arch }{ p_file }|.
  DATA content TYPE xstring.

  " 1. Read the file from AL11
  TRY.
      OPEN DATASET path FOR INPUT IN BINARY MODE.
      IF sy-subrc <> 0.
        MESSAGE |File { path } cannot be opened| TYPE 'E'.
      ENDIF.
      READ DATASET path INTO content.
      CLOSE DATASET path.
    CATCH cx_sy_file_access_error INTO DATA(file_error).
      MESSAGE file_error->get_text( ) TYPE 'E'.
  ENDTRY.

  " 2. Post it to the iFlow (SM59 destination of type G)
  DATA client TYPE REF TO if_http_client.
  cl_http_client=>create_by_destination(
    EXPORTING  destination = c_destination
    IMPORTING  client      = client
    EXCEPTIONS OTHERS      = 1 ).
  IF sy-subrc <> 0.
    MESSAGE |Destination { c_destination } cannot be used (SM59)| TYPE 'E'.
  ENDIF.

  client->request->set_method( if_http_request=>co_request_method_post ).
  client->request->set_content_type( 'application/octet-stream' ).
  client->request->set_header_field( name = 'FileName' value = CONV #( p_file ) ).
  client->request->set_data( content ).

  client->send( EXCEPTIONS OTHERS = 1 ).
  IF sy-subrc = 0.
    client->receive( EXCEPTIONS OTHERS = 1 ).
  ENDIF.
  IF sy-subrc <> 0.
    DATA error_text TYPE string.
    client->get_last_error( IMPORTING message = error_text ).
    MESSAGE error_text TYPE 'E'.
  ENDIF.

  DATA status TYPE i.
  DATA reason TYPE string.
  client->response->get_status( IMPORTING code = status reason = reason ).
  client->close( ).
  IF status <> 200.
    MESSAGE |Cloud Integration answered { status } { reason }| TYPE 'E'.
  ENDIF.

  " 3. Archive: write a copy, then delete the original
  OPEN DATASET archive FOR OUTPUT IN BINARY MODE.
  TRANSFER content TO archive.
  CLOSE DATASET archive.
  DELETE DATASET path.

  MESSAGE |{ p_file } sent to the SFTP server and archived| TYPE 'S'.

Para producción, ten en cuenta:

  • Nombres de archivo lógicos (transacción FILE) en lugar de rutas libres, y una comprobación de autorización sobre S_DATASET.
  • Un job en segundo plano (SM36) que recorra todo el directorio en lugar de un archivo por ejecución.

7. Prueba de extremo a extremo

  1. Ejecuta el report con un nombre de archivo de AL11.
  2. En Monitor → Message Processing el mensaje debe aparecer como Completed.
  3. El archivo está en /inbound/ del socio y en AL11 se ha movido a archive/.

Solución de problemas

Síntoma Causa probable Solución
Auth fail / clave de host rechazada Clave ausente o cambiada Paso 2 — actualizar known_hosts
Timeout de conexión Firewall / lista blanca El socio permite tus IP de CPI
No such file / permiso denegado Directorio o permisos incorrectos Prueba con Check Directory Access
HTTP 401 / 403 en ABAP Client ID/secret o rol incorrecto Revisar la clave de servicio y ESBMessaging.send
HTTP 403 con mensaje CSRF Protección CSRF activa Desmarcar CSRF Protected
El archivo llega con otro nombre Cabecera FileName descartada Añadirla en Allowed Header(s)
«El archivo ya existe» Handling for Existing Files = Fail Añadir una marca de tiempo al nombre

Lo bueno de este montaje es que cada pieza se prueba por separado: la conexión SSH, el iFlow y el report ABAP. Cuando algo falla, sabes enseguida dónde mirar.

Comentarios

Deja un comentario