Usando o Immutable Object Storage para proteger depósitos

O Immutable Object Storage preserva registros eletrônicos e mantém a integridade de dados. As políticas de retenção asseguram que os dados sejam armazenados em uma maneira WORM (Write-Once-Read-Many), não apagável e não regravável. Essa política é aplicada até o término de um período de retenção e a remoção de quaisquer retenções legais.

Atualmente, esse recurso não é compatível com o site Object Storage para Satellite. Saiba mais.

As políticas são aplicadas até o término de um período de retenção e não podem ser alteradas até que o período de retenção tenha expirado. Embora o site IBM Cloud Object Storage use a API S3 para a maioria das operações, as APIs usadas para configurar políticas de retenção não são as mesmas da API S3, embora algumas terminologias possam ser compartilhadas. Leia esta documentação com atenção para evitar que qualquer usuário da sua organização crie objetos que não possam ser excluídos, mesmo pelos administradores do site IBM Cloud.

Esse recurso pode ser usado por qualquer usuário que precise de retenção de dados de longo prazo em seu ambiente, incluindo, mas não se limitando a organizações nas indústrias a seguir:

  • Financeiro
  • Assistência médica
  • Archives de conteúdo de mídia
  • Qualquer um que pretenda evitar modificação ou exclusão privilegiada de objetos ou documentos

As políticas de retenção também podem ser usadas por organizações que lidam com o gerenciamento de registros financeiros, como transações de corretores, e podem precisar armazenar dados em um formato não regravável e não apagável.

O Immutable Object Storage está disponível apenas em determinadas regiões; consulte Serviços integrados para obter detalhes. Ele também requer um plano de precificação Standard. Consulte precificação para obter detalhes.

Não é possível usar o Aspera high-speed transfer com depósitos com uma política de retenção.

Terminologia e uso

Período de retenção

A duração do tempo em que um objeto deve ser armazenado no bucket IBM Cloud Object Storage.

Política de retenção

Uma política de retenção é ativada no nível do bucket IBM Cloud Object Storage. Os períodos mínimo, máximo e padrão de retenção são definidos por essa política e se aplicam a todos os objetos no depósito.

Período mínimo de retenção é a duração mínima de tempo que um objeto deve ser mantido não modificado no depósito.

Período máximo de retenção é a duração máxima de tempo que um objeto pode ser mantido não modificado no depósito.

Se um objeto for armazenado no depósito sem especificar um período de retenção customizado, o período de retenção padrão será usado. O período mínimo de retenção deve ser menor ou igual ao período de retenção padrão, que, por sua vez, deve ser menor ou igual ao período máximo de retenção.

Um período máximo de retenção de 99 anos pode ser especificado para os objetos.

Para criar uma política de retenção em um depósito, é necessária a função de Gerenciador. Consulte Permissões de depósito para obter mais detalhes.

Retenção legal

Determinados objetos podem precisar ser impedidos de modificação após a expiração de um período de retenção. Um exemplo é uma revisão legal incompleta, em que os registros podem precisar ficar acessíveis por uma duração estendida além do período de retenção configurado originalmente. Uma sinalização de retenção legal pode então ser aplicada no nível do objeto.     As retensões legais podem ser aplicadas a objetos durante os uploads iniciais ou após a gravação de um objeto.     Nota: um máximo de 100 retenções legais pode ser aplicado por objeto.

Retenção indefinida

Permite que o usuário configure o objeto para ser armazenado indefinidamente até que um novo período de retenção seja aplicado. Isso é configurado em um nível por objeto.

Um objeto que é retido usando retenção indefinida não é totalmente imutável até que a retenção do objeto tenha sido convertida de -1 para algum valor finito positivo. Embora um objeto gravado com -1 (Indefinite Retention) não possa ser excluído por meio da solicitação DELETE object ou sobrescrito, o objeto ainda pode ter a retenção atualizada de -1 para a data/hora atual, o que tornaria o objeto imediatamente excluído.

Os usuários devem considerar esse comportamento ao avaliar sua viabilidade para suas necessidades de armazenamento. Um caso de uso comum para Retenção Indefinida é descrito em Retenção baseada em evento. Se você quiser usar a retenção baseada em eventos, o Immutable Object Storage permite que os usuários definam a retenção indefinida no objeto se não tiverem certeza das necessidades de retenção quando o objeto for carregado pela primeira vez no sistema. Uma vez definido como indefinido, os aplicativos do usuário podem alterar a retenção do objeto para um valor finito quando um determinado evento ocorrer.

