Dockerizing CA Siteminder

How to leverage infrastructure-as-code to build a portable and lightweight CA Siteminder environment using Docker.

8
 min read

En nuestro post anterior analizamos varias ventajas de la contenedorización cuando se trata de la migración de aplicaciones de identidad heredadas a la nube. Permite una migración gradual que permite que la empresa funcione sin problemas durante todo el proceso (en contraposición al enfoque de «cambiar y cambiar») y, además, permite retrasar la toma de decisiones arquitectónicas «inamovibles», como el entorno de nube específico (y los conjuntos asociados) al que se dirigirá. En este artículo, pasamos de la teoría a la práctica: pasamos de una vista panorámica a implementar un entorno de CA Siteminder totalmente contenerizado con Docker. ‍

Enfoque de dockerización

Separar la instalación de la configuración

Siteminder ocupa un espacio bastante importante, al igual que otros productos empresariales, normalmente de Java EE. La instalación supone la intervención de una persona para lograr la configuración de última milla. Para superar estas restricciones y crear imágenes de forma repetible, la configuración de última milla se automatiza mediante la API de Siteminder, que permite insertar objetos de configuración y modificar los existentes según sea necesario.

Configuración basada en API

CA Siteminder incluye un SDK de Perl y «C» que nos permite aprovisionar y gestionar la mayoría de los objetos de configuración mediante programación. En aras de la simplicidad, hemos decidido optar por Perl, ya que no requiere un paso de compilación adicional. Vale la pena señalar que el aprovisionamiento basado en Ansible y todos los artefactos asociados (como los scripts y la configuración) también están en contenedores y, por lo tanto, están aislados del entorno anfitrión.

Aplicación de referencia ligera

Para lograr un tiempo de respuesta rápido con las pruebas de extremo a extremo y solucionar cualquier problema eventual, es posible que desee utilizar una aplicación que se encuentre lo más cerca posible de la pila de servidores http. Disponer de una aplicación empresarial completa (por ejemplo, JavaEE) puede ralentizar el trabajo, dado el tamaño considerable del entorno asociado (por ejemplo, SDK, JRE, etc.), además de requerir una compilación para cada pequeño cambio. Nuestra elección es basarnos en OpenResty (una bifurcación de Nginx), que permite una visibilidad y un control totales de la integración de Siteminder mediante el lenguaje de programación Lua.

Nuestro entorno de pruebas de CA Siteminder

Bloques de construcción

Vamos a crear las siguientes imágenes de Docker:

  • CA Directory: para conservar los objetos de configuración de Siteminder, así como las identidades y las entidades asociadas
  • Servidor de políticas: aloja los servicios de autenticación y autorización que consumen los agentes. Además, aloja la interfaz administrativa para la configuración y la administración
  • Almacén de políticas: almacena detalles específicos de la autorización (por ejemplo, reglas)
  • Access Gateway: también conocido como Secure Proxy Server (SPS), intercepta las solicitudes y se asegura de que solo las solicitudes autenticadas y autorizadas lleguen a la aplicación OpenResty
  • Aplicación OpenResty: actúa como una aplicación web segura para proporcionar un inicio de sesión único (SSO) sobre Siteminder

Mejores prácticas

El proceso de instalación y configuración de Siteminder requiere mucha mano de obra, con muchas piezas móviles. Además, cualquier error de configuración o estado intermedio inválido del sistema que se produzca durante este proceso puede traducirse en un sistema que no funcione con pocas posibilidades de recuperación. Por lo general, es menos descabellado volver a empezar desde cero que intentar arreglar una instalación que no funciona.

En general, la forma en que elegimos abordar la creación de una imagen de Docker para Siteminder es la siguiente:

Configurar un entorno de sandbox

Implemente un entorno de Siteminder aislado, idealmente como una máquina virtual (VM). Puede usar cualquier plataforma de virtualización (consejo: pruebe Oracle Virtualbox, es gratis). O bien, puede optar por una máquina virtual en cualquier plataforma de infraestructura como servicio (IaaS), pero una posible desventaja de esta opción es que tendrá que pagar por la máquina virtual aunque no esté encendida.

El objetivo principal de este entorno limitado es obtener las propiedades del instalador del producto Siteminder que contienen las preferencias de configuración que se utilizarán durante una instalación automática. Además, cualquier artefacto relevante puede proceder de este entorno (descriptores de configuración, por ejemplo) e incluirse en la imagen de Docker. Por último, funciona como referencia durante el proceso de creación de la imagen, lo que puede resultar útil para depurar errores cuando las cosas no funcionan según lo esperado.

