IBM Cloud Docs
Utilisation de Object Storage non modifiable pour protéger les compartiments

Utilisation de Object Storage non modifiable pour protéger les compartiments

La fonction Immutable Object Storage conserve les enregistrements électroniques et assure l'intégrité des données. Les règles de conservation permettent de garantir que les données sont stockées de manière non réinscriptible (WORM), c'est-à-dire qu'elles ne peuvent pas être effacées ou modifiées. Cette règle est appliquée jusqu'à la fin d'une durée de conservation et de la suppression de toute règle de conservation légale.

Cette fonction n'est actuellement pas prise en charge dans Object Storage pour Satellite. En savoir plus.

Les règles sont appliquées jusqu'à la fin d'une période de conservation et ne peuvent pas être modifiées tant que la période de conservation n'est pas arrivée à expiration. Alors que IBM Cloud Object Storage utilise l'API S3 pour la plupart des opérations, les API utilisées pour la configuration des règles de conservation ne sont pas les mêmes que celles de l'API S3, bien qu'une certaine terminologie puisse être partagée. Lisez attentivement cette documentation pour empêcher les utilisateurs de votre organisation de créer des objets qui ne peuvent pas être supprimés, même par les administrateurs IBM Cloud.

Cette fonction peut être utilisée par tous les utilisateurs ayant besoin de conserver les données à long terme dans leur environnement. Elle concerne, entre autres, les organisations dans les secteurs d'activité suivants :

  • Finances
  • Santé
  • Archivage de contenu multimédia
  • Toute personne cherchant à empêcher la modification ou la suppression privilégiée d'objets ou de documents

Des règles de conservation peuvent également être utilisées par des organisations spécialisées dans la gestion de documents financiers, tels que les transactions de courtier, et qui ont éventuellement besoin de stocker leurs données dans un format non réinscriptible et non effaçable.

La fonction Immutable Object Storage est disponible uniquement dans certaines régions, voir Services intégrés pour obtenir des détails. De plus, elle requiert un plan de tarification standard. Pour plus d'informations, voir la section sur la tarification.

Il est impossible d'utiliser Aspera High-Speed Transfer avec les compartiments dotés d'une règle de conservation.

Terminologie et utilisation

Durée de conservation

La durée pendant laquelle un objet doit être stocké dans le seau IBM Cloud Object Storage.

Stratégie de conservation

Une politique de conservation est activée au niveau du seau IBM Cloud Object Storage. Les durées de conservation minimum, maximum et par défaut sont définies par cette règle et s'appliquent à tous les objets contenus dans le compartiment.

La durée de conservation minimum est la durée minimale pendant laquelle un objet doit être conservé sans être modifié dans le compartiment.

La durée de conservation maximum est la durée maximale pendant laquelle un objet peut être conservé sans être modifié dans le compartiment.

Si un objet est stocké dans le compartiment sans qu'aucune durée de conservation personnalisée ne soit spécifiée, la durée de conservation par défaut est utilisée. La durée de conservation minimum doit être inférieure ou égale à la durée de conservation par défaut, laquelle doit être inférieure ou égale à la durée de conservation maximum.

Une durée de conservation maximum de 1000 ans peut être spécifiée pour les objets.

Pour créer une règle de conservation pour un compartiment, vous devez disposer du rôle Responsable. Pour plus d'informations, voir Droits des compartiments.

Conservation légale

Il peut s'avérer nécessaire d'empêcher la mise à jour de certains objets à l'issue d'une durée de conservation. Par exemple, suite à un examen juridique incomplet, où l'accès aux enregistrements doit être prolongé au-delà de la durée de conservation définie à l'origine. Un indicateur de conservation légale peut alors être appliqué au niveau de l'objet.     Des durées de conservation légale peuvent être appliquées aux objets lors de téléchargements initiaux ou après l'écriture d'un objet.   Remarque : un maximum de 100 conservations légales peut être appliqué par objet.

Conservation indéfinie

Permet à l'utilisateur de définir l'objet de telle manière qu'il soit stocké indéfiniment jusqu'à ce qu'une nouvelle durée de conservation soit appliquée. Cette valeur est définie au niveau des objets.

Un objet dont la conservation est indéfinie n'est pas entièrement immuable tant que la conservation de l'objet n'a pas été convertie de -1 en une valeur positive finie. Bien qu'un objet écrit avec -1 (rétention indéfinie) ne puisse pas être supprimé à l'aide de la requête DELETE object ou écrasé, la rétention de l'objet peut toujours être mise à jour de -1 à la date/heure actuelle, ce qui rendrait l'objet immédiatement supprimable.

