This blog describes how to configure an Oracle HTTP Server (OHS) 12c fronting a Fusion Middleware Forms and Reports in full SSL mode. This means, the HTTP Server listen in SSL and the mod_wl_ohs plugin is configured to connect to WebLogic Servers configured in SSL. As I did this configuration exercise for the YaK weblogic_domain component, the configuration has been written in a ansible role using jinja templates.

First step: prepare the certificates or wallets:

By default OHS uses a wallet containing a demo certificate to enable HTTPS. We will replace this demo certificate with a certificate from a certificate authority. As the Oracle HTTP Server is located on the same Unix server as the Fusion Middleware Forms & Reports WebLogic Domain, we will use the WebLogic identity keystore to create the wallet.

- name: Create Wallet directory for SSL configuration
  become: true
  become_user: '{{ pv_oracle_user }}'
  file: state=directory path={{ pv_target_jks_location }}/wallet
  when: pv_weblogic_domain_details.ohs_instance_name is defined and ( pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true )
  tags:
    - fmw-ohs-configuration

- name: Create Wallet file
  become: true
  become_user: '{{ pv_oracle_user }}'
  shell: "{{ pv_mw_home }}/oracle_common/bin/orapki wallet create -wallet {{ pv_target_jks_location }}/wallet -pwd {{ pv_weblogic_secrets.WalletPassword }} -auto_login"
  args:
    creates: '{{ pv_target_jks_location }}/wallet/ewallet.p12'
  when: pv_weblogic_domain_details.ohs_instance_name is defined and ( pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true )
  tags:
    - fmw-ohs-configuration

- name: Check if identity JKS already imported in Wallet file
  become: true
  become_user: '{{ pv_oracle_user }}'
  shell:
    cmd: "{{ pv_mw_home }}/oracle_common/bin/orapki wallet display -wallet {{ pv_target_jks_location }}/wallet"
    executable: /bin/bash
  register: wallet_content
  when: pv_weblogic_domain_details.ohs_instance_name is defined and ( pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true )
  changed_when: False
  tags:
    - fmw-ohs-configuration

- name: Check if identity JKS already imported in Wallet file
  set_fact:
     wallet_imported: "{{ wallet_content.stdout | regex_search( pv_ssl_details.ssl_domain_name) }}"
  when: pv_weblogic_domain_details.ohs_instance_name is defined and ( pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true )
  tags:
    - fmw-ohs-configuration

- name: Import identity JKS in  Wallet file
  become: true
  become_user: '{{ pv_oracle_user }}'
  shell: "{{ pv_mw_home }}/oracle_common/bin/orapki wallet jks_to_pkcs12 -wallet {{ pv_target_jks_location }}/wallet -pwd {{ pv_weblogic_secrets.WalletPassword }} -keystore {{ pv_target_jks_location }}/identity.jks -jkspwd {{ pv_weblogic_secrets.jks_id_pw }}"
  when: pv_weblogic_domain_details.ohs_instance_name is defined and ( pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true ) and (wallet_imported | length == 0)
  tags:
    - fmw-ohs-configuration


Line 12: orapki is used to create an empty wallet in auto-login mode. This mode is required for the Oracle HTTP Server to be able to handle it.

Line 23: orapki is used in display mode to get the already imported certificates. This is done to avoid errors when the role is called several times.

Line 33: Checks if the identity.jks keystore was already imported checking the result of the line 23.

Line 41: This orapki command imports the identity.jks if not already done.

When the Oracle HTTP Server mod_wl_ohs connects to a WebLogic Domain configured in SSL, a second wallet needs to be used. This second wallet must contain the root certificate and intermediate certificate if some used for the site.

- name: Create mod_wl Wallet file
  become: true
  become_user: '{{ pv_oracle_user }}'
  shell: "{{ pv_mw_home }}/oracle_common/bin/orapki wallet create -wallet {{ pv_target_jks_location }}/mod_wl_wallet -auto_login_only"
  args:
    creates: '{{ pv_target_jks_location }}/mod_wl_wallet/cwallet.sso'
  when: pv_weblogic_domain_details.ohs_instance_name is defined and ( pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true )
  tags:
    - fmw-ohs-configuration
- name: Import rootCa in  mod_wl_Wallet file
  become: true
  become_user: '{{ pv_oracle_user }}'
  shell: "{{ pv_mw_home }}/oracle_common/bin/orapki wallet add -wallet {{ pv_target_jks_location }}/mod_wl_wallet -trusted_cert -cert ~/certs/rootCA.crt -auto_login_only"
  register: rootCa_import
  failed_when: rootCa_import.stdout | regex_search('Could not install trusted cert') and not( rootCa_import.stdout | regex_search('PKI-04003') )
  when: pv_weblogic_domain_details.ohs_instance_name is defined and ( pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true )
  tags:
    - fmw-ohs-configuration

