Skip to content

Commit

Permalink
Merge branch 'main' into jans-cedaling-issue-10013
Browse files Browse the repository at this point in the history
  • Loading branch information
olehbozhok authored Jan 9, 2025
2 parents 904b3b7 + 5091b56 commit 5c3c3ce
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 22 deletions.
11 changes: 6 additions & 5 deletions .github/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ We appreciate your efforts to responsibly disclose your findings, and will make

## Supported versions

Security updates will typically only be applied to the latest release (at least until **Janssen** reaches first stable major version).
Security updates will typically only be applied to the latest release.

| Version | Supported |
| -------- | ------------------ |
| >=0.1 | :white_check_mark: |
| Version | Supported |
|---------|--------------------|
| <1.0.0 | :x: |
| >=1.0.0 | :white_check_mark: |

## Reporting a vulnerability

To report a security issue, send an email to [[email protected]](mailto:[email protected]?subject=SECURITY)
To report a security issue email [[email protected]](mailto:[email protected]?subject=SECURITY)

The **Janssen** team will send a response indicating the next steps in handling your report.
After the initial reply to your report, the team will keep you informed of the progress towards a fix and full announcement,
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ jobs:
- name: Build ${{ matrix.service }}
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
mvn -f ${{ matrix.service }}/pom.xml -Dcfg=${{ env.PROFILE_NAME }} -Dmaven.test.skip=${{ matrix.maven_skip_tests }} clean install -Drevision=${{ github.head_ref }}-nightly
revision=${{ github.sha }}-nightly
mvn -f ${{ matrix.service }}/pom.xml -Dcfg=${{ env.PROFILE_NAME }} -Dmaven.test.skip=${{ matrix.maven_skip_tests }} clean install -Drevision=$revision
else
mvn -f ${{ matrix.service }}/pom.xml -Dcfg=${{ env.PROFILE_NAME }} -Dmaven.test.skip=${{ matrix.maven_skip_tests }} clean install
fi
Expand Down
3 changes: 2 additions & 1 deletion jans-pycloudlib/jans/pycloudlib/config/file_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
class FileConfig(BaseConfig):
def __init__(self) -> None:
filepath = os.environ.get("CN_CONFIGURATOR_CONFIGURATION_FILE", "/etc/jans/conf/configuration.json")
key_file = os.environ.get("CN_CONFIGURATOR_KEY_FILE", "/etc/jans/conf/configuration.key")

out, err, code = load_schema_from_file(filepath, exclude_secret=True)
out, err, code = load_schema_from_file(filepath, exclude_secret=True, key_file=key_file)
if code != 0:
logger.warning(f"Unable to load configmaps from file {filepath}; error={err}; local configmaps will be excluded")

Expand Down
64 changes: 50 additions & 14 deletions jans-pycloudlib/jans/pycloudlib/schema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging
import re
from base64 import b64decode
from contextlib import suppress

import pem
from fqdn import FQDN
Expand All @@ -20,6 +21,7 @@
from marshmallow.validate import OneOf
from marshmallow.validate import Predicate
from marshmallow.validate import Range
from sprig_aes import sprig_decrypt_aes

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -884,38 +886,72 @@ class Meta:
_configmap = Nested(ConfigmapSchema, required=True)


def load_schema_from_file(path, exclude_configmap=False, exclude_secret=False):
def load_schema_from_file(path, exclude_configmap=False, exclude_secret=False, key_file=""):
"""Loads schema from file."""
out = {}
err = {}
code = 0
out, err, code = maybe_encrypted_schema(path, key_file)

try:
with open(path) as f:
docs = json.loads(f.read())
except (IOError, ValueError) as exc:
err = exc
code = 1
if code != 0:
return out, err, code

# dont exclude attributes
exclude_attrs = False
exclude_attrs = []

# exclude configmap from loading mechanism
if exclude_configmap:
key = "_configmap"
exclude_attrs = [key]
docs.pop(key, None)
out.pop(key, None)

# exclude secret from loading mechanism
if exclude_secret:
key = "_secret"
exclude_attrs = [key]
docs.pop(key, None)
out.pop(key, None)

