FileServiceSasSignatureValues.java
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.storage.file;
import com.azure.storage.common.Constants;
import com.azure.storage.common.IpRange;
import com.azure.storage.common.SasProtocol;
import com.azure.storage.common.Utility;
import com.azure.storage.common.credentials.SharedKeyCredential;
import java.time.OffsetDateTime;
/**
* FileServiceSasSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage service. Once
* all the values here are set appropriately, call generateSASQueryParameters to obtain a representation of the SAS
* which can actually be applied to file urls. Note: that both this class and {@link FileServiceSasQueryParameters}
* exist because the former is mutable and a logical representation while the latter is immutable and used to generate
* actual REST requests.
* <p>
* Please see <a href=https://docs.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1>here</a>
* for more conceptual information on SAS.
* <p>
* Please see <a href=https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas>here </a> for
* more details on each value, including which are required.
*
* <p>Please see
* <a href=https://github.com/Azure/azure-storage-java/file/master/src/test/java/com/microsoft/azure/storage/Samples.java>here</a>
* for additional samples.</p>
*/
public final class FileServiceSasSignatureValues {
private String version = Constants.HeaderConstants.TARGET_STORAGE_VERSION;
private SasProtocol protocol;
private OffsetDateTime startTime;
private OffsetDateTime expiryTime;
private String permissions;
private IpRange ipRange;
private String canonicalName;
private String resource;
private String identifier;
private String cacheControl;
private String contentDisposition;
private String contentEncoding;
private String contentLanguage;
private String contentType;
/**
* Creates an object with empty values for all fields.
*/
FileServiceSasSignatureValues() {
}
/**
* Creates an object with the specified expiry time and permissions
*
* @param expiryTime Time the SAS becomes valid
* @param permissions Permissions granted by the SAS
*/
FileServiceSasSignatureValues(OffsetDateTime expiryTime, String permissions) {
this.expiryTime = expiryTime;
this.permissions = permissions;
}
/**
* Creates an object with the specified identifier
*
* @param identifier Identifier for the SAS
*/
FileServiceSasSignatureValues(String identifier) {
this.identifier = identifier;
}
FileServiceSasSignatureValues(String version, SasProtocol sasProtocol, OffsetDateTime startTime,
OffsetDateTime expiryTime, String permission, IpRange ipRange, String identifier, String cacheControl,
String contentDisposition, String contentEncoding, String contentLanguage, String contentType) {
if (version != null) {
this.version = version;
}
this.protocol = sasProtocol;
this.startTime = startTime;
this.expiryTime = expiryTime;
this.permissions = permission;
this.ipRange = ipRange;
this.identifier = identifier;
this.cacheControl = cacheControl;
this.contentDisposition = contentDisposition;
this.contentEncoding = contentEncoding;
this.contentLanguage = contentLanguage;
this.contentType = contentType;
}
/**
* @return the version of the service this SAS will target. If not specified, it will default to the version
* targeted by the library.
*/
public String getVersion() {
return version;
}
/**
* Sets the version of the service this SAS will target. If not specified, it will default to the version targeted
* by the library.
*
* @param version Version to target
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setVersion(String version) {
this.version = version;
return this;
}
/**
* @return the {@link SasProtocol} which determines the protocols allowed by the SAS.
*/
public SasProtocol getProtocol() {
return protocol;
}
/**
* Sets the {@link SasProtocol} which determines the protocols allowed by the SAS.
*
* @param protocol Protocol for the SAS
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setProtocol(SasProtocol protocol) {
this.protocol = protocol;
return this;
}
/**
* @return when the SAS will take effect.
*/
public OffsetDateTime getStartTime() {
return startTime;
}
/**
* Sets when the SAS will take effect.
*
* @param startTime When the SAS takes effect
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setStartTime(OffsetDateTime startTime) {
this.startTime = startTime;
return this;
}
/**
* @return the time after which the SAS will no longer work.
*/
public OffsetDateTime getExpiryTime() {
return expiryTime;
}
/**
* Sets the time after which the SAS will no longer work.
*
* @param expiryTime When the SAS will no longer work
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setExpiryTime(OffsetDateTime expiryTime) {
this.expiryTime = expiryTime;
return this;
}
/**
* @return the permissions string allowed by the SAS. Please refer to either {@link ShareSasPermission} or {@link
* FileSasPermission} depending on the resource being accessed for help determining the permissions allowed.
*/
public String getPermissions() {
return permissions;
}
/**
* Sets the permissions string allowed by the SAS. Please refer to either {@link ShareSasPermission} or {@link
* FileSasPermission} depending on the resource being accessed for help constructing the permissions string.
*
* @param permissions Permissions string for the SAS
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setPermissions(String permissions) {
this.permissions = permissions;
return this;
}
/**
* @return the {@link IpRange} which determines the IP ranges that are allowed to use the SAS.
*/
public IpRange getIpRange() {
return ipRange;
}
/**
* Sets the {@link IpRange} which determines the IP ranges that are allowed to use the SAS.
*
* @param ipRange Allowed IP range to set
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setIpRange(IpRange ipRange) {
this.ipRange = ipRange;
return this;
}
/**
* @return the resource the SAS user may access.
*/
public String getResource() {
return resource;
}
/**
* Sets the resource the SAS user may access.
*
* @param resource Allowed resources string to set
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setResource(String resource) {
this.resource = resource;
return this;
}
/**
* @return the canonical name of the object the SAS user may access.
*/
public String getCanonicalName() {
return canonicalName;
}
/**
* Sets the canonical name of the object the SAS user may access.
*
* @param canonicalName Canonical name of the object the SAS grants access
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setCanonicalName(String canonicalName) {
this.canonicalName = canonicalName;
return this;
}
/**
* Sets the canonical name of the object the SAS user may access. Constructs a canonical name of
* "/file/{accountName}/{shareName}/{filePath}".
*
* @param shareName Name of the share
* @param filePath Name of the file
* @param accountName Name of the account that contains the object
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setCanonicalName(String shareName, String filePath, String accountName) {
this.canonicalName = String.format("/file/%s/%s/%s", accountName, shareName, filePath);
return this;
}
/**
* Sets the canonical name of the object the SAS user may access. Constructs a canonical name of
* "/file/{accountName}/{shareName}".
*
* @param shareName Name of the share
* @param accountName Name of the account that contains the object
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setCanonicalName(String shareName, String accountName) {
this.canonicalName = String.format("/file/%s/%s", accountName, shareName);
return this;
}
/**
* @return the name of the access policy on the share this SAS references if any. Please see
* <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/establishing-a-stored-access-policy">here</a>
* for more information.
*/
public String getIdentifier() {
return identifier;
}
/**
* Sets the name of the access policy on the share this SAS references if any. Please see
* <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/establishing-a-stored-access-policy">here</a>
* for more information.
*
* @param identifier Name of the access policy
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setIdentifier(String identifier) {
this.identifier = identifier;
return this;
}
/**
* @return the cache-control header for the SAS.
*/
public String getCacheControl() {
return cacheControl;
}
/**
* Sets the cache-control header for the SAS.
*
* @param cacheControl Cache-Control header value
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setCacheControl(String cacheControl) {
this.cacheControl = cacheControl;
return this;
}
/**
* @return the content-disposition header for the SAS.
*/
public String getContentDisposition() {
return contentDisposition;
}
/**
* Sets the content-disposition header for the SAS.
*
* @param contentDisposition Content-Disposition header value
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setContentDisposition(String contentDisposition) {
this.contentDisposition = contentDisposition;
return this;
}
/**
* @return the content-encoding header for the SAS.
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
* Sets the content-encoding header for the SAS.
*
* @param contentEncoding Content-Encoding header value
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setContentEncoding(String contentEncoding) {
this.contentEncoding = contentEncoding;
return this;
}
/**
* @return the content-language header for the SAS.
*/
public String getContentLanguage() {
return contentLanguage;
}
/**
* Sets the content-language header for the SAS.
*
* @param contentLanguage Content-Language header value
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setContentLanguage(String contentLanguage) {
this.contentLanguage = contentLanguage;
return this;
}
/**
* @return the content-type header for the SAS.
*/
public String getContentType() {
return contentType;
}
/**
* Sets the content-type header for the SAS.
*
* @param contentType Content-Type header value
* @return the updated FileServiceSasSignatureValues object
*/
public FileServiceSasSignatureValues setContentType(String contentType) {
this.contentType = contentType;
return this;
}
/**
* Uses an account's shared key credential to sign these signature values to produce the proper SAS query
* parameters.
*
* @param sharedKeyCredentials A {@link SharedKeyCredential} object used to sign the SAS values.
* @return {@link FileServiceSasQueryParameters}
* @throws IllegalStateException If the HMAC-SHA256 algorithm isn't supported, if the key isn't a valid Base64
* encoded string, or the UTF-8 charset isn't supported.
* @throws NullPointerException If {@code sharedKeyCredentials} is null. Or when any of {@code version},
* {@code canonicalName} or {@code resource} is null. Or if {@code identifier} is not set and any of
* {@code expiryTime} or {@code permissions} is null. Or if {@code expiryTime} and {@code permissions} are not set
* and {@code identifier} is null
*/
public FileServiceSasQueryParameters generateSASQueryParameters(SharedKeyCredential sharedKeyCredentials) {
Utility.assertNotNull("sharedKeyCredentials", sharedKeyCredentials);
assertGenerateOK();
// Signature is generated on the un-url-encoded values.
String signature = sharedKeyCredentials.computeHmac256(stringToSign());
return new FileServiceSasQueryParameters(this.version, this.protocol, this.startTime, this.expiryTime,
this.ipRange, this.identifier, this.resource, this.permissions, signature, this.cacheControl,
this.contentDisposition, this.contentEncoding, this.contentLanguage, this.contentType);
}
/**
* Common assertions for generateSASQueryParameters overloads.
*/
private void assertGenerateOK() {
Utility.assertNotNull("version", this.version);
Utility.assertNotNull("canonicalName", this.canonicalName);
Utility.assertNotNull("resource", this.resource);
// If a SignedIdentifier is not being used both expiryDate and permissions must be set.
if (identifier == null) {
Utility.assertNotNull("expiryTime", this.expiryTime);
Utility.assertNotNull("permissions", this.permissions);
}
// Still need to check identifier if expiry time and permissions are not both set
if (expiryTime == null || permissions == null) {
Utility.assertNotNull("identifier", identifier);
}
}
private String stringToSign() {
return String.join("\n",
this.permissions == null ? "" : this.permissions,
this.startTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.startTime),
this.expiryTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.expiryTime),
this.canonicalName == null ? "" : this.canonicalName,
this.identifier == null ? "" : this.identifier,
this.ipRange == null ? "" : this.ipRange.toString(),
this.protocol == null ? "" : protocol.toString(),
this.version == null ? "" : this.version,
this.cacheControl == null ? "" : this.cacheControl,
this.contentDisposition == null ? "" : this.contentDisposition,
this.contentEncoding == null ? "" : this.contentEncoding,
this.contentLanguage == null ? "" : this.contentLanguage,
this.contentType == null ? "" : this.contentType
);
}
}