def test_verify_all_publishers(self): u = profile.User(user_id="test") u.verify_all_publishers(u) old_user = profile.User() old_user.active.value = True with pytest.raises( cis_profile.exceptions.PublisherVerificationFailure): u.verify_all_publishers(old_user)
def test_verify_all_publishers_modify_metadata(self): u = profile.User(user_id="test", first_name="tester") u.user_id.metadata.display = "public" u.user_id.signature.publisher.name = "access_provider" old_user = profile.User() old_user.user_id.value = "test" # same value old_user.user_id.metadata.display = "private" # different display old_user.user_id.signature.publisher.name = u.user_id.signature.publisher.name assert u.verify_all_publishers(old_user) is True
def test_merge_return_value(self): a = profile.User(user_id="usera") b = profile.User(user_id="userb") res = a.merge(b) assert "user_id" in res b.access_information.hris.values = {"test_group": None} res = a.merge(b) assert "hris" in res
def test_merge_profiles(self): u_orig = profile.User() u_orig.access_information.ldap.values = {"test": None} u_patch = profile.User() u_patch.access_information.ldap.values = {"test_replacement": None} u_orig.merge(u_patch, "ldap") assert u_orig.as_dict()["access_information"]["ldap"]["values"] == { "test_replacement": None }
def test_merge_profiles(self): u_orig = profile.User() u_orig.access_information.ldap.values = {"test": None} u_orig.uuid.value = "31337" u_patch = profile.User() u_patch.access_information.ldap.values = {"test_replacement": None} u_orig.merge(u_patch) assert u_orig.as_dict()["access_information"]["ldap"]["values"] == {"test_replacement": None} assert u_orig.uuid.value == "31337" # This has not changed because it was null/None in the patched profile
def setup(self): os.environ[ "CIS_DISCOVERY_URL"] = "https://auth.allizom.org/.well-known/mozilla-iam" self.helper_configuration = helpers.Configuration() self.null_user = profile.User() u = fake_profile.FakeUser( config=fake_profile.FakeProfileConfig().default().create()) u.uuid = self.null_user.uuid u.primary_username = self.null_user.primary_username u = self.helper_configuration.ensure_appropriate_publishers_and_sign( fake_profile=u, condition="create") u.verify_all_publishers(profile.User(user_structure_json=None)) self.durable_profile = u.as_json()
def test_verify_can_publish_when_merging(self): u_orig = profile.User() u_orig.access_information.ldap.values = {"test": None} u_orig.uuid.value = "31337" u_orig.active.value = None for _ in ["ldap", "access_provider", "cis", "hris", "mozilliansorg"]: u_orig.sign_all(publisher_name=_, safety=False) u_patch = profile.User() u_patch.access_information.ldap.values = {"test_replacement": None} u_orig.merge(u_patch) u_orig.verify_all_publishers(u_patch) assert u_orig.active.value is None
def test_verify_all_publishers_mozillians_exception(self): """ This tests the whitelisted exception for DinoPark/Mozilliansorg to be allowed to change display or verified metadata values, when the actual value/values of the attribute is NOT modified """ u = profile.User(user_id="test", first_name="tester") u.first_name.metadata.display = "public" old_user = profile.User() old_user.first_name.value = "tester" # same value u.first_name.metadata.display = "private" # different display old_user.first_name.signature.publisher.name = "access_provider" assert u.verify_all_publishers(old_user) is True
def ensure_appropriate_publishers_and_sign(fake_profile, publisher_rules, condition): os.environ["CIS_SECRET_MANAGER"] = "file" os.environ[ "CIS_SIGNING_KEY_NAME"] = "signing_key_name=fake-publisher-key_0.priv.pem" temp_profile = fake_profile complex_structures = get_complex_structures() for attr in publisher_rules[condition]: if attr == "primary_username" and temp_profile[attr]["value"] == "None": temp_profile[attr]["value"] = "".join([ random.choice(string.ascii_letters + string.digits) for n in range(32) ]) if attr not in complex_structures: successful_random_publisher = random.choice( publisher_rules[condition][attr]) temp_profile[attr]["signature"]["publisher"][ "name"] = successful_random_publisher u = profile.User(user_structure_json=temp_profile) # Don't sign NULL attributes or invalid publishers if u._attribute_value_set(temp_profile[attr], strict=True) and ( temp_profile[attr]["signature"]["publisher"]["name"] == successful_random_publisher): u.sign_attribute(attr, successful_random_publisher) temp_profile = u.as_dict() else: if attr != "schema" and attr in complex_structures: for k in temp_profile[attr]: try: successful_random_publisher = random.choice( publisher_rules[condition][attr]) except KeyError: successful_random_publisher = random.choice( publisher_rules[condition][attr][k]) temp_profile[attr][k]["signature"]["publisher"][ "name"] = successful_random_publisher u = profile.User(user_structure_json=temp_profile) attribute = "{}.{}".format(attr, k) # Don't sign NULL attributes or invalid publishers if u._attribute_value_set( temp_profile[attr][k], strict=True) and ( temp_profile[attr][k]["signature"]["publisher"] ["name"] == successful_random_publisher): u.sign_attribute(attribute, successful_random_publisher) temp_profile = u.as_dict() return profile.User(user_structure_json=temp_profile)
def test_full_profile_signing(self): u = profile.User(user_id="test") u.access_information.ldap.values = { "SecurityWiki": None, "communitybuild": None, "all_scm_level_1": None, "active_scm_level_1": None, "all_scm_level_3": None, "active_scm_level_3": None, "active_scm_nss": None, "all_scm_sec_sensitive": None, "active_scm_sec_sensitive": None, "all_scm_level_2": None, "active_scm_level_2": None, "all_scm_nss": None, } u.fun_title.value = "test title" for _ in ["ldap", "access_provider", "cis", "hris", "mozilliansorg"]: u.sign_all(publisher_name=_, safety=False) # assert 2 different publisher attributes are signed properly assert u.user_id.signature.publisher.value is not None assert len(u.user_id.signature.publisher.value) > 0 assert u.fun_title.signature.publisher.value is not None assert len(u.fun_title.signature.publisher.value) > 0 assert u.access_information.ldap.signature.publisher.value is not None # Empty attributes should not be signed assert u.last_name.value is None
def test_full_profile_signing(self): u = profile.User(user_id="test") u.sign_all(publisher_name="ldap") assert u.user_id.signature.publisher.value is not None assert len(u.user_id.signature.publisher.value) > 0 # Empty attributes should not be signed assert u.fun_title.value is None
def test_single_attribute_signing_verification(self): u = profile.User(user_id="test") u.sign_attribute("user_id", publisher_name="ldap") ret = u.verify_attribute_signature("user_id") assert ret is not None with pytest.raises(cis_profile.exceptions.SignatureVerificationFailure): u.verify_attribute_signature("fun_title") # Unsigned, so should raise and fail
def test_single_attribute_signing(self): u = profile.User(user_id="test") u.sign_attribute("user_id", publisher_name="ldap") assert u.user_id.signature.publisher.value is not None assert len(u.user_id.signature.publisher.value) > 0 # Empty attributes should be signed in this case since it's directly requested to be signed # (empty but not None) u.fun_title.value = "" u.sign_attribute("fun_title", publisher_name="ldap") assert u.fun_title.signature.publisher.value is not None assert len(u.fun_title.signature.publisher.value) > 0 # test for subitems u.access_information.ldap.values = {"test": None} u.sign_attribute("access_information.ldap", publisher_name="ldap") assert u.access_information.ldap.signature.publisher.value is not None assert len(u.access_information.ldap.signature.publisher.value) > 0 # test for NULL values try: u.active.value = None u.sign_attribute("active", publisher_name="ldap") raise Exception("ValidationFailure", "Should have failed validation, did not") except cis_profile.exceptions.SignatureRefused: pass else: raise Exception("ValidationFailure", "Should have failed validation, did not")
def test_full_profile_signing_verification(self): u = profile.User(user_id="test") u.access_information.ldap.values = {"test_group": None, "test_group_2": None} for _ in ["ldap", "access_provider", "cis", "hris", "mozilliansorg"]: u.sign_all(publisher_name=_, safety=False) ret = u.verify_all_signatures() assert ret is True
def test_user_init(self): u = profile.User() j = u.as_json() d = u.as_dict() assert j is not None assert d is not None assert u is not None
def test_initialize_uuid_and_primary_username(self): u = profile.User(user_id="test") u.initialize_uuid_and_primary_username() assert u.uuid["value"] is not None assert u.uuid["value"] != "" assert u.primary_username["value"] is not None assert u.primary_username["value"].startswith("r--")
def test_profile_update(self): u = profile.User() old_ts = "1971-09-14T13:41:36.000Z" u.user_id.metadata.last_modified = old_ts u.user_id.value = "test" u.update_timestamp("user_id") assert old_ts != u.user_id.metadata.last_modified
def test_verify_all_publishers(self): u = profile.User(user_id="test", first_name="tester") u.verify_all_publishers(u) old_user = profile.User() old_user.active.value = True old_user.active.signature.publisher.name = "access_provider" with pytest.raises(cis_profile.exceptions.PublisherVerificationFailure): u.verify_all_publishers(old_user) old_user_2 = profile.User() old_user_2.first_name.value = "nottest" old_user_2.first_name.signature.publisher.name = "mozilliansorg" u.first_name.value = "test" u.first_name.signature.publisher.name = "access_provider" with pytest.raises(cis_profile.exceptions.PublisherVerificationFailure): u.verify_all_publishers(old_user_2)
def test_filter_scopes(self): u = profile.User() # Make sure a value is non-public u.user_id.metadata.classification = MozillaDataClassification.MOZILLA_CONFIDENTIAL[0] u.staff_information.title.metadata.classification = MozillaDataClassification.MOZILLA_CONFIDENTIAL[0] u.filter_scopes(MozillaDataClassification.PUBLIC) assert "user_id" not in u.as_dict().keys() assert "title" not in u.as_dict()["staff_information"].keys()
def test_initialize_uuid_and_primary_username(self, mock_salt): mock_salt.return_value = "12345" u = profile.User(user_id="test") u.initialize_uuid_and_primary_username() assert u.uuid["value"] is not None assert u.uuid["value"] != "" assert u.primary_username["value"] is not None assert u.primary_username["value"].startswith("r--")
def test_filter_display(self): u = profile.User() # Make sure a value is non-public u.user_id.metadata.display = DisplayLevel.STAFF u.staff_information.title.metadata.display = DisplayLevel.NULL u.filter_scopes(DisplayLevel.PUBLIC) assert "user_id" not in u.as_dict().keys() assert "title" not in u.as_dict()["staff_information"].keys()
def test_full_profile_signing_wrong_publisher(self): u = profile.User() u.fun_title.value = "test title" u.fun_title.signature.publisher.name = "wrong" try: u.sign_all(publisher_name="ldap") except cis_profile.exceptions.SignatureRefused: pass else: raise Exception("ValidationFailure", "Should have failed validation, did not")
def test_verify_can_publish(self): u_old = profile.User(user_id="test") u_new = copy.deepcopy(u_old) u_new.first_name["signature"]["publisher"]["name"] = "failure" u_new.first_name["value"] = "failure" with pytest.raises(cis_profile.exceptions.PublisherVerificationFailure): u_new.verify_can_publish(u_new.first_name, "first_name", previous_attribute=u_old.first_name) is True assert u_new.verify_can_publish(u_new.user_id, "user_id", previous_attribute=u_old.user_id)
def test_verify_can_publish(self): u = profile.User(user_id="test") attrfail = copy.deepcopy(u.first_name) attrfail["signature"]["publisher"]["name"] = "failure" attrfail["value"] = "failure" namefail = "first_name" assert u.verify_can_publish(u.user_id, "user_id") is True with pytest.raises( cis_profile.exceptions.PublisherVerificationFailure): u.verify_can_publish(attrfail, namefail)
def test_null_create_profile(self): empty_profile = profile.User() create_profile = fake_profile.FakeUser( seed=1337, config=fake_profile.FakeProfileConfig().default().create()) update_profile = fake_profile.FakeUser( seed=1337, config=fake_profile.FakeProfileConfig().default()) with pytest.raises(exceptions.PublisherVerificationFailure): update_profile.verify_all_publishers(empty_profile) assert create_profile.verify_all_publishers(empty_profile) is True assert update_profile.verify_all_publishers(create_profile) is True
def test_partial_update_it_should_fail(self, fake_jwks): os.environ["CIS_CONFIG_INI"] = "tests/mozilla-cis.ini" os.environ["AWS_XRAY_SDK_ENABLED"] = "false" os.environ["CIS_ENVIRONMENT"] = "local" os.environ["CIS_DYNALITE_PORT"] = self.dynalite_port os.environ["CIS_REGION_NAME"] = "us-east-1" os.environ["AWS_ACCESS_KEY_ID"] = "foo" os.environ["AWS_SECRET_ACCESS_KEY"] = "bar" os.environ["DEFAULT_AWS_REGION"] = "us-east-1" from cis_change_service import api fake_new_user = FakeUser(config=FakeProfileConfig().minimal()) # Create a brand new user patched_user_profile = ensure_appropriate_publishers_and_sign( fake_new_user.as_dict(), self.publisher_rules, "create") f = FakeBearer() fake_jwks.return_value = json_form_of_pk token = f.generate_bearer_without_scope() api.app.testing = True self.app = api.app.test_client() result = self.app.post( "/v2/user", headers={"Authorization": "Bearer " + token}, data=json.dumps(patched_user_profile.as_json()), content_type="application/json", follow_redirects=True, ) response = json.loads(result.get_data()) assert result.status_code == 200 assert response["condition"] == "create" logger.info("A stub user has been created and verified to exist.") logger.info("Attempting failing partial update.") null_profile = profile.User(user_structure_json=None) null_profile.alternative_name.value = "iamanewpreferredlastname" null_profile.sign_attribute("alternative_name", "mozilliansorg") null_profile.user_id.value = "ad|wrong|LDAP" null_profile.active.value = True null_profile.sign_attribute("active", "access_provider") result = self.app.post( "/v2/user?user_id={}".format("mismatching_user_id"), headers={"Authorization": "Bearer " + token}, data=json.dumps(null_profile.as_json()), content_type="application/json", follow_redirects=True, ) response = json.loads(result.get_data()) assert result.status_code == 400
def test_partial_update_it_should_succeed(self, fake_jwks): os.environ["CIS_STREAM_BYPASS"] = "******" os.environ["AWS_XRAY_SDK_ENABLED"] = "false" os.environ["CIS_VERIFY_PUBLISHERS"] = "true" from cis_change_service import api fake_new_user = FakeUser(config=FakeProfileConfig().minimal()) # Create a brand new user patched_user_profile = ensure_appropriate_publishers_and_sign( fake_new_user.as_dict(), self.publisher_rules, "create") f = FakeBearer() fake_jwks.return_value = json_form_of_pk token = f.generate_bearer_without_scope() api.app.testing = True self.app = api.app.test_client() result = self.app.post( "/v2/user", headers={"Authorization": "Bearer " + token}, data=json.dumps(patched_user_profile.as_json()), content_type="application/json", follow_redirects=True, ) response = json.loads(result.get_data()) assert result.status_code == 200 assert response["condition"] == "create" logger.info("A stub user has been created and verified to exist.") logger.info("Attempting partial update.") # Now let's try a partial update :) null_profile = profile.User(user_structure_json=None) null_profile.active.value = True null_profile.sign_attribute("active", "access_provider") null_profile.last_name.value = "iamanewpreferredlastname" null_profile.sign_attribute("last_name", "mozilliansorg") result = self.app.post( "/v2/user?user_id={}".format(patched_user_profile.user_id.value), headers={"Authorization": "Bearer " + token}, data=json.dumps(null_profile.as_json()), content_type="application/json", follow_redirects=True, ) logger.info(result.get_data()) response = json.loads(result.get_data()) assert result.status_code == 200 assert response["condition"] == "update"
def test_single_attribute_signing(self): u = profile.User(user_id="test") u.sign_attribute("user_id", publisher_name="ldap") assert u.user_id.signature.publisher.value is not None assert len(u.user_id.signature.publisher.value) > 0 # Empty attributes should be signed in this case since it's directly requested to be signed u.sign_attribute("fun_title", publisher_name="ldap") assert u.fun_title.signature.publisher.value is not None assert len(u.fun_title.signature.publisher.value) > 0 # test for subitems u.sign_attribute("access_information.ldap", publisher_name="ldap") assert u.access_information.ldap.signature.publisher.value is not None assert len(u.access_information.ldap.signature.publisher.value) > 0
def test_profile_validation(self): from cis_profile import profile import jsonschema.exceptions u = profile.User() u.validate() u.user_id.value = {"invalid": "test"} try: u.validate() raise Exception("ValidationFailure", "Should have failed validation, did not") except jsonschema.exceptions.ValidationError: pass else: raise Exception("ValidationFailure", "Should have failed validation, did not")
def test_null_create_profile(self): empty_profile = profile.User() create_profile = fake_profile.FakeUser( seed=1337, config=fake_profile.FakeProfileConfig().default().minimal().create( ).no_display()) update_profile = fake_profile.FakeUser( seed=1337, config=fake_profile.FakeProfileConfig().minimal().default( ).no_display()) update_profile.uuid = create_profile.uuid update_profile.user_id = create_profile.user_id update_profile.primary_username.value = "test" # invalid because default publisher is cis update_profile.primary_username.signature.publisher.name = "mozilliansorg" with pytest.raises(exceptions.PublisherVerificationFailure): update_profile.verify_all_publishers(empty_profile) assert create_profile.verify_all_publishers(empty_profile) is True assert update_profile.verify_all_publishers(create_profile) is True