Exemplo Considerando que uma empresa tem uma política de retenção de registros de funcionários por três anos após a saída do funcionário da empresa.

  • Quando um funcionário entra para trabalhar em uma empresa, os registros associados a ele podem ser mantidos indefinidamente.
  • E quando esse mesmo funcionário deixa a empresa, a retenção indefinida é então convertida em um valor finito de três anos a partir do momento atual, que é definido pela política da empresa.

Um aplicativo de usuário ou de terceiros pode mudar o período de retenção de retenção indefinida para finita que usa um SDK ou uma API de REST.

Os proprietários de buckets e os usuários permitidos podem limitar a nova retenção que pode ser configurada para um objeto que está atualmente retido usando a retenção indefinida. Isso é feito utilizando os valores mínimo e máximo permitidos de retenção de caçamba. Ao fazer isso, os usuários podem evitar um caso em que um objeto retido com retenção indefinida tenha sua retenção atualizada para a hora atual, de modo que possa ser excluído imediatamente.

Retenção baseada em evento

O Immutable Object Storage permite que os usuários configurem uma retenção indefinida no objeto caso não tenham certeza da duração final do período de retenção ou queiram usar a retenção baseada em evento. Depois de configurados como indefinidos, os aplicativos de usuário poderão então mudar a retenção do objeto para um valor finito posteriormente. Por exemplo, uma empresa tem uma política de retenção de registros de funcionários por três anos depois que o funcionário sai da empresa. Quando um funcionário se associa à empresa, os registros associados a ele podem ser retidos indefinidamente. Quando o funcionário sai da empresa, a retenção indefinida é convertida em um valor finito de três anos a partir do momento atual, conforme definido pela política da empresa. O objeto é então protegido por três anos após a mudança do período de retenção. Um aplicativo de usuário ou de terceiros pode mudar o período de retenção de retenção indefinida para finita que usa um SDK ou uma API de REST.

Retenção permanente

A retenção permanente garante que os dados não podem ser excluídos, nunca, por qualquer pessoa Leia a documentação cuidadosamente e não use retenção permanente, a menos que haja uma necessidade de regulamentação ou conformidade convincente para armazenamento de dados permanente.

A retenção permanente só pode ser ativada em um nível de bucket IBM Cloud Object Storage com a política de retenção ativada e os usuários podem selecionar a opção de período de retenção permanente durante os uploads de objetos. Depois de ativado, esse processo não pode ser revertido e os objetos transferidos por upload que usam um período de retenção permanente não podem ser excluídos. É responsabilidade dos usuários validar, no final, se há uma necessidade legítima de armazenar objetos permanentemente usando Object Storage buckets com uma política de retenção.

Ao usar o Immutable Object Storage, você é responsável por assegurar que sua Conta do IBM Cloud seja mantida em boas condições por políticas e diretrizes do IBM Cloud, desde que os dados estejam sujeitos a uma política de retenção. Consulte os termos do IBM Cloud Service para obter mais informações.

Immutable Object Storage e considerações para várias regulamentações

Ao usar o Immutable Object Storage, é responsabilidade do cliente verificar e assegurar se alguma das capacidades de recurso discutidas pode ser usada para satisfazer e obedecer às principais regras sobre armazenamento e retenção de registros eletrônicos geralmente governados por:

Para ajudar os clientes a tomar decisões baseadas em informações, a IBM contratou a Cohasset Associates Inc. para realizar uma avaliação independente do Immutable Object Storage da IBM. Analise o relatório da Cohasset Associates Inc. que fornece detalhes sobre a avaliação do recurso Immutable Object Storage do site IBM Cloud Object Storage.

Auditoria de acesso e transações

Os dados do log de acesso para o Immutable Object Storage para revisar as mudanças nos parâmetros de retenção, no período de retenção do objeto e no aplicativo de retenções legais estão disponíveis em uma base caso a caso, abrindo um chamado de atendimento ao cliente.

Usando o console

