|
25 | 25 | "lake_formation_config = LakeFormationConfig(\n", |
26 | 26 | " enabled=True, # Enable Lake Formation governance\n", |
27 | 27 | " use_service_linked_role=True, # Use LF service-linked role (default)\n", |
28 | | - " registration_role_arn=None, # Role used by LF to access your resources\n", |
29 | | - " disable_hybrid_access_mode # Revoke IAMAllowedPrincipal permissions (REQUIRED)\n", |
30 | | - " acknowledge_risk # Controls confirmation behavior for risky Lake Formation operations.\n", |
| 28 | + " registration_role_arn=None, # Role used by LF to access your S3 bucket\n", |
| 29 | + " hybrid_access_mode_enabled # Keep or revoke IAMAllowedPrincipal permissions (REQUIRED)\n", |
| 30 | + " acknowledge_risk # Controls confirmation behavior for risky Lake Formation operations. (REQUIRED)\n", |
31 | 31 | ")\n", |
32 | 32 | "```\n", |
33 | 33 | "\n", |
34 | | - "> **Note:** `disable_hybrid_access_mode` is a required field with no default. When `True`, IAMAllowedPrincipal permissions are revoked from the Glue table, enforcing Lake Formation-only governance. **Warning:** this may break existing jobs (e.g., training, processing, ETL) that access the table via IAM-based permissions. After this change, all principals must be granted access through Lake Formation. When `False`, an interactive prompt asks the user to confirm proceeding with hybrid access mode.\n", |
| 34 | + "> **Note:** `hybrid_access_mode_enabled` is a required field with no default. When `False`, IAMAllowedPrincipal permissions are revoked from the Glue table, enforcing Lake Formation-only governance. **Warning:** this may break existing jobs (e.g., training, processing, ETL) that access the table via IAM-based permissions. After this change, all principals must be granted access through Lake Formation.\n", |
35 | 35 | "\n", |
36 | 36 | "### New Parameter in `FeatureGroupManager.create()`: `lake_formation_config`\n", |
37 | 37 | "\n", |
|
51 | 51 | "\n", |
52 | 52 | "```python\n", |
53 | 53 | "fg.enable_lake_formation(\n", |
54 | | - " disable_hybrid_access_mode=True, # Revoke IAMAllowedPrincipal permissions (REQUIRED)\n", |
55 | | - " acknowledge_risk=None, # None=interactive prompt, True=skip prompt, False=abort\n", |
| 54 | + " hybrid_access_mode_enabled, # Revoke IAMAllowedPrincipal permissions (REQUIRED)\n", |
| 55 | + " acknowledge_risk, # True=proceed, False=abort (REQUIRED)\n", |
56 | 56 | " use_service_linked_role=True, # Use LF service-linked role (default)\n", |
57 | 57 | " registration_role_arn=None, # Custom role ARN (if not using SLR)\n", |
58 | 58 | " wait_for_active=False, # Wait for Feature Group to be Created\n", |
|
65 | 65 | "{\n", |
66 | 66 | " \"s3_location_registered\": True,\n", |
67 | 67 | " \"lf_permissions_granted\": True,\n", |
68 | | - " \"hybrid_access_mode_disabled\": True # Only True when disable_hybrid_access_mode=True\n", |
| 68 | + " \"hybrid_access_mode_enabled\": False # Only False when hybrid_access_mode_enabled=False\n", |
69 | 69 | "}\n", |
70 | 70 | "```\n", |
71 | 71 | "\n", |
|
100 | 100 | "\n", |
101 | 101 | "### Step 3: Revoke IAMAllowedPrincipal Permissions (conditional)\n", |
102 | 102 | "\n", |
103 | | - "This step only executes when `disable_hybrid_access_mode=True`. By default, Glue tables allow access to any IAM principal with appropriate IAM permissions (`IAMAllowedPrincipal`). This step revokes that default permission, ensuring that:\n", |
| 103 | + "This step only executes when `hybrid_access_mode_enabled=False`. By default, Glue tables allow access to any IAM principal with appropriate IAM permissions (`IAMAllowedPrincipal`). This step revokes that default permission, ensuring that:\n", |
104 | 104 | "\n", |
105 | 105 | "- Access is now controlled exclusively through Lake Formation\n", |
106 | 106 | "- Only principals explicitly granted permissions via Lake Formation can access the data\n", |
107 | 107 | "\n", |
108 | 108 | "**Warning:** Revoking IAMAllowedPrincipal may break existing jobs (e.g., training, processing, ETL) that access the table via IAM-based permissions. After this change, all principals must be granted access through Lake Formation.\n", |
109 | 109 | "\n", |
110 | | - "When `disable_hybrid_access_mode=False`, this step is skipped and an interactive prompt asks the user to confirm proceeding with hybrid access mode (IAM + Lake Formation permissions coexist).\n", |
| 110 | + "When `hybrid_access_mode_enabled=True`, this step is skipped and hybrid access mode remains active (IAM + Lake Formation permissions coexist). The `acknowledge_risk=True` parameter confirms acceptance of this configuration.\n", |
111 | 111 | "\n", |
112 | 112 | "### Step 4: Recommended S3 Deny Policy (always logged)\n", |
113 | 113 | "\n", |
|
409 | 409 | "Grant your Execution role permission to create and describe tables under `sagemaker_featurestore` database" |
410 | 410 | ] |
411 | 411 | }, |
412 | | - { |
413 | | - "cell_type": "code", |
414 | | - "execution_count": null, |
415 | | - "metadata": {}, |
416 | | - "outputs": [], |
417 | | - "source": [ |
418 | | - "lf_client.grant_permissions(\n", |
419 | | - " Principal={\"DataLakePrincipalIdentifier\": EXECUTION_ROLE_ARN},\n", |
420 | | - " Resource={\n", |
421 | | - " \"Database\": {\"Name\": \"sagemaker_featurestore\"}\n", |
422 | | - " },\n", |
423 | | - " Permissions=[\"CREATE_TABLE\", \"DESCRIBE\"],\n", |
424 | | - " PermissionsWithGrantOption=[],\n", |
425 | | - ")\n" |
426 | | - ] |
427 | | - }, |
428 | 412 | { |
429 | 413 | "cell_type": "markdown", |
430 | 414 | "metadata": {}, |
|
599 | 583 | "lake_formation_config = LakeFormationConfig(\n", |
600 | 584 | " enabled=True,\n", |
601 | 585 | " use_service_linked_role=True,\n", |
602 | | - " disable_hybrid_access_mode=False,\n", |
| 586 | + " hybrid_access_mode_enabled=True,\n", |
603 | 587 | " acknowledge_risk=True\n", |
604 | 588 | ")\n", |
605 | 589 | "print(\"\\nLake Formation Config:\")\n", |
|
830 | 814 | "feature_group = FeatureGroupManager.get(FG_NAME_WORKFLOW2, session=boto_session)\n", |
831 | 815 | "result = feature_group.enable_lake_formation( # new method\n", |
832 | 816 | " use_service_linked_role=True,\n", |
833 | | - " disable_hybrid_access_mode=True,\n", |
| 817 | + " hybrid_access_mode_enabled=False,\n", |
834 | 818 | " acknowledge_risk=True\n", |
835 | 819 | ")\n", |
836 | 820 | "data_catalog_config_2 = feature_group.offline_store_config.data_catalog_config\n", |
|
839 | 823 | "print(f\"\\nLake Formation setup results:\")\n", |
840 | 824 | "print(f\" s3_location_registered: {result['s3_location_registered']}\")\n", |
841 | 825 | "print(f\" lf_permissions_granted: {result['lf_permissions_granted']}\")\n", |
842 | | - "print(f\" hybrid_access_mode_disabled: {result['hybrid_access_mode_disabled']}\")" |
| 826 | + "print(f\" hybrid_access_mode_enabled: {result['hybrid_access_mode_enabled']}\")" |
843 | 827 | ] |
844 | 828 | }, |
845 | 829 | { |
|
891 | 875 | "### Grant Data Scientist Permission to Query the Table" |
892 | 876 | ] |
893 | 877 | }, |
| 878 | + { |
| 879 | + "cell_type": "markdown", |
| 880 | + "metadata": {}, |
| 881 | + "source": [ |
| 882 | + "we try to query before granting lakeformation permissions. Should fail unless the data scientist role was already granted lakefomration permission\n" |
| 883 | + ] |
| 884 | + }, |
| 885 | + { |
| 886 | + "cell_type": "code", |
| 887 | + "execution_count": null, |
| 888 | + "metadata": {}, |
| 889 | + "outputs": [], |
| 890 | + "source": [ |
| 891 | + "query_offline_store(str(data_catalog_config_2.database), str(data_catalog_config_2.table_name), data_scientist_session)" |
| 892 | + ] |
| 893 | + }, |
894 | 894 | { |
895 | 895 | "cell_type": "code", |
896 | 896 | "execution_count": null, |
|
1086 | 1086 | ], |
1087 | 1087 | "metadata": { |
1088 | 1088 | "kernelspec": { |
1089 | | - "display_name": "v3-lf", |
| 1089 | + "display_name": "Python 3 (ipykernel)", |
1090 | 1090 | "language": "python", |
1091 | 1091 | "name": "python3" |
1092 | 1092 | }, |
|
1105 | 1105 | "widgets": { |
1106 | 1106 | "application/vnd.jupyter.widget-state+json": { |
1107 | 1107 | "state": { |
1108 | | - "cbfddeb610c74e7886a4dcff89f2eb2e": { |
| 1108 | + "9293a7c9ef3d4430b61a6abe6a434fa7": { |
| 1109 | + "model_module": "@jupyter-widgets/base", |
| 1110 | + "model_module_version": "2.0.0", |
| 1111 | + "model_name": "LayoutModel", |
| 1112 | + "state": {} |
| 1113 | + }, |
| 1114 | + "e1dbeb64626e41b7bedd11144f50f168": { |
1109 | 1115 | "model_module": "@jupyter-widgets/base", |
1110 | 1116 | "model_module_version": "2.0.0", |
1111 | 1117 | "model_name": "LayoutModel", |
|
0 commit comments