try:
out = ConfigurationSchema().load(docs, partial=exclude_attrs)
out = ConfigurationSchema().load(out, partial=exclude_attrs)
except ValidationError as exc:
err = exc.messages
code = 1
return out, err, code


def load_schema_key(path):
try:
with open(path) as f:
key = f.read().strip()
except FileNotFoundError:
key = ""
return key


def maybe_encrypted_schema(path, key_file):
out, err, code = {}, {}, 0

try:
# read schema as raw string
with open(path) as f:
raw_txt = f.read()
except FileNotFoundError as exc:
err = {
"error": f"Unable to load schema {path}",
"reason": exc,
}
code = exc.errno
else:
if key := load_schema_key(key_file):
# try to decrypt schema (if applicable)
with suppress(ValueError):
raw_txt = sprig_decrypt_aes(raw_txt, key)

try:
out = json.loads(raw_txt)
except (json.decoder.JSONDecodeError, UnicodeDecodeError) as exc:
err = {
"error": f"Unable to decode JSON from {path}",
"reason": exc,
}
code = 1

# finalized results
return out, err, code
3 changes: 2 additions & 1 deletion jans-pycloudlib/jans/pycloudlib/secret/file_secret.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
class FileSecret(BaseSecret):
def __init__(self) -> None:
filepath = os.environ.get("CN_CONFIGURATOR_CONFIGURATION_FILE", "/etc/jans/conf/configuration.json")
key_file = os.environ.get("CN_CONFIGURATOR_KEY_FILE", "/etc/jans/conf/configuration.key")

out, err, code = load_schema_from_file(filepath, exclude_configmap=True)
out, err, code = load_schema_from_file(filepath, exclude_configmap=True, key_file=key_file)
if code != 0:
logger.warning(f"Unable to load secrets from file {filepath}; error={err}; local secrets will be excluded")

Expand Down
48 changes: 48 additions & 0 deletions jans-pycloudlib/tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,51 @@ def test_random_optional_scopes(value):

with pytest.raises(ValidationError):
ConfigmapSchema().validate_optional_scopes(value)


def test_load_schema_key(tmpdir):
from jans.pycloudlib.schema import load_schema_key

src = tmpdir.join("configuration.key")
src.write("abcd")
assert load_schema_key(str(src)) == "abcd"


def test_maybe_encrypted_schema_file_missing():
from jans.pycloudlib.schema import maybe_encrypted_schema

_, err, _ = maybe_encrypted_schema("/path/to/schema/file", "/path/to/schema/key")
assert "error" in err


def test_maybe_encrypted_schema(tmpdir):
from jans.pycloudlib.schema import maybe_encrypted_schema

src = tmpdir.join("configuration.json")
src.write("zLBGM41dAfA2JuIkVHRKa+/WwVo/8oQAdD0LUT3jGfhqp/euYdDhf+kTiKwfb1Sv28zYL12JlO+3oSl6ZlhiTw==")

src_key = tmpdir.join("configuration.key")
src_key.write("6Jsv61H7fbkeIkRvUpnZ98fu")

out, _, _ = maybe_encrypted_schema(str(src), str(src_key))
assert out == {"_configmap": {"hostname": "example.com"}}


def test_schema_exclude_configmap(tmpdir):
from jans.pycloudlib.schema import load_schema_from_file

src = tmpdir.join("configuration.json")
src.write('{"_configmap": {}, "_secret": {"admin_password": "Test1234#"}}')

out, _, code = load_schema_from_file(str(src), exclude_configmap=True)
assert "_configmap" not in out and code == 0


def test_schema_exclude_secret(tmpdir):
from jans.pycloudlib.schema import load_schema_from_file

src = tmpdir.join("configuration.json")
src.write('{"_configmap": {"city": "Austin", "country_code": "US", "admin_email": "[email protected]", "hostname": "example.com", "orgName": "Example Inc.", "state": "TX"}, "_secret": {}}')

out, _, code = load_schema_from_file(str(src), exclude_secret=True)
assert "_secret" not in out and code == 0

0 comments on commit 5c3c3ce

Please sign in to comment.