# Object Lock

**Object Lock** empêche la suppression des objets et de leurs versions, pendant une période définie par l'utilisateur.

La politique de rétention est définie à l'aide de l'API S3 ou des valeurs par défaut au niveau du **Bucket** ou directement sur l'objet.

Les objets sont verrouillés pour la durée de la période de rétention. Les scénarios de rétention légale sont également pris en charge.

Il existe deux types de protection:

* **Retention period:** Spécifie une période de temps fixe pendant laquelle une version d'objet est verrouillée. Pendant cette période, votre version de l'objet est **protégée** en écriture et ne peut pas être modifiée ou supprimée.
* **Legal hold:** Offre la même protection qu'une période de rétention, mais sans date d'expiration. Au contraire, Legal hold reste en place jusqu'à ce que vous la désactiviez explicitement. Les legal hold sont indépendantes des périodes de rétention.

Il existe **deux modes** pour la période de rétention :

<details>

<summary>Mode Gouvernance</summary>

Les utilisateurs ne peuvent pas modifier ou supprimer un objet, ni modifier ses paramètres de rétention, sauf s'ils disposent d'autorisations appropriées.

Avec le **mode Gouvernance**, vous protégez les objets contre la suppression par la plupart des Object Users, mais vous avez la possibilité d'autoriser certains Object Users à modifier les paramètres de rétention ou à supprimer l'objet si besoin.

Vous pouvez également utiliser le **mode Gouvernance** pour tester les paramètres des délais de conservation avant de créer un délai de conservation en **mode conformité**.

* Les Object Users ne peuvent pas modifier ou supprimer un objet.
* Les Object Users disposant de l'autorisation `s3:PutObjectRetention`, peuvent augmenter la période de rétention d'un objet.
* Les Object Users disposant de l'autorisation `s3:BypassGovernanceRetention`, peuvent supprimer ou réduire la période de rétention d'un objet.
* Les Object Users disposant de l'autorisation `s3:BypassGovernanceRetention` peuvent également supprimer les objets verrouillés.

</details>

<details>

<summary>Mode Conformité</summary>

Un objet protégé avec le **mode conformité** ne peut **être modifié ou supprimé par aucun Object Users, y compris l'Object Users root de votre compte**.

Lorsqu'un objet est protégé en mode conformité, son mode de rétention ne peut être modifié et sa période de rétention ne peut être réduite.

Le **mode conformité** permet de s'assurer qu'un objet ne peut pas être modifié ou supprimé pendant la durée de la période de rétention.

* Les **Object Users** ne peuvent pas modifier ou supprimer un objet.
* Les **Object Users** disposant de l'autorisation **`s3:PutObjectRetention`**, peuvent augmenter la période de rétention d'un objet.
* Les **Object Users ne peuvent pas supprimer** ou réduire la rétention d'un objet.

</details>

{% hint style="warning" %}
Avec le **mode conformité**, si vous appliquez une période de rétention par erreur (par exemple 6 ans au lieu de 6 jours), **cegedim.cloud** n'a aucune possibilité de supprimer ou de réduire la période de rétention.

Une bonne pratique consiste à commencer avec le **mode gouvernance** pour effectuer des tests, puis de passer ensuite, en **mode conformité**.
{% endhint %}

Pour plus d'informations, voir :

{% embed url="<https://aws.amazon.com/blogs/storage/protecting-data-with-amazon-s3-object-lock/>" %}

## Pré-requis

* Object Lock nécessite la désactivation de la fonctionnalité ADO (Access During Outage) au niveau du magasin d'objets.
  * :warning: Cela signifie que, sans ADO, toutes opérations (lecture, création, mise à jour et suppression ainsi que lister des buckets), sur un site qui n'est pas propriétaire de l'objet ou du bucket, échoueront.
  * Les Object Stores sans ADO ne peuvent pas être créés au travers d'**ITCare** et doivent manuellement par les équipes de cegedim.cloud.
* Object Lock ne fonctionne qu'avec les Object Users de type **IAM**.
  * :warning: Les Object Users de type **IAM** ne peuvent pas être gérés au travers d'**ITCare** et doivent être créés manuellement par les équipes de cegedim.cloud.