Les utilisateurs doivent tenir compte de ce comportement lorsqu'ils évaluent la viabilité du système pour leurs besoins de stockage. Un cas d'utilisation courant de la conservation indéfinie est décrit dans La conservation basée sur des événements. Si vous souhaitez utiliser la conservation basée sur les événements, Immutable Object Storage permet aux utilisateurs de définir une conservation indéfinie sur l'objet s'ils ne sont pas sûrs des besoins en matière de conservation lorsque l'objet est téléchargé pour la première fois dans le système. Une fois qu'elle est réglée sur une valeur indéfinie, les applications utilisateur peuvent alors modifier la rétention de l'objet pour lui donner une valeur finie lorsqu'un certain événement s'est produit.

Exemple Une entreprise a pour politique de conserver les dossiers de ses employés pendant trois ans après leur départ de l'entreprise.

  • Lorsqu'un employé entre au service d'une entreprise, les documents qui lui sont associés peuvent être conservés indéfiniment.
  • Et lorsque ce même salarié quitte l'entreprise, la conservation indéfinie est alors convertie en une valeur finie de trois ans à compter de la date actuelle, qui est définie par la politique de l'entreprise.

Un utilisateur ou une application tierce peut remplacer la conservation indéfinie par une conservation avec limite de durée en utilisant un kit SDK ou une API REST.

Les propriétaires de bacs et les utilisateurs autorisés peuvent limiter la nouvelle durée de conservation qui peut être configurée pour un objet actuellement conservé à l'aide de la conservation indéfinie. Pour ce faire, on utilise les valeurs minimales et maximales autorisées de la rétention du seau. Ce faisant, les utilisateurs peuvent éviter qu'un objet dont la durée de conservation est indéterminée ne soit mis à jour à l'heure actuelle, de sorte qu'il soit immédiatement supprimable.

Conservation en fonction d'un événement

La fonction Immutable Object Storage permet aux utilisateurs de définir une conservation indéfinie de l'objet s'ils ont un doute sur la durée de conservation finale ou s'ils souhaitent utiliser une conservation en fonction d'un événement. Lorsque la conservation de l'objet est indéfinie, les applications utilisateur pourront la remplacer par une valeur finie par la suite. Par exemple, une société a établi une règle qui prévoit de conserver des dossiers d'employés pendant trois années après le départ de ceux-ci. Lorsqu'un employé est embauché dans l'entreprise, les dossiers qui le concernent peuvent être conservés sans limite de durée. Lorsque l'employé quitte l'entreprise, la conservation sans limite de durée est convertie en une conservation avec une durée limitée de trois ans à partir du moment présent, comme stipulé par la règle de la société. L'objet est ensuite protégé pendant trois ans après la modification de la durée de conservation. Un utilisateur ou une application tierce peut remplacer la conservation indéfinie par une conservation avec limite de durée en utilisant un kit SDK ou une API REST.

Conservation permanente

La conservation permanente garantit que les données ne peuvent être supprimées, jamais, par quiconque. Lisez attentivement la documentation et n'utilisez pas la conservation permanente sauf s'il existe un besoin impérieux en matière de réglementation ou de conformité pour le stockage de données permanent.

La conservation permanente ne peut être activée qu'au niveau d'un godet IBM Cloud Object Storage lorsque la politique de conservation est activée et que les utilisateurs peuvent sélectionner l'option de période de conservation permanente lors du téléchargement d'objets. Une fois activé, ce processus est irréversible et les objets téléchargés qui ont une durée de conservation permanente ne peuvent plus être supprimés. Il incombe aux utilisateurs de valider de leur côté s'il existe un besoin légitime de stocker des objets de manière permanente en utilisant les buckets Object Storage avec une politique de rétention.

Lorsque vous utilisez Immutable Object Storage, il vous appartient de veiller à ce que votre compte IBM Cloud soit conforme à chacune des règles et instructions IBM Cloud tant que les données sont soumises à une règle de conservation. Pour plus d'informations, voir les conditions du service IBM Cloud.

Immutable Object Storage et remarques relatives à diverses réglementations

Lorsqu'Immutable Object Storage est utilisé, il incombe au client de s'assurer que les fonctionnalités présentées peuvent être utilisées pour respecter les principales règles relatives au stockage et à la conservation d'enregistrements électroniques régies en principe par :