Tres fases de creación de imágenes

El procedimiento de CA Siteminder incluye no solo la instalación pasiva del producto, sino también la realización de procedimientos de configuración que dependen de que un servicio previamente instalado esté en funcionamiento y de las solicitudes de servicio. Esto implicaría la necesidad de implementar un flujo de trabajo personalizado fuera de Docker para lanzar contenedores que expongan los servicios de red necesarios en el siguiente paso de la instalación. Además, el proceso de creación de imágenes tiene limitaciones importantes (por ejemplo, en lo que respecta a las redes) que no se aplican a los contenedores.

Para solucionar este problema, hemos dividido el proceso de creación de imágenes en tres fases:

Creación básica de imágenes

Se crea una imagen por producto de Siteminder. Durante el proceso de creación de la imagen no se requieren servicios de terceros.

Vamos a profundizar en el descriptor de Dockerfile que aparece a continuación, que muestra la creación de la imagen para el Policy Server:


FROM centos:8
#
#
# Environment variables required for this build (do NOT change)
# -------------------------------------------------------------
#
ENV PS_ZIP=ps-12.8-sp05-linux-x86-64.zip \
    ADMINUI_PRE_REQ_ZIP=adminui-pre-req-12.8-sp05-linux-x86-64.zip \
    ADMINUI_ZIP=adminui-12.8-sp05-linux-x86-64.zip \
    SDK_ZIP=smsdk-12.8-sp05-linux-x86-64.zip \
    BASE_DIR=/opt/CA/siteminder \
    INSTALL_TEMP=/tmp/sm_temp

ENV SCRIPT_DIR=${INSTALL_TEMP}/dockertools 

#
# Creation of User, Directories and Installation of OS packages
# ----------------------------------------------------------------
RUN yum install -y which unzip rng-tools java-1.8.0 ksh openldap-clients openssh-server xauth libnsl
RUN groupadd smuser && \
    useradd smuser -g smuser
RUN mkdir -p ${BASE_DIR} && \
    chmod a+xr ${BASE_DIR} && \ 
    chown smuser:smuser ${BASE_DIR} 
RUN mkdir -p ${INSTALL_TEMP} && \
    chmod a+xr ${INSTALL_TEMP} && chown smuser:smuser ${INSTALL_TEMP} 

# Setup SSH access
# ----------------
USER smuser 

RUN mkdir /home/smuser/.ssh && \
    chmod 700 /home/smuser/.ssh && \
    ssh-keygen -A && \
    echo "ssh-rsa " >> /home/smuser/.ssh/authorized_keys && \

USER root

RUN rm -f /run/nologin && \
    mkdir /var/run/sshd && \
    ssh-keygen -A && \
    sed -i "s/^.*PasswordAuthentication.*$/PasswordAuthentication no/" /etc/ssh/sshd_config && \
    sed -i "s/^.*X11Forwarding.*$/X11Forwarding yes/" /etc/ssh/sshd_config && \
    sed -i "s/^.*X11UseLocalhost.*$/X11UseLocalhost no/" /etc/ssh/sshd_config && \
    grep "^X11UseLocalhost" /etc/ssh/sshd_config || echo "X11UseLocalhost no" >> /etc/ssh/sshd_config

# Increase entropy
# ----------------
RUN mv /dev/random /dev/random.org && \
    ln -s /dev/urandom /dev/random