- name: Import intermediateCA in  mod_wl_Wallet file
  become: true
  become_user: '{{ pv_oracle_user }}'
  shell: "{{ pv_mw_home }}/oracle_common/bin/orapki wallet add -wallet {{ pv_target_jks_location }}/mod_wl_wallet -trusted_cert -cert ~/certs/intermediateCA.crt -auto_login_only"
  register: intermediateCA_import
  failed_when: intermediateCA_import.stdout | regex_search('Could not install trusted cert') and not( intermediateCA_import.stdout | regex_search('PKI-04003') )
  when: pv_weblogic_domain_details.ohs_instance_name is defined and ( pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true )
  tags:
    - fmw-ohs-configuration

Line 4: orapki is used to create an empty wallet in auto_login mode only.

line 13 and 15: The root CA certificate is imported and the command output checked for errors. PKI-04003 error is ignored as it means “already imported”.

Line 23 and 25: Same as the previous lines but imports the intermediate certificate.

Second step: Configure the Oracle HTTP Server and the mod_wl_ohs plugin

This is done through three templates: ssl-conf.jnj2, forms-conf.jnj2 and reports-conf.jnj2.
The first one is the ssl.conf file adapted to the Unix server or Web Site. I will not give the full template here but just the line where the wallet is referenced by the SSLWallet declaration

SSLWallet "{{ pv_target_jks_location }}/wallet"

The second and the third templates create the forms.conf and reports.conf in the moduleconf directory which makes them included by default in the http.conf file. If SSL is required, it changes the configuration to include the wallet created for the WLS module plugin.

forms-conf.j2

<IfModule weblogic_module>
<Location /forms>
        SetHandler weblogic-handler
        WebLogicHost {{ pv_adminHost }}
{% if pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true %}
        WebLogicPort {{ pv_weblogic_domain_details.instance_WLS_FORMS_SSL_port }}
        SecureProxy ON
        WLSSLWallet {{ pv_target_jks_location }}/mod_wl_wallet/
{% else %}
        WebLogicPort {{ pv_weblogic_domain_details.instance_WLS_FORMS_port }}
{% endif %}
</Location>
</IfModule>

reports-conf.j2

<IfModule weblogic_module>
<Location /reports>
        SetHandler weblogic-handler
        WebLogicHost {{ pv_adminHost }}
{% if pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true %}
        WebLogicPort {{ pv_weblogic_domain_details.instance_WLS_REPORTS_SSL_port }}
        SecureProxy ON
        WLSSLWallet {{ pv_target_jks_location }}/mod_wl_wallet/
{% else %}
        WebLogicPort {{ pv_weblogic_domain_details.instance_WLS_REPORTS_port }}
{% endif %}
</Location>
</IfModule>

In both templates, at lines 6, 7 and 8, there are the declaration of the WebLogic Server SSL listening port, the activation of the secured proxy and the wallet declaration.

Those templates are used to update the Oracle HTTP Server configuration and the Oracle HTTP Server instance

- name: Install the Oracle HTTP Server mod_wl reports configuration
  become: true
  become_user: '{{ pv_oracle_user }}'
  template:
    src: 'reports.conf'
    dest: '{{ pv_domain_home }}/config/fmwconfig/components/OHS/{{ pv_weblogic_domain_details.ohs_instance_name }}/moduleconf/reports.conf'
    mode: "u=rw,g=r"
  when: pv_weblogic_domain_details.ohs_instance_name is defined and pv_weblogic_domain_details.instance_WLS_REPORTS_port is defined
  tags:
    - fmw-ohs-configuration

- name: Install the Oracle HTTP Instance mod_wl reports configuration
  become: true
  become_user: '{{ pv_oracle_user }}'
  template:
    src: 'reports.conf'
    dest: '{{ pv_domain_home }}/config/fmwconfig/components/OHS/instances/{{ pv_weblogic_domain_details.ohs_instance_name }}/moduleconf/reports.conf'
    mode: "u=rw,g=r"
  when: pv_weblogic_domain_details.ohs_instance_name is defined and pv_weblogic_domain_details.instance_WLS_REPORTS_port is defined
  tags:
    - fmw-ohs-configuration

- name: Install the Oracle HTTP Server mod_wl forms configuration
  become: true
  become_user: '{{ pv_oracle_user }}'
  template:
    src: 'forms.conf'
    dest: '{{ pv_domain_home }}/config/fmwconfig/components/OHS/{{ pv_weblogic_domain_details.ohs_instance_name }}/moduleconf/forms.conf'
    mode: "u=rw,g=r"
  when: pv_weblogic_domain_details.ohs_instance_name is defined and pv_weblogic_domain_details.instance_WLS_FORMS_port is defined
  tags:
    - fmw-ohs-configuration

