If you start using the GoldenGate web UI after installing it, you might end up thinking that extending the session timeout would be nice. Since there is no clear Oracle documentation on that matter, here are multiple ways of doing it.

Modifying the configuration files: quick but with downtime

The first way of doing it is to modify the deploymentConfiguration.dat files located in your $OGG_CONF_HOME directory. By default, OGG_CONF_HOME is set to $OGG_ETC_HOME/conf.

Inside this directory, the deploymentConfiguration.dat file looks similar to this:

{
    "ServiceManager": {
        "$schema": "ogg:service",
        "config": {
            "csrfHeaderProtectionEnabled": false,
            "securityDetails": {
                "network": {
                    "common": {
                        "fipsEnabled": false,
                        "id": "OracleSSL"
                    },
                    "inbound": {
                        "authMode": "clientOptional_server",
                        "crlEnabled": false,
                        "sessionCacheDetails": {
                            "limit": 20480,
                            "timeoutSecs": 1800
                        },
                        "role": "server",
                        "cipherSuites": [
                            "TLS_AES_256_GCM_SHA384",
                            "TLS_AES_128_GCM_SHA256",
                            "TLS_CHACHA20_POLY1305_SHA256"
                        ],
                        "certACL": [
                            {
                                "name": "ANY",
                                "permission": "allow"
                            }
                        ],
                        "sessionCacheEnabled": false,
                        "protocolVersion": "TLS_ALL"
                    },
                    "outbound": {
                        "authMode": "clientOptional_server",
                        "crlEnabled": false,
                        "role": "client",
                        "cipherSuites": "^.*$",
                        "sessionCacheEnabled": false
                    }
                }
            },
            "workerThreadCount": 5,
            "csrfTokenProtectionEnabled": true,
            "network": {
                "ipACL": [
                    {
                        "address": "ANY",
                        "permission": "allow"
                    }
                ],
                "serviceListeningPort": {
                    "address": "0.0.0.0",
                    "port": 7809
                }
            },
            "hstsEnabled": true,
            "authorizationDetails": {
                "movingExpirationWindowSecs": 900,
                "common": {
                    "allow": [
                        "Digest",
                        "x-Cert",
                        "Basic",
                        "Bearer"
                    ],
                    "customAuthorizationEnabled": true
                },
                "useMovingExpirationWindow": false,
                "sessionDurationSecs": 3600
            },
            "security": true,
            "defaultSynchronousWait": 30,
            "authorizationEnabled": true,
            "hstsDetails": "max-age=31536000;includeSubDomains",
            "asynchronousOperationEnabled": true,
            "taskManagerEnabled": true,
            "legacyProtocolEnabled": false
        },
        "enabled": true,
        "id": "30316382-c77b-495c-b69e-fd910d525b36",
        "status": "restart"
    },
    "pluginsrvr": {
        "$schema": "ogg:service",
        "config": "external",
        "critical": true,
        "enabled": false,
        "status": "stopped",
        "locked": false,
        "id": "eea1497d-8ff2-473f-90b3-84fffa57ebc7"
    }
}

There are two parameters that impact session timeout:

  • sessionDurationSecs : Duration of the authorization. Defaults to 3600 (one hour). After this delay, the session will be terminated, even if it has been active.
  • sessionInactiveSecs : Maximum number of seconds an unexpired authorization session may be inactive before expiring. Defaults to 1800 (30 minutes). If set to 0, a session’s inactivity time will be unlimited. This parameter is the one responsible for the pop-up you see after some time in the UI (see below)

Depending on your goals, two changes can be made:

  • If you want to increase the overall session duration, but still want inactive sessions to be disconnected after 30 minutes, you just have to increase sessionDurationSecs.
  • If you feel limited by the inactivity timeout and want to increase it, then you have to increase sessionInactiveSecs. If you want your sessions to last longer than one hour, you will also have to increase sessionDurationSecs.

Let’s check how it looks inside the configuration file:

[oracle@vmogg conf]$ grep -E 'sessionDurationSecs|sessionInactiveSecs' deploymentConfiguration.dat
                "sessionDurationSecs": 3600

The authorization limit is present (and set to the default value of 3600 seconds), but the inactivity parameter is absent. If you want to modify it, you will first have to add it. To update the session timeout, just modify these parameters (in seconds). After this, just restart the service manager and it’s done !

Here is a full configuration file example, modified with the two parameters sessionDurationSecs and sessionInactiveSecs added:

{
    "ServiceManager": {
        "$schema": "ogg:service",
        "config": {
            "csrfHeaderProtectionEnabled": false,
            "securityDetails": {
                "network": {
                    "common": {
                        "fipsEnabled": false,
                        "id": "OracleSSL"
                    },
                    "inbound": {
                        "authMode": "clientOptional_server",
                        "crlEnabled": false,
                        "sessionCacheDetails": {
                            "limit": 20480,
                            "timeoutSecs": 1800
                        },
                        "role": "server",
                        "cipherSuites": [
                            "TLS_AES_256_GCM_SHA384",
                            "TLS_AES_128_GCM_SHA256",
                            "TLS_CHACHA20_POLY1305_SHA256"
                        ],
                        "certACL": [
                            {
                                "name": "ANY",
                                "permission": "allow"
                            }
                        ],
                        "sessionCacheEnabled": false,
                        "protocolVersion": "TLS_ALL"
                    },
                    "outbound": {
                        "authMode": "clientOptional_server",
                        "crlEnabled": false,
                        "role": "client",
                        "cipherSuites": "^.*$",
                        "sessionCacheEnabled": false
                    }
                }
            },
            "workerThreadCount": 5,
            "csrfTokenProtectionEnabled": true,
            "network": {
                "ipACL": [
                    {
                        "address": "ANY",
                        "permission": "allow"
                    }
                ],
                "serviceListeningPort": {
                    "address": "0.0.0.0",
                    "port": 7809
                }
            },
            "hstsEnabled": true,
            "authorizationDetails": {
                "movingExpirationWindowSecs": 900,
                "common": {
                    "allow": [
                        "Digest",
                        "x-Cert",
                        "Basic",
                        "Bearer"
                    ],
                    "customAuthorizationEnabled": true
                },
                "useMovingExpirationWindow": false,
                "sessionDurationSecs": 7200,
                "sessionInactiveSecs": 3600
            },
            "security": true,
            "defaultSynchronousWait": 30,
            "authorizationEnabled": true,
            "hstsDetails": "max-age=31536000;includeSubDomains",
            "asynchronousOperationEnabled": true,
            "taskManagerEnabled": true,
            "legacyProtocolEnabled": false
        },
        "enabled": true,
        "id": "30316382-c77b-495c-b69e-fd910d525b36",
        "status": "restart"
    },
    "pluginsrvr": {
        "$schema": "ogg:service",
        "config": "external",
        "critical": true,
        "enabled": false,
        "status": "stopped",
        "locked": false,
        "id": "eea1497d-8ff2-473f-90b3-84fffa57ebc7"
    }
}

Of course, you will have to do the same for all the services of all your deployments. You can repeat the same process (including a restart) for all deployments, or use one of the methods described below.

Warning: The root object will defer depending on the configuration file ! It is called ServiceManager for the service manager, and adminsrvr, recvsrvr, distsrvr and pmsrvr for the services of a deployment. Adapt the commands accordingly.

Update with jq

jq is a powerful utility to manage JSON objects. I described it in more details in a blog about Log Analysis in MongoDB. To put it simple, you can retrieve a configuration option like this:

[oracle@vmogg ~] jq '.ServiceManager.config.authorizationDetails.sessionDurationSecs' deploymentConfiguration.dat
3600

And change it with the following commands:

# For the service manager
cd /u01/app/oracle/product/ogg23ai_sm/etc/conf
jq '.ServiceManager.config.authorizationDetails.sessionDurationSecs = 7200' deploymentConfiguration.dat > tmp && mv tmp deploymentConfiguration.dat

