Skip to content

Commit

Permalink
make ranger usersync password configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
AmberCharitos committed Jul 23, 2024
1 parent 9f79ff8 commit 16fb61f
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 9 deletions.
13 changes: 12 additions & 1 deletion config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
options:
ranger-admin-password:
description: |
Password used for the policy manager (Web interface)
The password for Ranger Admin user.
Password can not be changed using this property after initial deployment.
It can be changed in the UI.
Password should be minimum 8 characters with min one alphabet and one numeric.
default: "rangerR0cks!"
type: string
tls-secret-name:
Expand Down Expand Up @@ -122,3 +125,11 @@ options:
functionality for Ranger service in ms.
type: int
default: 3000
ranger-usersync-password:
description: |
The password for the user that synchronizes users and groups from LDAP to Ranger admin.
Password can not be changed using this property after initial deployment.
It can be changed in the UI.
Password should be minimum 8 characters with min one alphabet and one numeric.
type: string
default: rangerR0cks!
2 changes: 2 additions & 0 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ def _configure_ranger_admin(self, container):
"DB_USER": db_conn["user"],
"DB_PWD": db_conn["password"],
"RANGER_ADMIN_PWD": self.config["ranger-admin-password"],
"RANGER_USERSYNC_PWD": self.config["ranger-usersync-password"],
"JAVA_OPTS": "-Duser.timezone=UTC0",
}
config = render("admin-config.jinja", context)
Expand Down Expand Up @@ -258,6 +259,7 @@ def _configure_ranger_usersync(self, container):
context.update(
{
"POLICY_MGR_URL": self.config["policy-mgr-url"],
"RANGER_USERSYNC_PWD": self.config["ranger-usersync-password"],
}
)
config = render("ranger-usersync-config.jinja", context)
Expand Down
27 changes: 26 additions & 1 deletion src/structured_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class CharmConfig(BaseConfigModel):
sync_ldap_user_group_name_attribute: Optional[str]
sync_ldap_deltasync: bool
sync_interval: Optional[int]
ranger_usersync_password: Optional[str]
ranger_usersync_password: str
policy_mgr_url: str
charm_function: FunctionType
lookup_timeout: int
Expand Down Expand Up @@ -133,3 +133,28 @@ def lookup_timeout_validator(cls, value: str) -> Optional[int]:
if 1000 <= int_value <= 10000:
return int_value
raise ValueError("Value out of range.")

@validator("ranger_admin_password", "ranger_usersync_password")
@classmethod
def password_validator(cls, value: str) -> Optional[str]:
"""Validate if the password meets the following requirements.
- Minimum 8 characters in length
- Contains at least one alphabetic character
- Contains at least one numeric character
Args:
value: The password to validate.
Returns:
value: The validated password if it meets the requirements.
Raises:
ValueError: If the password does not meet the requirements.
"""
pattern = re.compile(
r"^(?=.*[A-Za-z])(?=.*\d)(?=.*[\W_])[A-Za-z\d\W_]{8,}$"
)
if pattern.match(value):
return value
raise ValueError("Password does not match requirements.")
8 changes: 4 additions & 4 deletions templates/admin-config.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ db_password={{ DB_PWD }}

# change password. Password for below mentioned users can be changed only once using this property.
#PLEASE NOTE :: Password should be minimum 8 characters with min one alphabet and one numeric.
rangerAdmin_password={{ RANGER_ADMIN_PWD | default("rangerR0cks!") }}
rangerTagsync_password={{ RANGER_ADMIN_PWD | default("rangerR0cks!") }}
rangerUsersync_password={{ RANGER_ADMIN_PWD | default("rangerR0cks!") }}
keyadmin_password={{ RANGER_ADMIN_PWD | default("rangerR0cks!") }}
rangerAdmin_password={{ RANGER_ADMIN_PWD }}
rangerTagsync_password={{ RANGER_ADMIN_PWD }}
rangerUsersync_password={{ RANGER_USERSYNC_PWD }}
keyadmin_password={{ RANGER_ADMIN_PWD }}


#Source for Audit Store. Currently solr and elasticsearch are supported.
Expand Down
2 changes: 1 addition & 1 deletion templates/ranger-usersync-config.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ unix_group=ranger

# This password should be changed from the default.
# Please note that this password should be as per rangerusersync user in ranger admin.
rangerUsersync_password= rangerR0cks!
rangerUsersync_password= {{ RANGER_USERSYNC_PWD }}

hadoop_conf=/etc/hadoop/conf

Expand Down
1 change: 1 addition & 0 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ async def deploy(ops_test: OpsTest):
resources=resources,
application_name=APP_NAME,
num_units=1,
config={"ranger-usersync-password": "P@ssw0rd1234"},
)

await ops_test.model.wait_for_idle(
Expand Down
1 change: 1 addition & 0 deletions tests/integration/test_usersync.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ async def test_user_sync(self, ops_test: OpsTest):

ranger_config = {
"charm-function": "usersync",
"ranger-usersync-password": "P@ssw0rd1234",
}

charm = await ops_test.build_charm(".")
Expand Down
6 changes: 4 additions & 2 deletions tests/unit/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def test_admin_ready(self):
"DB_USER": "postgres_user",
"DB_PWD": "admin",
"RANGER_ADMIN_PWD": "rangerR0cks!",
"RANGER_USERSYNC_PWD": "rangerR0cks!",
"JAVA_OPTS": "-Duser.timezone=UTC0",
},
}
Expand Down Expand Up @@ -135,6 +136,7 @@ def test_usersync_ready(self):
"startup": "enabled",
"environment": {
"POLICY_MGR_URL": "http://ranger-k8s:6080",
"RANGER_USERSYNC_PWD": "rangerR0cks!",
"SYNC_GROUP_USER_MAP_SYNC_ENABLED": True,
"SYNC_GROUP_SEARCH_ENABLED": True,
"SYNC_GROUP_SEARCH_BASE": "dc=canonical,dc=dev,dc=com",
Expand Down Expand Up @@ -172,10 +174,10 @@ def test_config_changed(self):
simulate_admin_lifecycle(harness)

# Update the config.
self.harness.update_config({"ranger-admin-password": "secure-pass"})
self.harness.update_config({"ranger-admin-password": "s3cure-pass"})

# The new plan reflects the change.
want_admin_password = "secure-pass" # nosec
want_admin_password = "s3cure-pass" # nosec
got_admin_password = harness.get_container_pebble_plan(
"ranger"
).to_dict()["services"]["ranger"]["environment"]["RANGER_ADMIN_PWD"]
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/test_structured_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,33 @@ def test_string_values(_harness) -> None:
check_valid_values(_harness, "sync-ldap-url", accepted_values)


def test_password_fields(_harness) -> None:
"""Test password fields validation."""
erroneous_passwords = [
"onlyletters", # No numbers
"12345678", # No letters
"NoSpecialChar123", # No special characters
"Short1!", # Too short
]

valid_passwords = [
"Valid1Pass!",
"AnotherValid2#Password",
"Password1$",
"P@ssw0rd1234",
]

check_invalid_values(
_harness, "ranger-admin-password", erroneous_passwords
)
check_valid_values(_harness, "ranger-admin-password", valid_passwords)

check_invalid_values(
_harness, "ranger-usersync-password", erroneous_passwords
)
check_valid_values(_harness, "ranger-usersync-password", valid_passwords)


def check_valid_values(_harness, field: str, accepted_values: list) -> None:
"""Check the correctness of the passed values for a field.
Expand Down

0 comments on commit 16fb61f

Please sign in to comment.