Pour aider les clients à prendre des décisions réfléchies, IBM a engagé la société Cohasset Associates Inc. pour effectuer une évaluation indépendante d'Immutable Object Storage d'IBM. Consultez le rapport de Cohasset Associates Inc. qui fournit des détails sur l'évaluation de la fonctionnalité Immutable Object Storage de IBM Cloud Object Storage.

Audit de l'accès et des transactions

Les données de journal d'accès d'Immutable Object Storage permettant d'examiner les modifications des paramètres de conservation, de la durée de conservation des objets et de l'application de conservations légales sont disponibles au cas par cas en ouvrant un ticket de service client.

Utilisation de la console

Des règles de conservation peuvent être ajoutées à des compartiments vides nouveaux ou existants, et ne peuvent pas être retirées. Dans le cas d'un nouveau compartiment, vérifiez bien que vous créez le compartiment dans une région prise en charge, puis sélectionnez l'option Ajouter une règle de conservation. Dans le cas d'un compartiment existant, vérifiez que celui-ci ne comporte pas d'objet, puis accédez aux paramètres de configuration et cliquez sur le bouton Créer une règle au-dessous de la section Règle de conservation du compartiment. Dans les deux cas, définissez les durées de conservation minimum, maximum et par défaut.

Utilisation de l'API REST, de bibliothèques et de SDK

Plusieurs nouvelles API ont été introduites dans les SDK IBM Cloud Object Storage afin de fournir un support aux applications travaillant avec des politiques de conservation. Sélectionnez une langue ( HTTP, Java, JavaScript, ou Python ) au début de cette page pour voir les exemples qui utilisent le SDK Object Storage approprié.

Tous les exemples de code partent du principe qu'il existe un objet client appelé cos pouvant appeler les différentes méthodes. Pour plus de détails sur la création de clients, voir les guides SDK spécifiques.

Toutes les valeurs de date utilisées pour définir des durées de conservation sont exprimées au format GMT (Greenwich Mean Time). Un en-tête Content-MD5 ou un en-tête checksum (y compris x-amz-checksum-crc32, x-amz-checksum-crc32c, x-amz-checksum-crc64nvme, x-amz-checksum-sha1 ou x-amz-checksum-sha256) est nécessaire pour garantir l'intégrité des données. Notez qu'une valeur de hachage ou de somme de contrôle est automatiquement envoyée lors de l'utilisation d'un SDK.

Ajout d'une règle de conservation à un compartiment existant

Cette implémentation de l'opération PUT utilise le paramètre de requête protection pour définir les paramètres de conservation d'un compartiment existant. Cette opération vous permet de définir ou modifier la période de conservation minimale, par défaut et maximale. Cette opération vous permet également de modifier l'état de protection du compartiment.

Les objets écrits dans un compartiment protégé ne peuvent pas être supprimés tant que la période de protection n'est pas arrivée à expiration et que les conservations légales associées à l'objet n'ont pas toutes été retirées. La valeur de conservation par défaut du compartiment est attribuée à un objet, sauf si une valeur spécifique à l'objet est fournie lors de la création de l'objet. Lorsqu'ils sont écrasés, les objets des compartiments protégés auxquels plus aucune règle de conservation ne s'applique (la durée de conservation est arrivée à expiration et aucune conservation légale n'est associée à l'objet) sont de nouveau soumis à une durée de conservation. La nouvelle durée de conservation peut être fournie dans la demande d'écrasement de l'objet ou bien la durée de conservation par défaut du compartiment est attribuée à l'objet.

Les valeurs minimales et maximales prises en charge pour les paramètres de la période de conservation MinimumRetention, DefaultRetention et MaximumRetention sont un minimum de 0 jour et un maximum de 365243 jours (1000 ans).

Un en-tête Content-MD5 ou un en-tête checksum (y compris x-amz-checksum-crc32, x-amz-checksum-crc32c,x-amz-checksum-crc64nvme, x-amz-checksum-sha1 ou x-amz-checksum-sha256) est requis. Cette opération n'utilise pas d'autres paramètres de requête.

Pour plus d'informations sur les noeuds finaux, voir Noeuds finaux et emplacements de stockage.

Syntaxe

PUT https://{endpoint}/{bucket-name}?protection= # path style
PUT https://{bucket-name}.{endpoint}?protection= # virtual host style

Exemple de demande