# For the services of your deployment
cd /u01/app/oracle/product/ogg_test_01/etc/conf
jq '.adminsrvr.config.authorizationDetails.sessionDurationSecs = 7200' deploymentConfiguration.dat > tmp && mv tmp deploymentConfiguration.dat
jq '.recvsrvr.config.authorizationDetails.sessionDurationSecs = 7200'  deploymentConfiguration.dat > tmp && mv tmp deploymentConfiguration.dat
jq '.distsrvr.config.authorizationDetails.sessionDurationSecs = 7200' deploymentConfiguration.dat > tmp && mv tmp deploymentConfiguration.dat
jq '.pmsrvr.config.authorizationDetails.sessionDurationSecs = 7200' deploymentConfiguration.dat > tmp && mv tmp deploymentConfiguration.dat

Unfortunately, there is no option to edit files in place with jq. Even though it’s a powerful tool, you will have to go through a temporary file to modify files. To add the absent sessionInactiveSecs parameter, just use the exact same command, replacing sessionDurationSecs, and jq will take care of adding the necessary commas and delivering an uncorrupted file.

Finally, to verify the values across your deployments, use [] to go through all services, and ? to avoid errors for missing keys:

[oracle@vmogg ~] jq '.[].config?.authorizationDetails?.sessionDurationSecs' /u01/app/oracle/product/*/etc/conf/deploymentConfiguration.dat
7200
7200
7200
7200
7200
[oracle@vmogg ~] jq '.[].config?.authorizationDetails?.sessionInactiveSecs' /u01/app/oracle/product/*/etc/conf/deploymentConfiguration.dat
3600
3600
3600
3600
3600

Update via sed

Modifying the JSON file with sed is less practical, but probably more familiar. Unfortunately, the tool was not made to modify JSON directly. While you can edit an existing parameter, adding a new one without corrupting your configuration might be harder. Anyway, here is a command that will update sessionDurationSecs in all your deploymentConfiguration.dat files, keeping the correct indentation and not corrupting your file by keeping commas at the end of the lines when there is one.

sed -i 's/"sessionDurationSecs": [0-9]\+\(,\)\?/"sessionDurationSecs": 7200\1/g' /u01/app/oracle/product/*/etc/conf/deploymentConfiguration.dat

Warning: When applying changes to the configuration file, pay attention to the line endings ! If you don’t use the provided sed command, you might remove commas at the end of some lines, and your configuration file might become invalid !

Update with Python

If you plan on doing any serious automation work around your GoldenGate configuration files, you should most certainly use Python. With the native json module, you can easily access and modify not just these two session parameters, but any aspect of the configuration. Here is a little code snippet that will modify a specific configuration file from a service manager:

import json
import os

file = "deploymentConfiguration.dat"

if not os.path.exists(file):
    print(f"File not found: {file}")
    sys.exit(1)

with open(file, "r") as f:
    data = json.load(f)

# sessionDurationSecs and sessionInactiveSecs will be changed, or added if they didn't exist before
data["ServiceManager"]["config"]["authorizationDetails"]["sessionDurationSecs"] = 7200
data["ServiceManager"]["config"]["authorizationDetails"]["sessionInactiveSecs"] = 3600

with open(file, "w") as f:
    json.dump(data, f, indent=4)

Output example:

[oracle@vmogg ~]$ grep -E "sessionDurationSecs|sessionInactiveSecs" deploymentConfiguration.dat
                "sessionDurationSecs": 3600
[oracle@vmogg ~]$ python3 ogg_conf_session_setting.py
[oracle@vmogg ~]$ grep -E "sessionDurationSecs|sessionInactiveSecs" deploymentConfiguration.dat
                "sessionDurationSecs": 7200,
                "sessionInactiveSecs": 3600

And for a more robust code that will search in all */etc/conf/deploymentConfiguration.dat files, and for all services of GoldenGate, not just the service manager:

