#!/usr/bin/env bash
#
# Copyright 2018-2023 ForgeRock AS. All Rights Reserved
#
# Use of this code requires a commercial software license with ForgeRock AS.
# or with one of its affiliates. All use shall be exclusively subject
# to such license between the licensee and ForgeRock AS.
#

###
# Set up directory server replicas for CTS in appropriate shards.
# This is intended for evaluation on a single system.
#
# In deployment, each of these replicas would be on a separate host system.
#
# The proxy distributes data across two CTS shards, each with two replicas.
#
# Each shard is served by a pool of separate replicas.
# In other words, each server replicates within one shard only.
#
# All servers have the same uid=Proxy service account.
# The proxy binds with uid=Proxy and uses proxied authorization.
# This script adds an ACI to allow the proxy service account
# to perform proxied authorization under the CTS shards.
#
# All CTS shards have a CTS admin account, uid=openam_cts,ou=tokens.
# To modify the account, for example to change the password,
# you must modify it once for each shard, not through the proxy.
# The proxy would distribute the change to only one shard.
#
# The shards have the following replication configurations,
# with each server's (admin-port ldaps-port):
# cts 1: (5444 5636) <==> (15444 15636)
# cts 2: (6444 6636) <==> (16444 16636)
###

###
# Adjust these variables to fit your circumstances:
ZIP=~/Downloads/opendj-7.4.4-20250319151205-3e38ada61695e05f34ebbd799d03be9218ebe6be.zip
BASE_DIR=/path/to
FQDN=localhost
DEPLOYMENT_ID=ADaMkVIXfryp4tZN3_0V4WoB3BZc9SQ5CBVN1bkVDE6OSY5Kl7pIibg
DEPLOYMENT_PASSWORD=password
###

CURRENT_DIR=$(pwd)

# Install a single DS/RS with the CTS profile from the .zip distribution.
# The AM CTS reaper will manage token expiration and deletion.
# $1: instance number
# $2: bootstrap server base
install() {
  echo "### Installing ${BASE_DIR}/ds-rs-${1} ###"
  unzip -q "${ZIP}"
  mv opendj "ds-rs-${1}"

  "${BASE_DIR}/ds-rs-${1}/setup" \
   --deploymentId "$DEPLOYMENT_ID" \
   --deploymentIdPassword "$DEPLOYMENT_PASSWORD" \
   --serverId "ds-rs-${1}" \
   --adminConnectorPort "${1}444" \
   --hostname "${FQDN}" \
   --ldapsPort "${1}636" \
   --enableStartTls \
   --replicationPort "${1}989" \
   --bootstrapReplicationServer "${FQDN}:${2}989" \
   --bootstrapReplicationServer "${FQDN}:1${2}989" \
   --rootUserDN uid=admin \
   --rootUserPassword password \
   --profile am-cts \
   --set am-cts/amCtsAdminPassword:password \
   --profile ds-proxied-server \
   --set ds-proxied-server/baseDn:ou=tokens \
   --acceptLicense

  echo "### Starting ds-rs-${1} ###"
  "${BASE_DIR}/ds-rs-${1}/bin/start-ds" --quiet
}

move_cts_admin() {
  echo "### Moving CTS admin account above the distributed data ###"
  "${BASE_DIR}/ds-rs-${1}/bin/ldapmodify" \
   --hostname "${FQDN}" \
   --port "${1}636" \
   --useSsl \
   --usePkcs12TrustStore "${BASE_DIR}/ds-rs-${1}/config/keystore" \
   --trustStorePassword:file "${BASE_DIR}/ds-rs-${1}/config/keystore.pin" \
   --bindDn uid=admin \
   --bindPassword password << EOF
dn: uid=openam_cts,ou=admins,ou=famrecords,ou=openam-session,ou=tokens
changetype: moddn
newrdn: uid=openam_cts
deleteoldrdn: 0
newsuperior: ou=tokens
EOF
}

add_aci() {
  echo "### Adding ACIs for moved CTS admin account on ds-rs-${1} ###"
  "${BASE_DIR}/ds-rs-${1}/bin/ldapmodify" \
   --hostname "${FQDN}" \
   --port "${1}636" \
   --useSsl \
   --usePkcs12TrustStore "${BASE_DIR}/ds-rs-${1}/config/keystore" \
   --trustStorePassword:file "${BASE_DIR}/ds-rs-${1}/config/keystore.pin" \
   --bindDn uid=admin \
   --bindPassword password <<EOF
dn: ou=tokens
changetype: modify
add: aci
aci: (targetattr="*") (version 3.0; acl "Allow read access for debugging";
  allow(read, search, compare) userdn = "ldap:///uid=openam_cts,ou=tokens";)

dn: ou=famrecords,ou=openam-session,ou=tokens
changetype: modify
add: aci
aci: (targetattr="*") (version 3.0; acl "Create, delete, update token entries";
  allow(add, delete, write) userdn = "ldap:///uid=openam_cts,ou=tokens";)
EOF
}

cd "${BASE_DIR}" || exit 1

for i in 5 6
do
  install ${i} ${i}
  install 1${i} ${i}
done

for i in 5 6
do
  move_cts_admin ${i}
  add_aci ${i}
done

# In this example, all replicas have the same data to start with.
# If the data is not identical on each pair of replicas, initialize replication manually.

cd "${CURRENT_DIR}" || exit