* Object Lock ne fonctionne qu'avec des Buckets où le versionnage est activé.
* L'activation de Object Lock sur le Bucket active automatiquement le versionnage .
* Une fois Object Lock activé, il n'est pas possible de le désactiver ou de suspendre le versionnage au niveau du Bucket.
* Object Lock n'est pas compatible avec les Buckets où la fonctionnalité "système de fichiers" est activée.
* Object Lock est uniquement supporté l'API S3.
* Un Bucket peut avoir une configuration Object Lock par défaut comprenant un mode de rétention (gouvernance ou conformité) et une période de rétention (exprimée en jours ou en années).
* Object Lock s'appliquent uniquement aux versions individuelles des objets
* Les différentes versions d'un même objet peuvent avoir des modes et des périodes de rétention différents.
* Object Lock empêche la suppression ou la modification d'un objet. La modification ne signifie pas que de nouvelles versions ne peuvent pas être créées (de nouvelles versions peuvent être créées avec leurs propres paramètres de rétention).
* Un objet peut toujours être supprimé en fonction de sa version. Un marqueur de suppression est créé. La version existe toujours et est verrouillée.
* Le mode conformité est plus strict : les périodes de rétention ne peuvent pas être supprimées, réduites ou déclassés en mode gouvernance.
* Le mode gouvernance est moins strict : les période de rétention peuvent être supprimées, contournées, ou même élevés en mode conformité.
* La mise à jour des métadonnées d'une version d' un objet, qui se produit lorsque vous placez ou modifiez Object Lock, n'écrase pas la version de l'objet et ne réinitialise pas son horodatage "Last-Modified".
* La période de rétention peut être placée explicitement sur un objet ou implicitement, par le biais d'une configuration Object Lock définit au niveau du Bucket.
* Le fait de placer une une configuration Object Lock sur un Bucket n'a aucun effet les objets déjà présents dans le Bucket.
* La modification de période de rétention définit au niveau du Bucket ne change pas la période de rétention sur les objets déjà présent dans le Bucket.

## Cycle de vie

Les objets sous verrou sont protégés contre les suppressions de cycle de vie.

La logique du cycle de vie est rendue difficile en raison de la variété des comportements des différents verrous.

Du point de vue du cycle de vie, il existe des verrous sans date, des verrous dont la date peut être prolongée et des verrous dont la date peut être réduite.

* Pour le **Mode de conformité :** la date de conservation ne peut pas être réduite, mais elle peut être augmentée.
* Pour le **Mode de gouvernance :** la date de verrouillage peut augmenter, diminuer ou être supprimée.
* Pour la protection de type **Legal Hold**, la rétention est indéfinie.

## Conditions

Le contrôle d'accès au travers des **politiques IAM** est une partie importante de la fonctionnalité **Object Lock**.

La permission `s3:BypassGovernanceRetention` est importante car elle permet supprimer un objet protégé par **Object Lock** avec une configuration en **mode gouvernance**.

Les conditions des **politiques IAM** sont décrites ci-dessous et vous permettent de limiter la période de rétention et le type de protection (Legal Hold) spécifiés sur les objets.

{% hint style="warning" %}
Il n'est pas possible de gérer les politiques **IAM** avec **ITCare**.
{% endhint %}

| Condition                                 | Description                                                                    |
| ----------------------------------------- | ------------------------------------------------------------------------------ |
| `s3:object-lock-legal-hold`               | Permet l'application de la protection "Legal Hold" sur l'objet spécifié.       |
| `s3:object-lock-mode`                     | Active l'application de la protection "Retention Period" sur l'objet spécifié. |
| `s3:object-lock-retain-until-date`        | Permet l'application d'une date de conservation spécifique.                    |
| `s3:object-lock-remaining-retention-days` | Permet l'exécution d'un objet par rapport aux jours de rétention restants.     |

Ces condition peuvent être utilisées dans les **politiques de gestion des Buckets** et **IAM** pour contrôler les comportements de **Objet Lock** sur objets.

Par exemple: *s'assurer à ce que la période de rétention ne dépasse pas 5 ans.*

## Exemples et cas d'usage

### Buckets

