@azure/storage-blob 12.9.0-alpha.20220211.2 → 12.9.0-alpha.20220304.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -1
- package/dist/index.js +269 -8
- package/dist/index.js.map +1 -1
- package/dist-esm/storage-blob/src/Clients.js +7 -5
- package/dist-esm/storage-blob/src/Clients.js.map +1 -1
- package/dist-esm/storage-blob/src/Pipeline.js +4 -2
- package/dist-esm/storage-blob/src/Pipeline.js.map +1 -1
- package/dist-esm/storage-blob/src/generated/src/storageClientContext.js +1 -1
- package/dist-esm/storage-blob/src/generated/src/storageClientContext.js.map +1 -1
- package/dist-esm/storage-blob/src/index.js +1 -1
- package/dist-esm/storage-blob/src/index.js.map +1 -1
- package/dist-esm/storage-blob/src/models.js +14 -0
- package/dist-esm/storage-blob/src/models.js.map +1 -1
- package/dist-esm/storage-blob/src/policies/StorageBearerTokenChallengeAuthenticationPolicy.js +245 -0
- package/dist-esm/storage-blob/src/policies/StorageBearerTokenChallengeAuthenticationPolicy.js.map +1 -0
- package/dist-esm/storage-blob/src/policies/StorageSharedKeyCredentialPolicy.js +3 -1
- package/dist-esm/storage-blob/src/policies/StorageSharedKeyCredentialPolicy.js.map +1 -1
- package/dist-esm/storage-blob/src/utils/constants.js +2 -1
- package/dist-esm/storage-blob/src/utils/constants.js.map +1 -1
- package/package.json +1 -1
- package/types/3.1/storage-blob.d.ts +17 -0
- package/types/latest/storage-blob.d.ts +18 -0
package/CHANGELOG.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
-
## 12.9.0-beta.
|
3
|
+
## 12.9.0-beta.5 (Unreleased)
|
4
4
|
|
5
5
|
### Features Added
|
6
6
|
|
@@ -10,6 +10,16 @@
|
|
10
10
|
|
11
11
|
### Other Changes
|
12
12
|
|
13
|
+
## 12.9.0-beta.4 (2022-03-04)
|
14
|
+
|
15
|
+
### Features Added
|
16
|
+
|
17
|
+
- Added ability to specify Disk Compute AAD Audience in StoragePipelineOptions.
|
18
|
+
|
19
|
+
### Bugs Fixed
|
20
|
+
|
21
|
+
- Set correct content length in requests for uploading operations to avoid unexpected failure if customized content length is incorrect.
|
22
|
+
|
13
23
|
## 12.9.0-beta.3 (2022-02-11)
|
14
24
|
|
15
25
|
### Features Added
|
package/dist/index.js
CHANGED
@@ -13302,7 +13302,7 @@ const logger = logger$1.createClientLogger("storage-blob");
|
|
13302
13302
|
|
13303
13303
|
// Copyright (c) Microsoft Corporation.
|
13304
13304
|
// Licensed under the MIT license.
|
13305
|
-
const SDK_VERSION = "12.9.0-beta.
|
13305
|
+
const SDK_VERSION = "12.9.0-beta.5";
|
13306
13306
|
const SERVICE_VERSION = "2021-04-10";
|
13307
13307
|
const BLOCK_BLOB_MAX_UPLOAD_BLOB_BYTES = 256 * 1024 * 1024; // 256MB
|
13308
13308
|
const BLOCK_BLOB_MAX_STAGE_BLOCK_BYTES = 4000 * 1024 * 1024; // 4000MB
|
@@ -13495,6 +13495,7 @@ const StorageBlobLoggingAllowedQueryParameters = [
|
|
13495
13495
|
"skv",
|
13496
13496
|
"snapshot",
|
13497
13497
|
];
|
13498
|
+
const BlobUsesCustomerSpecifiedEncryptionMsg = "BlobUsesCustomerSpecifiedEncryption";
|
13498
13499
|
|
13499
13500
|
// Copyright (c) Microsoft Corporation.
|
13500
13501
|
/**
|
@@ -14728,6 +14729,247 @@ function getCachedDefaultHttpClient() {
|
|
14728
14729
|
return _defaultHttpClient;
|
14729
14730
|
}
|
14730
14731
|
|
14732
|
+
// Copyright (c) Microsoft Corporation.
|
14733
|
+
/**
|
14734
|
+
* A set of constants used internally when processing requests.
|
14735
|
+
*/
|
14736
|
+
const Constants = {
|
14737
|
+
DefaultScope: "/.default",
|
14738
|
+
/**
|
14739
|
+
* Defines constants for use with HTTP headers.
|
14740
|
+
*/
|
14741
|
+
HeaderConstants: {
|
14742
|
+
/**
|
14743
|
+
* The Authorization header.
|
14744
|
+
*/
|
14745
|
+
AUTHORIZATION: "authorization",
|
14746
|
+
},
|
14747
|
+
};
|
14748
|
+
// Default options for the cycler if none are provided
|
14749
|
+
const DEFAULT_CYCLER_OPTIONS = {
|
14750
|
+
forcedRefreshWindowInMs: 1000,
|
14751
|
+
retryIntervalInMs: 3000,
|
14752
|
+
refreshWindowInMs: 1000 * 60 * 2, // Start refreshing 2m before expiry
|
14753
|
+
};
|
14754
|
+
/**
|
14755
|
+
* Converts an an unreliable access token getter (which may resolve with null)
|
14756
|
+
* into an AccessTokenGetter by retrying the unreliable getter in a regular
|
14757
|
+
* interval.
|
14758
|
+
*
|
14759
|
+
* @param getAccessToken - a function that produces a promise of an access
|
14760
|
+
* token that may fail by returning null
|
14761
|
+
* @param retryIntervalInMs - the time (in milliseconds) to wait between retry
|
14762
|
+
* attempts
|
14763
|
+
* @param timeoutInMs - the timestamp after which the refresh attempt will fail,
|
14764
|
+
* throwing an exception
|
14765
|
+
* @returns - a promise that, if it resolves, will resolve with an access token
|
14766
|
+
*/
|
14767
|
+
async function beginRefresh(getAccessToken, retryIntervalInMs, timeoutInMs) {
|
14768
|
+
// This wrapper handles exceptions gracefully as long as we haven't exceeded
|
14769
|
+
// the timeout.
|
14770
|
+
async function tryGetAccessToken() {
|
14771
|
+
if (Date.now() < timeoutInMs) {
|
14772
|
+
try {
|
14773
|
+
return await getAccessToken();
|
14774
|
+
}
|
14775
|
+
catch (_a) {
|
14776
|
+
return null;
|
14777
|
+
}
|
14778
|
+
}
|
14779
|
+
else {
|
14780
|
+
const finalToken = await getAccessToken();
|
14781
|
+
// Timeout is up, so throw if it's still null
|
14782
|
+
if (finalToken === null) {
|
14783
|
+
throw new Error("Failed to refresh access token.");
|
14784
|
+
}
|
14785
|
+
return finalToken;
|
14786
|
+
}
|
14787
|
+
}
|
14788
|
+
let token = await tryGetAccessToken();
|
14789
|
+
while (token === null) {
|
14790
|
+
await coreHttp.delay(retryIntervalInMs);
|
14791
|
+
token = await tryGetAccessToken();
|
14792
|
+
}
|
14793
|
+
return token;
|
14794
|
+
}
|
14795
|
+
/**
|
14796
|
+
* Creates a token cycler from a credential, scopes, and optional settings.
|
14797
|
+
*
|
14798
|
+
* A token cycler represents a way to reliably retrieve a valid access token
|
14799
|
+
* from a TokenCredential. It will handle initializing the token, refreshing it
|
14800
|
+
* when it nears expiration, and synchronizes refresh attempts to avoid
|
14801
|
+
* concurrency hazards.
|
14802
|
+
*
|
14803
|
+
* @param credential - the underlying TokenCredential that provides the access
|
14804
|
+
* token
|
14805
|
+
* @param scopes - the scopes to request authorization for
|
14806
|
+
* @param tokenCyclerOptions - optionally override default settings for the cycler
|
14807
|
+
*
|
14808
|
+
* @returns - a function that reliably produces a valid access token
|
14809
|
+
*/
|
14810
|
+
function createTokenCycler(credential, scopes, tokenCyclerOptions) {
|
14811
|
+
let refreshWorker = null;
|
14812
|
+
let token = null;
|
14813
|
+
const options = Object.assign(Object.assign({}, DEFAULT_CYCLER_OPTIONS), tokenCyclerOptions);
|
14814
|
+
/**
|
14815
|
+
* This little holder defines several predicates that we use to construct
|
14816
|
+
* the rules of refreshing the token.
|
14817
|
+
*/
|
14818
|
+
const cycler = {
|
14819
|
+
/**
|
14820
|
+
* Produces true if a refresh job is currently in progress.
|
14821
|
+
*/
|
14822
|
+
get isRefreshing() {
|
14823
|
+
return refreshWorker !== null;
|
14824
|
+
},
|
14825
|
+
/**
|
14826
|
+
* Produces true if the cycler SHOULD refresh (we are within the refresh
|
14827
|
+
* window and not already refreshing)
|
14828
|
+
*/
|
14829
|
+
get shouldRefresh() {
|
14830
|
+
var _a;
|
14831
|
+
return (!cycler.isRefreshing &&
|
14832
|
+
((_a = token === null || token === void 0 ? void 0 : token.expiresOnTimestamp) !== null && _a !== void 0 ? _a : 0) - options.refreshWindowInMs < Date.now());
|
14833
|
+
},
|
14834
|
+
/**
|
14835
|
+
* Produces true if the cycler MUST refresh (null or nearly-expired
|
14836
|
+
* token).
|
14837
|
+
*/
|
14838
|
+
get mustRefresh() {
|
14839
|
+
return (token === null || token.expiresOnTimestamp - options.forcedRefreshWindowInMs < Date.now());
|
14840
|
+
},
|
14841
|
+
};
|
14842
|
+
/**
|
14843
|
+
* Starts a refresh job or returns the existing job if one is already
|
14844
|
+
* running.
|
14845
|
+
*/
|
14846
|
+
function refresh(getTokenOptions) {
|
14847
|
+
var _a;
|
14848
|
+
if (!cycler.isRefreshing) {
|
14849
|
+
// We bind `scopes` here to avoid passing it around a lot
|
14850
|
+
const tryGetAccessToken = () => credential.getToken(scopes, getTokenOptions);
|
14851
|
+
// Take advantage of promise chaining to insert an assignment to `token`
|
14852
|
+
// before the refresh can be considered done.
|
14853
|
+
refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs,
|
14854
|
+
// If we don't have a token, then we should timeout immediately
|
14855
|
+
(_a = token === null || token === void 0 ? void 0 : token.expiresOnTimestamp) !== null && _a !== void 0 ? _a : Date.now())
|
14856
|
+
.then((_token) => {
|
14857
|
+
refreshWorker = null;
|
14858
|
+
token = _token;
|
14859
|
+
return token;
|
14860
|
+
})
|
14861
|
+
.catch((reason) => {
|
14862
|
+
// We also should reset the refresher if we enter a failed state. All
|
14863
|
+
// existing awaiters will throw, but subsequent requests will start a
|
14864
|
+
// new retry chain.
|
14865
|
+
refreshWorker = null;
|
14866
|
+
token = null;
|
14867
|
+
throw reason;
|
14868
|
+
});
|
14869
|
+
}
|
14870
|
+
return refreshWorker;
|
14871
|
+
}
|
14872
|
+
return async (tokenOptions) => {
|
14873
|
+
//
|
14874
|
+
// Simple rules:
|
14875
|
+
// - If we MUST refresh, then return the refresh task, blocking
|
14876
|
+
// the pipeline until a token is available.
|
14877
|
+
// - If we SHOULD refresh, then run refresh but don't return it
|
14878
|
+
// (we can still use the cached token).
|
14879
|
+
// - Return the token, since it's fine if we didn't return in
|
14880
|
+
// step 1.
|
14881
|
+
//
|
14882
|
+
if (cycler.mustRefresh)
|
14883
|
+
return refresh(tokenOptions);
|
14884
|
+
if (cycler.shouldRefresh) {
|
14885
|
+
refresh(tokenOptions);
|
14886
|
+
}
|
14887
|
+
return token;
|
14888
|
+
};
|
14889
|
+
}
|
14890
|
+
/**
|
14891
|
+
* We will retrieve the challenge only if the response status code was 401,
|
14892
|
+
* and if the response contained the header "WWW-Authenticate" with a non-empty value.
|
14893
|
+
*/
|
14894
|
+
function getChallenge(response) {
|
14895
|
+
const challenge = response.headers.get("WWW-Authenticate");
|
14896
|
+
if (response.status === 401 && challenge) {
|
14897
|
+
return challenge;
|
14898
|
+
}
|
14899
|
+
return;
|
14900
|
+
}
|
14901
|
+
/**
|
14902
|
+
* Converts: `Bearer a="b" c="d"`.
|
14903
|
+
* Into: `[ { a: 'b', c: 'd' }]`.
|
14904
|
+
*
|
14905
|
+
* @internal
|
14906
|
+
*/
|
14907
|
+
function parseChallenge(challenge) {
|
14908
|
+
const bearerChallenge = challenge.slice("Bearer ".length);
|
14909
|
+
const challengeParts = `${bearerChallenge.trim()} `.split(" ").filter((x) => x);
|
14910
|
+
const keyValuePairs = challengeParts.map((keyValue) => (([key, value]) => ({ [key]: value }))(keyValue.trim().split("=")));
|
14911
|
+
// Key-value pairs to plain object:
|
14912
|
+
return keyValuePairs.reduce((a, b) => (Object.assign(Object.assign({}, a), b)), {});
|
14913
|
+
}
|
14914
|
+
// #endregion
|
14915
|
+
/**
|
14916
|
+
* Creates a new factory for a RequestPolicy that applies a bearer token to
|
14917
|
+
* the requests' `Authorization` headers.
|
14918
|
+
*
|
14919
|
+
* @param credential - The TokenCredential implementation that can supply the bearer token.
|
14920
|
+
* @param scopes - The scopes for which the bearer token applies.
|
14921
|
+
*/
|
14922
|
+
function storageBearerTokenChallengeAuthenticationPolicy(credential, scopes) {
|
14923
|
+
// This simple function encapsulates the entire process of reliably retrieving the token
|
14924
|
+
let getToken = createTokenCycler(credential, scopes);
|
14925
|
+
class StorageBearerTokenChallengeAuthenticationPolicy extends coreHttp.BaseRequestPolicy {
|
14926
|
+
constructor(nextPolicy, options) {
|
14927
|
+
super(nextPolicy, options);
|
14928
|
+
}
|
14929
|
+
async sendRequest(webResource) {
|
14930
|
+
if (!webResource.url.toLowerCase().startsWith("https://")) {
|
14931
|
+
throw new Error("Bearer token authentication is not permitted for non-TLS protected (non-https) URLs.");
|
14932
|
+
}
|
14933
|
+
const getTokenInternal = getToken;
|
14934
|
+
const token = (await getTokenInternal({
|
14935
|
+
abortSignal: webResource.abortSignal,
|
14936
|
+
tracingOptions: {
|
14937
|
+
tracingContext: webResource.tracingContext,
|
14938
|
+
},
|
14939
|
+
})).token;
|
14940
|
+
webResource.headers.set(Constants.HeaderConstants.AUTHORIZATION, `Bearer ${token}`);
|
14941
|
+
const response = await this._nextPolicy.sendRequest(webResource);
|
14942
|
+
if ((response === null || response === void 0 ? void 0 : response.status) === 401) {
|
14943
|
+
const challenge = getChallenge(response);
|
14944
|
+
if (challenge) {
|
14945
|
+
const challengeInfo = parseChallenge(challenge);
|
14946
|
+
const challengeScopes = challengeInfo.resource_id + Constants.DefaultScope;
|
14947
|
+
const parsedAuthUri = coreHttp.URLBuilder.parse(challengeInfo.authorization_uri);
|
14948
|
+
const pathSegments = parsedAuthUri.getPath().split("/");
|
14949
|
+
const tenantId = pathSegments[1];
|
14950
|
+
const getTokenForChallenge = createTokenCycler(credential, challengeScopes);
|
14951
|
+
const tokenForChallenge = (await getTokenForChallenge({
|
14952
|
+
abortSignal: webResource.abortSignal,
|
14953
|
+
tracingOptions: {
|
14954
|
+
tracingContext: webResource.tracingContext,
|
14955
|
+
},
|
14956
|
+
tenantId: tenantId,
|
14957
|
+
})).token;
|
14958
|
+
getToken = getTokenForChallenge;
|
14959
|
+
webResource.headers.set(Constants.HeaderConstants.AUTHORIZATION, `Bearer ${tokenForChallenge}`);
|
14960
|
+
return this._nextPolicy.sendRequest(webResource);
|
14961
|
+
}
|
14962
|
+
}
|
14963
|
+
return response;
|
14964
|
+
}
|
14965
|
+
}
|
14966
|
+
return {
|
14967
|
+
create: (nextPolicy, options) => {
|
14968
|
+
return new StorageBearerTokenChallengeAuthenticationPolicy(nextPolicy, options);
|
14969
|
+
},
|
14970
|
+
};
|
14971
|
+
}
|
14972
|
+
|
14731
14973
|
// Copyright (c) Microsoft Corporation.
|
14732
14974
|
/**
|
14733
14975
|
* A helper to decide if a given argument satisfies the Pipeline contract
|
@@ -14785,6 +15027,7 @@ class Pipeline {
|
|
14785
15027
|
* @returns A new Pipeline object.
|
14786
15028
|
*/
|
14787
15029
|
function newPipeline(credential, pipelineOptions = {}) {
|
15030
|
+
var _a;
|
14788
15031
|
if (credential === undefined) {
|
14789
15032
|
credential = new AnonymousCredential();
|
14790
15033
|
}
|
@@ -14815,7 +15058,7 @@ function newPipeline(credential, pipelineOptions = {}) {
|
|
14815
15058
|
factories.push(coreHttp.disableResponseDecompressionPolicy());
|
14816
15059
|
}
|
14817
15060
|
factories.push(coreHttp.isTokenCredential(credential)
|
14818
|
-
? attachCredential(
|
15061
|
+
? attachCredential(storageBearerTokenChallengeAuthenticationPolicy(credential, (_a = pipelineOptions.audience) !== null && _a !== void 0 ? _a : StorageOAuthScopes), credential)
|
14819
15062
|
: credential);
|
14820
15063
|
return new Pipeline(factories, pipelineOptions);
|
14821
15064
|
}
|
@@ -14842,7 +15085,9 @@ class StorageSharedKeyCredentialPolicy extends CredentialPolicy {
|
|
14842
15085
|
*/
|
14843
15086
|
signRequest(request) {
|
14844
15087
|
request.headers.set(HeaderConstants.X_MS_DATE, new Date().toUTCString());
|
14845
|
-
if (request.body &&
|
15088
|
+
if (request.body &&
|
15089
|
+
(typeof request.body === "string" || request.body !== undefined) &&
|
15090
|
+
request.body.length > 0) {
|
14846
15091
|
request.headers.set(HeaderConstants.CONTENT_LENGTH, Buffer.byteLength(request.body));
|
14847
15092
|
}
|
14848
15093
|
const stringToSign = [
|
@@ -14998,7 +15243,7 @@ class StorageSharedKeyCredential extends Credential {
|
|
14998
15243
|
* Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
14999
15244
|
*/
|
15000
15245
|
const packageName = "azure-storage-blob";
|
15001
|
-
const packageVersion = "12.9.0-beta.
|
15246
|
+
const packageVersion = "12.9.0-beta.5";
|
15002
15247
|
class StorageClientContext extends coreHttp__namespace.ServiceClient {
|
15003
15248
|
/**
|
15004
15249
|
* Initializes a new instance of the StorageClientContext class.
|
@@ -18177,6 +18422,20 @@ function ensureCpkIfSpecified(cpk, isHttps) {
|
|
18177
18422
|
cpk.encryptionAlgorithm = EncryptionAlgorithmAES25;
|
18178
18423
|
}
|
18179
18424
|
}
|
18425
|
+
/**
|
18426
|
+
* Defines the known cloud audiences for Storage.
|
18427
|
+
*/
|
18428
|
+
exports.StorageBlobAudience = void 0;
|
18429
|
+
(function (StorageBlobAudience) {
|
18430
|
+
/**
|
18431
|
+
* The OAuth scope to use to retrieve an AAD token for Azure Storage.
|
18432
|
+
*/
|
18433
|
+
StorageBlobAudience["StorageOAuthScopes"] = "https://storage.azure.com/.default";
|
18434
|
+
/**
|
18435
|
+
* The OAuth scope to use to retrieve an AAD token for Azure Disk.
|
18436
|
+
*/
|
18437
|
+
StorageBlobAudience["DiskComputeOAuthScopes"] = "https://disk.compute.azure.com/.default";
|
18438
|
+
})(exports.StorageBlobAudience || (exports.StorageBlobAudience = {}));
|
18180
18439
|
|
18181
18440
|
// Copyright (c) Microsoft Corporation.
|
18182
18441
|
// Licensed under the MIT license.
|
@@ -19268,12 +19527,14 @@ class BlobClient extends StorageClient {
|
|
19268
19527
|
}
|
19269
19528
|
catch (e) {
|
19270
19529
|
if (e.statusCode === 404) {
|
19271
|
-
|
19272
|
-
code: coreTracing.SpanStatusCode.ERROR,
|
19273
|
-
message: "Expected exception when checking blob existence",
|
19274
|
-
});
|
19530
|
+
// Expected exception when checking blob existence
|
19275
19531
|
return false;
|
19276
19532
|
}
|
19533
|
+
else if (e.statusCode === 409 &&
|
19534
|
+
e.details.errorCode === BlobUsesCustomerSpecifiedEncryptionMsg) {
|
19535
|
+
// Expected exception when checking blob existence
|
19536
|
+
return true;
|
19537
|
+
}
|
19277
19538
|
span.setStatus({
|
19278
19539
|
code: coreTracing.SpanStatusCode.ERROR,
|
19279
19540
|
message: e.message,
|