import json
import glob
import os

def modify_ogg_configs(path_pattern, duration=7200, inactive=3600):
    file_list = glob.glob(path_pattern, recursive=True)
    if not file_list:
        print("No configuration files found.")
        return
    services = ["ServiceManager", "adminsrvr", "distsrvr", "recvsrvr", "pmsrvr", "pluginsrvr"]
    for file in file_list:
        print(f"Modifying GoldenGate configuration file: {file}")
        try:
            with open(file, "r") as f:
                data = json.load(f)
        except Exception as e:
            print(f"  Skipping {file}: failed to parse JSON ({e})")
            continue
        modified = False
        for service in services:
            try:
                cfg = data[service]["config"]
                if "authorizationDetails" in cfg:
                    cfg["authorizationDetails"]["sessionDurationSecs"] = duration
                    cfg["authorizationDetails"]["sessionInactiveSecs"] = inactive
                    print(f"  Updated {service}")
                    modified = True
            except KeyError:
                print(f"  {service} section not found, skipping")
        if modified:
            backup_file = file + ".bak"
            os.replace(file, backup_file)
            with open(file, "w") as f:
                json.dump(data, f, indent=4)
            print(f"  Changes saved (backup at {backup_file})")
        else:
            print("  No changes made to this file.")

# Example usage:
modify_ogg_configs("/u01/app/oracle/product/*/etc/conf/deploymentConfiguration.dat")

Output example:

[oracle@vmogg ~]$ python3 ogg_conf_session_setting_global.py
Modifying GoldenGate configuration file: /u01/app/oracle/product/ogg23ai_sm/etc/conf/deploymentConfiguration.dat
  Updated ServiceManager
  adminsrvr section not found, skipping
  distsrvr section not found, skipping
  recvsrvr section not found, skipping
  pmsrvr section not found, skipping
  Changes saved (backup at /u01/app/oracle/product/ogg23ai_sm/etc/conf/deploymentConfiguration.dat.bak)
Modifying GoldenGate configuration file: /u01/app/oracle/product/ogg_test_01/etc/conf/deploymentConfiguration.dat
  ServiceManager section not found, skipping
  Updated adminsrvr
  Updated distsrvr
  Updated recvsrvr
  Updated pmsrvr
  pluginsrvr section not found, skipping
  Changes saved (backup at /u01/app/oracle/product/ogg_test_01/etc/conf/deploymentConfiguration.dat.bak)

Using the Rest API: online but more complex

GoldenGate Rest API is not so hard to use when you’re used to it. I will probably write about this soon, but in the meantime, I will summarize what you need to know. You cannot directly modify a single parameter through the Rest API. To do so, you first have to retrieve the whole configuration, update it and push it.

You can do this in many ways, but I will just give you a minimal script example with the requests module from Python, to achieve what we’re looking for here:

import requests
import json


