HyukjinKwon commented on code in PR #58614:
URL: https://github.com/apache/spark/pull/58614#discussion_r4001014258


##########
connector/avro/src/test/scala/org/apache/spark/sql/avro/AvroSuite.scala:
##########
@@ -1255,6 +1255,66 @@ abstract class AvroSuite
     assertExceptionMsg[FileNotFoundException](e, "File not_exists.avsc does 
not exist")
   }
 
+  // spark.sql.avro.schemaUrlAllowedSchemes is a static SQL config, so it 
cannot be set with
+  // withSQLConf; these drive AvroOptions directly under a SQLConf provided 
via withExistingConf.
+  // A scheme-less local path resolves to the default file system ("file").

Review Comment:
   Right -- `testFile` returns a `file:` URL, so nothing reached the default-FS 
branch. Added `SPARK-59329: avroSchemaUrl allowlist resolves a scheme-less path 
against the default file system` in 69dd3b5 (strips the scheme; permitted when 
`file` is allowed, rejected reporting `The scheme 'file'` otherwise), and 
corrected the misleading "scheme-less" comments and the description.



##########
sql/core/src/main/scala/org/apache/spark/sql/avro/AvroOptions.scala:
##########
@@ -76,7 +76,29 @@ private[sql] class AvroOptions(
     parameters.get(AVRO_SCHEMA).map(AvroUtils.parseAvroSchema).orElse({
       val avroUrlSchema = parameters.get(AVRO_SCHEMA_URL).map(url => {
         log.debug("loading avro schema from url: " + url)
-        val fs = FileSystem.get(new URI(url), conf)
+        val uri = new URI(url)
+        // Optional operator-configured allowlist of URI schemes for 
avroSchemaUrl. Empty by
+        // default, which permits any scheme and leaves the file-system 
resolution below unchanged.
+        // When set, the scheme is resolved and checked before the file system 
for the URL is
+        // instantiated, so a disallowed scheme is rejected with a clear error 
rather than a
+        // lower-level failure while opening it. A scheme-less URL takes the 
default file system's
+        // scheme, so it can be permitted by allowing that scheme.
+        val allowedSchemes = 
SQLConf.get.getConf(SQLConf.AVRO_SCHEMA_URL_ALLOWED_SCHEMES)
+          .map(_.toLowerCase(Locale.ROOT))
+        if (allowedSchemes.nonEmpty) {
+          // FileSystem.getDefaultUri always carries a scheme (it throws 
otherwise), so a
+          // scheme-less URL resolves to the default file system's scheme.
+          val scheme = Option(uri.getScheme)
+            .getOrElse(FileSystem.getDefaultUri(conf).getScheme)
+            .toLowerCase(Locale.ROOT)
+          if (!allowedSchemes.contains(scheme)) {
+            throw QueryCompilationErrors.avroOptionsException(
+              AVRO_SCHEMA_URL,
+              s"The scheme '$scheme' of avroSchemaUrl '$url' is not in the 
allowlist " +
+                s"configured by 
${SQLConf.AVRO_SCHEMA_URL_ALLOWED_SCHEMES.key}.")

Review Comment:
   Applied the suggestion in 69dd3b5 -- the message now echoes the parsed 
allowlist, e.g. `... is not in the allowlist [file://] configured by ...`. Both 
existing assertions still match.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to