1

How to change the blob access policy?

At the moment I am able to create some test blobs using the azure quick start. This works great but the blobs have a public access level of private by default in my case. I want to set public access level from Private (no anonymous access) to Blob (anonymous read access for blobs only).

I did some try & error and I found that setAccessPolicy could help me out. I want to implement this but I don't fully understand the .setPermissions("permissionString"). Do I need to change this to something like "anonymous read access for blobs only" or am I missing something?

My try & error code:

public static void main( String[] args ) throws IOException
    {
        BlobServiceClient blobServiceClient = new BlobServiceClientBuilder().connectionString(connectionString).buildClient();
        String containerName = "testblobs"+ UUID.randomUUID();

        BlobSignedIdentifier identifier = new BlobSignedIdentifier()
                .setId("name")
                .setAccessPolicy(new BlobAccessPolicy()
                .setStartsOn(OffsetDateTime.now())
                        .setExpiresOn(OffsetDateTime.now().plusDays(1))
                .setPermissions("permissionString")); //what should I put here?

        BlobContainerClient containerClient = blobServiceClient.createBlobContainer(containerName);

        try {
            containerClient.setAccessPolicy(PublicAccessType.CONTAINER, Collections.singletonList(identifier));
            System.out.println("Set Access Policy to 'Public read access for blobs only'.");
        } catch (UnsupportedOperationException err) {
            System.out.printf("Set Access Policy failed because: %s\n", err);
        }

        String localPath = "pathtofile";
        String fileName = "myfile.bpmn";
        File localFile = new File(localPath+fileName);

        BlobClient blobClient = containerClient.getBlobClient(fileName);

        System.out.println("\nUploading to Blob storage as blob:\n\t" + blobClient.getBlobUrl());

        blobClient.uploadFromFile(localPath + fileName);

        System.out.println("\nListing da blobs...");

        for (BlobItem blobItem : containerClient.listBlobs()) {
            System.out.println();
            System.out.println("\t" + blobItem.getName());
        }
    }

When I run this piece of code it will throw the following exception and I think it's because of the .setPermissions("permissionString") is not set correctly.

Exception stacktrace:

Exception in thread "main" com.azure.storage.blob.models.BlobStorageException: Status code 400, "InvalidXmlDocumentXML specified is not syntactically valid. RequestId:74403433-a01e-0086-17c1-1727cd000000 Time:2020-04-21T09:43:11.5943935Z00" at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) at com.azure.core.http.rest.RestProxy.instantiateUnexpectedException(RestProxy.java:357) at com.azure.core.http.rest.RestProxy.lambda$ensureExpectedStatus$3(RestProxy.java:398) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1705) at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.signalCached(MonoCacheTime.java:320) at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.onNext(MonoCacheTime.java:337) at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2267) at reactor.core.publisher.MonoCacheTime$CoordinatorSubscriber.onSubscribe(MonoCacheTime.java:276) at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:191) at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:48) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) at reactor.core.publisher.MonoCacheTime.subscribeOrReturn(MonoCacheTime.java:132) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:48) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150) at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onNext(FluxDoFinally.java:123) at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:112) at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:213) at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onNext(FluxDoFinally.java:123) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:178) at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.onNext(FluxContextStart.java:103) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1705) at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onComplete(MonoCollectList.java:121) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) at reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:419) at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:209) at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:367) at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:363) at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:412) at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:585) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:90) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:321) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:295) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355) at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1470) at io.netty.handler.ssl.SslHandler.decodeNonJdkCompatible(SslHandler.java:1231) at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1268) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:498) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:437) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:834) Suppressed: java.lang.Exception: #block terminated with an error at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99) at reactor.core.publisher.Mono.block(Mono.java:1664) at com.azure.storage.common.implementation.StorageImplUtils.blockWithOptionalTimeout(StorageImplUtils.java:99) at com.azure.storage.blob.BlobContainerClient.setAccessPolicyWithResponse(BlobContainerClient.java:416) at com.azure.storage.blob.BlobContainerClient.setAccessPolicy(BlobContainerClient.java:386) at Main.main(Main.java:33)

Any help on explaining the .setPermissions("permissionString") to me with some code examples how to set public access for blobs would be great.

Tobias S
  • 331
  • 2
  • 18

1 Answers1

3

Permissions that are applicable for a blob container are defined here.

Depending on the permissions you wish to include in your access policy, you can choose from one or more of the following permissions: Read (r), Add (a), Create (c), Write (w), Delete (d) and List (l).

Please note that ordering of these permissions is important. They must follow the following order: racwdl.

Also note that specifying permissions in shared access policy is optional so you can leave the permission string as empty as well.

Gaurav Mantri
  • 128,066
  • 12
  • 206
  • 241
  • Thank you for the fast response. I left the .setPermissions empty and it works now as expected. There is still something that I don't fully understand. Why is the shared access policy optional? – Tobias S Apr 21 '20 at 12:02
  • `Why is the shared access policy optional?` - Not sure I understand your question but access policies are used to create Shared Access Signature (SAS). You can create SAS Tokens with our without access policies. I guess that's why it is optional. HTH. – Gaurav Mantri Apr 21 '20 at 12:34