Skip to content

Commit

Permalink
Added support for SAS authorization akka#3253
Browse files Browse the repository at this point in the history
  • Loading branch information
sfali committed Aug 24, 2024
1 parent e41869e commit 5d3b55d
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 9 deletions.
10 changes: 8 additions & 2 deletions azure-storage/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@ alpakka {
signing-algorithm = "HmacSHA256"

credentials {
# valid values are anon (annonymous), SharedKey, SharedKeyLite, SAS
# valid values are anon (annonymous), SharedKey, SharedKeyLite, sas
authorization-type = anon
authorization-type = ${?AZURE_STORAGE_AUTHORIZATION_TYPE}

# following
# required for all authorization types
account-name = none
account-name = ${?AZURE_STORAGE_ACCOUNT_NAME}

# Account key is required for SharedKey or SharedKeyLite authorization
account-key = none
account-key = ${?AZURE_STORAGE_ACCOUNT_KEY}

# SAS token for sas authorization
sas-token = ""
sas-token = ${?AZURE_STORAGE_SAS_TOKEN}
}

# Default settings corresponding to automatic retry of requests in an S3 stream.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ final case class Signer(initialRequest: HttpRequest, settings: StorageSettings)
.addHeader(RawHeader(XmsDateHeaderKey, getFormattedDate))
.addHeader(RawHeader(XmsVersionHeaderKey, settings.apiVersion))

private val mac = {
private lazy val mac = {
val mac = Mac.getInstance(settings.algorithm)
mac.init(new SecretKeySpec(credential.accountKey, settings.algorithm))
mac
Expand All @@ -40,7 +40,7 @@ final case class Signer(initialRequest: HttpRequest, settings: StorageSettings)
def signedRequest: Source[HttpRequest, NotUsed] = {
import Signer._
val authorizationType = settings.authorizationType
if (authorizationType == "anon") Source.single(requestWithHeaders)
if (authorizationType == "anon" || authorizationType == "sas") Source.single(requestWithHeaders)
else {
val headersToSign =
if (authorizationType == "SharedKeyLite") buildHeadersToSign(SharedKeyLiteHeaders)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import akka.actor.ClassicActorSystemProvider
import com.typesafe.config.Config

import java.time.{Duration => JavaDuration}
import java.util.Objects
import java.util.{Objects, Optional}
import java.util.concurrent.TimeUnit
import scala.concurrent.duration._
import scala.jdk.OptionConverters._

final class StorageSettings(val apiVersion: String,
val authorizationType: String,
val azureNameKeyCredential: AzureNameKeyCredential,
val sasToken: Option[String],
val retrySettings: RetrySettings,
val algorithm: String) {

Expand All @@ -29,6 +31,9 @@ final class StorageSettings(val apiVersion: String,
/** Java API */
def getAzureNameKeyCredential: AzureNameKeyCredential = azureNameKeyCredential

/** Java API */
def getSasToken: Optional[String] = sasToken.toJava

/** Java API */
def getRetrySettings: RetrySettings = retrySettings

Expand All @@ -45,6 +50,9 @@ final class StorageSettings(val apiVersion: String,
def withAzureNameKeyCredential(azureNameKeyCredential: AzureNameKeyCredential): StorageSettings =
copy(azureNameKeyCredential = azureNameKeyCredential)

/** Java API */
def withSasToken(sasToken: String): StorageSettings = copy(sasToken = emptyStringToOption(sasToken))

/** Java API */
def withRetrySettings(retrySettings: RetrySettings): StorageSettings = copy(retrySettings = retrySettings)

Expand All @@ -56,6 +64,7 @@ final class StorageSettings(val apiVersion: String,
| apiVersion=$apiVersion,
| authorizationType=$authorizationType,
| azureNameKeyCredential=$azureNameKeyCredential,
| sasToken=$sasToken
| retrySettings=$retrySettings,
| algorithm=$algorithm
|)""".stripMargin.replaceAll(System.lineSeparator(), "")
Expand All @@ -65,23 +74,25 @@ final class StorageSettings(val apiVersion: String,
apiVersion == that.apiVersion &&
authorizationType == that.authorizationType &&
Objects.equals(azureNameKeyCredential, that.azureNameKeyCredential) &&
sasToken == that.sasToken &&
Objects.equals(retrySettings, that.retrySettings) &&
algorithm == that.algorithm

case _ => false
}

override def hashCode(): Int =
Objects.hash(apiVersion, authorizationType, azureNameKeyCredential, retrySettings, algorithm)
Objects.hash(apiVersion, authorizationType, azureNameKeyCredential, sasToken, retrySettings, algorithm)

private def copy(
apiVersion: String = apiVersion,
authorizationType: String = authorizationType,
azureNameKeyCredential: AzureNameKeyCredential = azureNameKeyCredential,
sasToken: Option[String] = sasToken,
retrySettings: RetrySettings = retrySettings,
algorithm: String = algorithm
) =
StorageSettings(apiVersion, authorizationType, azureNameKeyCredential, retrySettings, algorithm)
StorageSettings(apiVersion, authorizationType, azureNameKeyCredential, sasToken, retrySettings, algorithm)
}

object StorageSettings {
Expand All @@ -91,31 +102,41 @@ object StorageSettings {
apiVersion: String,
authorizationType: String,
azureNameKeyCredential: AzureNameKeyCredential,
sasToken: Option[String],
retrySettings: RetrySettings,
algorithm: String
): StorageSettings =
new StorageSettings(apiVersion, authorizationType, azureNameKeyCredential, retrySettings, algorithm)
new StorageSettings(apiVersion, authorizationType, azureNameKeyCredential, sasToken, retrySettings, algorithm)

/** Java API */
def create(
apiVersion: String,
authorizationType: String,
azureNameKeyCredential: AzureNameKeyCredential,
sasToken: Optional[String],
retrySettings: RetrySettings,
algorithm: String
): StorageSettings =
StorageSettings(apiVersion, authorizationType, azureNameKeyCredential, retrySettings, algorithm)
StorageSettings(apiVersion,
authorizationType,
azureNameKeyCredential,
Option(sasToken.orElse(null)),
retrySettings,
algorithm)

def apply(config: Config): StorageSettings = {
val apiVersion = config.getString("api-version")
val credentials = config.getConfig("credentials")
val authorizationType = credentials.getString("authorization-type")
val sasToken =
if (credentials.hasPath("sas-token")) emptyStringToOption(credentials.getString("sas-token")) else None
val algorithm = config.getString("signing-algorithm")

StorageSettings(
apiVersion = apiVersion,
authorizationType = authorizationType,
azureNameKeyCredential = AzureNameKeyCredential(credentials),
sasToken = sasToken,
retrySettings = RetrySettings(config.getConfig("retry-settings")),
algorithm = algorithm
)
Expand Down

0 comments on commit 5d3b55d

Please sign in to comment.