class OGGRestAPI:
    def __init__(self, host, port=7809, username=None, password=None, protocol='https'):
        """Initialize Oracle GoldenGate REST API client"""
        self.base_url = f'{protocol}://{host}:{port}'
        self.auth = (username, password)
        self.headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}

    def _get(self, path, params=None):
        url = f'{self.base_url}{path}'
        response = requests.get(url, auth=self.auth, headers=self.headers, params=params)
        self._check_response(response)
        return self._parse(response)

    def _post(self, path, data=None):
        url = f'{self.base_url}{path}'
        response = requests.post(url, auth=self.auth, headers=self.headers, data=json.dumps(data or {}))
        self._check_response(response)
        return self._parse(response)

    def _put(self, path, data=None):
        url = f'{self.base_url}{path}'
        response = requests.put(url, auth=self.auth, headers=self.headers, data=json.dumps(data or {}))
        self._check_response(response)
        return self._parse(response)

    def _patch(self, path, data=None):
        url = f'{self.base_url}{path}'
        response = requests.patch(url, auth=self.auth, headers=self.headers, data=json.dumps(data or {}))
        self._check_response(response)
        return self._parse(response)

    def _delete(self, path):
        url = f'{self.base_url}{path}'
        response = requests.delete(url, auth=self.auth, headers=self.headers)
        self._check_response(response)
        return self._parse(response)

    def _check_response(self, response):
        if not response.ok:
            print(f'HTTP {response.status_code}: {response.text}')
            response.raise_for_status()

    def _parse(self, response):
        try:
            return response.json()
        except ValueError:
            return response.text

    def _extract_main(self, result):
        if isinstance(result, dict):
            resp = result.get('response', result)
            if isinstance(resp, dict) and '$schema' in resp and 'items' in resp:
                resp_items = resp['items']
                exclude = ['links', '$schema']
                resp = [{k: v for k, v in d.items() if k not in exclude} for d in resp_items]
                return resp
            return resp
        return result

    def list_deployments(self, version='v2'):
        """
        GET /services/{version}/deployments
        Required Role: User
        Retrieve the collection of Oracle GoldenGate Deployments.

        Parameters:
            version (string): Oracle GoldenGate Service API version. Example: v2

        Example:
            client.list_deployments()

        """
        path = f"/services/{version}/deployments"
        result = self._get(path)
        return self._extract_main(result)

    def list_services(self, deployment, version='v2'):
        """
        GET /services/{version}/deployments/{deployment}/services
        Required Role: User
        Retrieve the collection of Oracle GoldenGate Services in a deployment.

        Parameters:
            deployment (string): Name for the Oracle GoldenGate deployment. Example: deployment_example
            version (string): Oracle GoldenGate Service API version. Example: v2

        Example:
            client.list_services(
                deployment='deployment_example'
            )
        """
        path = f"/services/{version}/deployments/{deployment}/services"
        result = self._get(path)
        return self._extract_main(result)

    def retrieve_service(self, service, deployment, version='v2'):
        """
        GET /services/{version}/deployments/{deployment}/services/{service}
        Required Role: User
        Retrieve the details of a service in an Oracle GoldenGate deployment.

        Parameters:
            service (string): Name of the service. Example: service_example
            deployment (string): Name for the Oracle GoldenGate deployment. Example: deployment_example
            version (string): Oracle GoldenGate Service API version. Example: v2

        Example:
            client.retrieve_service(
                service='service_example',
                deployment='deployment_example'
            )
        """
        path = f"/services/{version}/deployments/{deployment}/services/{service}"
        result = self._get(path)
        return self._extract_main(result)

    def update_service_properties(self, service, deployment, data=None, version='v2'):
        """
        PATCH /services/{version}/deployments/{deployment}/services/{service}
        Required Role: Administrator
        Update the properties of a service.

        Parameters:
            service (string): Name of the service. Example: service_example
            deployment (string): Name for the Oracle GoldenGate deployment. Example: deployment_example
            version (string): Oracle GoldenGate Service API version. Example: v2
            body (object):  Example: body_example

        Example:
            client.update_service_properties(
                service='service_example',
                deployment='deployment_example',
                data={
                    "enabled": true,
                    "status": "running"
                })
        """
        path = f"/services/{version}/deployments/{deployment}/services/{service}"
        result = self._patch(path, data=data)
        return self._extract_main(result)


