Skip to content

Commit

Permalink
[DOCS-7556] Alfresco Content Connector for Azure 5.0 (#1356)
Browse files Browse the repository at this point in the history
* [DOCS-7556] Update latest connector Azure 5.0

* [DOCS-7556] Update config and data file for Connector Azure 5.0

* [DOCS-7557] Update Supported Platforms for Connector for Azure 5.0 (#1355)

* Update supported platforms.md

* Update supported platforms
  • Loading branch information
mbujak-hyland authored Mar 4, 2024
1 parent 06ebb58 commit 2c48f30
Show file tree
Hide file tree
Showing 11 changed files with 1,081 additions and 10 deletions.
7 changes: 6 additions & 1 deletion _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ defaults:
toc: "microsoft-azure"
support: true
versions:
- 5.0
- 4.0
- 3.2
- 3.1
Expand All @@ -325,8 +326,12 @@ defaults:
- scope:
path: "microsoft-azure/latest"
values:
version: 4.0
version: 5.0
latest: true
- scope:
path: "microsoft-azure/4.0"
values:
version: 4.0
- scope:
path: "microsoft-azure/3.2"
values:
Expand Down
16 changes: 15 additions & 1 deletion _data/toc/microsoft-azure.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Microsoft Azure
- version: 4.0
- version: 5.0
pages:
- title: 'Introduction'
path: '/microsoft-azure/latest/'
Expand All @@ -13,6 +13,20 @@
path: '/microsoft-azure/latest/config/direct-access/'
- title: 'Administer'
path: '/microsoft-azure/latest/admin/'
- version: 4.0
pages:
- title: 'Introduction'
path: '/microsoft-azure/4.0/'
- title: 'Install'
path: '/microsoft-azure/4.0/install/'
- title: 'Configure'
pages:
- title: 'Overview'
path: '/microsoft-azure/4.0/config/'
- title: 'Direct access URLs'
path: '/microsoft-azure/4.0/config/direct-access/'
- title: 'Administer'
path: '/microsoft-azure/4.0/admin/'
- version: 3.2
pages:
- title: 'Introduction'
Expand Down
92 changes: 92 additions & 0 deletions microsoft-azure/4.0/admin/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
title: Administer Azure Connector
---

Use this information to administer the Azure Connector.

## Upgrade

Use this information to upgrade the Azure Connector from a previous version for Tomcat-based deployments only.

1. Stop the Content Services server.

2. Navigate to the root directory of your installation.

3. Use the following command to check for the module you wish to delete:

```bash
java -jar bin/alfresco-mmt.jar list tomcat/webapps/alfresco.war
```

This displays a list of the installed modules. Make a note of the module ID of the module you wish to uninstall, for example, `org_alfresco_integrations_AzureConnector`.

4. Use the Module Management Tool (MMT) to uninstall the AMP from the repository WAR (`alfresco.war`). For example:

```bash
java -jar bin/alfresco-mmt.jar uninstall org_alfresco_integrations_AzureConnector tomcat/webapps/alfresco.war
```

For more information, see [Using the Module Management Tool (MMT)]({% link content-services/latest/develop/extension-packaging.md %}#using-the-module-management-tool-(mmt)) and [Uninstall an AMP file]({% link content-services/latest/install/zip/amp.md %}#uninstall-an-amp-file).

5. Navigate to the `amps` directory.

6. Delete any previously installed Azure Connector AMP.

7. Copy the AMP file you downloaded during [installation]({% link microsoft-azure/4.0/install/index.md %}) to the `amps` directory.

8. Use the Module Management Tool (MMT) to install the AMP into the repository WAR (`alfresco.war`).

For more information, see [Using the Module Management Tool (MMT)]({% link content-services/latest/develop/extension-packaging.md %}#using-the-module-management-tool-(mmt))and [Install Alfresco Module Package]({% link content-services/latest/install/zip/amp.md %}).

> **Note:** You must install the Azure Connector AMP using `-force`.

9. Check that the [configuration]({% link microsoft-azure/4.0/config/index.md %}) is set up correctly for your environment.

> **Note:** When upgrading from Azure Connector version 1.0, make sure you define the Azure authentication mode and a supported value in your `alfresco-global.properties` file.

> **Note:** To upgrade a system that's never used the file system (i.e. on-premises installation without locally saved binaries), we recommend that you choose a pure Azure content store. See [Azure Connector content store subsystems]({% link microsoft-azure/4.0/config/index.md %}#azure-subsystems) for more details.
10. Starting from version 1.2, the Azure Connector has the deleted content store disabled by default, since this feature is already present in Microsoft's Azure Storage services. For details on how to re-enable it, see [Azure Connector deleted content store]({% link microsoft-azure/4.0/config/index.md %}#azure-connector-deleted-content-store).

11. Start the server.

## Known issues

Use this information to identity known issues and limitations while using Azure Connector.

### ReactiveX framework that AzureSDK is based on is not working with Security Manager enabled in Tomcat

This usually results in the following exception:

```bash
access: access denied ("java.util.PropertyPermission" "jctools.spsc.max.lookahead.step" "read")
java.lang.Exception: Stack trace
at java.base/java.lang.Thread.dumpStack(Thread.java:1387)
at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:462)
at java.base/java.security.AccessController.checkPermission(AccessController.java:895)
at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:322)
at java.base/java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1066)
at java.base/java.lang.System.getProperty(System.java:810)
at java.base/java.lang.Integer.getInteger(Integer.java:1331)
at java.base/java.lang.Integer.getInteger(Integer.java:1287)
at io.reactivex.internal.queue.SpscArrayQueue.<clinit>(SpscArrayQueue.java:43)
at io.reactivex.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.getMainQueue(FlowableFlatMap.java:222)
at io.reactivex.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.tryEmitScalar(FlowableFlatMap.java:245)
at io.reactivex.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.onNext(FlowableFlatMap.java:152)
at io.reactivex.internal.operators.flowable.FlowableMap$MapSubscriber.onNext(FlowableMap.java:68)
at com.microsoft.rest.v2.util.FlowableUtil$FileReadFlowable$FileReadSubscription.drain(FlowableUtil.java:311)
at com.microsoft.rest.v2.util.FlowableUtil$FileReadFlowable$FileReadSubscription.completed(FlowableUtil.java:383)
at com.microsoft.rest.v2.util.FlowableUtil$FileReadFlowable$FileReadSubscription.completed(FlowableUtil.java:258)
at java.base/sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:127)
at java.base/sun.nio.ch.SimpleAsynchronousFileChannelImpl$2.run(SimpleAsynchronousFileChannelImpl.java:335)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
at java.base/jdk.internal.misc.InnocuousThread.run(InnocuousThread.java:134)
access: domain that failed ProtectionDomain null
null
<no principals>
null
```

See [https://bz.apache.org/bugzilla/show\_bug.cgi?id=61568](https://bz.apache.org/bugzilla/show_bug.cgi?id=61568){:target="_blank"} for more.
168 changes: 168 additions & 0 deletions microsoft-azure/4.0/config/direct-access.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
---
title: Direct Access URLs
---

The main purpose of Direct Access URLs (or DAUs) is to accelerate the local download of content by allowing you to have
direct content URLs for your binary content that can help with distributed content repositories in customer environments,
and cloud deployments.

Azure Blob Storage provide [Shared Access Signature (SAS) tokens](https://docs.microsoft.com/en-us/rest/api/storageservices/delegate-access-with-shared-access-signature){:target="_blank"},
which as a part of the object's URL can be used for sharing objects. This feature is a perfect candidate for implementing
direct access to your content.

> **Note:** The Azure SAS tokens are temporary with an expiration time.
The Alfresco repository infrastructure now supports direct access URLs. This includes the `ContentService` and the
`ContentStore` interface for which default methods have been provided so that `ContentStore` implementations for older
versions of this interface throw a `Not Supported` exception. The new methods are auditable using the node reference and
time (in seconds) for which the DAU is valid as the parameters.

ReST API endpoints can be used for requesting a new *Direct Access URL* (i.e. a direct download link) for a specific
file in the content repository.

The access to direct access URLs is strictly controlled. Their expiration date is set/restricted by configurations in
the repository using global and content store specific properties.

* Values in the content store properties, **default expiry time** and **maximum expiry time**, are used in preference to the system-wide properties, if valid.
* If invalid, an attempt is made to default to the system-wide properties.
* However, if that still doesn't result in a valid configuration, the DAUs for that specific content store are disabled.

## Default configuration
Direct access URLs are disabled by default:

```text
system.directAccessUrl.enabled=false
restApi.directAccessUrl.enabled=false
connector.az.directAccessUrl.enabled=false
```

## System-wide configuration
Below are the system-wide configuration settings required in Content Services.

| Property | Description |
| -------- | ----------- |
| `system.directAccessUrl.enabled` | Controls whether this feature is available, system-wide (for example `false`). <br><br>For DAUs to work, the feature needs to be enabled both system-wide and on the individual Content Store. |
| `system.directAccessUrl.defaultExpiryTimeInSec` | Sets the default expiry time for the DAU across all Content Stores (for example `30`). <br><br>Its value cannot exceed the system-wide maximum expiry time (`system.directAccessUrl.maxExpiryTimeInSec`) - it can only be equal or lower (otherwise all DAUs are disabled). <br>**Note:** This property is **mandatory** if DAUs are enabled system-wide - (otherwise all DAUs are disabled). |
| `system.directAccessUrl.maxExpiryTimeInSec` | Sets the upper limit for the DAUs expiry time in seconds (for example `300`, i.e. `5 minutes`). <br><br>This means that a Content Store will be able to override this value but not exceed it, and the same goes for the clients. A service (Java Interface) client will be able to request a DAU for a custom expiry time but that time can't exceed this value. If the requested time exceeds the maximum value, the expiry time reverts to the default configured one. <br>**Note:** This property is **mandatory** if DAUs are enabled system-wide - (otherwise all DAUs are disabled). |

## ReST API configuration
The ReST API configuration only affects the ReST layer in Content Services.

| Property | Description |
| -------- | ----------- |
| restApi.directAccessUrl.enabled | Enables/disables DAU requests via the ReST API (for example `false`). |
| restApi.directAccessUrl.defaultExpiryTimeInSec | Sets the expiry time in seconds for all the DAUs requested via a ReST call (for example `30`). DAU ReST API calls cannot request an explicit expiry time - unlike the service layer calls).<br><br>Its value cannot exceed the system-wide maximum expiry time configuration (`system.directAccessUrl.maxExpiryTimeInSec`) - it can only be equal to or lower (otherwise the ReST API DAUs are disabled).<br><br>If it's not set, the default system-wide property is used (`system.directAccessUrl.defaultExpiryTimeInSec`). |

## Storage connector content store
In the example of the Azure Connector, each content store (i.e. "final" content store, one that provides actual storage,
as opposed to a caching content store), should have dedicated configuration options:

| Property | Description |
| -------- | ----------- |
| `connector.az.directAccessUrl.enabled` | Controls whether DAUs are enabled on this specific content store (for example `false`). |
| `connector.az.directAccessUrl.defaultExpiryTimeInSec` | Sets the expiry time in seconds for the DAU in this store, by overriding the global configuration (for example `30`). <br><br>If this value exceeds the content store limit (described below) or the global limit it should fallback to the global configuration. Its value cannot exceed the system-wide maximum expiry time configuration (`system.directAccessUrl.maxExpiryTimeInSec`) - it can only be equal or lower (otherwise DAUs for the specific content store will be disabled). <br><br>If it's not set, the default system-wide setting is used (`system.directAccessUrl.defaultExpiryTimeInSec`). |
| `connector.az.directAccessUrl.maxExpiryTimeInSec=300` | The maximum expiry time interval that can be requested by clients - content-store specific setting. <br><br>Its value cannot exceed the system-wide configuration (`system.directAccessUrl.maxExpiryTimeInSec`) - it can only be equal or lower (otherwise DAUs for the specific content store will be disabled). <br><br>If it's not set, the default system-wide setting is used (`system.directAccessUrl.maxExpiryTimeInSec`). |

> **Note:** Callers within the platform (i.e. Java interfaces) can either request a specific expiry time or rely on the
> default value.
> **Note:** When multiple Azure blob containers are used for storage in Alfresco, each Azure Content Store can be
> configured with either the default (common) Azure Connector-specific properties (i.e. `connector.az.directAccessUrl.enabled` etc.),
> or new separate properties can be defined for each and every store (i.e. `connector.az.store1.directAccessUrl.enabled`,
> `connector.az.store2.directAccessUrl.enabled`, etc.).
## Configuration priorities
For DAUs to be usable on the service-layer, the feature must be enabled both system-wide and on the content-store(s).
For the feature to be usable through ReST (outside the JVM) the *rest-api configuration* must also be enabled.

The `system.directAccessUrl.enabled` property is the main switch for this feature. If this is set to false, then **all**
DAUs are disabled.

The next configuration that controls specific DAUs is the one for the content store. The `connector.az.directAccessUrl.enabled`
property controls whether DAUs are enabled for that specific store.

Whether a client can request a DAU by using a ReST endpoint is controlled by the `restApi.directAccessUrl.enabled` property.
If the ReST endpoint is disabled, but the feature is enabled system-wide and on the content-store, then the DAUs will
only be usable by Java clients (i.e. only service-level requests will be possible).

## API
The ReST API.

### ReST endpoints
The following endpoints can be used to send requests to obtain DAUs in Content Services:

* `POST /nodes/{nodeId}/request-direct-access-url`
* `POST /nodes/{nodeId}/renditions/{renditionId}/request-direct-access-url`
* `POST /nodes/{nodeId}/versions/{versionId}/request-direct-access-url`
* `POST /nodes/{nodeId}/versions/{versionId}/renditions/{renditionId}/request-direct-access-url`
* `POST /deleted-nodes/{nodeId}/request-direct-access-url`
* `POST /deleted-nodes/{nodeId}/renditions/{renditionId}/request-direct-access-url`

Optionally, the POST body can specify an `attachment` flag. A value of `true` indicates that a download link is required;
`false` indicates an embedded link is required. This defaults to `true` if it's not specified.

The endpoints return the following type of response for the Azure connector:

```json
{
"entry": {
"contentUrl": "https://<storage_account_name>.blob.core.windows.net/<container_name>/<blob_name>?sv=2020-10-02&spr=https&se=2022-02-09T04%3A09%3A40Z&sr=b&sp=r&sig=LkznZiG6u2BUDprdKyk0Hm9XkURG%2BZZp0qy0Ls3kgVY%3D&rscd=attachment%3B%20filename%20%3D%22graph.JPG%22&rsct=image%2Fjpeg",
"attachment": true,
"expiryTime": "2022-02-09T04:09:40.638+0000"
}
}
```

The length of time for which a direct access URL is valid defaults to `30` seconds if not configured otherwise in
`alfresco-global.properties`.

**Method:** `POST`

**Response:**

Link to the resource wrapped in a JSON Object, which also contains an attachment flag, and the DAU expiration date.

**Error codes:**

If there's no DAU provider installed in Alfresco (such as the Azure Connector), or DAUs aren't enabled, then a `501` HTTP
status code is returned.

**Parameters:**

* `attachment` is an optional flag which controls the download method (attachment URL vs. embedded URL). Defaults to `true` when not specified, which means the value of the [Content-Disposition](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition){:target="_blank"} response header will be attachment.
* The `filename` part of the `Content-Disposition` header will be set in the service layer logic, and can't be controlled by the DAU client.

### Discovery API
The Discovery API provides status information about the DAUs feature (enabled/disabled) via a new field:

* `RepositoryInfo > StatusInfo > isDirectAccessUrlEnabled`

For example:

```json
"status": {
"isReadOnly": false,
"isAuditEnabled": true,
"isQuickShareEnabled": true,
"isThumbnailGenerationEnabled": true,
"isDirectAccessUrlEnabled": true
},
```

This field is `true` only when **all** of the following conditions are met:

* DAUs are enabled system-wide.
* DAUs are enabled on the ReST API.
* If there's at least one ContentStore that's configured and has DAUs enabled.

#### Azure Connector
Several Azure Java SDK objects (see [BlobSasPermission](https://docs.microsoft.com/en-us/java/api/com.azure.storage.blob.sas.blobsaspermission?view=azure-java-stable){:target="_blank"} and [BlobServiceSasSignatureValues](https://docs.microsoft.com/en-us/java/api/com.azure.storage.blob.sas.blobservicesassignaturevalues?view=azure-java-stable){:target="_blank"}),
are used to generate SAS (Shared Access Signature), which is then used to generate direct access URLs with the configured
duration (see Repository and Content Store expiry times configurations).

The pre-signed request generates a download for the remote content.

>**Known Limitations:** SAS generation on Azure Blob depends on the authorization type used (only valid for Azure AD or
> shared key authorization), see: [https://docs.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas](https://docs.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas){:target="_blank"}
See also the [GitHub project documentation](https://github.com/Alfresco/acs-packaging/blob/master/docs/direct-access-urls.md#main-flows){:target="_blank"} for a detailed view of the main flows and other parts of the implementation.
Loading

0 comments on commit 2c48f30

Please sign in to comment.