PUT /example-bucket?protection= HTTP/1.1
Authorization: {authorization-string}
x-amz-date: 20181011T190354Z
x-amz-content-sha256: 2938f51643d63c864fdbea618fe71b13579570a86f39da2837c922bae68d72df
Content-MD5: GQmpTNpruOyK6YrxHnpj7g==
Content-Type: text/plain
Host: 67.228.254.193
Content-Length: 299
<ProtectionConfiguration>
  <Status>Retention</Status>
  <MinimumRetention>
    <Days>100</Days>
  </MinimumRetention>
  <MaximumRetention>
    <Days>10000</Days>
  </MaximumRetention>
  <DefaultRetention>
    <Days>2555</Days>
  </DefaultRetention>
</ProtectionConfiguration>

Exemple de réponse

HTTP/1.1 200 OK
Date: Wed, 5 Oct 2018 15:39:38 GMT
X-Clv-Request-Id: 7afca6d8-e209-4519-8f2c-1af3f1540b42
Accept-Ranges: bytes
Server: Cleversafe/3.14.1
X-Clv-S3-Version: 2.5
x-amz-request-id: 7afca6d8-e209-4519-8f2c-1af3f1540b42
Content-Length: 0
def add_protection_configuration_to_bucket(bucket_name):
    try:
        new_protection_config = {
            "Status": "Retention",
            "MinimumRetention": {"Days": 10},
            "DefaultRetention": {"Days": 100},
            "MaximumRetention": {"Days": 1000}
        }

        cos.put_bucket_protection_configuration(Bucket=bucket_name, ProtectionConfiguration=new_protection_config)

        print("Protection added to bucket {0}\n".format(bucket_name))
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to set bucket protection config: {0}".format(e))
function addProtectionConfigurationToBucket(bucketName) {
    console.log(`Adding protection to bucket ${bucketName}`);
    return cos.putBucketProtectionConfiguration({
        Bucket: bucketName,
        ProtectionConfiguration: {
            'Status': 'Retention',
            'MinimumRetention': {'Days': 10},
            'DefaultRetention': {'Days': 100},
            'MaximumRetention': {'Days': 1000}
        }
    }).promise()
    .then(() => {
        console.log(`Protection added to bucket ${bucketName}!`);
    })
    .catch((e) => {
        console.log(`ERROR: ${e.code} - ${e.message}\n`);
    });
}
public static void addProtectionConfigurationToBucket(String bucketName) {
    System.out.printf("Adding protection to bucket: %s\n", bucketName);

    BucketProtectionConfiguration newConfig = new BucketProtectionConfiguration()
        .withStatus(BucketProtectionStatus.Retention)
        .withMinimumRetentionInDays(10)
        .withDefaultRetentionInDays(100)
        .withMaximumRetentionInDays(1000);

    cos.setBucketProtection(bucketName, newConfig);

    System.out.printf("Protection added to bucket %s\n", bucketName);
}

public static void addProtectionConfigurationToBucketWithRequest(String bucketName) {
    System.out.printf("Adding protection to bucket: %s\n", bucketName);

    BucketProtectionConfiguration newConfig = new BucketProtectionConfiguration()
        .withStatus(BucketProtectionStatus.Retention)
        .withMinimumRetentionInDays(10)
        .withDefaultRetentionInDays(100)
        .withMaximumRetentionInDays(1000);

    SetBucketProtectionConfigurationRequest newRequest = new SetBucketProtectionConfigurationRequest()
        .withBucketName(bucketName)
        .withProtectionConfiguration(newConfig);

    cos.setBucketProtectionConfiguration(newRequest);

    System.out.printf("Protection added to bucket %s\n", bucketName);
}

Vérification de la règle de conservation d'un compartiment

Cette implémentation d'une opération GET extrait les paramètres de conservation pour un compartiment existant.

Syntaxe

GET https://{endpoint}/{bucket-name}?protection= # path style
GET https://{bucket-name}.{endpoint}?protection= # virtual host style

Exemple de demande

GET /example-bucket?protection= HTTP/1.1
Authorization: {authorization-string}
x-amz-date: 20181011T190354Z
Content-Type: text/plain
Host: 67.228.254.193

Exemple de réponse