{% hint style="info" %}
Nous utilisons les utilitaires **aws s3** et **aws s3api** issues du client S3 **AWSCLIv2** sur Linux. `${S3_ENDPOINT}` & `${S3_PROFILE}` sont des variables d'environnement.
{% endhint %}

Créez un **Bucket** avec le **Object Lock** activé :

{% code overflow="wrap" %}

```bash
aws s3api --endpoint-url=${S3_ENDPOINT} create-bucket --bucket bucket-with-lock --object-lock-enabled-for-bucket --profile ${S3_PROFILE}
```

{% endcode %}

{% code title="Résultat" %}

```json
{
    "Location": "/bucket-with-lock"
}
```

{% endcode %}

{% hint style="warning" %}
Vous ne pouvez activer Object Lock **uniquement à la création** d'un Bucket.

Vous ne pouvez pas activer Object Lock sur un Bucket **existant**.
{% endhint %}

Ajoutez une configuration **Object Lock** sur votre **Bucket** :

{% code title="governance.json" lineNumbers="true" %}

```json
{
  "ObjectLockEnabled": "Enabled",
  "Rule": {
    "DefaultRetention": {
      "Mode": "GOVERNANCE",
      "Days": 1
    }
  }
}
```

{% endcode %}

{% code overflow="wrap" %}

```bash
aws s3api --endpoint-url=${S3_ENDPOINT} put-object-lock-configuration --bucket bucket-with-lock --object-lock-configuration file://governance.json --profile ${S3_PROFILE}
```

{% endcode %}

Obtenir la configuration **Object Lock** actuelle d'un **Bucket** :

{% code overflow="wrap" %}

```bash
aws s3api --endpoint-url=${S3_ENDPOINT} get-object-lock-configuration --bucket bucket-with-lock --profile ${S3_PROFILE}
```

{% endcode %}

{% code title="Résultat" lineNumbers="true" %}

```json
{
    "ObjectLockConfiguration": {
        "ObjectLockEnabled": "Enabled",
        "Rule": {
            "DefaultRetention": {
                "Mode": "GOVERNANCE",
                "Days": 1
            }
        }
    }
}
```

{% endcode %}

### Objects

Dans ce contexte, il n'y a pas de configuration **Object Lock** définie au niveau du **Bucket**.\
Mais le **Bucket** a été créé avec le paramètre `--object-lock-enabled-for-bucket.`

{% hint style="info" %}
Nous utilisons les utilitaires **aws s3** et **aws s3api** issues du client S3 **AWSCLIv2** sur Linux. `${S3_ENDPOINT}` & `${S3_PROFILE}` sont des variables d'environnement.
{% endhint %}

Téléchargez un objet dans un **Bucket** :

{% code overflow="wrap" %}

```bash
aws --endpoint-url=${S3_ENDPOINT} --profile=${S3_PROFILE} s3 cp feather.ttf s3://bucket-test
```

{% endcode %}

{% code title="Résultat" %}

```
upload: ./feather.ttf to s3://bucket-test/feather.ttf
```

{% endcode %}

Appliquez la période de rétention sur l'objet :

{% code overflow="wrap" %}

```bash
aws --profile=${PROFILE} --endpoint ${S3_ENDPOINT} s3api put-object-retention --retention Mode=GOVERNANCE,RetainUntilDate=2022-08-26T17:00:00 --bucket bucket-test --key feather.ttf
```

{% endcode %}

Utilisez `head-object` pour obtenir les métadonnées de l'objet et les informations sur la rétention :

{% code overflow="wrap" %}

```bash
aws --profile=${PROFILE} --endpoint ${S3_ENDPOINT} s3api head-object --bucket bucket-test --key feather.ttf
```

{% endcode %}

{% code title="Résultat" lineNumbers="true" %}

```json
{
    "LastModified": "Thu, 25 Aug 2022 12:32:09 GMT",
    "ContentLength": 81512,
    "ETag": "\"2232dadea2f05fa28e3f08b5b3346df9\"",
    "VersionId": "1661430729953",
    "ContentType": "font/ttf",
    "ServerSideEncryption": "AES256",
    "Metadata": {},
    "ObjectLockMode": "GOVERNANCE",
    "ObjectLockRetainUntilDate": "2022-08-26T17:00:00.000Z"
}
```