As políticas de retenção podem ser incluídas em depósitos vazios novos ou existentes e não podem ser removidas. Para um novo depósito, assegure-se de que o esteja criando em uma região suportada e, em seguida, escolha a opção Incluir política de retenção. Para um depósito existente, assegure-se de que ele não tenha objetos e, em seguida, navegue para as definições de configuração e clique no botão Criar política abaixo da seção de política de retenção do depósito. Em qualquer um dos casos, configure os períodos mínimo, máximo e padrão de retenção.

Usando a API de REST, as bibliotecas e os SDKs

Várias novas APIs foram introduzidas nos SDKs do IBM Cloud Object Storage para oferecer suporte a aplicativos que trabalham com políticas de retenção. Selecione um idioma ( HTTP, Java, JavaScript, ou Python ) no início desta página para visualizar exemplos que usam o SDK Object Storage apropriado.

Todos os exemplos de código presumem a existência de um objeto do cliente chamado cos que pode chamar os diferentes métodos. Para obter detalhes sobre como criar clientes, consulte os guias de SDK específicos.

Todos os valores de data usados para configurar períodos de retenção representam a Hora de Greenwich. Um cabeçalho Content-MD5 ou um cabeçalho checksum (incluindo x-amz-checksum-crc32, x-amz-checksum-crc32c, x-amz-checksum-crc64nvme, x-amz-checksum-sha1 ou x-amz-checksum-sha256) é necessário para garantir a integridade dos dados. Observe que um valor de hash ou soma de verificação é enviado automaticamente ao usar um SDK.

Incluir uma política de retenção em um depósito existente

Essa implementação da operação PUT usa o parâmetro de consulta protection para configurar os parâmetros de retenção para um depósito existente. Essa operação permite configurar ou mudar os períodos mínimo, padrão e máximo de retenção. Essa operação também permite mudar o estado de proteção do depósito.

Os objetos gravados em um depósito protegido não podem ser excluídos até que o período de proteção tenha expirado e todas as retenções legais no objeto sejam removidas. O valor de retenção padrão do depósito é fornecido para um objeto, a menos que um valor específico do objeto seja fornecido quando o objeto é criado. Os objetos em depósitos protegidos que não estão mais sob retenção (o período de retenção expirou e o objeto não tem nenhuma retenção legal), quando sobrescritos, ficarão novamente sob retenção. O novo período de retenção pode ser fornecido como parte da solicitação de sobrescrição do objeto ou o tempo de retenção padrão do depósito será fornecido para o objeto.

Os valores mínimo e máximo suportados para as configurações de período de retenção MinimumRetention, DefaultRetention e MaximumRetention são um mínimo de 0 dias e um máximo de 36135 dias (99 anos).

É necessário um cabeçalho Content-MD5 ou um cabeçalho checksum (incluindo x-amz-checksum-crc32, x-amz-checksum-crc32c,x-amz-checksum-crc64nvme, x-amz-checksum-sha1 ou x-amz-checksum-sha256). Essa operação não usa parâmetros de consulta extras.

Para obter mais informações sobre terminais, consulte Terminais e locais de armazenamento

Sintaxe

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

Exemplo de solicitação

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>

Exemplo de resposta

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);
}

Verificar a política de retenção em um depósito

Essa implementação de uma operação GET busca os parâmetros de retenção para um depósito existente.

Sintaxe

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

Exemplo de solicitação

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

Exemplo de resposta

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>

Se não houver configuração de proteção no depósito, o servidor responderá com status desativado no lugar.

<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());
    }
}

Fazer upload de um objeto em um depósito com política de retenção

Esse aprimoramento da operação PUT inclui três novos cabeçalhos de solicitação: dois para especificar o período de retenção de diferentes formas e um para incluir uma única retenção legal no novo objeto. Novos erros são definidos para valores ilegais para os novos cabeçalhos e, se um objeto estiver sob retenção, quaisquer sobrescrições falharão.

Os objetos em depósitos com política de retenção que não estão mais sob retenção (o período de retenção expirou e o objeto não tem nenhuma retenção legal), quando sobrescritos, ficarão novamente sob retenção. O novo período de retenção pode ser fornecido como parte da solicitação de sobrescrição do objeto ou o tempo de retenção padrão do depósito será fornecido para o objeto.