HTTP/1.1 200 OK
Date: Wed, 5 Oct 2018 15:39:38 GMT
X-Clv-Request-Id: 7afca6d8-e209-4519-8f2c-1af3f1540b42
Accept-Ranges: bytes
Server: Cleversafe/3.13.1
X-Clv-S3-Version: 2.5
x-amz-request-id: 7afca6d8-e209-4519-8f2c-1af3f1540b42
Content-Length: 299
<ProtectionConfiguration>
  <Status>Retention</Status>
  <MinimumRetention>
    <Days>100</Days>
  </MinimumRetention>
  <MaximumRetention>
    <Days>10000</Days>
  </MaximumRetention>
  <DefaultRetention>
    <Days>2555</Days>
  </DefaultRetention>
</ProtectionConfiguration>

Si aucune configuration de protection n'est associée au compartiment, le serveur répond en émettant un statut désactivé.

<ProtectionConfiguration>
  <Status>Disabled</Status>
</ProtectionConfiguration>
def get_protection_configuration_on_bucket(bucket_name):
    try:
        response = cos.get_bucket_protection_configuration(Bucket=bucket_name)
        protection_config = response.get("ProtectionConfiguration")

        print("Bucket protection config for {0}\n".format(bucket_name))
        print(protection_config)
        print("\n")
    except ClientError as be:
        print("CLIENT ERROR: {0}\n".format(be))
    except Exception as e:
        print("Unable to get bucket protection config: {0}".format(e))