{% endcode %}

Augmentez la rétention (+1 jours) :

{% code overflow="wrap" %}

```bash
aws --profile=${PROFILE} --endpoint ${S3_ENDPOINT} s3api put-object-retention --retention Mode=GOVERNANCE,RetainUntilDate=2022-08-27T17:00:00 --bucket bucket-test --key feather.ttf
```

{% endcode %}

{% code title="Résultat" %}

```json
{
    "LastModified": "Thu, 25 Aug 2022 12:32:09 GMT",
    "ContentLength": 81512,
    "ETag": "\"2232dadea2f05fa28e3f08b5b3346df9\"",
    "VersionId": "1661430729953",
    "ContentType": "font/ttf",
    "ServerSideEncryption": "AES256",
    "Metadata": {},
    "ObjectLockMode": "GOVERNANCE",
    "ObjectLockRetainUntilDate": "2022-08-27T17:00:00.000Z"
}
```

{% endcode %}

Supprimez l'objet :

{% code overflow="wrap" %}

```bash
aws --endpoint-url=${S3_ENDPOINT} --profile=${S3_PROFILE} s3 rm s3://bucket-test/feather.ttf
```

{% endcode %}

{% code title="Résultat" %}

```
delete: s3://bucket-test/feather.ttf
```

{% endcode %}

{% code overflow="wrap" %}

```bash
# Lister le contenu du bucket, le fichier feather.ttf n'est plus visible
aws --endpoint-url=${S3_ENDPOINT} --profile=${S3_PROFILE} s3 ls s3://bucket-test/
 
# Aucun résultat
```

{% endcode %}

Vérifiez la version :

{% hint style="info" %}
Cela affichera toutes les versions de l'objet ainsi que le **`marqueur de suppression`** **`(DeleteMarker)`**, créé lorsque nous avons supprimé l'objet.
{% endhint %}

{% code overflow="wrap" %}

```bash
aws --profile=${PROFILE} --endpoint ${S3_ENDPOINT} s3api list-object-versions --bucket bucket-test --prefix feather.ttf
```

{% endcode %}

{% code title="résultat" lineNumbers="true" %}

```json
{
    "Versions": [
        {
            "ETag": "\"1747b668712195f92c827c7b23a169fc\"",
            "Size": 5,
            "StorageClass": "STANDARD",
            "Key": "feather.ttf",
            "VersionId": "1661431782902",
            "IsLatest": false,
            "LastModified": "2022-08-25T12:49:42.902Z",
            "Owner": {
                "DisplayName": "urn:ecs:iam::cos-cegedimit-test-lock:root",
                "ID": "urn:ecs:iam::cos-cegedimit-test-lock:root"
            }
        }
    ],
    "DeleteMarkers": [
        {
            "Owner": {
                "DisplayName": "urn:ecs:iam::cos-cegedimit-test-lock:user/cloud",
                "ID": "urn:ecs:iam::cos-cegedimit-test-lock:user/cloud"
            },
            "Key": "feather.ttf",
            "VersionId": "1661431795694",
            "IsLatest": true,
            "LastModified": "2022-08-25T12:49:55.694Z"
        }
    ]
}
```

{% endcode %}

Supprimez le **`marqueur de suppression`** **`(DeleteMarker)`** en utilisant l'identifiant de la version :

{% code overflow="wrap" %}

```bash
aws --profile=${S3_PROFILE} --endpoint ${S3_ENDPOINT} s3api delete-object --bucket bucket-test --key feather.ttf --version-id 1661431795694
```

{% endcode %}

{% code title="résultat" %}

```json
{
    "DeleteMarker": true,
    "VersionId": "1661431795694"
}
```

{% endcode %}

{% code overflow="wrap" %}

```bash
# Once delete marker deleted, the object can be listed again
aws --endpoint-url=${S3_ENDPOINT} --profile=${S3_PROFILE} s3 ls s3://bucket-test/feather.ttf
```

{% endcode %}

{% code title="résultat" %}

```
2022-08-25 14:49:42          5 feather.ttf
```

{% endcode %}

Uploadez une nouvelle version de l'objet :