if __name__ == "__main__":
    client = OGGRestAPI(
        host="10.0.0.1",
        port=7809,
        username="ogg",
        password="password_ogg",
        protocol="http")

    deployments = [d["name"] for d in client.list_deployments()]
    for deployment in deployments:
        services = [s["name"] for s in client.list_services(deployment)]
        for service in services:
            print(f'\n\ndeployment: {deployment}, service: {service}')
            modified = False
            data = client.retrieve_service(service, deployment)

            try:
                if "authorizationDetails" in data["config"]:
                    data["config"]["authorizationDetails"]["sessionDurationSecs"] = 7200
                    data["config"]["authorizationDetails"]["sessionInactiveSecs"] = 3600
                    print(f"  Updated {service}")
                    modified = True
                else:
                    print(f"  'authorizationDetails' not found in {service} section, skipping")
            except KeyError:
                print(f"  'config' not found in {service} section, skipping")

            if modified:
                patch_data = {
                    "config": data['config']
                }
                print("Updating service properties...")
                client.update_service_properties(service, deployment, patch_data)
                print("Service properties updated.")
                data = client.retrieve_service(service, deployment)
                print(f"  sessionDurationSecs: {data['config']['authorizationDetails']['sessionDurationSecs']}")
                print(f"  sessionInactiveSecs: {data['config']['authorizationDetails']['sessionInactiveSecs']}")

And the output from the script:

[oracle@vmogg ~]$ python3 minimal_example_update_service_properties.py

deployment: ServiceManager, service: ServiceManager
  Updated ServiceManager
Updating service properties...
Service properties updated.
  sessionDurationSecs: 7200
  sessionInactiveSecs: 3600


deployment: ServiceManager, service: pluginsrvr
  'authorizationDetails' not found in pluginsrvr section, skipping


deployment: ogg_test_01, service: adminsrvr
  Updated adminsrvr
Updating service properties...
Service properties updated.
  sessionDurationSecs: 7200
  sessionInactiveSecs: 3600


deployment: ogg_test_01, service: distsrvr
  Updated distsrvr
Updating service properties...
Service properties updated.
  sessionDurationSecs: 7200
  sessionInactiveSecs: 3600


deployment: ogg_test_01, service: pmsrvr
  Updated pmsrvr
Updating service properties...
Service properties updated.
  sessionDurationSecs: 7200
  sessionInactiveSecs: 3600


deployment: ogg_test_01, service: recvsrvr
  Updated recvsrvr
Updating service properties...
Service properties updated.
  sessionDurationSecs: 7200
  sessionInactiveSecs: 3600

Do I have to update the configuration file after modifying the configuration with the Rest API ?

When modifying the configuration with the Rest API, changes are dynamic, but the configuration file is also updated, so there is nothing else to change in the configuration file.

Will the parameters affect connections opened through the adminclient ?

Yes, connections opened through the adminclient will be impacted when changing the value of sessionDurationSecs. These connections will not be asked for credentials again, but you will receive the following error:

# Connected to the deployment for less than sessionDurationSecs
OGG (http://vmogg:7809 ServiceManager) 2> status service * deployment *
Deployment Name                   Service Name     Service Status

ServiceManager                    SERVICEMANAGER   RUNNING
ServiceManager                    PLUGINSRVR       STOPPED
ogg_test_01                       ADMINSRVR        RUNNING
ogg_test_01                       DISTSRVR         RUNNING
ogg_test_01                       PMSRVR           RUNNING
ogg_test_01                       RECVSRVR         RUNNING

# After at least sessionDurationSecs seconds of inactivity
OGG (http://vmogg:7809 ServiceManager) 3> status service * deployment *

Error: Authorization failure for user 'ogg'.

# Whenever you enter the command again, you will be connected without having to re-enter credentials
OGG (http://vmogg:7809 ServiceManager) 4> status service * deployment *
Deployment Name                   Service Name     Service Status

ServiceManager                    SERVICEMANAGER   RUNNING
ServiceManager                    PLUGINSRVR       STOPPED
ogg_test_01                       ADMINSRVR        RUNNING
ogg_test_01                       DISTSRVR         RUNNING
ogg_test_01                       PMSRVR           RUNNING
ogg_test_01                       RECVSRVR         RUNNING

After modifying the configuration files manually and restarting GoldenGate, my sessions are not affected by the changes

If you try the non-dynamic methods described earlier on your deployments, make sure to log out from the UI and log in again. Even after restarting the service manager and services, old sessions could still be connected and benefit from the old sessionDurationSecs and sessionInactiveSecs value.