function getProtectionConfigurationOnBucket(bucketName) {
    console.log(`Retrieve the protection on bucket ${bucketName}`);
    return cos.getBucketProtectionConfiguration({
        Bucket: bucketName
    }).promise()
    .then((data) => {
        console.log(`Configuration on bucket ${bucketName}:`);
        console.log(data);
    }
    .catch((e) => {
        console.log(`ERROR: ${e.code} - ${e.message}\n`);
    });
}
public static void getProtectionConfigurationOnBucket(String bucketName) {
    System.out.printf("Retrieving protection configuration from bucket: %s\n", bucketName;

    BucketProtectionConfiguration config = cos.getBucketProtection(bucketName);

    String status = config.getStatus();

    System.out.printf("Status: %s\n", status);

    if (!status.toUpperCase().equals("DISABLED")) {
        System.out.printf("Minimum Retention (Days): %s\n", config.getMinimumRetentionInDays());
        System.out.printf("Default Retention (Days): %s\n", config.getDefaultRetentionInDays());
        System.out.printf("Maximum Retention (Days): %s\n", config.getMaximumRetentionInDays());
    }
}

Téléchargement d'un objet dans un compartiment avec une règle de conservation

Cette amélioration de l'opération PUT permet d'ajouter trois nouveaux en-têtes de demande, deux pour spécifier la durée de conservation de différentes manières, et un pour ajouter une conservation légale au nouvel objet. De nouvelles erreurs sont définies pour signaler les valeurs non admises contenues dans les nouveaux en-têtes, et si un objet est soumis à une durée de conservation, toute tentative d'écrasement échoue.

Lorsqu'ils sont écrasés, les objets des compartiments qui étaient soumis à une règle de conservation mais ne le sont plus (leur durée de conservation est arrivée à expiration et aucune conservation légale n'est associée à l'objet) sont de nouveau soumis à une durée de conservation. La nouvelle durée de conservation peut être fournie dans la demande d'écrasement de l'objet ou bien la durée de conservation par défaut du compartiment est attribuée à l'objet.

Un en-tête Content-MD5 ou un en-tête checksum (y compris x-amz-checksum-crc32, x-amz-checksum-crc32c, x-amz-checksum-crc64nvme, x-amz-checksum-sha1 ou x-amz-checksum-sha256) est nécessaire pour vérifier l'intégrité de la charge utile de tout type de demande de téléchargement d'objet vers un panier doté d'une politique de conservation.

Valeur Type Description
Retention-Period Entier non négatif (secondes) Durée de conservation, exprimée en secondes, pendant laquelle stocker l'objet. L'objet ne peut être ni écrasé, ni supprimé tant que la durée de conservation n'est pas écoulée. Si cette zone et la zone Retention-Expiration-Date sont spécifiées, un code d'erreur 400 est renvoyé. Si aucune de ces deux zones n'est spécifiée, la période DefaultRetention du compartiment est utilisée. Zéro (0) est une valeur légale qui part du principe que la durée de conservation minimale du compartiment est également fixée à 0.
Retention-expiration-date Date (format ISO 8601) Date à laquelle la suppression ou la modification de l'objet devient légale. Vous pouvez uniquement spécifier cette zone ou bien la zone d'en-tête Retention-Period. Si ces deux zones sont spécifiées, un code d'erreur 400 est renvoyé. Si aucune de ces deux zones n'est spécifiée, la période DefaultRetention du compartiment est utilisée. Le format ISO 8601 pris en charge est [YYYY]-[MM]-[DD]T[hh]:[mm]:[ss]Z ou [YYYY][MM][DD]T[hh][mm][ss]Z (par exemple, 2020-11-28T03:10:01Z ou 20201128T031001Z sont tous deux valides).
Retention-legal-hold-id Chaîne Conservation légale unique à appliquer à l'objet. Une conservation légale est une chaîne comportant Y caractères. L'objet ne peut être ni écrasé ni supprimé tant que les conservations légales associées à l'objet n'ont pas toutes été retirées.
def put_object_add_legal_hold(bucket_name, object_name, file_text, legal_hold_id):
    print("Add legal hold {0} to {1} in bucket {2} with a putObject operation.\n".format(legal_hold_id, object_name, bucket_name))

    cos.put_object(
        Bucket=bucket_name,
        Key=object_name,
        Body=file_text,
        RetentionLegalHoldId=legal_hold_id)

    print("Legal hold {0} added to object {1} in bucket {2}\n".format(legal_hold_id, object_name, bucket_name))

def copy_protected_object(source_bucket_name, source_object_name, destination_bucket_name, new_object_name):
    print("Copy protected object {0} from bucket {1} to {2}/{3}.\n".format(source_object_name, source_bucket_name, destination_bucket_name, new_object_name))

    copy_source = {
        "Bucket": source_bucket_name,
        "Key": source_object_name
    }

    cos.copy_object(
        Bucket=destination_bucket_name,
        Key=new_object_name,
        CopySource=copy_source,
        RetentionDirective="Copy"
    )

    print("Protected object copied from {0}/{1} to {2}/{3}\n".format(source_bucket_name, source_object_name, destination_bucket_name, new_object_name));

def complete_multipart_upload_with_retention(bucket_name, object_name, upload_id, retention_period):
    print("Completing multi-part upload for object {0} in bucket {1}\n".format(object_name, bucket_name))

    cos.complete_multipart_upload(
        Bucket=bucket_name,
        Key=object_name,
        MultipartUpload={
            "Parts":[{
                "ETag": part["ETag"],
                "PartNumber": 1
            }]
        },
        UploadId=upload_id,
        RetentionPeriod=retention_period
    )

    print("Multi-part upload completed for object {0} in bucket {1}\n".format(object_name, bucket_name))

def upload_file_with_retention(bucket_name, object_name, path_to_file, retention_period):
    print("Uploading file {0} to object {1} in bucket {2}\n".format(path_to_file, object_name, bucket_name))

    args = {
        "RetentionPeriod": retention_period
    }

    cos.upload_file(
        Filename=path_to_file,
        Bucket=bucket_name,
        Key=object_name,
        ExtraArgs=args
    )

    print("File upload complete to object {0} in bucket {1}\n".format(object_name, bucket_name))
function putObjectAddLegalHold(bucketName, objectName, legalHoldId) {
    console.log(`Add legal hold ${legalHoldId} to ${objectName} in bucket ${bucketName} with a putObject operation.`);
    return cos.putObject({
        Bucket: bucketName,
        Key: objectName,
        Body: 'body',
        RetentionLegalHoldId: legalHoldId
    }).promise()
    .then((data) => {
        console.log(`Legal hold ${legalHoldId} added to object ${objectName} in bucket ${bucketName}`);
    })
    .catch((e) => {
        console.log(`ERROR: ${e.code} - ${e.message}\n`);
    });
}

function copyProtectedObject(sourceBucketName, sourceObjectName, destinationBucketName, newObjectName, ) {
    console.log(`Copy protected object ${sourceObjectName} from bucket ${sourceBucketName} to ${destinationBucketName}/${newObjectName}.`);
    return cos.copyObject({
        Bucket: destinationBucketName,
        Key: newObjectName,
        CopySource: sourceBucketName + '/' + sourceObjectName,
        RetentionDirective: 'Copy'
    }).promise()
    .then((data) => {
        console.log(`Protected object copied from ${sourceBucketName}/${sourceObjectName} to ${destinationBucketName}/${newObjectName}`);
    })
    .catch((e) => {
        console.log(`ERROR: ${e.code} - ${e.message}\n`);
    });
}
public static void putObjectAddLegalHold(String bucketName, String objectName, String fileText, String legalHoldId) {
    System.out.printf("Add legal hold %s to %s in bucket %s with a putObject operation.\n", legalHoldId, objectName, bucketName);

    InputStream newStream = new ByteArrayInputStream(fileText.getBytes(StandardCharsets.UTF_8));

    ObjectMetadata metadata = new ObjectMetadata();
    metadata.setContentLength(fileText.length());

    PutObjectRequest req = new PutObjectRequest(
        bucketName,
        objectName,
        newStream,
        metadata
    );
    req.setRetentionLegalHoldId(legalHoldId);

    cos.putObject(req);

    System.out.printf("Legal hold %s added to object %s in bucket %s\n", legalHoldId, objectName, bucketName);
}

public static void copyProtectedObject(String sourceBucketName, String sourceObjectName, String destinationBucketName, String newObjectName) {
    System.out.printf("Copy protected object %s from bucket %s to %s/%s.\n", sourceObjectName, sourceBucketName, destinationBucketName, newObjectName);

    CopyObjectRequest req = new CopyObjectRequest(
        sourceBucketName,
        sourceObjectName,
        destinationBucketName,
        newObjectName
    );
    req.setRetentionDirective(RetentionDirective.COPY);


    cos.copyObject(req);

    System.out.printf("Protected object copied from %s/%s to %s/%s\n", sourceObjectName, sourceBucketName, destinationBucketName, newObjectName);
}

Prolongement de la durée de conservation d'un objet

Cette implémentation de l'opération POST utilise le paramètre de requête extendRetention pour prolonger la durée de conservation d'un objet protégé dans un compartiment protégé.

La durée de conservation d'un objet ne peut être que prolongée. La valeur actuellement configurée ne peut pas être diminuée.

La valeur de prolongement de la conservation est définie de l'une des trois façons suivantes :

  • En ajoutant une durée supplémentaire par rapport à la valeur en cours (Additional-Retention-Period ou méthode similaire)
  • En définissant une nouvelle période de prolongement, exprimée en secondes (Extend-Retention-From-Current-Time ou méthode similaire)
  • En définissant une nouvelle date d'expiration de la conservation de l'objet (New-Retention-Expiration-Date ou méthode similaire)

La durée de conservation en cours qui est stockée dans les métadonnées de l'objet est soit augmentée de la durée prolongée indiquée, soit remplacée par la nouvelle valeur, en fonction du paramètre défini dans la demande extendRetention. Dans tous les cas, le paramètre de prolongement de la conservation est vérifié par rapport à la durée de conservation en cours et le paramètre de prolongement n'est accepté que si la durée de conservation mise à jour est supérieure à la durée de conservation en cours.

Le format ISO 8601 pris en charge pour New-Retention-Expiration-Date est [YYYY]-[MM]-[DD]T[hh]:[mm]:[ss]Z ou [YYYY][MM][DD]T[hh][mm][ss]Z (par exemple, 2020-11-28T03:10:01Z ou 20201128T031001Z sont tous deux valides).

Lorsqu'ils sont écrasés, les objets des compartiments protégés auxquels plus aucune règle de conservation ne s'applique (la durée de conservation est arrivée à expiration et aucune conservation légale n'est associée à l'objet) sont de nouveau soumis à une durée de conservation. La nouvelle durée de conservation peut être fournie dans la demande d'écrasement de l'objet ou bien la durée de conservation par défaut du compartiment est attribuée à l'objet.

Syntaxe

POST https://{endpoint}/{bucket-name}/{object-name}?extendRetention= # path style
POST https://{bucket-name}.{endpoint}/{object-name}?extendRetention= # virtual host style

Exemple de demande

POST /BucketName/ObjectName?extendRetention HTTP/1.1
Host: myBucket.mydsNet.corp.com
Date: Fri, 8 Dec 2018 17:50:00GMT
Authorization: authorization string
Content-Type: text/plain
Additional-Retention-Period: 31470552

Exemple de réponse

HTTP/1.1 200 OK
Date: Fri, 8 Dec 2018 17:50:00GMT
Connection: close
def extend_retention_period_on_object(bucket_name, object_name, additional_seconds):
    print("Extend the retention period on {0} in bucket {1} by {2} seconds.\n".format(object_name, bucket_name, additional_seconds))

    cos.extend_object_retention(
        Bucket=bucket_ame,
        Key=object_name,
        AdditionalRetentionPeriod=additional_seconds
    )

    print("New retention period on {0} is {1}\n".format(object_name, additional_seconds))
function extendRetentionPeriodOnObject(bucketName, objectName, additionalSeconds) {
    console.log(`Extend the retention period on ${objectName} in bucket ${bucketName} by ${additionalSeconds} seconds.`);
    return cos.extendObjectRetention({
        Bucket: bucketName,
        Key: objectName,
        AdditionalRetentionPeriod: additionalSeconds
    }).promise()
    .then((data) => {
        console.log(`New retention period on ${objectName} is ${data.RetentionPeriod}`);
    })
    .catch((e) => {
        console.log(`ERROR: ${e.code} - ${e.message}\n`);
    });
}
public static void extendRetentionPeriodOnObject(String bucketName, String objectName, Long additionalSeconds) {
    System.out.printf("Extend the retention period on %s in bucket %s by %s seconds.\n", objectName, bucketName, additionalSeconds);

    ExtendObjectRetentionRequest req = new ExtendObjectRetentionRequest(
        bucketName,
        objectName)
        .withAdditionalRetentionPeriod(additionalSeconds);

    cos.extendObjectRetention(req);

    System.out.printf("New retention period on %s is %s\n", objectName, additionalSeconds);
}

Création de la liste des conservations légales associées à un objet

Cette implémentation de l'opération GET utilise le paramètre de requête legalHold pour renvoyer la liste des conservations légales associées à un objet et l'état de conservation connexe dans un corps de réponse XML.

Cette opération renvoie les éléments suivants :

  • La date de création de l'objet
  • La durée de conservation, exprimée en secondes
  • La date d'expiration de la conservation, calculée sur la base de la durée de conservation et de la date de création
  • La liste des conservations légales
  • L'identificateur de conservation légale
  • L'horodatage correspondant à l'application de la conservation légale

Si aucune conservation légale n'est associée à l'objet, un élément LegalHoldSet vide est renvoyé. Si aucune durée de conservation n'est spécifiée pour l'objet, un code d'erreur 404 est renvoyé.

Syntaxe

GET https://{endpoint}/{bucket-name}/{object-name}?legalHold= # path style
GET https://{bucket-name}.{endpoint}/{object-name}?legalHold= # virtual host style

Exemple de demande

GET /BucketName/ObjectName?legalHold HTTP/1.1
Host: myBucket.mydsNet.corp.com
Date: Fri, 8 Dec 2018 17:50:00 GMT
Authorization: {authorization-string}
Content-Type: text/plain

Exemple de réponse

HTTP/1.1 200 OK
Date: Fri, 8 Dec 2018 17:51:00 GMT
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<RetentionState>
  <CreateTime>Fri, 8 Sep 2018 21:33:08 GMT</CreateTime>
  <RetentionPeriod>220752000</RetentionPeriod>
  <RetentionPeriodExpirationDate>Fri, 1 Sep 2023 21:33:08
GMT</RetentionPeriodExpirationDate>
  <LegalHoldSet>
    <LegalHold>
      <ID>SomeLegalHoldID</ID>
      <Date>Fri, 8 Sep 2018 23:13:18 GMT</Date>
    </LegalHold>
    <LegalHold>
    ...
    </LegalHold>
  </LegalHoldSet>
</RetentionState>
def list_legal_holds_on_object(bucket_name, object_name):
    print("List all legal holds on object {0} in bucket {1}\n".format(object_name, bucket_name));

    response = cos.list_legal_holds(
        Bucket=bucket_name,
        Key=object_name
    )

    print("Legal holds on bucket {0}: {1}\n".format(bucket_name, response))
function listLegalHoldsOnObject(bucketName, objectName) {
    console.log(`List all legal holds on object ${objectName} in bucket ${bucketName}`);
    return cos.listLegalHolds({
        Bucket: bucketName,
        Key: objectId
    }).promise()
    .then((data) => {
        console.log(`Legal holds on bucket ${bucketName}: ${data}`);
    })
    .catch((e) => {
        console.log(`ERROR: ${e.code} - ${e.message}\n`);
    });
}
public static void listLegalHoldsOnObject(String bucketName, String objectName) {
    System.out.printf("List all legal holds on object %s in bucket %s\n", objectName, bucketName);

    ListLegalHoldsResult result = cos.listLegalHolds(
        bucketName,
        objectName
    );

    System.out.printf("Legal holds on bucket %s: \n", bucketName);

    List<LegalHold> holds = result.getLegalHolds();
    for (LegalHold hold : holds) {
        System.out.printf("Legal Hold: %s", hold);
    }
}