diff --git a/extensions/auth/ranger/README.md b/extensions/auth/ranger/README.md index 78b1bc480a..1b5594c02e 100644 --- a/extensions/auth/ranger/README.md +++ b/extensions/auth/ranger/README.md @@ -38,4 +38,22 @@ polaris.authorization.ranger.authz.audit.destination.solr.urls=http://solr-servi ``` -3. Run or restart Polaris to see that all accesses are authorized by Ranger policies, with access audit records available in Apache Ranger console. +3. Register the Polaris service type with Ranger Admin using the service definition shipped at + `src/main/resources/polaris-ranger-servicedef.json` (packaged as `polaris-ranger-servicedef.json` + on the classpath of `polaris-extensions-auth-ranger`), for example: +``` +curl -u : -X POST \ + -H "Content-Type: application/json" \ + -d @polaris-ranger-servicedef.json \ + http://ranger-admin:6080/service/public/v2/api/servicedef +``` + This is the same `serviceDef` exercised by `RangerPolarisAuthorizerTest`: its fixture is + generated by embedding this shipped `serviceDef` (see `RangerTestUtils.createConfig` for the + unit test, and the `generateAuthzItTestFixture` Gradle task for the integration test), so any + access type available to grant through Ranger policies is guaranteed to be understood by the + authorizer. + +4. Create a Ranger service instance of type `polaris` (matching the `service-name` configured + above), then define policies against it. + +5. Run or restart Polaris to see that all accesses are authorized by Ranger policies, with access audit records available in Apache Ranger console. diff --git a/extensions/auth/ranger/build.gradle.kts b/extensions/auth/ranger/build.gradle.kts index 92bc854ea9..fd94d8e061 100644 --- a/extensions/auth/ranger/build.gradle.kts +++ b/extensions/auth/ranger/build.gradle.kts @@ -28,6 +28,70 @@ plugins { val intTestJvmVersion = 21 +val polarisRangerServiceDefFile = + layout.projectDirectory.file("src/main/resources/polaris-ranger-servicedef.json") +val servicedefPlaceholder = "@@POLARIS_RANGER_SERVICE_DEF@@" + +// Strips the ASF license header (required since these templates are checked-in source files) +// that precedes the "{" starting the actual, not-quite-valid-JSON template content. +fun stripLicenseHeader(text: String) = text.substringAfter("*/").trimStart() + +// The intTest authz fixture asserts against the shipped `serviceDef`, so rather than checking +// in a byte-for-byte copy of it (which can silently drift), it's a template with the shipped +// `polaris-ranger-servicedef.json` spliced in at build time. The unit-test equivalent fixture is +// generated the same way, but by test Java code at test-run time (see RangerTestUtils), since +// RangerPolarisAuthorizerTest runs in-process and can just write into a JUnit-managed temp dir. +val generateAuthzItTestFixture = + tasks.register("generateAuthzItTestFixture") { + val templateFile = + layout.projectDirectory.file("src/intTest/resources/authz_it_tests/dev_polaris.json.template") + val rolesFile = + layout.projectDirectory.file("src/intTest/resources/authz_it_tests/dev_polaris_roles.json") + val userStoreFile = + layout.projectDirectory.file( + "src/intTest/resources/authz_it_tests/dev_polaris_userstore.json" + ) + val outputDir = layout.buildDirectory.dir("generated/resources/intTest/authz_it_tests") + inputs.file(polarisRangerServiceDefFile) + inputs.file(templateFile) + inputs.file(rolesFile) + inputs.file(userStoreFile) + outputs.dir(outputDir) + doLast { + // The sensitivity-based IT authz test exercises a boolean-expression policy condition + // that isn't part of the operator-facing artifact, so it's appended to the shipped + // serviceDef here rather than shipped in polaris-ranger-servicedef.json itself. + val policyConditions = + """ + , + "policyConditions": [ + { + "itemId": 1, + "name": "_expression", + "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator", + "evaluatorOptions": { "engineName": "JavaScript" }, + "label": "Enter boolean expression", + "description": "Boolean expression" + } + ] + """ + .trimIndent() + val shippedServiceDef = polarisRangerServiceDefFile.asFile.readText().trim() + check(shippedServiceDef.endsWith("}")) { + "unexpected trailing content in $polarisRangerServiceDefFile" + } + val serviceDefWithConditions = + shippedServiceDef.removeSuffix("}").trimEnd() + policyConditions + "\n}" + + val template = stripLicenseHeader(templateFile.asFile.readText()) + val merged = template.replace(servicedefPlaceholder, serviceDefWithConditions) + val outDir = outputDir.get().asFile.apply { mkdirs() } + outDir.resolve("dev_polaris.json").writeText(merged) + rolesFile.asFile.copyTo(outDir.resolve("dev_polaris_roles.json"), overwrite = true) + userStoreFile.asFile.copyTo(outDir.resolve("dev_polaris_userstore.json"), overwrite = true) + } + } + dependencies { polarisServer(project(path = ":polaris-server", configuration = "quarkusRunner")) @@ -84,9 +148,9 @@ testing { targets { all { val buildDir = project.layout.buildDirectory - val policyDir = - project.layout.projectDirectory.dir("src/intTest/resources/authz_it_tests") + val policyDir = buildDir.dir("generated/resources/intTest/authz_it_tests") testTask.configure { + dependsOn(generateAuthzItTestFixture) environment( "AWS_REGION", providers.environmentVariable("AWS_REGION").getOrElse("us-west-2"), @@ -124,7 +188,7 @@ testing { "polaris.authorization.ranger.authz.default.enable.implicit.userstore.enricher" to "true", "polaris.authorization.ranger.authz.default.policy.source.local_folder.path" to - policyDir.asFile.absolutePath, + policyDir.get().asFile.absolutePath, "polaris.features.\"SUPPORTED_CATALOG_STORAGE_TYPES\"" to "[\"FILE\"]", "polaris.features.\"ALLOW_INSECURE_STORAGE_TYPES\"" to "true", "polaris.readiness.ignore-severe-issues" to "true", diff --git a/extensions/auth/ranger/src/intTest/resources/authz_it_tests/dev_polaris.json b/extensions/auth/ranger/src/intTest/resources/authz_it_tests/dev_polaris.json deleted file mode 100644 index 701746f589..0000000000 --- a/extensions/auth/ranger/src/intTest/resources/authz_it_tests/dev_polaris.json +++ /dev/null @@ -1,730 +0,0 @@ -{ - "serviceId": 1, "serviceName": "dev_polaris", "policyVersion": 15, - "serviceDef": { - "name": "polaris", - "displayName": "Polaris (draft)", - "label": "Apache Polaris", - "description": "Apache Polaris", - "guid": "ca1b484b-e397-4ab4-b6e3-36a154662d7d", - "resources": [ - { - "itemId": 1, - "name": "root", - "label": "Root", - "description": "Root", - "parent": "", - "level": 10, - "isValidLeaf": true, - "accessTypeRestrictions": [ - "service-access-manage", - "catalog-create", - "catalog-list", - "principal-create", - "principal-list" - ] - }, - { - "itemId": 2, - "name": "catalog", - "label": "Catalog", - "description": "Catalog", - "parent": "root", - "level": 20, - "isValidLeaf": true, - "accessTypeRestrictions": [ - "catalog-drop", - "catalog-properties-read", - "catalog-properties-write", - "catalog-metadata-full", - "catalog-metadata-manage", - "catalog-content-manage", - "catalog-policy-attach", - "catalog-policy-detach" - ] - }, - { - "itemId": 3, - "name": "principal", - "label": "Principal", - "description": "Principal", - "parent": "root", - "level": 20, - "isValidLeaf": true, - "accessTypeRestrictions": [ - "principal-drop", - "principal-properties-read", - "principal-properties-write", - "principal-metadata-full", - "principal-credentials-rotate", - "principal-credentials-reset" - ] - }, - { - "itemId": 4, - "name": "namespace", - "label": "Namespace", - "description": "Namespace", - "parent": "catalog", - "level": 30, - "isValidLeaf": true, - "accessTypeRestrictions": [ - "namespace-create", - "namespace-drop", - "namespace-list", - "namespace-properties-read", - "namespace-properties-write", - "namespace-metadata-full", - "namespace-policy-attach", - "namespace-policy-detach", - "table-create", - "table-list", - "view-create", - "view-list", - "policy-create", - "policy-list" - ] - }, - { - "itemId": 5, - "name": "table", - "label": "Table", - "description": "Table", - "parent": "namespace", - "level": 40, - "isValidLeaf": true, - "accessTypeRestrictions": [ - "table-drop", - "table-data-read", - "table-data-write", - "table-properties-read", - "table-properties-write", - "table-properties-set", - "table-properties-remove", - "table-metadata-full", - "table-policy-attach", - "table-policy-detach", - "table-uuid-assign", - "table-format-version-upgrade", - "table-schema-add", - "table-schema-set-current", - "table-partition-spec-add", - "table-partition-specs-remove", - "table-sort-order-add", - "table-sort-order-set-default", - "table-snapshot-add", - "table-snapshots-remove", - "table-snapshot-ref-set", - "table-snapshot-ref-remove", - "table-location-set", - "table-statistics-set", - "table-statistics-remove", - "table-structure-manage", - "view-drop", - "view-properties-read", - "view-properties-write", - "view-metadata-full" - ] - }, - { - "itemId": 6, - "name": "policy", - "label": "Policy", - "description": "Policy", - "parent": "namespace", - "level": 40, - "isValidLeaf": true, - "accessTypeRestrictions": [ - "policy-read", - "policy-drop", - "policy-write", - "policy-metadata-full", - "policy-attach", - "policy-detach" - ] - } - ], - "accessTypes": [ - { "itemId": 1, "name": "service-access-manage", "label": "Service Manage Access", "category": "MANAGE", - "impliedGrants": [ - "catalog-create", - "catalog-drop", - "catalog-list", - "catalog-properties-read", - "catalog-properties-write", - "catalog-metadata-full", - "principal-create", - "principal-drop", - "principal-list", - "principal-properties-read", - "principal-properties-write", - "principal-metadata-full", - "principal-credentials-reset" - ] - }, - - { "itemId": 2, "name": "catalog-create", "label": "Catalog Create", "category": "CREATE", "impliedGrants": [ "catalog-list" ] }, - { "itemId": 3, "name": "catalog-drop", "label": "Catalog Drop", "category": "DELETE" }, - { "itemId": 4, "name": "catalog-list", "label": "Catalog List", "category": "READ" }, - { "itemId": 5, "name": "catalog-content-manage", "label": "Catalog Manage Content", "category": "MANAGE", - "impliedGrants": [ - "catalog-list", - "catalog-metadata-manage", - "catalog-properties-read", - "catalog-properties-write", - "catalog-policy-attach", - "catalog-policy-detach", - "namespace-create", - "namespace-drop", - "namespace-list", - "namespace-metadata-full", - "namespace-properties-read", - "namespace-properties-write", - "namespace-policy-attach", - "namespace-policy-detach", - "table-create", - "table-drop", - "table-list", - "table-data-read", - "table-data-write", - "table-metadata-full", - "table-properties-read", - "table-properties-write", - "table-properties-set", - "table-properties-remove", - "table-uuid-assign", - "table-format-version-upgrade", - "table-schema-add", - "table-schema-set-current", - "table-partition-spec-add", - "table-partition-specs-remove", - "table-policy-attach", - "table-policy-detach", - "table-sort-order-add", - "table-sort-order-set-default", - "table-snapshot-add", - "table-snapshots-remove", - "table-snapshot-ref-set", - "table-snapshot-ref-remove", - "table-location-set", - "table-statistics-set", - "table-statistics-remove", - "table-structure-manage", - "view-create", - "view-drop", - "view-list", - "view-metadata-full", - "view-properties-read", - "view-properties-write", - "policy-create", - "policy-drop", - "policy-list", - "policy-read", - "policy-write", - "policy-attach", - "policy-detach" - ] - }, - { "itemId": 6, "name": "catalog-metadata-full", "label": "Catalog Metadata Full", "category": "MANAGE", "impliedGrants": [ "catalog-create", "catalog-drop", "catalog-list", "catalog-properties-read", "catalog-properties-write" ] }, - { "itemId": 7, "name": "catalog-metadata-manage", "label": "Catalog Metadata Manage", "category": "MANAGE", - "impliedGrants": [ - "catalog-list", - "catalog-properties-read", - "catalog-properties-write", - "catalog-policy-attach", - "catalog-policy-detach", - "namespace-create", - "namespace-drop", - "namespace-list", - "namespace-properties-read", - "namespace-properties-write", - "namespace-metadata-full", - "namespace-policy-attach", - "namespace-policy-detach", - "table-create", - "table-drop", - "table-list", - "table-properties-read", - "table-properties-write", - "table-properties-set", - "table-properties-remove", - "table-metadata-full", - "table-uuid-assign", - "table-format-version-upgrade", - "table-schema-add", - "table-schema-set-current", - "table-partition-spec-add", - "table-partition-specs-remove", - "table-policy-attach", - "table-policy-detach", - "table-sort-order-add", - "table-sort-order-set-default", - "table-snapshot-add", - "table-snapshots-remove", - "table-snapshot-ref-set", - "table-snapshot-ref-remove", - "table-location-set", - "table-statistics-set", - "table-statistics-remove", - "table-structure-manage", - "view-create", - "view-drop", - "view-list", - "view-properties-read", - "view-properties-write", - "view-metadata-full", - "policy-create", - "policy-drop", - "policy-list", - "policy-read", - "policy-write", - "policy-attach", - "policy-detach" - ] - }, - { "itemId": 8, "name": "catalog-policy-attach", "label": "Catalog Policy Attach", "category": "MANAGE" }, - { "itemId": 9, "name": "catalog-policy-detach", "label": "Catalog Policy Detach", "category": "MANAGE" }, - { "itemId": 10, "name": "catalog-properties-read", "label": "Catalog Properties Read", "category": "READ", "impliedGrants": [ "catalog-list" ] }, - { "itemId": 11, "name": "catalog-properties-write", "label": "Catalog Properties Write", "category": "UPDATE", "impliedGrants": [ "catalog-list", "catalog-properties-read" ] }, - - { "itemId": 12, "name": "principal-create", "label": "Principal Create", "category": "CREATE", "impliedGrants": [ "principal-list" ] }, - { "itemId": 13, "name": "principal-drop", "label": "Principal Drop", "category": "DELETE" }, - { "itemId": 14, "name": "principal-list", "label": "Principal List", "category": "READ" }, - { "itemId": 15, "name": "principal-credentials-reset", "label": "Principal Credentials Reset", "category": "MANAGE" }, - { "itemId": 16, "name": "principal-credentials-rotate", "label": "Principal Credentials Rotate", "category": "MANAGE" }, - { "itemId": 17, "name": "principal-metadata-full", "label": "Principal Metadata Full", "category": "MANAGE", "impliedGrants": [ "principal-create", "principal-drop", "principal-list", "principal-properties-read", "principal-properties-write" ] }, - { "itemId": 18, "name": "principal-properties-read", "label": "Principal Properties Read", "category": "READ", "impliedGrants": [ "principal-list" ] }, - { "itemId": 19, "name": "principal-properties-write", "label": "Principal Properties Write", "category": "UPDATE", "impliedGrants": [ "principal-list", "principal-properties-read" ] }, - - { "itemId": 20, "name": "namespace-create", "label": "Namespace Create", "category": "CREATE", "impliedGrants": [ "namespace-list" ] }, - { "itemId": 21, "name": "namespace-drop", "label": "Namespace Drop", "category": "DELETE" }, - { "itemId": 22, "name": "namespace-list", "label": "Namespace List", "category": "READ" }, - { "itemId": 23, "name": "namespace-metadata-full", "label": "Namespace Metadata Full", "category": "MANAGE", "impliedGrants": [ "namespace-create", "namespace-drop", "namespace-list", "namespace-properties-read", "namespace-properties-write" ] }, - { "itemId": 24, "name": "namespace-policy-attach", "label": "Namespace Policy Attach", "category": "MANAGE" }, - { "itemId": 25, "name": "namespace-policy-detach", "label": "Namespace Policy Detach", "category": "MANAGE" }, - { "itemId": 26, "name": "namespace-properties-read", "label": "Namespace Properties Read", "category": "READ", "impliedGrants": [ "namespace-list" ] }, - { "itemId": 27, "name": "namespace-properties-write", "label": "Namespace Properties Write", "category": "UPDATE", "impliedGrants": [ "namespace-list", "namespace-properties-read" ] }, - - { "itemId": 28, "name": "table-create", "label": "Table Create", "category": "CREATE", "impliedGrants": [ "table-list" ] }, - { "itemId": 29, "name": "table-drop", "label": "Table Drop", "category": "DELETE" }, - { "itemId": 30, "name": "table-list", "label": "Table List", "category": "READ" }, - { "itemId": 31, "name": "table-data-read", "label": "Table Data Read", "category": "READ", "impliedGrants": [ "table-list", "table-properties-read" ] }, - { "itemId": 32, "name": "table-data-write", "label": "Table Data Write", "category": "UPDATE", - "impliedGrants": [ - "table-list", - "table-data-read", - "table-properties-read", - "table-properties-set", - "table-properties-remove", - "table-uuid-assign", - "table-format-version-upgrade", - "table-schema-add", - "table-schema-set-current", - "table-sort-order-add", - "table-sort-order-set-default", - "table-snapshot-add", - "table-snapshots-remove", - "table-snapshot-ref-set", - "table-snapshot-ref-remove", - "table-location-set", - "table-statistics-set", - "table-statistics-remove", - "table-partition-spec-add", - "table-partition-specs-remove", - "table-structure-manage" - ] - }, - { "itemId": 33, "name": "table-metadata-full", "label": "Table Metadata Full", "category": "MANAGE", - "impliedGrants": [ - "table-create", - "table-drop", - "table-list", - "table-properties-read", - "table-properties-write", - "table-properties-set", - "table-properties-remove", - "table-uuid-assign", - "table-format-version-upgrade", - "table-schema-add", - "table-schema-set-current", - "table-partition-spec-add", - "table-partition-specs-remove", - "table-sort-order-add", - "table-sort-order-set-default", - "table-snapshot-add", - "table-snapshots-remove", - "table-snapshot-ref-set", - "table-snapshot-ref-remove", - "table-location-set", - "table-statistics-set", - "table-statistics-remove", - "table-structure-manage" - ] - }, - { "itemId": 34, "name": "table-policy-attach", "label": "Table Policy Attach", "category": "MANAGE" }, - { "itemId": 35, "name": "table-policy-detach", "label": "Table Policy Detach", "category": "MANAGE" }, - { "itemId": 36, "name": "table-properties-read", "label": "Table Properties Read", "category": "READ", "impliedGrants": [ "table-list" ] }, - { "itemId": 37, "name": "table-properties-write", "label": "Table Properties Write", "category": "UPDATE", - "impliedGrants": [ - "table-list", - "table-properties-read", - "table-properties-set", - "table-properties-remove", - "table-uuid-assign", - "table-format-version-upgrade", - "table-schema-add", - "table-schema-set-current", - "table-partition-spec-add", - "table-partition-specs-remove", - "table-sort-order-add", - "table-sort-order-set-default", - "table-snapshot-add", - "table-snapshots-remove", - "table-snapshot-ref-set", - "table-snapshot-ref-remove", - "table-location-set", - "table-statistics-set", - "table-statistics-remove", - "table-structure-manage" - ] - }, - { "itemId": 38, "name": "table-properties-set", "label": "Table Properties Set", "category": "UPDATE" }, - { "itemId": 39, "name": "table-properties-remove", "label": "Table Properties Remove", "category": "UPDATE" }, - { "itemId": 40, "name": "table-uuid-assign", "label": "Table UUID Assign", "category": "UPDATE" }, - { "itemId": 41, "name": "table-format-version-upgrade", "label": "Table Format Version Upgrade", "category": "UPDATE" }, - { "itemId": 42, "name": "table-schema-add", "label": "Table Schema Add", "category": "UPDATE" }, - { "itemId": 43, "name": "table-schema-set-current", "label": "Table Schema Set Current", "category": "UPDATE" }, - { "itemId": 44, "name": "table-partition-spec-add", "label": "Table Partition Spec Add", "category": "UPDATE" }, - { "itemId": 45, "name": "table-partition-specs-remove", "label": "Table Partition Specs Remove", "category": "UPDATE" }, - { "itemId": 46, "name": "table-sort-order-add", "label": "Table Sort Order Add", "category": "UPDATE" }, - { "itemId": 47, "name": "table-sort-order-set-default", "label": "Table Sort Order Set Default", "category": "UPDATE" }, - { "itemId": 48, "name": "table-snapshot-add", "label": "Table Snapshot Add", "category": "UPDATE" }, - { "itemId": 49, "name": "table-snapshots-remove", "label": "Table Snapshots Remove", "category": "UPDATE" }, - { "itemId": 50, "name": "table-snapshot-ref-set", "label": "Table Snapshot-ref Set", "category": "UPDATE" }, - { "itemId": 51, "name": "table-snapshot-ref-remove", "label": "Table Snapshot-ref Remove", "category": "UPDATE" }, - { "itemId": 52, "name": "table-location-set", "label": "Table Location Set", "category": "UPDATE" }, - { "itemId": 53, "name": "table-statistics-set", "label": "Table Statistics Set", "category": "UPDATE" }, - { "itemId": 54, "name": "table-statistics-remove", "label": "Table Statistics Remove", "category": "UPDATE" }, - { "itemId": 55, "name": "table-structure-manage", "label": "Table Structure Manage", "category": "UPDATE", - "impliedGrants": [ - "table-properties-set", - "table-properties-remove", - "table-uuid-assign", - "table-format-version-upgrade", - "table-schema-add", - "table-schema-set-current", - "table-partition-spec-add", - "table-partition-specs-remove", - "table-sort-order-add", - "table-sort-order-set-default", - "table-snapshots-remove", - "table-snapshot-ref-remove", - "table-location-set", - "table-statistics-set", - "table-statistics-remove" - ] - }, - - { "itemId": 56, "name": "view-create", "label": "View Create", "category": "CREATE", "impliedGrants": [ "view-list" ] }, - { "itemId": 57, "name": "view-drop", "label": "View Drop", "category": "DELETE" }, - { "itemId": 58, "name": "view-list", "label": "View List", "category": "READ" }, - { "itemId": 59, "name": "view-metadata-full", "label": "View Metadata Full", "category": "MANAGE", "impliedGrants": [ "view-create", "view-drop", "view-list", "view-properties-read", "view-properties-write" ] }, - { "itemId": 60, "name": "view-properties-read", "label": "View Properties Read", "category": "READ", "impliedGrants": [ "view-list" ] }, - { "itemId": 61, "name": "view-properties-write", "label": "View Properties Write", "category": "UPDATE", "impliedGrants": [ "view-list", "view-properties-read" ] }, - - { "itemId": 62, "name": "policy-create", "label": "Policy Create", "category": "CREATE", "impliedGrants": [ "policy-list" ] }, - { "itemId": 63, "name": "policy-drop", "label": "Policy Drop", "category": "DELETE" }, - { "itemId": 64, "name": "policy-list", "label": "Policy List", "category": "READ" }, - { "itemId": 65, "name": "policy-read", "label": "Policy Read", "category": "READ", "impliedGrants": [ "policy-list" ] }, - { "itemId": 66, "name": "policy-write", "label": "Policy Write", "category": "UPDATE", "impliedGrants": [ "policy-list", "policy-read" ] }, - { "itemId": 67, "name": "policy-attach", "label": "Policy Attach", "category": "MANAGE" }, - { "itemId": 68, "name": "policy-detach", "label": "Policy Detach", "category": "MANAGE" }, - { "itemId": 69, "name": "policy-metadata-full", "label": "Policy Metadata Full", "category": "MANAGE", "impliedGrants": [ "policy-create", "policy-drop", "policy-list", "policy-read", "policy-write" ] } - ], - "policyConditions": [ - { - "itemId":1, - "name":"_expression", - "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator", - "evaluatorOptions" : {"engineName":"JavaScript"}, - "label":"Enter boolean expression", - "description": "Boolean expression" - } - ] - }, - "policies": [ - { - "id": 1, "name": "root:POLARIS", - "resources": { "root": { "values": [ "POLARIS" ] } }, - "policyItems": [ - { - "accesses": [ - { "type": "service-access-manage" }, - { "type": "catalog-create" }, - { "type": "catalog-list" }, - { "type": "principal-create" }, - { "type": "principal-list" } - ], - "users": [ "admin1", "root" ] - }, - { - "accesses": [ - { "type": "catalog-list" }, - { "type": "principal-list" } - ], - "users": [ "user1" ] } - ] - }, - { - "id": 2, "name": "catalog:POLARIS/catalog1", "version": 1, - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "catalog1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "catalog-drop" }, - { "type": "catalog-properties-read" }, - { "type": "catalog-properties-write" }, - { "type": "catalog-metadata-full" }, - { "type": "catalog-metadata-manage" }, - { "type": "catalog-content-manage" }, - { "type": "catalog-policy-attach" }, - { "type": "catalog-policy-detach" } - ], - "users": [ "admin1" ] } - ] - }, - { - "id": 3, "name": "principal:POLARIS/principal1", "version": 1, - "resources": { - "root": { "values": [ "POLARIS" ] }, - "principal": { "values": [ "principal1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "principal-drop" }, - { "type": "principal-properties-read" }, - { "type": "principal-properties-write" }, - { "type": "principal-metadata-full" }, - { "type": "principal-credentials-rotate" }, - { "type": "principal-credentials-reset" } - ], - "users": [ "admin1" ] - } - ] - }, - { - "id": 4, "name": "namespace:POLARIS/catalog1/namespace1", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "catalog1" ] }, - "namespace": { "values": [ "namespace1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "namespace-create" }, - { "type": "namespace-drop" }, - { "type": "namespace-list" }, - { "type": "namespace-properties-read" }, - { "type": "namespace-properties-write" }, - { "type": "namespace-metadata-full" }, - { "type": "namespace-policy-attach" }, - { "type": "namespace-policy-detach" }, - { "type": "table-create" }, - { "type": "table-drop" }, - { "type": "table-list" }, - { "type": "table-data-write" }, - { "type": "table-properties-write" }, - { "type": "view-create" }, - { "type": "view-drop" }, - { "type": "view-list" }, - { "type": "policy-create" }, - { "type": "policy-list" } - ], - "users": [ "admin1" ] - } - ] - }, - { - "id": 5, "name": "table:POLARIS/catalog1/namespace1/table1", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "catalog1" ] }, - "namespace": { "values": [ "namespace1" ] }, - "table": { "values": [ "table1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "table-drop" }, - { "type": "table-properties-read" }, - { "type": "table-properties-write" }, - { "type": "table-properties-set" }, - { "type": "table-properties-remove" }, - { "type": "table-data-read" }, - { "type": "table-data-write" }, - { "type": "table-metadata-full" }, - { "type": "table-policy-attach" }, - { "type": "table-policy-detach" }, - { "type": "table-uuid-assign" }, - { "type": "table-format-version-upgrade" }, - { "type": "table-schema-add" }, - { "type": "table-schema-set-current" }, - { "type": "table-partition-spec-add" }, - { "type": "table-partition-specs-remove" }, - { "type": "table-sort-order-add" }, - { "type": "table-sort-order-set-default" }, - { "type": "table-snapshot-add" }, - { "type": "table-snapshots-remove" }, - { "type": "table-snapshot-ref-set" }, - { "type": "table-snapshot-ref-remove" }, - { "type": "table-location-set" }, - { "type": "table-statistics-set" }, - { "type": "table-statistics-remove" }, - { "type": "table-structure-manage" } - ], - "users": [ "admin1" ] } - ] - }, - { - "id": 6, "name": "table:POLARIS/catalog1/namespace1/view1", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "catalog1" ] }, - "namespace": { "values": [ "namespace1" ] }, - "table": { "values": [ "view1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "view-drop" }, - { "type": "view-properties-read" }, - { "type": "view-properties-write" }, - { "type": "view-metadata-full" } - ], - "users": [ "admin1" ] } - ] - }, - { - "id": 7, "name": "policy:POLARIS/catalog1/namespace1/policy1", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "catalog1" ] }, - "namespace": { "values": [ "namespace1" ] }, - "policy": { "values": [ "policy1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "policy-read" }, - { "type": "policy-drop" }, - { "type": "policy-write" }, - { "type": "policy-metadata-full" }, - { "type": "policy-attach" }, - { "type": "policy-detach" } - ], - "users": [ "admin1" ] } - ] - }, - { - "id": 8, "name": "policy:POLARIS/all_catalog", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "*" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "namespace-create" }, - { "type": "catalog-policy-attach" }, - { "type": "catalog-policy-detach" }, - { "type": "catalog-drop" } - ], - "users": [ "root" ] } - ] - }, - { - "id": 9, "name": "policy:POLARIS/all_catalog/all_namespace/table-operations", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "*" ] }, - "namespace": { "values": [ "*" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "table-create" }, - { "type": "namespace-drop" }, - { "type": "policy-create" } - ], - "users": [ "root" ] } - ] - }, - { - "id": 10, "name": "policy:POLARIS/all_catalog/all_namespace/all_tables/table-operations", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "*" ] }, - "namespace": { "values": [ "*" ] }, - "table": { "values": [ "*" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "table-drop" } - ], - "users": [ "root" ] } - ] - }, - { - "id": 11, "name": "policy:POLARIS/all_catalog/all_namespace/all_policy", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "*" ] }, - "namespace": { "values": [ "*" ] }, - "policy": { "values": [ "*" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "policy-read" }, - { "type": "policy-drop" }, - { "type": "policy-write" }, - { "type": "policy-metadata-full" }, - { "type": "policy-attach" }, - { "type": "policy-detach" } - ], - "users": [ "root" ] } - ] - }, - { - "id": 12, "name": "Realm:POLARIS", - "resources": { - "root": { "values": [ "POLARIS" ] } - }, - "policyItems": [ - { - "accesses": [ - { - "type": "catalog-list" - } - ], - "users": [ - "polcondu1", "polcondu2" - ], - "conditions": [ - { - "type": "_expression", - "values": [ - "USER.allowedSensitiveLevel > 5" - ] - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/extensions/auth/ranger/src/intTest/resources/authz_it_tests/dev_polaris.json.template b/extensions/auth/ranger/src/intTest/resources/authz_it_tests/dev_polaris.json.template new file mode 100644 index 0000000000..87c0dd8a74 --- /dev/null +++ b/extensions/auth/ranger/src/intTest/resources/authz_it_tests/dev_polaris.json.template @@ -0,0 +1,301 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + * Not valid JSON as-is: this is a template with a serviceDef placeholder, stripped of this + * header and spliced with the shipped polaris-ranger-servicedef.json before use. + */ +{ + "serviceId": 1, "serviceName": "dev_polaris", "policyVersion": 15, + "serviceDef": @@POLARIS_RANGER_SERVICE_DEF@@, + "policies": [ + { + "id": 1, "name": "root:POLARIS", + "resources": { "root": { "values": [ "POLARIS" ] } }, + "policyItems": [ + { + "accesses": [ + { "type": "service-access-manage" }, + { "type": "catalog-create" }, + { "type": "catalog-list" }, + { "type": "principal-create" }, + { "type": "principal-list" } + ], + "users": [ "admin1", "root" ] + }, + { + "accesses": [ + { "type": "catalog-list" }, + { "type": "principal-list" } + ], + "users": [ "user1" ] } + ] + }, + { + "id": 2, "name": "catalog:POLARIS/catalog1", "version": 1, + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "catalog1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "catalog-drop" }, + { "type": "catalog-properties-read" }, + { "type": "catalog-properties-write" }, + { "type": "catalog-metadata-full" }, + { "type": "catalog-metadata-manage" }, + { "type": "catalog-content-manage" }, + { "type": "catalog-policy-attach" }, + { "type": "catalog-policy-detach" } + ], + "users": [ "admin1" ] } + ] + }, + { + "id": 3, "name": "principal:POLARIS/principal1", "version": 1, + "resources": { + "root": { "values": [ "POLARIS" ] }, + "principal": { "values": [ "principal1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "principal-drop" }, + { "type": "principal-properties-read" }, + { "type": "principal-properties-write" }, + { "type": "principal-metadata-full" }, + { "type": "principal-credentials-rotate" }, + { "type": "principal-credentials-reset" } + ], + "users": [ "admin1" ] + } + ] + }, + { + "id": 4, "name": "namespace:POLARIS/catalog1/namespace1", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "catalog1" ] }, + "namespace": { "values": [ "namespace1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "namespace-create" }, + { "type": "namespace-drop" }, + { "type": "namespace-list" }, + { "type": "namespace-properties-read" }, + { "type": "namespace-properties-write" }, + { "type": "namespace-metadata-full" }, + { "type": "namespace-policy-attach" }, + { "type": "namespace-policy-detach" }, + { "type": "table-create" }, + { "type": "table-drop" }, + { "type": "table-list" }, + { "type": "table-data-write" }, + { "type": "table-properties-write" }, + { "type": "view-create" }, + { "type": "view-drop" }, + { "type": "view-list" }, + { "type": "policy-create" }, + { "type": "policy-list" } + ], + "users": [ "admin1" ] + } + ] + }, + { + "id": 5, "name": "table:POLARIS/catalog1/namespace1/table1", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "catalog1" ] }, + "namespace": { "values": [ "namespace1" ] }, + "table": { "values": [ "table1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "table-drop" }, + { "type": "table-properties-read" }, + { "type": "table-properties-write" }, + { "type": "table-properties-set" }, + { "type": "table-properties-remove" }, + { "type": "table-data-read" }, + { "type": "table-data-write" }, + { "type": "table-metadata-full" }, + { "type": "table-policy-attach" }, + { "type": "table-policy-detach" }, + { "type": "table-uuid-assign" }, + { "type": "table-format-version-upgrade" }, + { "type": "table-schema-add" }, + { "type": "table-schema-set-current" }, + { "type": "table-partition-spec-add" }, + { "type": "table-partition-specs-remove" }, + { "type": "table-sort-order-add" }, + { "type": "table-sort-order-set-default" }, + { "type": "table-snapshot-add" }, + { "type": "table-snapshots-remove" }, + { "type": "table-snapshot-ref-set" }, + { "type": "table-snapshot-ref-remove" }, + { "type": "table-location-set" }, + { "type": "table-statistics-set" }, + { "type": "table-statistics-remove" }, + { "type": "table-structure-manage" } + ], + "users": [ "admin1" ] } + ] + }, + { + "id": 6, "name": "table:POLARIS/catalog1/namespace1/view1", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "catalog1" ] }, + "namespace": { "values": [ "namespace1" ] }, + "table": { "values": [ "view1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "view-drop" }, + { "type": "view-properties-read" }, + { "type": "view-properties-write" }, + { "type": "view-metadata-full" } + ], + "users": [ "admin1" ] } + ] + }, + { + "id": 7, "name": "policy:POLARIS/catalog1/namespace1/policy1", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "catalog1" ] }, + "namespace": { "values": [ "namespace1" ] }, + "policy": { "values": [ "policy1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "policy-read" }, + { "type": "policy-drop" }, + { "type": "policy-write" }, + { "type": "policy-metadata-full" }, + { "type": "policy-attach" }, + { "type": "policy-detach" } + ], + "users": [ "admin1" ] } + ] + }, + { + "id": 8, "name": "policy:POLARIS/all_catalog", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "*" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "namespace-create" }, + { "type": "catalog-policy-attach" }, + { "type": "catalog-policy-detach" }, + { "type": "catalog-drop" } + ], + "users": [ "root" ] } + ] + }, + { + "id": 9, "name": "policy:POLARIS/all_catalog/all_namespace/table-operations", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "*" ] }, + "namespace": { "values": [ "*" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "table-create" }, + { "type": "namespace-drop" }, + { "type": "policy-create" } + ], + "users": [ "root" ] } + ] + }, + { + "id": 10, "name": "policy:POLARIS/all_catalog/all_namespace/all_tables/table-operations", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "*" ] }, + "namespace": { "values": [ "*" ] }, + "table": { "values": [ "*" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "table-drop" } + ], + "users": [ "root" ] } + ] + }, + { + "id": 11, "name": "policy:POLARIS/all_catalog/all_namespace/all_policy", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "*" ] }, + "namespace": { "values": [ "*" ] }, + "policy": { "values": [ "*" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "policy-read" }, + { "type": "policy-drop" }, + { "type": "policy-write" }, + { "type": "policy-metadata-full" }, + { "type": "policy-attach" }, + { "type": "policy-detach" } + ], + "users": [ "root" ] } + ] + }, + { + "id": 12, "name": "Realm:POLARIS", + "resources": { + "root": { "values": [ "POLARIS" ] } + }, + "policyItems": [ + { + "accesses": [ + { + "type": "catalog-list" + } + ], + "users": [ + "polcondu1", "polcondu2" + ], + "conditions": [ + { + "type": "_expression", + "values": [ + "USER.allowedSensitiveLevel > 5" + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/extensions/auth/ranger/src/test/resources/authz_tests/dev_polaris.json b/extensions/auth/ranger/src/main/resources/polaris-ranger-servicedef.json similarity index 77% rename from extensions/auth/ranger/src/test/resources/authz_tests/dev_polaris.json rename to extensions/auth/ranger/src/main/resources/polaris-ranger-servicedef.json index f55a328659..7f786efad8 100644 --- a/extensions/auth/ranger/src/test/resources/authz_tests/dev_polaris.json +++ b/extensions/auth/ranger/src/main/resources/polaris-ranger-servicedef.json @@ -1,6 +1,4 @@ { - "serviceId": 1, "serviceName": "dev_polaris", "policyVersion": 15, - "serviceDef": { "name": "polaris", "displayName": "Polaris (draft)", "label": "Apache Polaris", @@ -440,184 +438,4 @@ { "itemId": 68, "name": "policy-detach", "label": "Policy Detach", "category": "MANAGE" }, { "itemId": 69, "name": "policy-metadata-full", "label": "Policy Metadata Full", "category": "MANAGE", "impliedGrants": [ "policy-create", "policy-drop", "policy-list", "policy-read", "policy-write" ] } ] - }, - "policies": [ - { - "id": 1, "name": "root:POLARIS", - "resources": { "root": { "values": [ "POLARIS" ] } }, - "policyItems": [ - { - "accesses": [ - { "type": "service-access-manage" }, - { "type": "catalog-create" }, - { "type": "catalog-list" }, - { "type": "principal-create" }, - { "type": "principal-list" } - ], - "users": [ "admin1", "root" ] - }, - { - "accesses": [ - { "type": "catalog-list" }, - { "type": "principal-list" } - ], - "users": [ "user1" ] } - ] - }, - { - "id": 2, "name": "catalog:POLARIS/catalog1", "version": 1, - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "catalog1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "catalog-drop" }, - { "type": "catalog-properties-read" }, - { "type": "catalog-properties-write" }, - { "type": "catalog-metadata-full" }, - { "type": "catalog-metadata-manage" }, - { "type": "catalog-content-manage" }, - { "type": "catalog-policy-attach" }, - { "type": "catalog-policy-detach" } - ], - "users": [ "admin1" ] } - ] - }, - { - "id": 3, "name": "principal:POLARIS/principal1", "version": 1, - "resources": { - "root": { "values": [ "POLARIS" ] }, - "principal": { "values": [ "principal1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "principal-drop" }, - { "type": "principal-properties-read" }, - { "type": "principal-properties-write" }, - { "type": "principal-metadata-full" }, - { "type": "principal-credentials-rotate" }, - { "type": "principal-credentials-reset" } - ], - "users": [ "admin1" ] - } - ] - }, - { - "id": 4, "name": "namespace:POLARIS/catalog1/namespace1", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "catalog1" ] }, - "namespace": { "values": [ "namespace1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "namespace-create" }, - { "type": "namespace-drop" }, - { "type": "namespace-list" }, - { "type": "namespace-properties-read" }, - { "type": "namespace-properties-write" }, - { "type": "namespace-metadata-full" }, - { "type": "namespace-policy-attach" }, - { "type": "namespace-policy-detach" }, - { "type": "table-create" }, - { "type": "table-drop" }, - { "type": "table-list" }, - { "type": "table-data-write" }, - { "type": "table-properties-write" }, - { "type": "view-create" }, - { "type": "view-drop" }, - { "type": "view-list" }, - { "type": "policy-create" }, - { "type": "policy-list" } - ], - "users": [ "admin1" ] - } - ] - }, - { - "id": 5, "name": "table:POLARIS/catalog1/namespace1/table1", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "catalog1" ] }, - "namespace": { "values": [ "namespace1" ] }, - "table": { "values": [ "table1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "table-drop" }, - { "type": "table-properties-read" }, - { "type": "table-properties-write" }, - { "type": "table-properties-set" }, - { "type": "table-properties-remove" }, - { "type": "table-data-read" }, - { "type": "table-data-write" }, - { "type": "table-metadata-full" }, - { "type": "table-policy-attach" }, - { "type": "table-policy-detach" }, - { "type": "table-uuid-assign" }, - { "type": "table-format-version-upgrade" }, - { "type": "table-schema-add" }, - { "type": "table-schema-set-current" }, - { "type": "table-partition-spec-add" }, - { "type": "table-partition-specs-remove" }, - { "type": "table-sort-order-add" }, - { "type": "table-sort-order-set-default" }, - { "type": "table-snapshot-add" }, - { "type": "table-snapshots-remove" }, - { "type": "table-snapshot-ref-set" }, - { "type": "table-snapshot-ref-remove" }, - { "type": "table-location-set" }, - { "type": "table-statistics-set" }, - { "type": "table-statistics-remove" }, - { "type": "table-structure-manage" } - ], - "users": [ "admin1" ] } - ] - }, - { - "id": 6, "name": "table:POLARIS/catalog1/namespace1/view1", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "catalog1" ] }, - "namespace": { "values": [ "namespace1" ] }, - "table": { "values": [ "view1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "view-drop" }, - { "type": "view-properties-read" }, - { "type": "view-properties-write" }, - { "type": "view-metadata-full" } - ], - "users": [ "admin1" ] } - ] - }, - { - "id": 7, "name": "policy:POLARIS/catalog1/namespace1/policy1", - "resources": { - "root": { "values": [ "POLARIS" ] }, - "catalog": { "values": [ "catalog1" ] }, - "namespace": { "values": [ "namespace1" ] }, - "policy": { "values": [ "policy1" ] } - }, - "policyItems": [ - { - "accesses": [ - { "type": "policy-read" }, - { "type": "policy-drop" }, - { "type": "policy-write" }, - { "type": "policy-metadata-full" }, - { "type": "policy-attach" }, - { "type": "policy-detach" } - ], - "users": [ "admin1" ] } - ] - } - ] -} + } diff --git a/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactoryTest.java b/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactoryTest.java index 557551ec3f..0337a43e69 100644 --- a/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactoryTest.java +++ b/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerFactoryTest.java @@ -25,13 +25,16 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.nio.file.Path; import java.util.Collections; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; public class RangerPolarisAuthorizerFactoryTest { @Test - public void testAuthorizerInstantiation() { - RangerPolarisAuthorizerFactory factory = new RangerPolarisAuthorizerFactory(createConfig()); + public void testAuthorizerInstantiation(@TempDir Path tempDir) { + RangerPolarisAuthorizerFactory factory = + new RangerPolarisAuthorizerFactory(createConfig(tempDir)); RangerPolarisAuthorizer authorizer = factory.create(createRealmConfig()); assertNotNull(authorizer); authorizer.setRealmContext(createRealmContext()); diff --git a/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerTest.java b/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerTest.java index ea88fab97d..bddfffedda 100644 --- a/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerTest.java +++ b/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerPolarisAuthorizerTest.java @@ -36,6 +36,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -69,6 +70,7 @@ import org.apache.ranger.authz.model.RangerMultiAuthzRequest; import org.apache.ranger.authz.model.RangerMultiAuthzResult; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.mockito.ArgumentCaptor; import tools.jackson.core.JsonParser; import tools.jackson.databind.DatabindException; @@ -85,8 +87,9 @@ public class RangerPolarisAuthorizerTest { private final PolarisAuthorizer authorizer; - public RangerPolarisAuthorizerTest() { - RangerPolarisAuthorizerFactory factory = new RangerPolarisAuthorizerFactory(createConfig()); + public RangerPolarisAuthorizerTest(@TempDir Path tempDir) { + RangerPolarisAuthorizerFactory factory = + new RangerPolarisAuthorizerFactory(createConfig(tempDir)); RangerPolarisAuthorizer rangerPolarisAuthorizer = factory.create(createRealmConfig()); rangerPolarisAuthorizer.setRealmContext(createRealmContext()); this.authorizer = rangerPolarisAuthorizer; diff --git a/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerTestUtils.java b/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerTestUtils.java index 27998ae50c..1ee4789c0b 100644 --- a/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerTestUtils.java +++ b/extensions/auth/ranger/src/test/java/org/apache/polaris/extension/auth/ranger/RangerTestUtils.java @@ -19,6 +19,12 @@ package org.apache.polaris.extension.auth.ranger; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -30,18 +36,56 @@ public class RangerTestUtils { private static final String REALM_CONTEXT_NAME = "POLARIS"; + private static final String SERVICE_DEF_PLACEHOLDER = "@@POLARIS_RANGER_SERVICE_DEF@@"; - public static RangerPolarisAuthorizerConfig createConfig() { - Map properties = new HashMap<>(); + /** + * Writes the {@code dev_polaris.json} authz fixture into {@code policyDir} by splicing the + * shipped {@code polaris-ranger-servicedef.json} into the checked-in template, then points the + * returned config at that directory via {@code LocalFolderPolicySource}. Keeping this in test + * code (rather than a build-time Gradle task) keeps the fixture generation next to the test that + * actually consumes it. + */ + public static RangerPolarisAuthorizerConfig createConfig(Path policyDir) { + writeAuthzTestFixture(policyDir); + Map properties = new HashMap<>(); properties.put( "authz.default.policy.source.impl", - "org.apache.ranger.admin.client.EmbeddedResourcePolicySource"); - properties.put("authz.default.policy.source.embedded_resource.path", "/authz_tests"); + "org.apache.ranger.admin.client.LocalFolderPolicySource"); + properties.put("authz.default.policy.source.local_folder.path", policyDir.toString()); return createConfig("dev_polaris", properties); } + private static void writeAuthzTestFixture(Path policyDir) { + String serviceDef = readClasspathResource("/polaris-ranger-servicedef.json"); + String template = + stripLicenseHeader(readClasspathResource("/authz_tests/dev_polaris.json.template")); + String merged = template.replace(SERVICE_DEF_PLACEHOLDER, serviceDef); + try { + Files.writeString(policyDir.resolve("dev_polaris.json"), merged); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + // Strips the ASF license header (required since this template is a checked-in source file) + // that precedes the "{" starting the actual, not-quite-valid-JSON template content. + private static String stripLicenseHeader(String text) { + return text.substring(text.indexOf("*/") + 2).stripLeading(); + } + + private static String readClasspathResource(String resourcePath) { + try (InputStream in = RangerTestUtils.class.getResourceAsStream(resourcePath)) { + if (in == null) { + throw new IOException(resourcePath + " not found on classpath"); + } + return new String(in.readAllBytes(), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public static RangerPolarisAuthorizerConfig createConfig( String serviceName, Map properties) { return new RangerPolarisAuthorizerConfig() { diff --git a/extensions/auth/ranger/src/test/resources/authz_tests/dev_polaris.json.template b/extensions/auth/ranger/src/test/resources/authz_tests/dev_polaris.json.template new file mode 100644 index 0000000000..8e13853f60 --- /dev/null +++ b/extensions/auth/ranger/src/test/resources/authz_tests/dev_polaris.json.template @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + * Not valid JSON as-is: this is a template with a serviceDef placeholder, stripped of this + * header and spliced with the shipped polaris-ranger-servicedef.json before use. + */ +{ + "serviceId": 1, "serviceName": "dev_polaris", "policyVersion": 15, + "serviceDef": @@POLARIS_RANGER_SERVICE_DEF@@, + "policies": [ + { + "id": 1, "name": "root:POLARIS", + "resources": { "root": { "values": [ "POLARIS" ] } }, + "policyItems": [ + { + "accesses": [ + { "type": "service-access-manage" }, + { "type": "catalog-create" }, + { "type": "catalog-list" }, + { "type": "principal-create" }, + { "type": "principal-list" } + ], + "users": [ "admin1", "root" ] + }, + { + "accesses": [ + { "type": "catalog-list" }, + { "type": "principal-list" } + ], + "users": [ "user1" ] } + ] + }, + { + "id": 2, "name": "catalog:POLARIS/catalog1", "version": 1, + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "catalog1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "catalog-drop" }, + { "type": "catalog-properties-read" }, + { "type": "catalog-properties-write" }, + { "type": "catalog-metadata-full" }, + { "type": "catalog-metadata-manage" }, + { "type": "catalog-content-manage" }, + { "type": "catalog-policy-attach" }, + { "type": "catalog-policy-detach" } + ], + "users": [ "admin1" ] } + ] + }, + { + "id": 3, "name": "principal:POLARIS/principal1", "version": 1, + "resources": { + "root": { "values": [ "POLARIS" ] }, + "principal": { "values": [ "principal1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "principal-drop" }, + { "type": "principal-properties-read" }, + { "type": "principal-properties-write" }, + { "type": "principal-metadata-full" }, + { "type": "principal-credentials-rotate" }, + { "type": "principal-credentials-reset" } + ], + "users": [ "admin1" ] + } + ] + }, + { + "id": 4, "name": "namespace:POLARIS/catalog1/namespace1", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "catalog1" ] }, + "namespace": { "values": [ "namespace1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "namespace-create" }, + { "type": "namespace-drop" }, + { "type": "namespace-list" }, + { "type": "namespace-properties-read" }, + { "type": "namespace-properties-write" }, + { "type": "namespace-metadata-full" }, + { "type": "namespace-policy-attach" }, + { "type": "namespace-policy-detach" }, + { "type": "table-create" }, + { "type": "table-drop" }, + { "type": "table-list" }, + { "type": "table-data-write" }, + { "type": "table-properties-write" }, + { "type": "view-create" }, + { "type": "view-drop" }, + { "type": "view-list" }, + { "type": "policy-create" }, + { "type": "policy-list" } + ], + "users": [ "admin1" ] + } + ] + }, + { + "id": 5, "name": "table:POLARIS/catalog1/namespace1/table1", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "catalog1" ] }, + "namespace": { "values": [ "namespace1" ] }, + "table": { "values": [ "table1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "table-drop" }, + { "type": "table-properties-read" }, + { "type": "table-properties-write" }, + { "type": "table-properties-set" }, + { "type": "table-properties-remove" }, + { "type": "table-data-read" }, + { "type": "table-data-write" }, + { "type": "table-metadata-full" }, + { "type": "table-policy-attach" }, + { "type": "table-policy-detach" }, + { "type": "table-uuid-assign" }, + { "type": "table-format-version-upgrade" }, + { "type": "table-schema-add" }, + { "type": "table-schema-set-current" }, + { "type": "table-partition-spec-add" }, + { "type": "table-partition-specs-remove" }, + { "type": "table-sort-order-add" }, + { "type": "table-sort-order-set-default" }, + { "type": "table-snapshot-add" }, + { "type": "table-snapshots-remove" }, + { "type": "table-snapshot-ref-set" }, + { "type": "table-snapshot-ref-remove" }, + { "type": "table-location-set" }, + { "type": "table-statistics-set" }, + { "type": "table-statistics-remove" }, + { "type": "table-structure-manage" } + ], + "users": [ "admin1" ] } + ] + }, + { + "id": 6, "name": "table:POLARIS/catalog1/namespace1/view1", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "catalog1" ] }, + "namespace": { "values": [ "namespace1" ] }, + "table": { "values": [ "view1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "view-drop" }, + { "type": "view-properties-read" }, + { "type": "view-properties-write" }, + { "type": "view-metadata-full" } + ], + "users": [ "admin1" ] } + ] + }, + { + "id": 7, "name": "policy:POLARIS/catalog1/namespace1/policy1", + "resources": { + "root": { "values": [ "POLARIS" ] }, + "catalog": { "values": [ "catalog1" ] }, + "namespace": { "values": [ "namespace1" ] }, + "policy": { "values": [ "policy1" ] } + }, + "policyItems": [ + { + "accesses": [ + { "type": "policy-read" }, + { "type": "policy-drop" }, + { "type": "policy-write" }, + { "type": "policy-metadata-full" }, + { "type": "policy-attach" }, + { "type": "policy-detach" } + ], + "users": [ "admin1" ] } + ] + } + ] +}