{% hint style="info" %}
Nous avons maintenant 2 versions de l'objet **feather.ttf**.
{% endhint %}

{% code overflow="wrap" %}

```bash
aws --profile=${PROFILE} --endpoint ${S3_ENDPOINT} s3api list-object-versions --bucket bucket-test --prefix feather.ttf
```

{% endcode %}

{% code title="résultat" lineNumbers="true" %}

```json
{
    "Versions": [
        {
            "ETag": "\"2232dadea2f05fa28e3f08b5b3346df9\"",
            "Size": 81512,
            "StorageClass": "STANDARD",
            "Key": "feather.ttf",
            "VersionId": "1661432092692",
            "IsLatest": true,
            "LastModified": "2022-08-25T12:54:52.692Z",
            "Owner": {
                "DisplayName": "urn:ecs:iam::cos-cegedimit-test-lock:root",
                "ID": "urn:ecs:iam::cos-cegedimit-test-lock:root"
            }
        },
        {
            "ETag": "\"1747b668712195f92c827c7b23a169fc\"",
            "Size": 5,
            "StorageClass": "STANDARD",
            "Key": "feather.ttf",
            "VersionId": "1661431782902",
            "IsLatest": false,
            "LastModified": "2022-08-25T12:49:55.694Z",
            "Owner": {
                "DisplayName": "urn:ecs:iam::cos-cegedimit-test-lock:root",
                "ID": "urn:ecs:iam::cos-cegedimit-test-lock:root"
            }
        }
    ]
}
```

{% endcode %}

Supprimez une version spécifique :

{% hint style="info" %}
La version de l'objet supprimée "devient" un **`marqueur de suppression`** **`(DeleteMarker).`**
{% endhint %}

{% code overflow="wrap" %}

```bash
aws --profile=${S3_PROFILE} --endpoint ${S3_ENDPOINT} s3api delete-object --bucket bucket-test --key feather.ttf --version-id 1661432092692
```

{% endcode %}

{% code title="résultat" %}

```json
{
    "VersionId": "1661432092692"
}
```

{% endcode %}

Lister les versions :

{% code overflow="wrap" %}

```bash
aws --profile=${PROFILE} --endpoint ${S3_ENDPOINT} s3api list-object-versions --bucket bucket-test --prefix feather.ttf
```

{% endcode %}

{% code title="résultat" %}

```json
{
    "Versions": [
        {
            "ETag": "\"1747b668712195f92c827c7b23a169fc\"",
            "Size": 5,
            "StorageClass": "STANDARD",
            "Key": "feather.ttf",
            "VersionId": "1661431782902",
            "IsLatest": false,
            "LastModified": "2022-08-25T12:49:55.694Z",
            "Owner": {
                "DisplayName": "urn:ecs:iam::cos-cegedimit-test-lock:root",
                "ID": "urn:ecs:iam::cos-cegedimit-test-lock:root"
            }
        }
    ],
    "DeleteMarkers": [
        {
            "Owner": {
                "DisplayName": "urn:ecs:iam::cos-cegedimit-test-lock:user/cloud",
                "ID": "urn:ecs:iam::cos-cegedimit-test-lock:user/cloud"
            },
            "Key": "feather.ttf",
            "VersionId": "1661432197362",
            "IsLatest": true,
            "LastModified": "2022-08-25T12:56:37.362Z"
        }
    ]
}
```

{% endcode %}

Utilisez l'option `--bypass-governance-retention` pour contourner la mode gouvernance et supprimer le **`marqueur de suppression`** **`(DeleteMarker)`** :

{% code overflow="wrap" %}

```bash
aws --profile=${S3_PROFILE} --endpoint ${S3_ENDPOINT} s3api delete-object --bucket bucket-test --key feather.ttf --version-id 1661432197362 --bypass-governance-retention
```

{% endcode %}

{% code title="résultat" %}

```json
{
    "DeleteMarker": true,
    "VersionId": "1661432197362"
}
```

{% endcode %}

Lister les versions :

{% code overflow="wrap" %}

```bash
aws --profile=${PROFILE} --endpoint ${S3_ENDPOINT} s3api list-object-versions --bucket bucket-test --prefix feather.ttf
```