- name: Install the Oracle HTTP Instance mod_wl forms configuration
  become: true
  become_user: '{{ pv_oracle_user }}'
  template:
    src: 'forms.conf'
    dest: '{{ pv_domain_home }}/config/fmwconfig/components/OHS/instances/{{ pv_weblogic_domain_details.ohs_instance_name }}/moduleconf/forms.conf'
    mode: "u=rw,g=r"
  when: pv_weblogic_domain_details.ohs_instance_name is defined and pv_weblogic_domain_details.instance_WLS_FORMS_port is defined
  tags:
    - fmw-ohs-configuration

After those configuration steps, a stop and start of the HTTP Server component is required.

During the testing of the configured environment, I have seen that some https requests were redirected to http. The fact that the WebLogic Servers are fronted by a SSL configured Oracle HTTP Server requires the WLS Plugin to be enabled in both WLS_FORMS and WLS_REPORTS WebLogic Server.

- name: configure WebLogic WLS Plugin
  become: true
  become_user: '{{ pv_oracle_user }}'
  command: "{{ pv_mw_home }}/oracle_common/common/bin/wlst.sh {{ pv_dmk_home }}/wlst/configureDomainWLSPlugin.py {{ pv_domain_name }}"
  environment:
    WEBLOGIC_DOMAIN_DEF_DIR: '{{ pv_domain_config_base }}'
  when: pv_weblogic_domain_details.ohs_instance_name is defined
  tags:
    - wls-ssl-config

configureDomainWLSPlugin.py

def configureServerWLSPlugin(serverName):
    print '>>> Managed Server: ' + serverName + ' Configuring WLS_plugin'
    cd('/Servers/' + serverName )
    cmo.setWeblogicPluginEnabled(true)
    print '>>> WebLogic Server: ' + serverName + ' WLS_plugin enabled !'

def getAllServers():
  domainConfig()
  cd ('/')
  return cmo.getServers()

try:
    #Connect to AdminServer
    connect(userConfigFile=CONFIG_FILE,userKeyFile=KEY_FILE,url=ADMIN_URL)
    #connect()

    redirect('/dev/null','false')
    #Retrieve Server Names
    servers = getAllServers()

    # Start Edit Session
    edit()
    startEdit()
    stopRedirect()

    for server in servers:
        configureServerWLSPlugin(server.name)

except Exception, e:
    print "ERROR... check error messages for cause."
    print e
    exit(exitcode=1)

redirect('/dev/null','false')
save()
activate()
disconnect()
exit(exitcode=0)

Those changes required the WebLogic servers to be restarted a new time. But after this the Fusion Middleware Forms & Reports WebLogic domain and front-end Oracle HTTP Server were fully configured in SSL. The last point was the login to Enterprise Manager not working or better said looping indefinitely after the credentials were submitted. After some googling, I came over a Oracle Support note that said that if the WebLogic domain is totally configured in SSL, no HTTP port listening anymore, the connection between the Enterprise Manager and the WebLogic embedded ldap server using the libovd will not work due to the miss of the keystore to connect. This requires the libovdconfig.sh script to be executed. But this was not easy in ansible code as the libovdconfig.sh script doesn’t accept the username and password in silent mode. Found Oracle support note 1938474.1 “How to Pass to the libovdconfig.sh Script a User and Password Using a File?” that provided me the solution. It requires the patch 31713426 “Oracle Virtual Directory Bug 31713426 libovd in SSL” to be installed and the script to be called as shown in the ansible code extract below. Be aware that this script works only if it can connect to the WebLogic Admin Server in non-SSL. So I had to run it before configuring my WebLogic domain in full SSL.

- name: Configure SSL access to libovd
  become: true
  become_user: 'root'
  shell: su - {{ pv_oracle_user }} -c "export ORACLE_HOME={{pv_oracle_home}} && echo -e '{{ pv_weblogic_secrets.weblogic_admin_pass }}\n{{ pv_weblogic_secrets.libovd_keystore_pass }}\n' | {{pv_oracle_home}}/oracle_common/bin/libovdconfig.sh -host {{ pv_wls_host_fqdn }} -port {{ pv_weblogic_domain_details.admin_listen_port }}  -domainPath {{ pv_domain_home }} -userName {{ pv_weblogic_domain_details.weblogic_admin }} -createKeystore -silent"
  args:
    creates: "{{ pv_domain_home }}/config/fmwconfig/ovd/default/keystores/adapters.jks"
  when: pv_ssl_details.ssl_required is defined and pv_ssl_details.ssl_required == true
  tags:
    - fmw-ssl-preparation

I had still an issue with the login to Enterprise Manager due to the Java version used. Starting from JDK 1.8 u331 the URI parsing has been made strict. This is explained in Oracle Support note 2864307.1 “13.5 EM Login Failure – An internal error has occurred ADFSHARE-00120 Malformed address”. An other patch to install, patch 34065178.

I finally got it to work and was able to deploy the full stack using YaK in 38 minutes on a on-premise virtual machine and a little bit more on a AWS or OCI compute instance due to my network bandwidth.

Note that the Fusion Middleware repository is created in a Oracle 19c PDB database also created with YaK