如何为每个容器的SAS令牌访问实现SASTokenProvider ?



根据文档,通过实现org.apache.hadoop.fs.azurebfs.extensions.SASTokenProvider接口,您可以使用SAS令牌访问Azure Data Lake Storage Gen2。

请参阅此处的文档:https://learn.microsoft.com/en-us/azure/databricks/data/data-sources/azure/adls-gen2/azure-datalake-gen2-sas-access

但是,只提供了一个模拟实现,它使用对主帐户密钥的直接访问来生成SAS令牌:

try {
AbfsConfiguration abfsConfig = new AbfsConfiguration(configuration, accountName);
accountKey = Base64.decode(abfsConfig.getStorageAccountKey());
} catch (Exception ex) {
throw new IOException(ex);
}
generator = new ServiceSASGenerator(accountKey);

当代码运行在一个可以访问主帐户密钥的上下文中时,通过提供SAS令牌来限制访问是完全没有意义的,显然这是一个仅用于测试目的的模拟实现。

所以,这个类的正确实现应该是:

  • 应该在包单元中运行,这样它就可以访问secret作用域
  • 将在scala中实现,因为java不支持
  • 从secret作用域
  • 获取SAS令牌返回SAS令牌

这样的实现是怎么写的?

下面是证明可以执行的最基本和最简单的解版本:

%scala
package com.foo
class CustomTokenProvider extends org.apache.hadoop.fs.azurebfs.extensions.SASTokenProvider {
def getSASToken(accountName: String,fileSystem: String,path: String,operation: String): String = {
return "sp=...etc etc"
}
def initialize(configuration: org.apache.hadoop.conf.Configuration, accountName: String): Unit = {    
}
}
...
spark.conf.set("fs.azure.account.auth.type.STORAGE_ACC.dfs.core.windows.net", "SAS")
spark.conf.set("fs.azure.sas.token.provider.type.STORAGE_ACC.dfs.core.windows.net", "com.foo.CustomTokenProvider")
dbutils.fs.ls("abfss://sandbox@STORAGE_ACC.dfs.core.windows.net/")
> [FileInfo(path='abfss://sandbox@STORAGE_ACC.dfs.core.windows.net/t.py', name='t.py', size=112)]
dbutils.fs.ls("abfss://restricted@STORAGE_ACC.dfs.core.windows.net/")
> Operation failed: "Server failed to authenticate the request.

但是,如何将这个实现更改为从秘密存储中提取密钥而不是硬编码呢?

专门注意:

  • 这是指abfss驱动程序,而不是旧的水洗驱动程序。

  • 这个问题是关于从秘密存储中获取SAS令牌,这可以限制在组/用户级别;在集群级别分配令牌(例如:(环境变量)不是一个有效的解决方案,因为它意味着所有集群用户被授予相同的权限。

  • …是的,我知道,databricks有自己的自定义身份提供者系统(Unity),但这只适用于hive metastore中的数据集。这个问题是专门针对低层存储帐户访问的。

%scala
package com.foo
import org.apache.hadoop.fs.FileSystem
import org.apache.spark.sql.catalyst.DefinedByConstructorParams
import scala.util.Try
import scala.language.implicitConversions
import scala.language.reflectiveCalls
trait DBUtilsApi {
type SecretUtils
type SecretMetadata
type SecretScope
val secrets: SecretUtils
}
object ReflectiveDBUtils extends DBUtilsApi {

private lazy val dbutils: DBUtils =
Class.forName("com.databricks.service.DBUtils$").getField("MODULE$").get().asInstanceOf[DBUtils]
override lazy val secrets: SecretUtils = dbutils.secrets
type DBUtils = AnyRef {
val secrets: SecretUtils
}
type SecretUtils = AnyRef {
def get(scope: String, key: String): String
def getBytes(scope: String, key: String): Array[Byte]
def list(scope: String): Seq[SecretMetadata]
def listScopes(): Seq[SecretScope]
}
type SecretMetadata = DefinedByConstructorParams { val key: String }
type SecretScope = DefinedByConstructorParams { val name: String }
}
class VaultTokenProvider extends org.apache.hadoop.fs.azurebfs.extensions.SASTokenProvider {
def getSASToken(accountName: String,fileSystem: String,path: String,operation: String): String = {
return ReflectiveDBUtils.secrets.get("scope", "SECRET")
}
def initialize(configuration: org.apache.hadoop.conf.Configuration, accountName: String): Unit = {    
}
}

spark.conf.set("fs.azure.account.auth.type.bidbtests.dfs.core.windows.net", "SAS")
spark.conf.set("fs.azure.sas.token.provider.type.bidbtests.dfs.core.windows.net", "com.foo.VaultTokenProvider")

这只是一个基本的例子;真正的解决方案将根据帐户和文件系统选择正确的密钥。

您可以使用以下代码访问Azure ADLS(Azure数据湖存储Gen2)到Azure Databricks,您只需要添加存储帐户名称和SAS令牌密钥,SAS令牌将从存储帐户

获得spark.conf.set("fs.azure.account.auth.type灵活;storage_account_name> .dfs.core.windows.net","SAS")

spark.conf.set("fs.azure.sas.token.provider.type灵活;storage_account_name> .dfs.core.windows.net","org.apache.hadoop.fs.azurebfs.sas.FixedSASTokenProvider")

spark.conf.set("fs.azure.sas.fixed.token灵活;storage_account_name> .dfs.core.windows.net","& lt; SAS_Token>")

列表显示容器

中可用的文件dbutils.fs.ls("abfss://& lt; container_name> @.dfs.core.windows.net/InputData/")

最新更新