{% endcode %}

{% code title="résultat" %}

```json
{
    "Versions": [
        {
            "ETag": "\"1747b668712195f92c827c7b23a169fc\"",
            "Size": 5,
            "StorageClass": "STANDARD",
            "Key": "feather.ttf",
            "VersionId": "1661431782902",
            "IsLatest": true,
            "LastModified": "2022-08-25T12:49:55.694Z",
            "Owner": {
                "DisplayName": "urn:ecs:iam::cos-cegedimit-test-lock:root",
                "ID": "urn:ecs:iam::cos-cegedimit-test-lock:root"
            }
        }
    ]
}
```

{% endcode %}

Supprimer la dernière version de l'objet avec `--bypass-governance-retention` :

{% code overflow="wrap" %}

```bash
aws --profile=${S3_PROFILE} --endpoint ${S3_ENDPOINT} s3api delete-object --bucket bucket-test --key feather.ttf --version-id 1661431782902 --bypass-governance-retention
```

{% endcode %}

{% code title="résultat" %}

```json
{
    "VersionId": "1661431782902"
}
```

{% endcode %}

Lister les versions :

{% code overflow="wrap" %}

```bash
aws --profile=${PROFILE} --endpoint ${S3_ENDPOINT} s3api list-object-versions --bucket bucket-test --prefix feather.ttf
```

{% endcode %}

Résultat vide.

{% code overflow="wrap" %}

```bash
aws --endpoint-url=${S3_ENDPOINT} --profile=${S3_PROFILE} s3 ls s3://bucket-test/
```

{% endcode %}

Résultat vide - bucket vide.

### Configuration Object Lock

Les configurations **Object Lock** peuvent être appliquées au niveau du **Bucket**.

La rétention sera appliquée sur chaque objet mis dans le **Bucket**.

{% hint style="info" %}
Definition d'une configuration Object Lock

La configuration **Object Lock** est un document JSON :

```json
{
  "ObjectLockEnabled": "Enabled",
  "Rule": {
    "DefaultRetention": {
      "Mode": "GOVERNANCE"|"COMPLIANCE",
      "Days": integer,
      "Years": integer
    }
  }
}
```

{% endhint %}

#### **Mode**

Le mode de rétention par défaut que vous souhaitez appliquer aux nouveaux objets placés dans le **Bucket**. Doit être utilisé avec **Jours** ou **Années**.

Les valeurs possibles sont **COMPLIANCE** ou **GOVERNANCE.**

#### **Jours**

Le nombre de jours de la période de rétention appliquée par défaut. Doit être utilisé avec **Mode**.

**Années**

Le nombre d'années de la période de rétention appliquée par défaut. Doit être utilisé avec **Mode**.\
Les **jours** et les **années** sont mutuellement exclusif.

<details>

<summary>Configuration mode Gouvernance</summary>

```json
{
    "ObjectLockConfiguration": {
        "ObjectLockEnabled": "Enabled",
        "Rule": {
            "DefaultRetention": {
                "Mode": "GOVERNANCE",
                "Years": 1
            }
        }
    }
}
```

</details>

<details>

<summary>Configuration mode Conformité</summary>

```json
{
    "ObjectLockConfiguration": {
        "ObjectLockEnabled": "Enabled",
        "Rule": {
            "DefaultRetention": {
                "Mode": "COMPLIANCE",
                "Days": 60
            }
        }
    }
}
```

</details>

### S3 Browser

[**s3Browser**](https://s3browser.com/) est un client Windows freeware pour [Amazon S3](http://aws.amazon.com/s3/).

{% hint style="info" %}
**s3Browser** ne vous permet pas de gérer les configurations **Object Lock** sur les **Buckets** ou les objets.
{% endhint %}

Avec **s3Browser**, vous pouvez voir les métadonnées des objets et obtenir la configuration **Object Lock** actuellement définie sur l'objet :

<figure><img src="https://1991151216-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fu3cmMjeBxFoEweG69ePZ%2Fuploads%2Fgit-blob-6d8309a0bf2b152266351b0ebbf0c636776f1184%2Fimage2022-8-29_11-57-17.png?alt=media" alt=""><figcaption></figcaption></figure>