# Copy packages and scripts
# -------------------------
COPY --chown=smuser:smuser install/* ${INSTALL_TEMP}/
COPY --chown=smuser:smuser ca-ps-installer.properties ${INSTALL_TEMP}/
COPY --chown=smuser:smuser prerequisite-installer.properties ${INSTALL_TEMP}/
COPY --chown=smuser:smuser smwamui-installer.properties ${INSTALL_TEMP}/
COPY --chown=smuser:smuser sdk-installer.properties ${INSTALL_TEMP}/
COPY --chown=smuser:smuser sm.registry ${INSTALL_TEMP}/
COPY --chown=smuser:smuser container-scripts/* ${SCRIPT_DIR}/
RUN chmod +x ${SCRIPT_DIR}/*.sh

USER smuser

# Install Policy Server
# -------------------------
RUN unzip ${INSTALL_TEMP}/${PS_ZIP} -d ${INSTALL_TEMP} && \
    chmod +x ${INSTALL_TEMP}/ca-ps-12.8-sp05-linux-x86-64.bin && \
    ${INSTALL_TEMP}/ca-ps-12.8-sp05-linux-x86-64.bin -i silent -f ${INSTALL_TEMP}/ca-ps-installer.properties

RUN cp ${INSTALL_TEMP}/smreg /opt/CA/siteminder/bin && \
    cp ${INSTALL_TEMP}/sm.registry /opt/CA/siteminder/registry/sm.registry

RUN echo ". /opt/CA/siteminder/ca_ps_env.ksh" >> /home/smuser/.bash_profile

# Install Administrative Interface Prerequisites
# -----------------------------------------------
RUN unzip ${INSTALL_TEMP}/${ADMINUI_PRE_REQ_ZIP} -d ${INSTALL_TEMP} && \
    chmod +x ${INSTALL_TEMP}/adminui-pre-req-12.8-sp05-linux-x86-64.bin && \
    ${INSTALL_TEMP}/adminui-pre-req-12.8-sp05-linux-x86-64.bin -i silent -f ${INSTALL_TEMP}/prerequisite-installer.properties

# Install Administrative Interface
# -----------------------------------------------
RUN unzip ${INSTALL_TEMP}/${ADMINUI_ZIP} -d ${INSTALL_TEMP} && \
    chmod +x ${INSTALL_TEMP}/ca-adminui-12.8-sp05-linux-x86-64.bin && \
    ${INSTALL_TEMP}/ca-adminui-12.8-sp05-linux-x86-64.bin -i silent -f ${INSTALL_TEMP}/smwamui-installer.properties

# Install the SDK
# -----------------------------------------------
RUN unzip ${INSTALL_TEMP}/${SDK_ZIP} -d ${INSTALL_TEMP} && \
    chmod +x ${INSTALL_TEMP}/ca-sdk-12.8-sp05-linux-x86-64.bin && \
    ${INSTALL_TEMP}/ca-sdk-12.8-sp05-linux-x86-64.bin -i silent -f ${INSTALL_TEMP}/sdk-installer.properties

# Important note: Make sure to SSH and run the setup_ps.sh script for registering the adminitrative UI with the policy server. 
#                 *This has to be performed only once*

# Define default command to start bash.
USER root 
CMD ["/usr/sbin/sshd", "-D"]

Realiza principalmente lo siguiente:

  1. Selecciona CentOS como sistema operativo
  2. Copia las imágenes del instalador del host a la imagen
  3. Crea el usuario de Siteminder, los directorios y los paquetes del sistema operativo instalados que son necesarios
  4. Configura el acceso SSH, que es necesario para que Ansible acceda y lleve a cabo la operación de configuración tan pronto como se haga girar el contenedor
  5. Copia los descriptores de configuración y los archivos de script que ejecutará Ansible durante la siguiente fase
  6. Ejecuta los instaladores de Siteminder para el servidor de políticas, la interfaz de usuario administrativa y el SDK
  7. Finalmente, genera el servidor SSH para que el usuario de Ansible acceda en la siguiente fase, para llevar a cabo los pasos posteriores a la instalación

Los Dockerfiles restantes siguen prácticamente el mismo patrón.

Configuración de imágenes

Todos los contenedores de las imágenes generadas se giran y configuran en consecuencia mediante un script de Ansible.


---
  - name: Setup CA Directory
    hosts: dx
    tasks:
      - name: Execute CA Directory post installation script
        shell: nohup /tmp/cadir_temp/dockertools/setup_psdsa.sh /dev/null 2>&1 &
  - name: Run Siteminder Policy Server
    hosts: ps
    tasks:
      - name: Execute the PS start command
        shell: nohup /opt/CA/siteminder/start-all /dev/null 2>&1 &
  - name: Configure Siteminder Policy Server
    hosts: ps
    tasks:
      - name: Execute PS post-install  command
        register: out
        command: "/tmp/sm_temp/dockertools/setup_ps.sh"
      - debug:
          var: out.stdout_lines
  - name: Setup Siteminder AG
    hosts: ag
    tasks:
      - name: Execute AG configuration command
        register: out
        command: "/tmp/sp_temp/dockertools/setup_ag.sh"
      - debug:
          var: out.stdout_lines
  - name: Post installation of AG
    hosts: ps
    tasks:
      - name: Execute AG post install command
        register: out
        shell: "source /opt/CA/siteminder/ca_ps_env.ksh && perl /tmp/sm_temp/dockertools/ProxyUIPostInstall.pl"
      - debug:
          var: out.stdout_lines
  - name: Run Siteminder AdminUI
    hosts: ps
    tasks:
      - name: Launch SM AdminUI
        shell: nohup /opt/CA/siteminder/adminui/bin/standalone.sh /dev/null 2>&1 &
  - name: Stop SPS UI
    hosts: ag
    tasks:
      - name: Kill SPS UI
        register: out
        shell: sleep 40 && /opt/CA/secure-proxy/default/proxy-engine/sps-ctl stop
        ignore_errors: True
      - debug:
          var: out.stdout_lines
  - name: Start SPS UI
    hosts: ag
    tasks:
      - name: Launch SPS UI
        register: out
        shell: /opt/CA/secure-proxy/default/proxy-engine/sps-ctl start
      - debug:
          var: out.stdout_lines

Consiste principalmente en configurar el directorio de CA (que actúa como fuente de políticas e identidades), el servidor de políticas, la interfaz de usuario de administrador, la puerta de enlace de acceso y la interfaz de usuario de proxy. Se ejecutan tanto scripts específicos de Siteminder como guiones ad hoc. Los primeros se encargan de gestionar el ciclo de vida del sistema de destino (iniciándolo y deteniéndolo, por ejemplo) y los segundos llevan a cabo las acciones posteriores a la instalación que se habrían realizado a través de una GUI si se tratara de una instalación manual.

A continuación se muestra uno de los scripts de Perl necesarios para configurar el servidor de políticas:


$adminName          = 'siteminder';
$adminPwd           = 'siteminder';

$userdir_namespace  = 'LDAP:';
$userdir_server     = 'dx:7777';  # IP Address if LDAP, Data Source Name if ODBC

#
# LDAP User Directory Settings
#
$ldap_srchroot      = 'ou=Contoso,o=psdsa,C=US';
$ldap_usrlkp_start  = 'cn=';
$ldap_usrlkp_end    = ',ou=Contoso,o=psdsa,c=US';
$ldap_usrname       = '';
$ldap_usrpwd        = '';
$ldap_require_creds = 0;

#
# Host Config settings
#
$host_conf_name     = "sps-hco";
$host_conf_desc     = "Secure Proxy Server Host";

#
# Policy server host
#
$policy_svr_host    = "ps";

#                                                                              #
# End site-specific configuration                                              #
#                                                                              #

$policymgtapi = Netegrity::PolicyMgtAPI->New();
$session = $policymgtapi->CreateSession($adminName, $adminPwd);
 
die "\nFATAL: Cannot create session. Please check admin credentials\n" 
    unless ($session != undef);

clean_ps_store();

setup_ps_store();

sub setup_ps_store {

    # Create a User Directory
    print "\tCreating User Directory \'contoso-userdir\'...";

    $userdir = $session->CreateUserDir( "contoso-userdir",
                                        $userdir_namespace,
                                        $userdir_server,
                                        $odbc_queryscheme,
                                        "Contoso User Directory",
                                        $ldap_srchroot,
                                        $ldap_usrlkp_start,
                                        $ldap_usrlkp_end,
                                        $ldap_usrname,
                                        $ldap_usrpwd,
                                        0,
                                        2,
                                        10,
                                        0,
                                        $ldap_require_creds
                                        );

    if(!defined $userdir) {
        die "\nFATAL: Unable to create User Directory \'contoso-userdir\'\n";
    }

    print "done\n";


    print "\tCreating Host Configuration for SPS \'sps-hco\'...";


    $hco = $session->CreateHostConfig( $host_conf_name,
                                    $host_conf_name,
                                    1,
                                    20,
                                    2,
                                    2,
                                    60
                                    );

    if(!defined $hco) {
        die "\nFATAL: Unable to create HCO \'sps-hco\'\n";
    }

    $hco->AddServer($policy_svr_host, 44441, 44442, 44443);

    print "done\n";

    print "\tCreating Agent \'spsapacheagent\'...";
    $agent = $session->CreateAgent( "spsapacheagent",
                                    $session->GetAgentType("Web Agent"),
                                    "Secure Proxy UI Agent"
                                );
    if(!defined $agent) {
        die "\nFATAL: Unable to create Agent \'spsapacheagent\'\n";
    }

    print "done\n";
}

sub clean_ps_store() {

    $session->DeleteDomain('DOMAIN-SPSADMINUI-spsapacheagent');
    if($status == -1) {
        print "Error deleting domain\n";
    }

    $session->DeleteAgentConfig( 'spsapacheagent-settings');
    if($status == -1) {
        print "Error deleting agent s\n";
    }

    $status = $session->DeleteHostConfig( $host_conf_name );
    if($status == -1) {
        print "Error deleting host config\n";
    }

    $status = $session->DeleteAgent( "spsapacheagent");
    if($status == -1) {
        print "Error deleting agent\n";
    }

    $status = $session->DeleteUserDir("contoso-userdir");
    if($status == -1) {
        print "Error deleting contoso-userdir\n";
    }

}

Más específicamente, el objetivo principal de este script es crear un agente, un directorio de usuarios y un objeto de configuración de host.

El proceso de configuración de imágenes de Ansible se ejecuta desde un contenedor, por lo que no requiere ningún entorno o paquete específico en la máquina host.

Aprovisionamiento de imágenes finales

Una vez que las imágenes se hayan ensamblado correctamente, se pueden etiquetar y enviar al repositorio para su consumo. Se pueden usar tal cual o como imágenes base para ofrecer despliegues de Siteminder más personalizados.

Optar por la orquestación en lugar de los scripts de host

Los scripts de host son principalmente programas escritos en lenguajes de programación de alto nivel o shell que viven dentro del host. Como regla general, crear imágenes utilizando secuencias de comandos de shell del host se considera una mala práctica, ya que se espera un entorno específico en la máquina host, que consiste en un conjunto específico de herramientas disponibles en la ruta actual, lo que puede traducirse como «funciona en mi síndrome de la «máquina». Es importante hacer que el proceso de automatización sea lo más portátil posible, de modo que pueda funcionar en un entorno de servidor y estación de trabajo, independientemente del sistema operativo y de los paquetes instalados. Elegimos Docker Compose para nuestra herramienta de orquestación. Es más que suficiente para crear nuestro flujo de trabajo y no requiere la instalación de ningún paquete DevOps adicional.

A continuación se muestra el descriptor de redacción de Docker para CA Siteminder:


version: "3"
services:
  dx:
    build:
      context: ./dockerfiles/cadir/14.1.00
    image: atricore/dx
    hostname: dx
    networks:
      - sm
    ports:
      - "7777:7777"
      - "5022:22"
    stdin_open: true
    tty: true
  ps:
    build:
      context: ./dockerfiles/siteminder/12.8/ps
    image: atricore/ps
    hostname: ps
    networks:
      - sm
    ports:
      - "2022:22"
      - "8443:8443"
    depends_on:
      - dx
    stdin_open: true
    tty: true
  ag:
    build:
      context: ./dockerfiles/siteminder/12.8/ag
    image: atricore/ag
    hostname: ag
    ports:
      - "3022:22"
      - "9090:8080"
      - "9191:8181"
    depends_on:
        - ps
    stdin_open: true
    tty: true
    networks:
      sm:
        aliases:
          - extapp
  app:
    build:
      context: ./dockerfiles/apps/resty
    image: atricore/app
    hostname: app
    networks:
      - sm
    ports:
      - "7070:80"
    depends_on:
      - ag
    stdin_open: true
    tty: true
  browser:
    build:
      context: ./dockerfiles/apps/browser
    image: atricore/browser
    hostname: browser
    networks:
      - sm
    ports:
      - "4022:22"
    depends_on:
        - app
    stdin_open: true
    tty: true
  ansible:
    build:
      context: ./dockerfiles/ansible
    image: atricore/ansible
    hostname: ansible
    networks:
      - sm
    depends_on:
        - dx
        - ps
        - ag
    stdin_open: true
    tty: true
networks:
  sm:
    name: sm-net

¿Estás listo para crear Siteminder con Dockerizar?

Si quieres hacerte con el paquete completo, no dudes en revisar el código en este Github repositorio.

__wf_reserved_heredar

Subscribe to our newsletter now!

Thanks for joining our newsletter.
¡Uy! Algo salió mal.