Skip to content

Commit

Permalink
🚚 Default to using a local cache if no Redis server information is pr…
Browse files Browse the repository at this point in the history
…ovided
  • Loading branch information
jemrobinson committed Feb 27, 2024
1 parent 58cde67 commit 52e08d6
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 24 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ The name is a slightly tortured acronym for: LD**A**P **pr**oxy for Open**I**D *

## Usage

**N.B.** As Apricot uses a Redis server to store generated `uidNumber` and `gidNumber` values.
**N.B.**

Start the `Apricot` server on port 1389 by running:

Expand All @@ -21,6 +21,11 @@ docker compose up

from the `docker` directory.

### Using Redis [Optional]

You can use a Redis server to store generated `uidNumber` and `gidNumber` values in a more persistent way.
To do this, you will need to provide the `--redis-host` and `--redis-port` arguments to `run.py`.

## Outputs

This will create an LDAP tree that looks like this:
Expand Down
18 changes: 14 additions & 4 deletions apricot/apricot_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from twisted.internet.interfaces import IReactorCore, IStreamServerEndpoint
from twisted.python import log

from apricot.cache import LocalCache, RedisCache
from apricot.ldap import OAuthLDAPServerFactory
from apricot.oauth import OAuthBackend, OAuthClientMap

Expand All @@ -18,21 +19,30 @@ def __init__(
client_secret: str,
domain: str,
port: int,
redis_host: str,
redis_port: int,
redis_host: str | None = None,
redis_port: int | None = None,
**kwargs: Any,
) -> None:
# Log to stdout
log.startLogging(sys.stdout)

# Initialise the UID cache
if redis_host and redis_port:
log.msg(
f"Using a Redis user-id cache at host '{redis_host}' on port '{redis_port}'."
)
uid_cache = RedisCache(redis_host=redis_host, redis_port=redis_port)
else:
log.msg("Using a local user-id cache.")
uid_cache = LocalCache()

# Initialize the appropriate OAuth client
try:
oauth_client = OAuthClientMap[backend](
client_id=client_id,
client_secret=client_secret,
domain=domain,
redis_host=redis_host,
redis_port=redis_port,
uid_cache=uid_cache,
**kwargs,
)
except Exception as exc:
Expand Down
2 changes: 2 additions & 0 deletions apricot/cache/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from .local_cache import LocalCache
from .redis_cache import RedisCache
from .uid_cache import UidCache

__all__ = [
"LocalCache",
"RedisCache",
"UidCache",
]
7 changes: 3 additions & 4 deletions apricot/oauth/oauth_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from requests_oauthlib import OAuth2Session
from twisted.python import log

from apricot.cache import RedisCache
from apricot.cache import UidCache
from apricot.models import (
LdapGroupOfNames,
LdapInetOrgPerson,
Expand All @@ -35,17 +35,16 @@ def __init__(
client_secret: str,
domain: str,
redirect_uri: str,
redis_host: str,
redis_port: str,
scopes: list[str],
token_url: str,
uid_cache: UidCache,
) -> None:
# Set attributes
self.bearer_token_: str | None = None
self.client_secret = client_secret
self.domain = domain
self.token_url = token_url
self.uid_cache = RedisCache(redis_host=redis_host, redis_port=redis_port)
self.uid_cache = uid_cache
# Allow token scope to not match requested scope. (Other auth libraries allow
# this, but Requests-OAuthlib raises exception on scope mismatch by default.)
os.environ["OAUTHLIB_RELAX_TOKEN_SCOPE"] = "1" # noqa: S105
Expand Down
20 changes: 9 additions & 11 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,33 @@ if [ -z "${DOMAIN}" ]; then
exit 1
fi

if [ -z "${REDIS_HOST}" ]; then
echo "$(date +'%Y-%m-%d %H:%M:%S+0000') [-] REDIS_HOST environment variable is not set"
exit 1
fi

# Arguments with defaults
if [ -z "${PORT}" ]; then
PORT="1389"
echo "$(date +'%Y-%m-%d %H:%M:%S+0000') [-] PORT environment variable is not set: using default of '${PORT}'"
fi

if [ -z "${REDIS_PORT}" ]; then
REDIS_PORT="6379"
echo "$(date +'%Y-%m-%d %H:%M:%S+0000') [-] REDIS_PORT environment variable is not set: using default of '${REDIS_PORT}'"
fi


# Optional arguments
EXTRA_OPTS=""
if [ -n "${ENTRA_TENANT_ID}" ]; then
EXTRA_OPTS="${EXTRA_OPTS} --entra-tenant-id $ENTRA_TENANT_ID"
fi

if [ -n "${REDIS_HOST}" ]; then
if [ -z "${REDIS_PORT}" ]; then
REDIS_PORT="6379"
echo "$(date +'%Y-%m-%d %H:%M:%S+0000') [-] REDIS_PORT environment variable is not set: using default of '${REDIS_PORT}'"
fi
EXTRA_OPTS="${EXTRA_OPTS} --redis-host $REDIS_HOST --redis-port $REDIS_PORT"
fi

# Run the server
hatch run python run.py \
--backend "${BACKEND}" \
--client-id "${CLIENT_ID}" \
--client-secret "${CLIENT_SECRET}" \
--domain "${DOMAIN}" \
--port "${PORT}" \
--redis-host "${REDIS_HOST}" \
--redis-port "${REDIS_PORT}" \
$EXTRA_OPTS
10 changes: 6 additions & 4 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
parser.add_argument("-s", "--client-secret", type=str, help="OAuth client secret.")
parser.add_argument("-d", "--domain", type=str, help="Which domain users belong to.")
parser.add_argument("-p", "--port", type=int, default=1389, help="Port to run on.")
parser.add_argument("--redis-host", type=str, help="Host for Redis server.")
parser.add_argument("--redis-port", type=int, help="Port for Redis server.")
# Options for Microsoft Entra backend
group = parser.add_argument_group("Microsoft Entra")
group.add_argument("-t", "--entra-tenant-id", type=str, help="Microsoft Entra tenant ID.", required=False)
entra_group = parser.add_argument_group("Microsoft Entra")
entra_group.add_argument("-t", "--entra-tenant-id", type=str, help="Microsoft Entra tenant ID.", required=False)
# Options for Redis cache
redis_group = parser.add_argument_group("Redis")
redis_group.add_argument("--redis-host", type=str, help="Host for Redis server.")
redis_group.add_argument("--redis-port", type=int, help="Port for Redis server.")
# Parse arguments
args = parser.parse_args()

Expand Down

0 comments on commit 52e08d6

Please sign in to comment.