diff --git a/plugins/modules/cm_service_config.py b/plugins/modules/cm_service_config.py
new file mode 100644
index 00000000..436eba18
--- /dev/null
+++ b/plugins/modules/cm_service_config.py
@@ -0,0 +1,282 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright 2024 Cloudera, Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+DOCUMENTATION = r"""
+module: cm_service_config
+short_description: Manage the Cloudera Manager service configuration
+description:
+  - Manage a configuration (service-wide) for the Cloudera Manager service.
+author:
+  - "Webster Mudge (@wmudge)"
+requirements:
+  - cm-client
+options:
+  parameters:
+    description:
+      - The service-wide configuration to set.
+      - To unset a parameter, use C(None) as the value.
+    type: dict
+    required: yes
+    aliases:
+      - params
+  view:
+    description:
+      - The view to materialize.
+    type: str
+    default: summary
+    choices:
+        - summary
+        - full
+extends_documentation_fragment:
+  - ansible.builtin.action_common_attributes
+  - cloudera.cluster.cm_options
+  - cloudera.cluster.cm_endpoint
+  - cloudera.cluster.purge
+  - cloudera.cluster.message
+attributes:
+  check_mode:
+    support: full
+  diff_mode:
+    support: full
+  platform:
+    platforms: all
+"""
+
+EXAMPLES = r"""
+- name: Update (append) several service-wide parameters
+  cloudera.cluster.cm_service_config:
+    host: example.cloudera.com
+    username: "jane_smith"
+    password: "S&peR4Ec*re"
+    parameters:
+      a_configuration: "schema://host:port"
+      another_configuration: 234
+
+- name: Reset a service-wide parameter
+  cloudera.cluster.cm_service_config:
+    host: example.cloudera.com
+    username: "jane_smith"
+    password: "S&peR4Ec*re"
+    parameters:
+      some_conf: None
+
+- name: Update (purge) service-wide parameters
+  cloudera.cluster.cm_service_config:
+    host: example.cloudera.com
+    username: "jane_smith"
+    password: "S&peR4Ec*re"
+    cluster: example-cluster
+    service: example-service
+    parameters:
+      config_one: ValueOne
+      config_two: 4567
+    purge: yes
+
+- name: Reset all service-wide parameters
+  cloudera.cluster.cm_service_config:
+    host: example.cloudera.com
+    username: "jane_smith"
+    password: "S&peR4Ec*re"
+    cluster: example-cluster
+    service: example-service
+    parameters: {}
+    purge: yes
+"""
+
+RETURN = r"""
+config:
+  description: Service-wide configuration details for the Cloudera Manager service.
+  type: list
+  elements: dict
+  contains:
+    name:
+      description: The canonical name that identifies this configuration parameter.
+      type: str
+      returned: always
+    value:
+      description:
+        - The user-defined value.
+        - When absent, the default value (if any) will be used.
+        - Can also be absent, when enumerating allowed configs.
+      type: str
+      returned: always
+    required:
+      description:
+        - Whether this configuration is required for the service.
+        - If any required configuration is not set, operations on the service may not work.
+        - Available using I(view=full).
+      type: bool
+      returned: when supported
+    default:
+      description:
+        - The default value.
+        - Available using I(view=full).
+      type: str
+      returned: when supported
+    display_name:
+      description:
+        - A user-friendly name of the parameters, as would have been shown in the web UI.
+        - Available using I(view=full).
+      type: str
+      returned: when supported
+    description:
+      description:
+        - A textual description of the parameter.
+        - Available using I(view=full).
+      type: str
+      returned: when supported
+    related_name:
+      description:
+        - If applicable, contains the related configuration variable used by the source project.
+        - Available using I(view=full).
+      type: str
+      returned: when supported
+    sensitive:
+      description:
+        - Whether this configuration is sensitive, i.e. contains information such as passwords, which might affect how the value of this configuration might be shared by the caller.
+      type: bool
+      returned: when supported
+    validation_state:
+      description:
+        - State of the configuration parameter after validation.
+        - Available using I(view=full).
+      type: str
+      returned: when supported
+      sample:
+        - OK
+        - WARNING
+        - ERROR
+    validation_message:
+      description:
+        - A message explaining the parameter's validation state.
+        - Available using I(view=full).
+      type: str
+      returned: when supported
+    validation_warnings_suppressed:
+      description:
+        - Whether validation warnings associated with this parameter are suppressed.
+        - In general, suppressed validation warnings are hidden in the Cloudera Manager UI.
+        - Configurations that do not produce warnings will not contain this field.
+        - Available using I(view=full).
+      type: bool
+      returned: when supported
+"""
+
+import json
+
+from ansible_collections.cloudera.cluster.plugins.module_utils.cm_utils import (
+    ClouderaManagerMutableModule,
+)
+from ansible_collections.cloudera.cluster.plugins.module_utils.service_utils import (
+    ServiceConfigUpdates,
+)
+
+
+from cm_client import (
+    MgmtServiceResourceApi,
+)
+from cm_client.rest import ApiException
+
+
+class ClouderaManagerServiceConfig(ClouderaManagerMutableModule):
+    def __init__(self, module):
+        super(ClouderaManagerServiceConfig, self).__init__(module)
+
+        # Set the parameters
+        self.params = self.get_param("parameters")
+        self.purge = self.get_param("purge")
+        self.view = self.get_param("view")
+
+        # Initialize the return value
+        self.changed = False
+        self.diff = {}
+        self.config = []
+
+        # Execute the logic
+        self.process()
+
+    @ClouderaManagerMutableModule.handle_process
+    def process(self):
+        refresh = True
+        api_instance = MgmtServiceResourceApi(self.api_client)
+
+        try:
+            existing = api_instance.read_service_config()
+        except ApiException as ex:
+            if ex.status == 404:
+                self.module.fail_json(msg=json.loads(ex.body)["message"])
+            else:
+                raise ex
+
+        updates = ServiceConfigUpdates(existing, self.params, self.purge)
+
+        if updates.changed:
+            self.changed = True
+
+            if self.module._diff:
+                self.diff = updates.diff
+
+            if not self.module.check_mode:
+                self.config = [
+                    p.to_dict()
+                    for p in api_instance.update_service_config(
+                        message=self.message, body=updates.config
+                    ).items
+                ]
+
+                if self.view == "full":
+                    refresh = False
+
+        if refresh:
+            self.config = [
+                p.to_dict()
+                for p in api_instance.read_service_config(view=self.view).items
+            ]
+
+
+def main():
+    module = ClouderaManagerMutableModule.ansible_module(
+        argument_spec=dict(
+            parameters=dict(type="dict", required=True, aliases=["params"]),
+            purge=dict(type="bool", default=False),
+            view=dict(
+                default="summary",
+                choices=["summary", "full"],
+            ),
+        ),
+        supports_check_mode=True,
+    )
+
+    result = ClouderaManagerServiceConfig(module)
+
+    output = dict(
+        changed=result.changed,
+        config=result.config,
+    )
+
+    if module._diff:
+        output.update(diff=result.diff)
+
+    if result.debug:
+        log = result.log_capture.getvalue()
+        output.update(debug=log, debug_lines=log.split("\n"))
+
+    module.exit_json(**output)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/tests/unit/plugins/modules/cm_service_config/test_cm_service_config.py b/tests/unit/plugins/modules/cm_service_config/test_cm_service_config.py
new file mode 100644
index 00000000..e7f81dbb
--- /dev/null
+++ b/tests/unit/plugins/modules/cm_service_config/test_cm_service_config.py
@@ -0,0 +1,175 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2024 Cloudera, Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import logging
+import os
+import pytest
+
+from ansible_collections.cloudera.cluster.plugins.modules import cm_service_config
+from ansible_collections.cloudera.cluster.tests.unit import (
+    AnsibleExitJson,
+    AnsibleFailJson,
+)
+
+LOG = logging.getLogger(__name__)
+
+
+@pytest.fixture
+def conn():
+    conn = dict(username=os.getenv("CM_USERNAME"), password=os.getenv("CM_PASSWORD"))
+
+    if os.getenv("CM_HOST", None):
+        conn.update(host=os.getenv("CM_HOST"))
+
+    if os.getenv("CM_PORT", None):
+        conn.update(port=os.getenv("CM_PORT"))
+
+    if os.getenv("CM_ENDPOINT", None):
+        conn.update(url=os.getenv("CM_ENDPOINT"))
+
+    if os.getenv("CM_PROXY", None):
+        conn.update(proxy=os.getenv("CM_PROXY"))
+
+    return {
+        **conn,
+        "verify_tls": "no",
+        "debug": "no",
+    }
+
+
+def test_missing_required(conn, module_args):
+    module_args(conn)
+
+    with pytest.raises(AnsibleFailJson, match="parameters"):
+        cm_service_config.main()
+
+
+def test_present_invalid_parameter(conn, module_args):
+    conn.update(
+        parameters=dict(example="Example"),
+    )
+    module_args(conn)
+
+    with pytest.raises(
+        AnsibleFailJson, match="Unknown configuration attribute 'example'"
+    ):
+        cm_service_config.main()
+
+
+def test_set_parameters(conn, module_args):
+    conn.update(
+        parameters=dict(mgmt_emit_sensitive_data_in_stderr=True),
+        # _ansible_check_mode=True,
+        # _ansible_diff=True,
+        message="test_cm_service_config::test_set_parameters",
+    )
+    module_args(conn)
+
+    with pytest.raises(AnsibleExitJson) as e:
+        cm_service_config.main()
+
+    assert e.value.changed == True
+    assert {c["name"]: c["value"] for c in e.value.config}[
+        "mgmt_emit_sensitive_data_in_stderr"
+    ] == "true"
+
+    # Idempotency
+    with pytest.raises(AnsibleExitJson) as e:
+        cm_service_config.main()
+
+    assert e.value.changed == False
+    assert {c["name"]: c["value"] for c in e.value.config}[
+        "mgmt_emit_sensitive_data_in_stderr"
+    ] == "true"
+
+
+def test_unset_parameters(conn, module_args):
+    conn.update(
+        parameters=dict(mgmt_emit_sensitive_data_in_stderr=None),
+        message="test_cm_service_config::test_unset_parameters",
+    )
+    module_args(conn)
+
+    with pytest.raises(AnsibleExitJson) as e:
+        cm_service_config.main()
+
+    assert e.value.changed == True
+    results = {c["name"]: c["value"] for c in e.value.config}
+    assert "mgmt_emit_sensitive_data_in_stderr" not in results
+
+    with pytest.raises(AnsibleExitJson) as e:
+        cm_service_config.main()
+
+    # Idempotency
+    assert e.value.changed == False
+    results = {c["name"]: c["value"] for c in e.value.config}
+    assert "mgmt_emit_sensitive_data_in_stderr" not in results
+
+
+def test_set_parameters_with_purge(conn, module_args):
+    conn.update(
+        parameters=dict(mgmt_emit_sensitive_data_in_stderr=True),
+        purge=True,
+        message="test_cm_service_config::test_set_parameters_with_purge",
+        # _ansible_check_mode=True,
+        # _ansible_diff=True,
+    )
+    module_args(conn)
+
+    with pytest.raises(AnsibleExitJson) as e:
+        cm_service_config.main()
+
+    assert e.value.changed == True
+    assert {c["name"]: c["value"] for c in e.value.config}[
+        "mgmt_emit_sensitive_data_in_stderr"
+    ] == "true"
+
+    with pytest.raises(AnsibleExitJson) as e:
+        cm_service_config.main()
+
+    # Idempotency
+    assert e.value.changed == False
+    assert {c["name"]: c["value"] for c in e.value.config}[
+        "mgmt_emit_sensitive_data_in_stderr"
+    ] == "true"
+
+
+def test_purge_all_parameters(conn, module_args):
+    conn.update(
+        parameters=dict(),
+        purge=True,
+        message="test_cm_service_config::test_purge_all_parameters",
+        # _ansible_check_mode=True,
+        # _ansible_diff=True,
+    )
+    module_args(conn)
+
+    with pytest.raises(AnsibleExitJson) as e:
+        cm_service_config.main()
+
+    assert e.value.changed == True
+    assert len(e.value.config) == 0
+
+    # Idempotency
+    with pytest.raises(AnsibleExitJson) as e:
+        cm_service_config.main()
+
+    assert e.value.changed == False
+    assert len(e.value.config) == 0