Um cabeçalho Content-MD5 ou um cabeçalho checksum (incluindo x-amz-checksum-crc32, x-amz-checksum-crc32c, x-amz-checksum-crc64nvme, x-amz-checksum-sha1 ou x-amz-checksum-sha256) é necessário como uma verificação de integridade para a carga útil de qualquer tipo de solicitação de upload de objeto em um bucket com uma política de retenção.

Valor Tipo Descrição
Retention-Period Número inteiro não negativo (segundos) O período de retenção para armazenar o objeto em segundos. O objeto não pode ser sobrescrito nem excluído até que o período de tempo especificado no período de retenção tenha decorrido. Se esse campo e Retention-Expiration-Date forem especificados, um erro 400 será retornado. Se nenhum for especificado, o período DefaultRetention do depósito será usado. Zero (0) é um valor legal que supõe que o período mínimo de retenção do depósito também é 0.
Retention-expiration-date Data (formato ISO 8601) A data em que é legal excluir ou modificar o objeto. É possível especificar somente isso ou o cabeçalho Retention-Period. Se ambos forem especificados, um erro 400 será retornado. Se nenhum for especificado, o período DefaultRetention do depósito será usado. O formato ISO 8601 suportado é [YYYY]-[MM]-[DD]T[hh]:[mm]:[ss]Z ou [YYYY][MM][DD]T[hh][mm][ss]Z (por exemplo, 2020-11-28T03:10:01Z ou 20201128T031001Z são válidos).
Retention-legal-hold-id Sequência Uma única retenção legal para aplicar ao objeto. Uma retenção legal é uma sequência longa de caracteres Y. O objeto não pode ser sobrescrito nem excluído até que todas as retenções legais associadas ao objeto sejam removidas.
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);
}

Ampliar o período de retenção de um objeto

Essa implementação da operação POST usa o parâmetro de consulta extendRetention para ampliar o período de retenção de um objeto protegido em um depósito protegido.

O período de retenção de um objeto pode somente ser ampliado. Ele não pode ser diminuído do valor configurado atualmente.

O valor de expansão de retenção é configurado de uma de três maneiras:

  • tempo adicional do valor atual (Additional-Retention-Period ou método semelhante)
  • novo período de extensão em segundos (Extend-Retention-From-Current-Time ou método semelhante)
  • nova data de validade de retenção do objeto (New-Retention-Expiration-Date ou método semelhante)

O período de retenção atual armazenado nos metadados do objeto é aumentado pelo tempo extra especificado ou substituído pelo novo valor, dependendo do parâmetro configurado na solicitação extendRetention. Em todos os casos, o parâmetro de ampliação de retenção é verificado com relação ao período de retenção atual e o parâmetro ampliado será aceito somente se o período de retenção atualizado for maior que o período de retenção atual.

O formato ISO 8601 suportado para New-Retention-Expiration-Date é [YYYY]-[MM]-[DD]T[hh]:[mm]:[ss]Z ou [YYYY][MM][DD]T[hh][mm][ss]Z (por exemplo, 2020-11-28T03:10:01Z ou 20201128T031001Z são válidos).

Os objetos em depósitos protegidos que não estão mais sob retenção (o período de retenção expirou e o objeto não tem nenhuma retenção legal), quando sobrescritos, ficarão novamente sob retenção. O novo período de retenção pode ser fornecido como parte da solicitação de sobrescrição do objeto ou o tempo de retenção padrão do depósito será fornecido para o objeto.

Sintaxe

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

Exemplo de solicitação

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

Exemplo de resposta

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);
}

Listar retenções legais em um objeto

Essa implementação da operação GET usa o parâmetro de consulta legalHold para retornar a lista de retenções legais em um objeto e estado de retenção relacionado em um corpo de resposta XML.

Essa operação retorna:

  • Data de criação do objeto
  • Período de retenção do objeto em segundos
  • Data de expiração de retenção calculada com base no período e data de criação
  • Lista de retenções legais
  • Identificador de retenção legal
  • Registro de data e hora em que a retenção legal foi aplicada

Se não houver retenções legais no objeto, um LegalHoldSet vazio será retornado. Se não houver nenhum período de retenção especificado no objeto, um erro 404 será retornado.

Sintaxe

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

Exemplo de solicitação

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

Exemplo de resposta

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);
    }
}