Utilización de Object Storage inmutable para proteger grupos
El Almacenamiento de objetos inmutables conserva registros electrónicos y mantiene la integridad de los datos. Las políticas de retención garantizan que los datos se almacenan como WORM (Write-Once-Read-Read-Many) y que no se pueden borrar ni sobrescribir. Esa política se impone hasta que finaliza el periodo de retención y se elimina cualquier retención legal.
Esta función no está disponible actualmente en Object Storage para Satellite. Más información.
Las políticas se aplican hasta el final de un periodo de retención y no se pueden modificar hasta que el periodo de retención haya caducado. Mientras que IBM Cloud Object Storage hace uso de la API S3 para la mayoría de las operaciones, la API utilizada para configurar las políticas de retención no es la misma que la API S3, aunque puede compartir cierta terminología. Lea atentamente esta documentación para evitar que cualquier usuario de su organización cree objetos que no puedan ser eliminados, incluso por los administradores de IBM Cloud.
Puede utilizar esta característica cualquier usuario que tenga que conservar datos a largo plazo en su entorno, incluidas, aunque sin limitarse a las mismas, organizaciones de los siguientes sectores:
- Financiero
- Asistencia médica
- Archivos de contenido multimedia
- Cualquiera que desee impedir la modificación o supresión con privilegios de objetos o documentos
También pueden utilizar las políticas de retención las organizaciones que se ocupan de la gestión de registros financieros, como transacciones de agentes de bolsa, que pueden tener necesidad de almacenar datos en un formato que no se pueda rescribir ni eliminar.
Immutable Object Storage solo está disponible en determinadas regiones. Consulte Servicios integrados para obtener más información. También requiere un plan de precios Estándar. Consulte el tema sobre precios para obtener detalles.
No se puede utilizar la transferencia de alta velocidad de Aspera con grupos con una política de retención.
Terminología y uso
Periodo de retención
El tiempo que un objeto debe estar almacenado en el cubo IBM Cloud Object Storage.
Política de retención
Se activa una política de retención en el nivel de cubo IBM Cloud Object Storage. Esta política define el periodo de retención mínimo, máximo y predeterminado y se aplica a todos los objetos del grupo.
El periodo de retención mínimo es la duración mínima del tiempo que un objeto debe conservarse sin modificar en el grupo.
El periodo de retención máximo es la duración máxima del tiempo que un objeto se puede conservar sin modificar en el grupo.
Si un objeto se almacena en el grupo sin especificar un periodo de retención personalizado, se utiliza el periodo de retención predeterminado. El periodo de retención mínimo debe ser menor o igual que el periodo de retención predeterminado, que a su vez debe ser menor o igual que el periodo de retención máximo.
Se puede especificar un periodo máximo de conservación de 99 años para los objetos.
Para crear una política de retención sobre un grupo, necesita el rol de Gestor. Consulte el tema sobre Permisos de grupo para obtener más detalles.
Retención legal
Es posible que sea necesario evitar la modificación de determinados objetos una vez transcurrido el periodo de retención. Un ejemplo es una revisión legal incompleta, en la que es posible que sea necesario acceder a los registros más allá del periodo de retención establecido originalmente. Se puede aplicar un distintivo de retención legal a nivel de objeto. Las retenciones legales se pueden aplicar a los objetos durante las cargas iniciales o después de que se escriba un objeto. Nota: se puede aplicar un máximo de 100 retenciones legales por objeto.
Retención indefinida
Permite al usuario definir que el objeto que almacene de forma indefinida hasta que se aplique un nuevo periodo de retención. Esta característica se define objeto a objeto.
Un objeto que se retiene utilizando retención indefinida no es completamente inmutable hasta que la retención del objeto se haya convertido de -1 a algún valor finito positivo. Mientras que un objeto escrito con -1 (Retención Indefinida) no
puede ser borrado utilizando la petición DELETE object o sobrescrito, el objeto puede tener la retención actualizada de -1 a la fecha/hora actual, lo que haría que el objeto pudiera ser borrado inmediatamente.
Los usuarios deben tener en cuenta este comportamiento a la hora de evaluar su viabilidad para sus necesidades de almacenamiento. Un caso de uso común para la Retención Indefinida se describe en Retención basada en eventos. En o desea utilizar la retención basada en eventos, Inmutable Object Storage permite a los usuarios establecer una retención indefinida en el objeto si no están seguros de las necesidades de retención cuando el objeto se carga por primera vez en el sistema. Una vez configurado como indefinido, las aplicaciones de usuario pueden cambiar la retención del objeto a un valor finito cuando se haya producido un determinado evento.
Ejemplo Dado que una empresa tiene la política de conservar los expedientes de los empleados durante tres años después de que el empleado abandone la empresa.
- Cuando un empleado se incorpora para empezar a trabajar en una empresa, los registros asociados a ese empleado pueden conservarse indefinidamente.
- Y cuando ese mismo empleado deja la empresa, la retención indefinida se convierte entonces en un valor finito de tres años a partir del momento actual, definido por la política de la empresa.
Una aplicación de usuario o de un tercero puede cambiar el periodo de retención indefinido por un valor finito mediante un SDK o una API REST.
Los propietarios de cubos y los usuarios autorizados pueden limitar la nueva retención que se puede configurar para un objeto que actualmente se retiene utilizando la retención indefinida. Para ello se utilizan los valores mínimo y máximo de retención de cubos permitidos. De este modo, los usuarios pueden evitar que un objeto retenido con retención indefinida tenga su retención actualizada a la hora actual, de modo que sea inmediatamente borrable.
Retención basada en suceso
Immutable Object Storage permite al usuario definir una retención indefinida sobre el objeto si no está seguro de la duración final del periodo de retención o si desea utilizar la función de retención basada en suceso. Una vez definida la retención indefinida, las aplicaciones de usuario pueden cambiar la retención del objeto por un valor finito más adelante. Por ejemplo, supongamos que una empresa tiene una política de retención de registros de empleados de tres años después de que el empleado abandone la empresa. Cuando un empleado comienza a trabajar en la empresa, los registros asociados a dicho empleado se pueden retener de forma indefinida. Cuando el empleado abandona la empresa, la retención indefinida se convierte en un valor finito de tres años a partir de la fecha actual, tal como define la política de la empresa. Luego el objeto queda protegido durante tres años a partir del momento del cambio de periodo de retención. Una aplicación de usuario o de un tercero puede cambiar el periodo de retención indefinido por un valor finito mediante un SDK o una API REST.
Retención permanente
La retención permanente asegura que los datos no pueden ser eliminados, nunca, por nadie. Lea la documentación detenidamente y no utilice la retención permanente a menos que haya una necesidad normativa o de conformidad convincente para el almacenamiento de datos permanente.
La retención permanente sólo puede activarse a nivel de cubo de IBM Cloud Object Storage con la política de retención activada y los usuarios pueden seleccionar la opción de periodo de retención permanente durante la carga de objetos. Una vez habilitado, este proceso no se puede revertir y los objetos que se cargan con un periodo de retención permanente no se pueden suprimir. Es responsabilidad de los usuarios validar en su extremo si existe una necesidad legítima de almacenar objetos de forma permanente mediante el uso de cubos Object Storage con una política de retención.
Cuando se utiliza Immutable Object Storage, el usuario es el responsable de garantizar que la cuenta de IBM Cloud resulta adecuada para las políticas y directrices de IBM Cloud durante el periodo en que los datos están sujetos a una política de retención. Consulte los términos del servicio IBM Cloud para obtener más información.
Immutable Object Storage y consideraciones sobre diversos reglamentos
Cuando se utiliza Immutable Object Storage, es responsabilidad del cliente comprobar y garantizar si alguna de las funciones de la característica se puede utilizar para cumplir con las reglas de claves relacionadas con el almacenamiento de registros electrónico y la retención, que se suelen regir por:
- Securities and Exchange Commission(SEC)Rule 17a-4(f),
- Financial Industry Regulatory Authority(FINRA)Rule 4511(c), y
- Regla de CFTC(Commodity Futures Trading Commission)1.31(c)-(d)
Para ayudar a los clientes a tomar decisiones informadas, IBM se ha asociado a Cohasset Associates Inc. para realizar una evaluación independiente de Immutable Object Storage de IBM. Revise el informe de Cohasset Associates Inc. que proporciona detalles sobre la evaluación de la función Inmutable Object Storage de IBM Cloud Object Storage.
Auditoría del acceso y de las transacciones
Acceda a los datos de registro correspondientes a Immutable Object Storage para revisar si los cambios en los parámetros de retención, el periodo de retención de objetos y la aplicación de retenciones legales está disponible, caso por caso, abriendo una incidencia de servicio al cliente.
Utilización de la consola
Las políticas de retención se pueden añadir a grupos vacíos nuevos o existentes, y no se pueden eliminar. En el caso de un grupo nuevo, asegúrese de que crea el grupo en una región admitida y luego seleccione la opción Añadir política de retención. En el caso de un grupo existente, asegúrese de que no tiene ningún objeto y luego vaya a los valores de configuración y pulse el botón Crear política que hay bajo la sección de política de retención de grupo. En cualquiera de los casos, establezca periodos de retención mínimo, máximo y predeterminado.
Utilización de API REST, bibliotecas y SDK
Se han introducido varias API nuevas en los SDK de IBM Cloud Object Storage para dar soporte a las aplicaciones que trabajan con políticas de retención. Seleccione un idioma ( HTTP, Java, JavaScript, o Python ) al principio de esta página para ver los ejemplos que utilizan el SDK Object Storage correspondiente.
En todos los ejemplos de código se da por supuesto que existe un objeto de cliente llamado cos que puede llamar a los distintos métodos. Para ver información sobre cómo crear clientes, consulte las guías de SDK específicas.
Todos los valores de fecha utilizados para establecer periodos de retención están en GMT (Greenwich Mean Time). Se requiere un encabezado Content-MD5 o un encabezado checksum (incluyendo x-amz-checksum-crc32,
x-amz-checksum-crc32c, x-amz-checksum-crc64nvme, x-amz-checksum-sha1, o x-amz-checksum-sha256) para garantizar la integridad de los datos. Tenga en cuenta que se envía automáticamente un
valor hash o de suma de comprobación cuando se utiliza un SDK.
Adición de una política de retención en un grupo existente
Esta implementación de la operación PUT utiliza el parámetro de consulta protection para definir los parámetros de retención para un grupo existente. Esta operación le permite establecer o cambiar el periodo de retención
mínimo, predeterminado y máximo. Esta operación también le permite cambiar el estado de protección del grupo.
Los objetos que se escriben en un grupo protegido no se pueden suprimir hasta que transcurre el periodo de protección y se eliminan todas las retenciones legales sobre el objeto. Se proporciona el valor de retención predeterminado del grupo a un objeto a menos que se proporcione un valor específico de objeto cuando se crea el objeto. Los objetos de grupos protegidos que ya no están bajo retención (el periodo de retención ha caducado y el objeto no tiene retenciones legales) vuelven a estar bajo retención cuando se sobrescriben. El nuevo periodo de retención se puede proporcionar como parte de la solicitud de sobrescritura del objeto o se asigna el tiempo de retención predeterminado del grupo al objeto.
Los valores mínimo y máximo admitidos para los ajustes del periodo de conservación MinimumRetention, DefaultRetention, y MaximumRetention son un mínimo de 0 días y un máximo de 36135 días (99 años).
Se requiere un encabezado Content-MD5 o un encabezado checksum (incluyendo x-amz-checksum-crc32, x-amz-checksum-crc32c,x-amz-checksum-crc64nvme, x-amz-checksum-sha1,
o x-amz-checksum-sha256). Esta operación no utiliza ningún parámetro de consulta adicional.
Para obtener más información sobre puntos finales, consulte Puntos finales y ubicaciones de almacenamiento
Sintaxis
PUT https://{endpoint}/{bucket-name}?protection= # path style
PUT https://{bucket-name}.{endpoint}?protection= # virtual host style
Solicitud de ejemplo
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>
Respuesta de ejemplo
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);
}
Comprobación de la política de retención en un grupo
Esta implementación de una operación GET capta los parámetros de retención de un grupo existente.
Sintaxis
GET https://{endpoint}/{bucket-name}?protection= # path style
GET https://{bucket-name}.{endpoint}?protection= # virtual host style
Solicitud de ejemplo
GET /example-bucket?protection= HTTP/1.1
Authorization: {authorization-string}
x-amz-date: 20181011T190354Z
Content-Type: text/plain
Host: 67.228.254.193
Respuesta de ejemplo
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 no hay ninguna configuración de protección en el grupo, el servidor responde en su lugar con el estado inhabilitado.
<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());
}
}
Carga de un objeto a un grupo con una política de retención
Esta mejora de la operación PUT añade tres nuevas cabeceras de solicitud: dos para especificar el periodo de retención de diferentes maneras, y una para añadir una única retención legal al nuevo objeto. Se definen nuevos errores
para los valores no permitidos para las nuevas cabeceras y, si un objeto está bajo retención, cualquier operación de sobrescritura fallará.
Los objetos de grupos con una política de retención que ya no están bajo retención (el periodo de retención ha caducado y el objeto no tiene retenciones legales) vuelven a estar bajo retención cuando se sobrescriben. El nuevo periodo de retención se puede proporcionar como parte de la solicitud de sobrescritura del objeto o se asigna el tiempo de retención predeterminado del grupo al objeto.
Se requiere un encabezado Content-MD5 o un encabezado checksum (incluidos x-amz-checksum-crc32, x-amz-checksum-crc32c, x-amz-checksum-crc64nvme, x-amz-checksum-sha1 o x-amz-checksum-sha256) como comprobación de integridad de la carga útil para cualquier tipo de solicitud de carga de objetos contra un bucket con una política de retención.
| Valor | Tipo | Descripción |
|---|---|---|
Retention-Period |
Entero no negativo (segundos) | Periodo de retención para almacenar el objeto en segundos. El objeto no se puede sobrescribir ni suprimir hasta que transcurre el periodo de tiempo especificado en el período de retención. Si se especifica este campo y Retention-Expiration-Date,
se devuelve el error 400. Si no se especifica ninguno de los dos, se utiliza el periodo DefaultRetention del grupo. Cero (0) es un valor válido, siempre y cuando el periodo mínimo de retención
del grupo también sea 0. |
Retention-expiration-date |
Fecha (formato ISO 8601) | Fecha en la que se puede suprimir o modificar el objeto. Solo puede especificar esta cabecera o la cabecera Retention-Period. Si se especifican ambas, se devuelve el error 400. Si no se especifica ninguno de los dos, se
utiliza el periodo DefaultRetention del grupo. El formato ISO 8601 soportado es [YYYY]-[MM]-[DD]T[hh]:[mm]:[ss]Z o [YYYY][MM][DD]T[hh][mm][ss]Z (por ejemplo, 2020-11-28T03:10:01Z o 20201128T031001Z son válidos). |
Retention-legal-hold-id |
Serie | Una sola retención legal que se aplicará al objeto. Una retención legal es una serie larga de caracteres Y. El objeto no se puede sobrescribir ni suprimir hasta que se eliminen todas las retenciones legales asociadas con el objeto. |
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);
}
Adición de una retención legal a un objeto o eliminación de una retención legal del mismo
Esta implementación de la operación POST utiliza el parámetro de consulta legalHold y los parámetros de consulta add y remove para añadir o eliminar una única retención legal de un objeto
protegido de un grupo protegido.
El objeto da soporte a 100 retenciones legales:
- Un identificador de retención legal es una serie de caracteres con una longitud máxima de 64 caracteres y una longitud mínima de un carácter. Los caracteres válidos son letras, números,
!,_,.,*,(,),-, y'. - Si la adición de la retención legal especificada supera las 100 retenciones legales en total del objeto, la nueva retención legal no se añade y se devuelve el error
400. - Si un identificador es demasiado largo, no se añade al objeto y se devuelve el error
400. - Si un identificador contiene caracteres no válidos, no se añade al objeto y se devuelve el error
400. - Si un identificador ya se está utilizando sobre un objeto, la retención legal existente no se modifica y la respuesta indica que el identificador ya se está utilizando con el error
409. - Si un objeto no tiene metadatos de periodo de retención, se devuelve el error
400y no se permite añadir ni eliminar una retención legal.
Es necesario que haya una cabecera de periodo de retención; de lo contrario, se devuelve el error 400.
Sintaxis
POST https://{endpoint}/{bucket-name}/{object-name}?legalHold # path style
POST https://{bucket-name}.{endpoint}/{object-name}?legalHold= # virtual host style
Solicitud de ejemplo
POST /BucketName/ObjectName?legalHold&add=legalHoldID HTTP/1.1
Host: myBucket.mydsNet.corp.com
Date: Fri, 8 Dec 2018 17:50:00 GMT
Authorization: authorization string
Content-Type: text/plain
Respuesta de ejemplo
HTTP/1.1 200 OK
Date: Fri, 8 Dec 2018 17:51:00 GMT
Connection: close
def add_legal_hold_to_object(bucket_name, object_name, legal_hold_id):
print("Adding legal hold {0} to object {1} in bucket {2}\n".format(legal_hold_id, object_name, bucket_name))
cos.add_legal_hold(
Bucket=bucket_name,
Key=object_name,
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 delete_legal_hold_from_object(bucket_name, object_name, legal_hold_id):
print("Deleting legal hold {0} from object {1} in bucket {2}\n".format(legal_hold_id, object_name, bucket_name))
cos.delete_legal_hold(
Bucket=bucket_name,
Key=object_name,
RetentionLegalHoldId=legal_hold_id
)
print("Legal hold {0} deleted from object {1} in bucket {2}!\n".format(legal_hold_id, object_name, bucket_name))
function addLegalHoldToObject(bucketName, objectName, legalHoldId) {
console.log(`Adding legal hold ${legalHoldId} to object ${objectName} in bucket ${bucketName}`);
return cos.client.addLegalHold({
Bucket: bucketName,
Key: objectId,
RetentionLegalHoldId: legalHoldId
}).promise()
.then(() => {
console.log(`Legal hold ${legalHoldId} added to object ${objectName} in bucket ${bucketName}!`);
})
.catch((e) => {
console.log(`ERROR: ${e.code} - ${e.message}\n`);
});
}
function deleteLegalHoldFromObject(bucketName, objectName, legalHoldId) {
console.log(`Deleting legal hold ${legalHoldId} from object ${objectName} in bucket ${bucketName}`);
return cos.client.deleteLegalHold({
Bucket: bucketName,
Key: objectId,
RetentionLegalHoldId: legalHoldId
}).promise()
.then(() => {
console.log(`Legal hold ${legalHoldId} deleted from object ${objectName} in bucket ${bucketName}!`);
})
.catch((e) => {
console.log(`ERROR: ${e.code} - ${e.message}\n`);
});
}
public static void addLegalHoldToObject(String bucketName, String objectName, String legalHoldId) {
System.out.printf("Adding legal hold %s to object %s in bucket %s\n", legalHoldId, objectName, bucketName);
cos.addLegalHold(
bucketName,
objectName,
legalHoldId
);
System.out.printf("Legal hold %s added to object %s in bucket %s!\n", legalHoldId, objectName, bucketName);
}
public static void deleteLegalHoldFromObject(String bucketName, String objectName, String legalHoldId) {
System.out.printf("Deleting legal hold %s from object %s in bucket %s\n", legalHoldId, objectName, bucketName);
cos.deleteLegalHold(
bucketName,
objectName,
legalHoldId
);
System.out.printf("Legal hold %s deleted from object %s in bucket %s!\n", legalHoldId, objectName, bucketName);
}
Ampliación del periodo de retención de un objeto
Esta implementación de la operación POST utiliza el parámetro de consulta extendRetention para ampliar el periodo de retención de un objeto protegido en un grupo protegido.
El periodo de retención de un objeto solo se puede ampliar. No se puede reducir con respecto al valor configurado actualmente.
El valor de ampliación de retención se establece de una de las tres maneras siguientes:
- tiempo adicional a partir del valor actual (
Additional-Retention-Periodo un método similar) - nuevo periodo de ampliación en segundos (
Extend-Retention-From-Current-Timeo un método similar) - nueva fecha de caducidad de retención del objeto (
New-Retention-Expiration-Dateo método similar)
El periodo de retención actual almacenado en los metadatos de objeto se incrementa en el tiempo adicional especificado o bien se sustituye por el nuevo valor, en función del parámetro establecido en la solicitud extendRetention.
En cualquiera de los casos, el parámetro de retención de ampliación se comprueba con respecto al periodo de retención actual y el parámetro ampliado solo se acepta si el periodo de retención actualizado es mayor que el periodo de retención
actual.
El formato ISO 8601 soportado para New-Retention-Expiration-Date es [YYYY]-[MM]-[DD]T[hh]:[mm]:[ss]Z o [YYYY][MM][DD]T[hh][mm][ss]Z (por ejemplo, 2020-11-28T03:10:01Z o 20201128T031001Z son válidos).
Los objetos de grupos protegidos que ya no están bajo retención (el periodo de retención ha caducado y el objeto no tiene retenciones legales) vuelven a estar bajo retención cuando se sobrescriben. El nuevo periodo de retención se puede proporcionar como parte de la solicitud de sobrescritura del objeto o se asigna el tiempo de retención predeterminado del grupo al objeto.
Sintaxis
POST https://{endpoint}/{bucket-name}/{object-name}?extendRetention= # path style
POST https://{bucket-name}.{endpoint}/{object-name}?extendRetention= # virtual host style
Solicitud de ejemplo
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
Respuesta de ejemplo
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);
}
Obtención de una lista de las retenciones legales sobre un objeto
Esta implementación de la operación GET utiliza el parámetro de consulta legalHold para devolver la lista de retenciones legales sobre un objeto y el estado de retención relacionado en el cuerpo de una respuesta XML.
Esta operación devuelve:
- Fecha de creación del objeto
- Periodo de retención del objeto en segundos
- Fecha de caducidad de retención calculada en función del periodo y de la fecha de creación
- Lista de retenciones legales
- Identificador de retención legal
- Indicación de fecha y hora en que se ha aplicado la retención legal
Si no hay ninguna retención legal sobre el objeto, se devuelve un LegalHoldSet vacío. Si no se ha especificado ningún periodo de retención sobre el objeto, se devuelve el error 404.
Sintaxis
GET https://{endpoint}/{bucket-name}/{object-name}?legalHold= # path style
GET https://{bucket-name}.{endpoint}/{object-name}?legalHold= # virtual host style
Solicitud de ejemplo
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
Respuesta de ejemplo
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);
}
}