Repository: getmoto/moto
Pull request #8881 (2025-05-07 13:52:50)

[Glue] Resource Policies
Resolves https://github.com/getmoto/moto/issues/8861

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/getmoto/moto/pull/8881?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) Report
Attention: Patch coverage is `94.23077%` with `3 lines` in your changes missing coverage. Please review.
> Project coverage is 92.85%. Comparing base [(`570069d`)](https://app.codecov.io/gh/getmoto/moto/commit/570069d50a0d3a5b1de649c0b2410d3a0397f6fb?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) to head [(`fd66ad4`)](https://app.codecov.io/gh/getmoto/moto/commit/fd66ad414e897aa0aa092e368c637940b053b601?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).

| [Files with missing lines](https://app.codecov.io/gh/getmoto/moto/pull/8881?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Patch % | Lines |
|---|---|---|
| [moto/glue/responses.py](https://app.codecov.io/gh/getmoto/moto/pull/8881?src=pr&el=tree&filepath=moto%2Fglue%2Fresponses.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#diff-bW90by9nbHVlL3Jlc3BvbnNlcy5weQ==) | 85.00% | [3 Missing :warning: ](https://app.codecov.io/gh/getmoto/moto/pull/8881?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) |

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master    #8881   +/-   ##
=======================================
  Coverage   92.85%   92.85%           
=======================================
  Files        1282     1282           
  Lines      111792   111844   +52     
=======================================
+ Hits       103804   103854   +50     
- Misses       7988     7990    +2     
```

| [Flag](https://app.codecov.io/gh/getmoto/moto/pull/8881/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Coverage Δ | |
|---|---|---|
| [servertests](https://app.codecov.io/gh/getmoto/moto/pull/8881/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `27.97% <13.46%> (-0.01%)` | :arrow_down: |
| [unittests](https://app.codecov.io/gh/getmoto/moto/pull/8881/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `92.83% <94.23%> (+<0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/getmoto/moto/pull/8881?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>

Patch:
diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md
index 0d25141b5..ec9c35299 100644
--- a/IMPLEMENTATION_COVERAGE.md
+++ b/IMPLEMENTATION_COVERAGE.md
@@ -1001,6 +1001,78 @@
 - [X] update_cost_category_definition
 </details>
 
+## clouddirectory
+<details>
+<summary>10% implemented</summary>
+
+- [ ] add_facet_to_object
+- [ ] apply_schema
+- [ ] attach_object
+- [ ] attach_policy
+- [ ] attach_to_index
+- [ ] attach_typed_link
+- [ ] batch_read
+- [ ] batch_write
+- [X] create_directory
+- [ ] create_facet
+- [ ] create_index
+- [ ] create_object
+- [ ] create_schema
+- [ ] create_typed_link_facet
+- [X] delete_directory
+- [ ] delete_facet
+- [ ] delete_object
+- [ ] delete_schema
+- [ ] delete_typed_link_facet
+- [ ] detach_from_index
+- [ ] detach_object
+- [ ] detach_policy
+- [ ] detach_typed_link
+- [ ] disable_directory
+- [ ] enable_directory
+- [ ] get_applied_schema_version
+- [X] get_directory
+- [ ] get_facet
+- [ ] get_link_attributes
+- [ ] get_object_attributes
+- [ ] get_object_information
+- [ ] get_schema_as_json
+- [ ] get_typed_link_facet_information
+- [ ] list_applied_schema_arns
+- [ ] list_attached_indices
+- [ ] list_development_schema_arns
+- [X] list_directories
+- [ ] list_facet_attributes
+- [ ] list_facet_names
+- [ ] list_incoming_typed_links
+- [ ] list_index
+- [ ] list_managed_schema_arns
+- [ ] list_object_attributes
+- [ ] list_object_children
+- [ ] list_object_parent_paths
+- [ ] list_object_parents
+- [ ] list_object_policies
+- [ ] list_outgoing_typed_links
+- [ ] list_policy_attachments
+- [ ] list_published_schema_arns
+- [X] list_tags_for_resource
+- [ ] list_typed_link_facet_attributes
+- [ ] list_typed_link_facet_names
+- [ ] lookup_policy
+- [ ] publish_schema
+- [ ] put_schema_from_json
+- [ ] remove_facet_from_object
+- [X] tag_resource
+- [X] untag_resource
+- [ ] update_facet
+- [ ] update_link_attributes
+- [ ] update_object_attributes
+- [ ] update_schema
+- [ ] update_typed_link_facet
+- [ ] upgrade_applied_schema
+- [ ] upgrade_published_schema
+</details>
+
 ## cloudformation
 <details>
 <summary>37% implemented</summary>
@@ -2193,7 +2265,7 @@
 
 ## dms
 <details>
-<summary>6% implemented</summary>
+<summary>8% implemented</summary>
 
 - [ ] add_tags_to_resource
 - [ ] apply_pending_maintenance_action
@@ -2201,7 +2273,7 @@
 - [ ] cancel_replication_task_assessment_run
 - [ ] create_data_migration
 - [ ] create_data_provider
-- [ ] create_endpoint
+- [X] create_endpoint
 - [ ] create_event_subscription
 - [ ] create_fleet_advisor_collector
 - [ ] create_instance_profile
@@ -2234,7 +2306,7 @@
 - [ ] describe_data_providers
 - [ ] describe_endpoint_settings
 - [ ] describe_endpoint_types
-- [ ] describe_endpoints
+- [X] describe_endpoints
 - [ ] describe_engine_versions
 - [ ] describe_event_categories
 - [ ] describe_event_subscriptions
@@ -2271,7 +2343,7 @@
 - [ ] describe_table_statistics
 - [ ] export_metadata_model_assessment
 - [ ] import_certificate
-- [ ] list_tags_for_resource
+- [X] list_tags_for_resource
 - [ ] modify_conversion_configuration
 - [ ] modify_data_migration
 - [ ] modify_data_provider
@@ -4194,7 +4266,7 @@
 - [ ] get_plan
 - [X] get_registry
 - [ ] get_resource_policies
-- [ ] get_resource_policy
+- [X] get_resource_policy
 - [X] get_schema
 - [X] get_schema_by_definition
 - [X] get_schema_version
@@ -4250,7 +4322,7 @@
 - [ ] modify_integration
 - [X] put_data_catalog_encryption_settings
 - [ ] put_data_quality_profile_annotation
-- [ ] put_resource_policy
+- [X] put_resource_policy
 - [X] put_schema_version_metadata
 - [ ] put_workflow_run_properties
 - [ ] query_schema_version_metadata
@@ -6109,6 +6181,57 @@
 - [X] stop_db_cluster
 </details>
 
+## network-firewall
+<details>
+<summary>11% implemented</summary>
+
+- [ ] associate_firewall_policy
+- [ ] associate_subnets
+- [X] create_firewall
+- [ ] create_firewall_policy
+- [ ] create_rule_group
+- [ ] create_tls_inspection_configuration
+- [ ] delete_firewall
+- [ ] delete_firewall_policy
+- [ ] delete_resource_policy
+- [ ] delete_rule_group
+- [ ] delete_tls_inspection_configuration
+- [X] describe_firewall
+- [ ] describe_firewall_policy
+- [ ] describe_flow_operation
+- [X] describe_logging_configuration
+- [ ] describe_resource_policy
+- [ ] describe_rule_group
+- [ ] describe_rule_group_metadata
+- [ ] describe_tls_inspection_configuration
+- [ ] disassociate_subnets
+- [ ] get_analysis_report_results
+- [ ] list_analysis_reports
+- [ ] list_firewall_policies
+- [X] list_firewalls
+- [ ] list_flow_operation_results
+- [ ] list_flow_operations
+- [ ] list_rule_groups
+- [ ] list_tags_for_resource
+- [ ] list_tls_inspection_configurations
+- [ ] put_resource_policy
+- [ ] start_analysis_report
+- [ ] start_flow_capture
+- [ ] start_flow_flush
+- [ ] tag_resource
+- [ ] untag_resource
+- [ ] update_firewall_analysis_settings
+- [ ] update_firewall_delete_protection
+- [ ] update_firewall_description
+- [ ] update_firewall_encryption_configuration
+- [ ] update_firewall_policy
+- [ ] update_firewall_policy_change_protection
+- [X] update_logging_configuration
+- [ ] update_rule_group
+- [ ] update_subnet_change_protection
+- [ ] update_tls_inspection_configuration
+</details>
+
 ## networkmanager
 <details>
 <summary>20% implemented</summary>
@@ -7820,7 +7943,7 @@
 
 ## s3
 <details>
-<summary>69% implemented</summary>
+<summary>72% implemented</summary>
 
 - [X] abort_multipart_upload
 - [X] complete_multipart_upload
@@ -7853,7 +7976,7 @@
 - [X] get_bucket_cors
 - [X] get_bucket_encryption
 - [ ] get_bucket_intelligent_tiering_configuration
-- [ ] get_bucket_inventory_configuration
+- [X] get_bucket_inventory_configuration
 - [X] get_bucket_lifecycle
 - [ ] get_bucket_lifecycle_configuration
 - [X] get_bucket_location
@@ -7883,7 +8006,7 @@
 - [X] head_object
 - [ ] list_bucket_analytics_configurations
 - [ ] list_bucket_intelligent_tiering_configurations
-- [ ] list_bucket_inventory_configurations
+- [X] list_bucket_inventory_configurations
 - [ ] list_bucket_metrics_configurations
 - [X] list_buckets
 - [ ] list_directory_buckets
@@ -7898,7 +8021,7 @@
 - [X] put_bucket_cors
 - [X] put_bucket_encryption
 - [ ] put_bucket_intelligent_tiering_configuration
-- [ ] put_bucket_inventory_configuration
+- [X] put_bucket_inventory_configuration
 - [X] put_bucket_lifecycle
 - [ ] put_bucket_lifecycle_configuration
 - [X] put_bucket_logging
@@ -9957,7 +10080,6 @@
 - cleanroomsml
 - cloud9
 - cloudcontrol
-- clouddirectory
 - cloudfront-keyvaluestore
 - cloudhsm
 - cloudsearch
@@ -10086,7 +10208,6 @@
 - mwaa
 - neptune-graph
 - neptunedata
-- network-firewall
 - networkflowmonitor
 - networkmonitor
 - notifications
diff --git a/docs/docs/services/clouddirectory.rst b/docs/docs/services/clouddirectory.rst
new file mode 100644
index 000000000..3870d3692
--- /dev/null
+++ b/docs/docs/services/clouddirectory.rst
@@ -0,0 +1,85 @@
+.. _implementedservice_clouddirectory:
+
+.. |start-h3| raw:: html
+
+    <h3>
+
+.. |end-h3| raw:: html
+
+    </h3>
+
+==============
+clouddirectory
+==============
+
+.. autoclass:: moto.clouddirectory.models.CloudDirectoryBackend
+
+|start-h3| Implemented features for this service |end-h3|
+
+- [ ] add_facet_to_object
+- [ ] apply_schema
+- [ ] attach_object
+- [ ] attach_policy
+- [ ] attach_to_index
+- [ ] attach_typed_link
+- [ ] batch_read
+- [ ] batch_write
+- [X] create_directory
+- [ ] create_facet
+- [ ] create_index
+- [ ] create_object
+- [ ] create_schema
+- [ ] create_typed_link_facet
+- [X] delete_directory
+- [ ] delete_facet
+- [ ] delete_object
+- [ ] delete_schema
+- [ ] delete_typed_link_facet
+- [ ] detach_from_index
+- [ ] detach_object
+- [ ] detach_policy
+- [ ] detach_typed_link
+- [ ] disable_directory
+- [ ] enable_directory
+- [ ] get_applied_schema_version
+- [X] get_directory
+- [ ] get_facet
+- [ ] get_link_attributes
+- [ ] get_object_attributes
+- [ ] get_object_information
+- [ ] get_schema_as_json
+- [ ] get_typed_link_facet_information
+- [ ] list_applied_schema_arns
+- [ ] list_attached_indices
+- [ ] list_development_schema_arns
+- [X] list_directories
+- [ ] list_facet_attributes
+- [ ] list_facet_names
+- [ ] list_incoming_typed_links
+- [ ] list_index
+- [ ] list_managed_schema_arns
+- [ ] list_object_attributes
+- [ ] list_object_children
+- [ ] list_object_parent_paths
+- [ ] list_object_parents
+- [ ] list_object_policies
+- [ ] list_outgoing_typed_links
+- [ ] list_policy_attachments
+- [ ] list_published_schema_arns
+- [X] list_tags_for_resource
+- [ ] list_typed_link_facet_attributes
+- [ ] list_typed_link_facet_names
+- [ ] lookup_policy
+- [ ] publish_schema
+- [ ] put_schema_from_json
+- [ ] remove_facet_from_object
+- [X] tag_resource
+- [X] untag_resource
+- [ ] update_facet
+- [ ] update_link_attributes
+- [ ] update_object_attributes
+- [ ] update_schema
+- [ ] update_typed_link_facet
+- [ ] upgrade_applied_schema
+- [ ] upgrade_published_schema
+
diff --git a/docs/docs/services/comprehend.rst b/docs/docs/services/comprehend.rst
index cd8e710ef..976ca99c7 100644
--- a/docs/docs/services/comprehend.rst
+++ b/docs/docs/services/comprehend.rst
@@ -29,8 +29,8 @@ comprehend
 - [X] create_endpoint
 - [X] create_entity_recognizer
   
-The ClientRequestToken-parameter is not yet implemented
-
+        The ClientRequestToken-parameter is not yet implemented
+        
 
 - [X] create_flywheel
 - [X] delete_document_classifier
@@ -68,32 +68,32 @@ The ClientRequestToken-parameter is not yet implemented
 - [ ] list_document_classifier_summaries
 - [X] list_document_classifiers
   
-List document classifiers with optional filtering.
-Pagination is not yet implemented.
-
+        List document classifiers with optional filtering.
+        Pagination is not yet implemented.
+        
 
 - [ ] list_dominant_language_detection_jobs
 - [X] list_endpoints
   
-List endpoints with optional filtering.
-Pagination is not yet implemented.
-
+        List endpoints with optional filtering.
+        Pagination is not yet implemented.
+        
 
 - [ ] list_entities_detection_jobs
 - [ ] list_entity_recognizer_summaries
 - [X] list_entity_recognizers
   
-Pagination is not yet implemented.
-The following filters are not yet implemented: Status, SubmitTimeBefore, SubmitTimeAfter
-
+        Pagination is not yet implemented.
+        The following filters are not yet implemented: Status, SubmitTimeBefore, SubmitTimeAfter
+        
 
 - [ ] list_events_detection_jobs
 - [ ] list_flywheel_iteration_history
 - [X] list_flywheels
   
-List flywheels with optional filtering.
-Pagination is not yet implemented.
-
+        List flywheels with optional filtering.
+        Pagination is not yet implemented.
+        
 
 - [ ] list_key_phrases_detection_jobs
 - [ ] list_pii_entities_detection_jobs
diff --git a/docs/docs/services/dms.rst b/docs/docs/services/dms.rst
index d0a5e0092..b526f60f6 100644
--- a/docs/docs/services/dms.rst
+++ b/docs/docs/services/dms.rst
@@ -20,7 +20,7 @@ dms
 - [ ] cancel_replication_task_assessment_run
 - [ ] create_data_migration
 - [ ] create_data_provider
-- [ ] create_endpoint
+- [X] create_endpoint
 - [ ] create_event_subscription
 - [ ] create_fleet_advisor_collector
 - [ ] create_instance_profile
@@ -58,7 +58,7 @@ dms
 - [ ] describe_data_providers
 - [ ] describe_endpoint_settings
 - [ ] describe_endpoint_types
-- [ ] describe_endpoints
+- [X] describe_endpoints
 - [ ] describe_engine_versions
 - [ ] describe_event_categories
 - [ ] describe_event_subscriptions
@@ -101,7 +101,7 @@ dms
 - [ ] describe_table_statistics
 - [ ] export_metadata_model_assessment
 - [ ] import_certificate
-- [ ] list_tags_for_resource
+- [X] list_tags_for_resource
 - [ ] modify_conversion_configuration
 - [ ] modify_data_migration
 - [ ] modify_data_provider
diff --git a/docs/docs/services/glue.rst b/docs/docs/services/glue.rst
index d9be0d2ab..e1ce4657b 100644
--- a/docs/docs/services/glue.rst
+++ b/docs/docs/services/glue.rst
@@ -166,7 +166,7 @@ glue
 - [ ] get_plan
 - [X] get_registry
 - [ ] get_resource_policies
-- [ ] get_resource_policy
+- [X] get_resource_policy
 - [X] get_schema
 - [X] get_schema_by_definition
 - [X] get_schema_version
@@ -222,7 +222,7 @@ glue
 - [ ] modify_integration
 - [X] put_data_catalog_encryption_settings
 - [ ] put_data_quality_profile_annotation
-- [ ] put_resource_policy
+- [X] put_resource_policy
 - [X] put_schema_version_metadata
 - [ ] put_workflow_run_properties
 - [ ] query_schema_version_metadata
diff --git a/docs/docs/services/network-firewall.rst b/docs/docs/services/network-firewall.rst
new file mode 100644
index 000000000..0895bedcd
--- /dev/null
+++ b/docs/docs/services/network-firewall.rst
@@ -0,0 +1,64 @@
+.. _implementedservice_network-firewall:
+
+.. |start-h3| raw:: html
+
+    <h3>
+
+.. |end-h3| raw:: html
+
+    </h3>
+
+================
+network-firewall
+================
+
+.. autoclass:: moto.networkfirewall.models.NetworkFirewallBackend
+
+|start-h3| Implemented features for this service |end-h3|
+
+- [ ] associate_firewall_policy
+- [ ] associate_subnets
+- [X] create_firewall
+- [ ] create_firewall_policy
+- [ ] create_rule_group
+- [ ] create_tls_inspection_configuration
+- [ ] delete_firewall
+- [ ] delete_firewall_policy
+- [ ] delete_resource_policy
+- [ ] delete_rule_group
+- [ ] delete_tls_inspection_configuration
+- [X] describe_firewall
+- [ ] describe_firewall_policy
+- [ ] describe_flow_operation
+- [X] describe_logging_configuration
+- [ ] describe_resource_policy
+- [ ] describe_rule_group
+- [ ] describe_rule_group_metadata
+- [ ] describe_tls_inspection_configuration
+- [ ] disassociate_subnets
+- [ ] get_analysis_report_results
+- [ ] list_analysis_reports
+- [ ] list_firewall_policies
+- [X] list_firewalls
+- [ ] list_flow_operation_results
+- [ ] list_flow_operations
+- [ ] list_rule_groups
+- [ ] list_tags_for_resource
+- [ ] list_tls_inspection_configurations
+- [ ] put_resource_policy
+- [ ] start_analysis_report
+- [ ] start_flow_capture
+- [ ] start_flow_flush
+- [ ] tag_resource
+- [ ] untag_resource
+- [ ] update_firewall_analysis_settings
+- [ ] update_firewall_delete_protection
+- [ ] update_firewall_description
+- [ ] update_firewall_encryption_configuration
+- [ ] update_firewall_policy
+- [ ] update_firewall_policy_change_protection
+- [X] update_logging_configuration
+- [ ] update_rule_group
+- [ ] update_subnet_change_protection
+- [ ] update_tls_inspection_configuration
+
diff --git a/docs/docs/services/s3.rst b/docs/docs/services/s3.rst
index 5162361cb..f5d238441 100644
--- a/docs/docs/services/s3.rst
+++ b/docs/docs/services/s3.rst
@@ -47,7 +47,7 @@ s3
 - [X] get_bucket_cors
 - [X] get_bucket_encryption
 - [ ] get_bucket_intelligent_tiering_configuration
-- [ ] get_bucket_inventory_configuration
+- [X] get_bucket_inventory_configuration
 - [X] get_bucket_lifecycle
 - [ ] get_bucket_lifecycle_configuration
 - [X] get_bucket_location
@@ -81,7 +81,7 @@ s3
 - [X] head_object
 - [ ] list_bucket_analytics_configurations
 - [ ] list_bucket_intelligent_tiering_configurations
-- [ ] list_bucket_inventory_configurations
+- [X] list_bucket_inventory_configurations
 - [ ] list_bucket_metrics_configurations
 - [X] list_buckets
 - [ ] list_directory_buckets
@@ -124,7 +124,7 @@ s3
 
 - [X] put_bucket_encryption
 - [ ] put_bucket_intelligent_tiering_configuration
-- [ ] put_bucket_inventory_configuration
+- [X] put_bucket_inventory_configuration
 - [X] put_bucket_lifecycle
 - [ ] put_bucket_lifecycle_configuration
 - [X] put_bucket_logging
diff --git a/moto/glue/models.py b/moto/glue/models.py
index 91bc61eae..a81bafc42 100644
--- a/moto/glue/models.py
+++ b/moto/glue/models.py
@@ -1,3 +1,4 @@
+import hashlib
 import json
 import re
 import time
@@ -210,6 +211,8 @@ class GlueBackend(BaseBackend):
 
     def __init__(self, region_name: str, account_id: str):
         super().__init__(region_name, account_id)
+        self.region_name = region_name
+        self.account_id = account_id
         self.databases: Dict[str, FakeDatabase] = OrderedDict()
         self.crawlers: Dict[str, FakeCrawler] = OrderedDict()
         self.connections: Dict[str, FakeConnection] = OrderedDict()
@@ -223,6 +226,8 @@ class GlueBackend(BaseBackend):
         self.num_schema_versions = 0
         self.dev_endpoints: Dict[str, FakeDevEndpoint] = OrderedDict()
         self.data_catalog_encryption_settings: Dict[str, Dict[str, Any]] = {}
+        self.resource_policies: Dict[str, Dict[str, Any]] = {}
+        self.default_catalog_arn = f"arn:{get_partition(self.region_name)}:glue:{self.region_name}:{self.account_id}:catalog"
 
     def create_database(
         self,
@@ -1276,6 +1281,85 @@ class GlueBackend(BaseBackend):
 
         return response
 
+    def put_resource_policy(
+        self,
+        policy_in_json: str,
+        resource_arn: Optional[str] = None,
+        policy_hash_condition: Optional[str] = None,
+        policy_exists_condition: Optional[str] = None,
+        enable_hybrid: Optional[str] = None,
+    ) -> Dict[str, str]:
+        if resource_arn is None:
+            resource_arn = self.default_catalog_arn
+
+        policy_dict = self.resource_policies.get(resource_arn, {})
+
+        if policy_exists_condition and policy_exists_condition != "NONE":
+            if policy_exists_condition == "MUST_EXIST" and not policy_dict:
+                raise JsonRESTError(
+                    "ResourceNumberLimitExceededException", "Policy does not exist"
+                )
+            elif policy_exists_condition == "NOT_EXIST" and policy_dict:
+                raise JsonRESTError(
+                    "ResourceNumberLimitExceededException", "Policy already exists"
+                )
+
+        if (
+            policy_hash_condition
+            and policy_dict
+            and policy_hash_condition != policy_dict.get("PolicyHash")
+        ):
+            raise JsonRESTError(
+                "ConcurrentModificationException", "Policy hash condition not met"
+            )
+
+        policy_hash = hashlib.md5(policy_in_json.encode()).hexdigest()
+
+        if not policy_dict:
+            policy_dict = {
+                "PolicyInJson": policy_in_json,
+                "PolicyHash": policy_hash,
+                "CreateTime": utcnow(),
+                "UpdateTime": utcnow(),
+            }
+        else:
+            policy_dict.update(
+                {
+                    "PolicyInJson": policy_in_json,
+                    "PolicyHash": policy_hash,
+                    "UpdateTime": utcnow(),
+                }
+            )
+
+        if enable_hybrid in ("TRUE", "FALSE"):
+            policy_dict["EnableHybrid"] = enable_hybrid
+
+        self.resource_policies[resource_arn] = policy_dict
+
+        return {"PolicyHash": policy_hash}
+
+    def get_resource_policy(self, resource_arn: Optional[str] = None) -> Dict[str, Any]:
+        if resource_arn is None:
+            resource_arn = self.default_catalog_arn
+
+        if resource_arn not in self.resource_policies:
+            return {}
+
+        policy = self.resource_policies[resource_arn]
+
+        response = {
+            "PolicyInJson": policy["PolicyInJson"],
+            "PolicyHash": policy["PolicyHash"],
+            "CreateTime": policy["CreateTime"].isoformat()
+            if isinstance(policy["CreateTime"], datetime)
+            else policy["CreateTime"],
+            "UpdateTime": policy["UpdateTime"].isoformat()
+            if isinstance(policy["UpdateTime"], datetime)
+            else policy["UpdateTime"],
+        }
+
+        return response
+
 
 class FakeDatabase(BaseModel):
     def __init__(
diff --git a/moto/glue/responses.py b/moto/glue/responses.py
index 77841cdbc..6effc42b3 100644
--- a/moto/glue/responses.py
+++ b/moto/glue/responses.py
@@ -1,4 +1,5 @@
 import json
+from datetime import datetime
 from typing import Any, Dict, List
 
 from moto.core.common_types import TYPE_RESPONSE
@@ -14,6 +15,13 @@ from .models import (
 )
 
 
+class DateTimeEncoder(json.JSONEncoder):
+    def default(self, o: Any) -> Any:
+        if isinstance(o, datetime):
+            return o.isoformat()
+        return super().default(o)
+
+
 class GlueResponse(BaseResponse):
     def __init__(self) -> None:
         super().__init__(service_name="glue")
@@ -875,3 +883,30 @@ class GlueResponse(BaseResponse):
         )
 
         return json.dumps(response)
+
+    def put_resource_policy(self) -> str:
+        params = json.loads(self.body)
+        policy_in_json = params.get("PolicyInJson")
+        resource_arn = params.get("ResourceArn")
+        policy_hash_condition = params.get("PolicyHashCondition")
+        policy_exists_condition = params.get("PolicyExistsCondition")
+        enable_hybrid = params.get("EnableHybrid")
+
+        policy_hash = self.glue_backend.put_resource_policy(
+            policy_in_json=policy_in_json,
+            resource_arn=resource_arn,
+            policy_hash_condition=policy_hash_condition,
+            policy_exists_condition=policy_exists_condition,
+            enable_hybrid=enable_hybrid,
+        )
+
+        return json.dumps(policy_hash, cls=DateTimeEncoder)
+
+    def get_resource_policy(self) -> str:
+        params = json.loads(self.body)
+        resource_arn = params.get("ResourceArn")
+        response = self.glue_backend.get_resource_policy(
+            resource_arn=resource_arn,
+        )
+
+        return json.dumps(response, cls=DateTimeEncoder)
diff --git a/moto/ram/models.py b/moto/ram/models.py
index 87915b088..69fb55375 100644
--- a/moto/ram/models.py
+++ b/moto/ram/models.py
@@ -225,5 +225,82 @@ class ResourceAccessManagerBackend(BaseBackend):
 
         return dict(returnValue=True)
 
+    def get_resource_share_associations(self, **kwargs: Any) -> Dict[str, Any]:
+        association_type = kwargs["associationType"]
+        if association_type not in ["PRINCIPAL", "RESOURCE"]:
+            raise InvalidParameterException(
+                f"{association_type} is not a valid association type. "
+                "Specify either PRINCIPAL or RESOURCE and try again."
+            )
+
+        association_status = kwargs.get("associationStatus")
+        if association_status and association_status not in [
+            "ASSOCIATING",
+            "ASSOCIATED",
+            "FAILED",
+            "DISASSOCIATING",
+            "DISASSOCIATED",
+        ]:
+            raise InvalidParameterException(
+                f"{association_status} is not a valid association status."
+            )
+
+        resource_share_arns = kwargs.get("resourceShareArns", [])
+        resource_arn = kwargs.get("resourceArn")
+        principal = kwargs.get("principal")
+
+        if association_type == "PRINCIPAL" and resource_arn:
+            raise InvalidParameterException(
+                "You cannot specify a resource ARN when the association type is PRINCIPAL."
+            )
+        if association_type == "RESOURCE" and principal:
+            raise InvalidParameterException(
+                "You cannot specify a principal when the association type is RESOURCE."
+            )
+
+        associations = []
+        for resource_share in self.resource_shares:
+            if resource_share_arns and resource_share.arn not in resource_share_arns:
+                continue
+
+            if association_type == "PRINCIPAL":
+                for principal_id in resource_share.principals:
+                    if principal and principal != principal_id:
+                        continue
+                    associations.append(
+                        {
+                            "resourceShareArn": resource_share.arn,
+                            "resourceShareName": resource_share.name,
+                            "associatedEntity": principal_id,
+                            "associationType": "PRINCIPAL",
+                            "status": association_status or "ASSOCIATED",
+                            "creationTime": unix_time(resource_share.creation_time),
+                            "lastUpdatedTime": unix_time(
+                                resource_share.last_updated_time
+                            ),
+                            "external": False,
+                        }
+                    )
+            else:  # RESOURCE
+                for resource_id in resource_share.resource_arns:
+                    if resource_arn and resource_arn != resource_id:
+                        continue
+                    associations.append(
+                        {
+                            "resourceShareArn": resource_share.arn,
+                            "resourceShareName": resource_share.name,
+                            "associatedEntity": resource_id,
+                            "associationType": "RESOURCE",
+                            "status": association_status or "ASSOCIATED",
+                            "creationTime": unix_time(resource_share.creation_time),
+                            "lastUpdatedTime": unix_time(
+                                resource_share.last_updated_time
+                            ),
+                            "external": False,
+                        }
+                    )
+
+        return dict(resourceShareAssociations=associations)
+
 
 ram_backends = BackendDict(ResourceAccessManagerBackend, "ram")
diff --git a/moto/ram/responses.py b/moto/ram/responses.py
index 6f20efff7..93ea41153 100644
--- a/moto/ram/responses.py
+++ b/moto/ram/responses.py
@@ -36,3 +36,8 @@ class ResourceAccessManagerResponse(BaseResponse):
 
     def enable_sharing_with_aws_organization(self) -> str:
         return json.dumps(self.ram_backend.enable_sharing_with_aws_organization())
+
+    def get_resource_share_associations(self) -> str:
+        return json.dumps(
+            self.ram_backend.get_resource_share_associations(**self.request_params)
+        )
diff --git a/moto/ram/urls.py b/moto/ram/urls.py
index 09d782e6b..1b5775bb0 100644
--- a/moto/ram/urls.py
+++ b/moto/ram/urls.py
@@ -7,5 +7,6 @@ url_paths = {
     "{0}/deleteresourceshare/?$": ResourceAccessManagerResponse.dispatch,
     "{0}/enablesharingwithawsorganization$": ResourceAccessManagerResponse.dispatch,
     "{0}/getresourceshares$": ResourceAccessManagerResponse.dispatch,
+    "{0}/getresourceshareassociations$": ResourceAccessManagerResponse.dispatch,
     "{0}/updateresourceshare$": ResourceAccessManagerResponse.dispatch,
 }


Test patch:
diff --git a/tests/test_glue/test_glue.py b/tests/test_glue/test_glue.py
index 2fddc6a63..01bbedd85 100644
--- a/tests/test_glue/test_glue.py
+++ b/tests/test_glue/test_glue.py
@@ -1,5 +1,6 @@
 """Unit tests for glue-supported APIs."""
 
+import json
 from random import randint
 from uuid import uuid4
 
@@ -1063,3 +1064,226 @@ def test_put_data_catalog_encryption_settings():
     )
 
     assert catalog_get_response["DataCatalogEncryptionSettings"] == catalog_settings
+
+
+@mock_aws
+def test_put_resource_policy():
+    client = boto3.client("glue", region_name="us-east-1")
+
+    policy_json = json.dumps(
+        {
+            "Version": "2012-10-17",
+            "Statement": [
+                {
+                    "Effect": "Allow",
+                    "Principal": {"Service": "glue.amazonaws.com"},
+                    "Action": ["glue:*"],
+                    "Resource": ["*"],
+                }
+            ],
+        }
+    )
+
+    response = client.put_resource_policy(PolicyInJson=policy_json)
+
+    assert "PolicyHash" in response
+    policy_hash = response["PolicyHash"]
+
+    get_response = client.get_resource_policy()
+    assert "PolicyInJson" in get_response
+    assert get_response["PolicyInJson"] == policy_json
+    assert "PolicyHash" in get_response
+    assert get_response["PolicyHash"] == policy_hash
+    assert "CreateTime" in get_response
+    assert "UpdateTime" in get_response
+
+    response = client.put_resource_policy(
+        PolicyInJson=policy_json,
+        PolicyHashCondition=policy_hash,
+    )
+
+    assert "PolicyHash" in response
+
+    resource_arn = "arn:aws:glue:us-east-2:123456789012:catalog"
+    response = client.put_resource_policy(
+        PolicyInJson=policy_json, ResourceArn=resource_arn
+    )
+
+    assert "PolicyHash" in response
+
+    get_resource_response = client.get_resource_policy(ResourceArn=resource_arn)
+    assert "PolicyInJson" in get_resource_response
+    assert get_resource_response["PolicyInJson"] == policy_json
+
+    response = client.put_resource_policy(
+        PolicyInJson=policy_json,
+        ResourceArn=resource_arn,
+        PolicyExistsCondition="MUST_EXIST",
+    )
+    assert "PolicyHash" in response
+
+    unique_arn = "arn:aws:glue:us-east-2:123456789012:unique-resource"
+    response = client.put_resource_policy(
+        PolicyInJson=policy_json, ResourceArn=unique_arn, PolicyExistsCondition="NONE"
+    )
+    assert "PolicyHash" in response
+
+    response = client.put_resource_policy(PolicyInJson=policy_json, EnableHybrid="TRUE")
+    assert "PolicyHash" in response
+
+
+@mock_aws
+def test_get_resource_policy():
+    client = boto3.client("glue", region_name="us-east-1")
+
+    response = client.get_resource_policy()
+    assert "PolicyInJson" not in response
+
+    policy_json = json.dumps(
+        {
+            "Version": "2012-10-17",
+            "Statement": [
+                {
+                    "Effect": "Allow",
+                    "Principal": {"Service": "glue.amazonaws.com"},
+                    "Action": ["glue:*"],
+                    "Resource": ["*"],
+                }
+            ],
+        }
+    )
+
+    put_response = client.put_resource_policy(PolicyInJson=policy_json)
+
+    response = client.get_resource_policy()
+
+    assert "PolicyInJson" in response
+    assert response["PolicyInJson"] == policy_json
+    assert "PolicyHash" in response
+
+    if (
+        isinstance(put_response["PolicyHash"], dict)
+        and "PolicyHash" in put_response["PolicyHash"]
+    ):
+        assert response["PolicyHash"] == put_response["PolicyHash"]["PolicyHash"]
+    else:
+        assert response["PolicyHash"] == put_response["PolicyHash"]
+
+    assert "CreateTime" in response
+    assert "UpdateTime" in response
+
+    catalog_arn = "arn:aws:glue:us-east-1:123456789012:catalog"
+    database_arn = "arn:aws:glue:us-east-1:123456789012:database/mydb"
+    table_arn = "arn:aws:glue:us-east-1:123456789012:table/mydb/mytable"
+
+    catalog_policy = json.dumps(
+        {
+            "Version": "2012-10-17",
+            "Statement": [
+                {
+                    "Effect": "Allow",
+                    "Principal": {"AWS": "arn:aws:iam::123456789012:root"},
+                    "Action": ["glue:*"],
+                    "Resource": [catalog_arn],
+                }
+            ],
+        }
+    )
+    client.put_resource_policy(PolicyInJson=catalog_policy, ResourceArn=catalog_arn)
+
+    database_policy = json.dumps(
+        {
+            "Version": "2012-10-17",
+            "Statement": [
+                {
+                    "Effect": "Allow",
+                    "Principal": {"AWS": "arn:aws:iam::123456789012:role/GlueRole"},
+                    "Action": ["glue:GetDatabase", "glue:UpdateDatabase"],
+                    "Resource": [database_arn],
+                }
+            ],
+        }
+    )
+    client.put_resource_policy(PolicyInJson=database_policy, ResourceArn=database_arn)
+
+    table_policy = json.dumps(
+        {
+            "Version": "2012-10-17",
+            "Statement": [
+                {
+                    "Effect": "Allow",
+                    "Principal": {"AWS": "arn:aws:iam::987654321098:root"},
+                    "Action": ["glue:GetTable"],
+                    "Resource": [table_arn],
+                }
+            ],
+        }
+    )
+    client.put_resource_policy(PolicyInJson=table_policy, ResourceArn=table_arn)
+
+    catalog_response = client.get_resource_policy(ResourceArn=catalog_arn)
+    assert catalog_response["PolicyInJson"] == catalog_policy
+
+    database_response = client.get_resource_policy(ResourceArn=database_arn)
+    assert database_response["PolicyInJson"] == database_policy
+
+    table_response = client.get_resource_policy(ResourceArn=table_arn)
+    assert table_response["PolicyInJson"] == table_policy
+
+    nonexistent_response = client.get_resource_policy(
+        ResourceArn="arn:aws:glue:us-east-1:123456789012:nonexistent"
+    )
+    assert "PolicyInJson" not in nonexistent_response
+
+
+@mock_aws
+def test_put_resource_policy_error_conditions():
+    client = boto3.client("glue", region_name="us-east-1")
+
+    policy_json = json.dumps(
+        {
+            "Version": "2012-10-17",
+            "Statement": [
+                {
+                    "Effect": "Allow",
+                    "Principal": {"Service": "glue.amazonaws.com"},
+                    "Action": ["glue:*"],
+                    "Resource": ["*"],
+                }
+            ],
+        }
+    )
+
+    resource_arn = "arn:aws:glue:us-west-2:123456789012:catalog"
+
+    response = client.put_resource_policy(
+        PolicyInJson=policy_json,
+        ResourceArn=resource_arn,
+        PolicyExistsCondition="NOT_EXIST",
+    )
+    assert "PolicyHash" in response
+
+    with pytest.raises(ClientError) as excinfo:
+        client.put_resource_policy(
+            PolicyInJson=policy_json,
+            ResourceArn=resource_arn,
+            PolicyExistsCondition="NOT_EXIST",
+        )
+    assert "ResourceNumberLimitExceededException" in str(excinfo.value)
+
+    with pytest.raises(ClientError) as excinfo:
+        client.put_resource_policy(
+            PolicyInJson=policy_json,
+            ResourceArn=resource_arn,
+            PolicyHashCondition="incorrect-hash",
+        )
+    assert "ConcurrentModificationException" in str(excinfo.value)
+
+    nonexistent_arn = "arn:aws:glue:us-west-2:123456789012:nonexistent-resource"
+    with pytest.raises(ClientError) as excinfo:
+        client.put_resource_policy(
+            PolicyInJson=policy_json,
+            ResourceArn=nonexistent_arn,
+            PolicyExistsCondition="MUST_EXIST",
+        )
+    assert "ResourceNumberLimitExceededException" in str(excinfo.value)
diff --git a/tests/test_ram/test_ram.py b/tests/test_ram/test_ram.py
index 6b4ed32f8..da782ad8d 100644
--- a/tests/test_ram/test_ram.py
+++ b/tests/test_ram/test_ram.py
@@ -377,3 +377,156 @@ def test_enable_sharing_with_aws_organization_errors():
         "following error message: "
         "You don't have permissions to access this resource."
     )
+
+
+@mock_aws
+def test_get_resource_share_associations_with_principals():
+    # given
+    client = boto3.client("ram", region_name="us-east-1")
+    response = client.create_resource_share(
+        name="test",
+        principals=["123456789012"],
+        resourceArns=[
+            f"arn:aws:ec2:us-east-1:{ACCOUNT_ID}:transit-gateway/tgw-123456789"
+        ],
+    )
+    resource_share_arn = response["resourceShare"]["resourceShareArn"]
+
+    # when
+    response = client.get_resource_share_associations(
+        associationType="PRINCIPAL", resourceShareArns=[resource_share_arn]
+    )
+
+    # then
+    assert len(response["resourceShareAssociations"]) == 1
+    association = response["resourceShareAssociations"][0]
+    assert association["resourceShareArn"] == resource_share_arn
+    assert association["resourceShareName"] == "test"
+    assert association["associatedEntity"] == "123456789012"
+    assert association["associationType"] == "PRINCIPAL"
+    assert association["status"] == "ASSOCIATED"
+    assert isinstance(association["creationTime"], datetime)
+    assert isinstance(association["lastUpdatedTime"], datetime)
+    assert association["external"] is False
+
+
+@mock_aws
+def test_get_resource_share_associations_with_resources():
+    # given
+    client = boto3.client("ram", region_name="us-east-1")
+    resource_arn = f"arn:aws:ec2:us-east-1:{ACCOUNT_ID}:transit-gateway/tgw-123456789"
+    response = client.create_resource_share(
+        name="test",
+        principals=["123456789012"],
+        resourceArns=[resource_arn],
+    )
+    resource_share_arn = response["resourceShare"]["resourceShareArn"]
+
+    # when
+    response = client.get_resource_share_associations(
+        associationType="RESOURCE", resourceShareArns=[resource_share_arn]
+    )
+
+    # then
+    assert len(response["resourceShareAssociations"]) == 1
+    association = response["resourceShareAssociations"][0]
+    assert association["resourceShareArn"] == resource_share_arn
+    assert association["resourceShareName"] == "test"
+    assert association["associatedEntity"] == resource_arn
+    assert association["associationType"] == "RESOURCE"
+    assert association["status"] == "ASSOCIATED"
+    assert isinstance(association["creationTime"], datetime)
+    assert isinstance(association["lastUpdatedTime"], datetime)
+    assert association["external"] is False
+
+
+@mock_aws
+def test_get_resource_share_associations_with_filters():
+    # given
+    client = boto3.client("ram", region_name="us-east-1")
+    resource_arn = f"arn:aws:ec2:us-east-1:{ACCOUNT_ID}:transit-gateway/tgw-123456789"
+    response = client.create_resource_share(
+        name="test",
+        principals=["123456789012"],
+        resourceArns=[resource_arn],
+    )
+
+    # when filtering by principal
+    response = client.get_resource_share_associations(
+        associationType="PRINCIPAL", principal="123456789012"
+    )
+
+    # then
+    assert len(response["resourceShareAssociations"]) == 1
+    assert (
+        response["resourceShareAssociations"][0]["associatedEntity"] == "123456789012"
+    )
+
+    # when filtering by resource
+    response = client.get_resource_share_associations(
+        associationType="RESOURCE", resourceArn=resource_arn
+    )
+
+    # then
+    assert len(response["resourceShareAssociations"]) == 1
+    assert response["resourceShareAssociations"][0]["associatedEntity"] == resource_arn
+
+
+@mock_aws
+def test_get_resource_share_associations_errors():
+    # given
+    client = boto3.client("ram", region_name="us-east-1")
+    resource_arn = f"arn:aws:ec2:us-east-1:{ACCOUNT_ID}:transit-gateway/tgw-123456789"
+    client.create_resource_share(
+        name="test",
+        principals=["123456789012"],
+        resourceArns=[resource_arn],
+    )
+
+    # when invalid association type
+    with pytest.raises(ClientError) as e:
+        client.get_resource_share_associations(associationType="INVALID")
+    ex = e.value
+    assert ex.operation_name == "GetResourceShareAssociations"
+    assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
+    assert "InvalidParameterException" in ex.response["Error"]["Code"]
+    assert "is not a valid association type" in ex.response["Error"]["Message"]
+
+    # when invalid association status
+    with pytest.raises(ClientError) as e:
+        client.get_resource_share_associations(
+            associationType="PRINCIPAL", associationStatus="INVALID"
+        )
+    ex = e.value
+    assert ex.operation_name == "GetResourceShareAssociations"
+    assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
+    assert "InvalidParameterException" in ex.response["Error"]["Code"]
+    assert "is not a valid association status" in ex.response["Error"]["Message"]
+
+    # when resource ARN with PRINCIPAL type
+    with pytest.raises(ClientError) as e:
+        client.get_resource_share_associations(
+            associationType="PRINCIPAL", resourceArn=resource_arn
+        )
+    ex = e.value
+    assert ex.operation_name == "GetResourceShareAssociations"
+    assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
+    assert "InvalidParameterException" in ex.response["Error"]["Code"]
+    assert (
+        "You cannot specify a resource ARN when the association type is PRINCIPAL"
+        in ex.response["Error"]["Message"]
+    )
+
+    # when principal with RESOURCE type
+    with pytest.raises(ClientError) as e:
+        client.get_resource_share_associations(
+            associationType="RESOURCE", principal="123456789012"
+        )
+    ex = e.value
+    assert ex.operation_name == "GetResourceShareAssociations"
+    assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400
+    assert "InvalidParameterException" in ex.response["Error"]["Code"]
+    assert (
+        "You cannot specify a principal when the association type is RESOURCE"
+        in ex.response["Error"]["Message"]
+    )
diff --git a/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py b/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py
index c6e938616..1437df8ee 100644
--- a/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py
+++ b/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py
@@ -937,9 +937,7 @@ def test_get_resources_workspaces():
 
     # Create two tagged Workspaces
     directory_id = create_directory()
-    workspaces.register_workspace_directory(
-        DirectoryId=directory_id, EnableWorkDocs=False
-    )
+    workspaces.register_workspace_directory(DirectoryId=directory_id)
     workspaces.create_workspaces(
         Workspaces=[
             {
@@ -986,10 +984,7 @@ def test_get_resources_workspace_directories():
         directory_id = create_directory()
         workspaces.register_workspace_directory(
             DirectoryId=directory_id,
-            EnableWorkDocs=False,
-            Tags=[
-                {"Key": "Test", "Value": i_str},
-            ],
+            Tags=[{"Key": "Test", "Value": i_str}],
         )
 
     rtapi = boto3.client("resourcegroupstaggingapi", region_name="eu-central-1")
@@ -1013,9 +1008,7 @@ def test_get_resources_workspace_images():
 
     # Create two tagged Workspace Images
     directory_id = create_directory()
-    workspaces.register_workspace_directory(
-        DirectoryId=directory_id, EnableWorkDocs=False
-    )
+    workspaces.register_workspace_directory(DirectoryId=directory_id)
     resp = workspaces.create_workspaces(
         Workspaces=[
             {
diff --git a/tests/test_workspaces/test_workspaces.py b/tests/test_workspaces/test_workspaces.py
index d3b69fa15..b93fc02e2 100644
--- a/tests/test_workspaces/test_workspaces.py
+++ b/tests/test_workspaces/test_workspaces.py
@@ -1,13 +1,19 @@
 """Unit tests for workspaces-supported APIs."""
 
+import sys
+from unittest import SkipTest
+
 import boto3
 import pytest
 from botocore.exceptions import ClientError
 
 from moto import mock_aws
 from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
+from moto.utilities.distutils_version import LooseVersion
 from tests.test_ds.test_ds_simple_ad_directory import create_test_directory
 
+botocore_version = sys.modules["botocore"].__version__
+
 
 def create_directory():
     """Create a Directory"""
@@ -28,7 +34,7 @@ def create_security_group(client):
 def test_create_workspaces():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     resp = client.create_workspaces(
         Workspaces=[
             {
@@ -108,7 +114,7 @@ def test_create_workspaces_with_unknown_directory_id():
 def test_create_workspaces_with_auto_stop_timeout_and_alwayson():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     resp = client.create_workspaces(
         Workspaces=[
             {
@@ -134,7 +140,7 @@ def test_create_workspaces_with_auto_stop_timeout_and_alwayson():
 def test_create_workspaces_with_auto_stop_timeout_and_manual():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     resp = client.create_workspaces(
         Workspaces=[
             {
@@ -160,7 +166,7 @@ def test_create_workspaces_with_auto_stop_timeout_and_manual():
 def test_describe_workspaces():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     for _ in range(2):
         client.create_workspaces(
             Workspaces=[
@@ -185,7 +191,7 @@ def test_describe_workspaces():
 def test_describe_workspaces_with_directory_and_username():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     client.create_workspaces(
         Workspaces=[
             {
@@ -208,7 +214,7 @@ def test_describe_workspaces_with_directory_and_username():
 def test_describe_workspaces_invalid_parameters():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     response = client.create_workspaces(
         Workspaces=[
             {
@@ -243,7 +249,7 @@ def test_describe_workspaces_invalid_parameters():
 def test_describe_workspaces_only_user_name_used():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     client.create_workspaces(
         Workspaces=[
             {
@@ -262,15 +268,36 @@ def test_describe_workspaces_only_user_name_used():
 
 
 @mock_aws
-def test_register_workspace_directory():
+@pytest.mark.parametrize("enable_work_docs", [True, False])
+def test_register_workspace_directory_with_workdocs(enable_work_docs):
+    # The WorkDocs-service has been deprecated:
+    # https://www.reddit.com/r/aws/comments/1cd1iqb/workdocsamazon_has_decided_to_end_support_for_the/
+    # Botocore 1.38.13 has removed support for the EnableWorkdocs-parameter,
+    # so we can only test this on older versions of botocore
+    if LooseVersion(botocore_version) >= LooseVersion("1.38.13"):
+        raise SkipTest("Parameter EnableWorkdocs is only available in older versions")
+
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(
+        DirectoryId=directory_id, EnableWorkDocs=enable_work_docs
+    )
+
     resp = client.describe_workspace_directories(DirectoryIds=[directory_id])
-    assert "RegistrationCode" in resp["Directories"][0]
     assert (
-        resp["Directories"][0]["WorkspaceCreationProperties"]["EnableWorkDocs"] is False
+        resp["Directories"][0]["WorkspaceCreationProperties"]["EnableWorkDocs"]
+        is enable_work_docs
     )
+
+
+@mock_aws
+def test_register_workspace_directory():
+    client = boto3.client("workspaces", region_name="eu-west-1")
+    directory_id = create_directory()
+    client.register_workspace_directory(DirectoryId=directory_id)
+    resp = client.describe_workspace_directories(DirectoryIds=[directory_id])
+    assert "RegistrationCode" in resp["Directories"][0]
+    assert "EnableWorkDocs" not in resp["Directories"][0]["WorkspaceCreationProperties"]
     assert resp["Directories"][0]["Tenancy"] == "SHARED"
 
 
@@ -280,16 +307,12 @@ def test_register_workspace_directory_enable_self_service():
     directory_id = create_directory()
     client.register_workspace_directory(
         DirectoryId=directory_id,
-        EnableWorkDocs=True,
         EnableSelfService=True,
         Tenancy="DEDICATED",
     )
     resp = client.describe_workspace_directories(DirectoryIds=[directory_id])
     self_service_permissions = resp["Directories"][0]["SelfservicePermissions"]
     assert "RegistrationCode" in resp["Directories"][0]
-    assert (
-        resp["Directories"][0]["WorkspaceCreationProperties"]["EnableWorkDocs"] is True
-    )
     assert self_service_permissions["IncreaseVolumeSize"] == "ENABLED"
     assert self_service_permissions["ChangeComputeType"] == "ENABLED"
     assert self_service_permissions["SwitchRunningMode"] == "ENABLED"
@@ -297,28 +320,12 @@ def test_register_workspace_directory_enable_self_service():
     assert resp["Directories"][0]["Tenancy"] == "DEDICATED"
 
 
-@mock_aws
-def test_register_workspace_directory_with_subnets():
-    client = boto3.client("workspaces", region_name="eu-west-1")
-    directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
-    resp = client.describe_workspace_directories(DirectoryIds=[directory_id])
-    assert "RegistrationCode" in resp["Directories"][0]
-    assert (
-        resp["Directories"][0]["WorkspaceCreationProperties"]["EnableWorkDocs"] is False
-    )
-    assert resp["Directories"][0]["Tenancy"] == "SHARED"
-
-
 @mock_aws
 def test_describe_workspace_directories():
     client = boto3.client("workspaces", region_name="eu-west-1")
     for _ in range(2):
         directory_id = create_directory()
-        client.register_workspace_directory(
-            DirectoryId=directory_id,
-            EnableWorkDocs=True,
-        )
+        client.register_workspace_directory(DirectoryId=directory_id)
     resp = client.describe_workspace_directories()
     assert len(resp["Directories"]) == 2
     directory = resp["Directories"][0]
@@ -344,10 +351,7 @@ def test_describe_workspace_directories():
 def test_describe_workspace_directories_with_directory_id():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(
-        DirectoryId=directory_id,
-        EnableWorkDocs=True,
-    )
+    client.register_workspace_directory(DirectoryId=directory_id)
     resp = client.describe_workspace_directories(DirectoryIds=[directory_id])
     assert len(resp["Directories"]) == 1
     directory = resp["Directories"][0]
@@ -369,11 +373,10 @@ def test_modify_workspace_creation_properties():
     ec2_client = boto3.client("ec2", region_name="eu-west-1")
     directory_id = create_directory()
     sg = create_security_group(client=ec2_client)
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     client.modify_workspace_creation_properties(
         ResourceId=directory_id,
         WorkspaceCreationProperties={
-            "EnableWorkDocs": False,
             "CustomSecurityGroupId": sg["GroupId"],
         },
     )
@@ -394,7 +397,6 @@ def test_modify_workspace_creation_properties_invalid_request():
         client.modify_workspace_creation_properties(
             ResourceId="d-9067f6c44b",  # Invalid DirectoryID
             WorkspaceCreationProperties={
-                "EnableWorkDocs": False,
                 "CustomSecurityGroupId": sg["GroupId"],
             },
         )
@@ -408,16 +410,11 @@ def test_create_tags():
     directory_id = create_directory()
     client.register_workspace_directory(
         DirectoryId=directory_id,
-        EnableWorkDocs=True,
-        Tags=[
-            {"Key": "foo1", "Value": "bar1"},
-        ],
+        Tags=[{"Key": "foo1", "Value": "bar1"}],
     )
     client.create_tags(
         ResourceId=directory_id,
-        Tags=[
-            {"Key": "foo2", "Value": "bar2"},
-        ],
+        Tags=[{"Key": "foo2", "Value": "bar2"}],
     )
     resp = client.describe_tags(ResourceId=directory_id)
     assert resp["TagList"][1]["Key"] == "foo2"
@@ -429,10 +426,7 @@ def test_describe_tags():
     directory_id = create_directory()
     client.register_workspace_directory(
         DirectoryId=directory_id,
-        EnableWorkDocs=True,
-        Tags=[
-            {"Key": "foo", "Value": "bar"},
-        ],
+        Tags=[{"Key": "foo", "Value": "bar"}],
     )
     resp = client.describe_tags(ResourceId=directory_id)
     assert resp["TagList"][0]["Key"] == "foo"
@@ -442,10 +436,7 @@ def test_describe_tags():
 def test_describe_client_properties():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(
-        DirectoryId=directory_id,
-        EnableWorkDocs=True,
-    )
+    client.register_workspace_directory(DirectoryId=directory_id)
     resp = client.describe_client_properties(ResourceIds=[directory_id])
     assert "ClientProperties" in resp["ClientPropertiesList"][0]
 
@@ -454,10 +445,7 @@ def test_describe_client_properties():
 def test_modify_client_properties():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(
-        DirectoryId=directory_id,
-        EnableWorkDocs=True,
-    )
+    client.register_workspace_directory(DirectoryId=directory_id)
     client.modify_client_properties(
         ResourceId=directory_id,
         ClientProperties={
@@ -475,7 +463,7 @@ def test_modify_client_properties():
 def test_create_workspace_image():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     workspace = client.create_workspaces(
         Workspaces=[
             {
@@ -517,7 +505,7 @@ def test_create_workspace_image_invalid_workspace():
 def test_create_workspace_image_already_exists():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     workspace = client.create_workspaces(
         Workspaces=[
             {
@@ -547,7 +535,7 @@ def test_create_workspace_image_already_exists():
 def test_describe_workspace_images():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     workspace = client.create_workspaces(
         Workspaces=[
             {
@@ -578,7 +566,7 @@ def test_describe_workspace_images():
 def test_update_workspace_image_permission():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     workspace = client.create_workspaces(
         Workspaces=[
             {
@@ -611,7 +599,7 @@ def test_update_workspace_image_permission():
 def test_describe_workspace_image_permissions():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     workspace = client.create_workspaces(
         Workspaces=[
             {
@@ -648,7 +636,7 @@ def test_describe_workspace_image_permissions_with_invalid_image_id():
 def test_deregister_workspace_directory():
     client = boto3.client("workspaces", region_name="eu-west-1")
     directory_id = create_directory()
-    client.register_workspace_directory(DirectoryId=directory_id, EnableWorkDocs=False)
+    client.register_workspace_directory(DirectoryId=directory_id)
     resp = client.describe_workspace_directories(DirectoryIds=[directory_id])
     assert len(resp["Directories"]) > 0
     client.deregister_workspace_directory(DirectoryId=directory_id)
@@ -661,10 +649,7 @@ def test_modify_selfservice_permissions():
     client = boto3.client("workspaces", region_name="eu-west-1")
 
     directory_id = create_directory()
-    client.register_workspace_directory(
-        DirectoryId=directory_id,
-        EnableWorkDocs=True,
-    )
+    client.register_workspace_directory(DirectoryId=directory_id)
     resp = client.describe_workspace_directories(DirectoryIds=[directory_id])
     assert (
         resp["Directories"][0]["SelfservicePermissions"]["IncreaseVolumeSize"]