Como acessar chaves de buckets com pontos (.) Em seus nomes usando boto3?

Contexto

Estou tentando obter um status de criptografia para todos os meus buckets para um relatório de segurança. No entanto, como a criptografia é baseada no nível da chave, desejo percorrer todas as chaves e obter um status geral de criptografia. Por exemplo, "yes" é que todas as chaves são criptografadas, "no" se nenhuma for criptografada e "parcialmente" é que algumas são criptografadas.
Devo usar o boto3 porque há um problema conhecido no boto em que o status de criptografia de cada chave sempre retorna Nenhum.Veja aqui.

Problema

Estou tentando iterar sobre todas as chaves em cada um dos meus baldes usando boto3. O código a seguir funciona bem até ser executado em buckets com nomes que contêm pontos, como "my.test.bucket".

from boto3.session import Session

session = Session(aws_access_key_id=<ACCESS_KEY>,
                  aws_secret_access_key=<SECRET_KEY>,
                  aws_session_token=<TOKEN>)
s3_resource = session.resource('s3')

for bucket in s3_resource.buckets.all():
    for obj in bucket.objects.all():
        key = s3_resource.Object(bucket.name, obj.key)
        # Do some stuff with the key...

Quando atinge um intervalo com um ponto no nome, lança essa exceção quandobucket.objects.all() é chamado, me dizendo para enviar todas as solicitações para um endpoint específico. Esse terminal pode ser encontrado no objeto de exceção lançado.

for obj in bucket.objects.all():
File "/usr/local/lib/python2.7/site-packages/boto3/resources/collection.py", line 82, in __iter__
for page in self.pages():
File "/usr/local/lib/python2.7/site-packages/boto3/resources/collection.py", line 165, in pages
for page in pages:
File "/usr/lib/python2.7/dist-packages/botocore/paginate.py", line 85, in __iter__
response = self._make_request(current_kwargs)
File "/usr/lib/python2.7/dist-packages/botocore/paginate.py", line 157, in _make_request
return self._method(**current_kwargs)
File "/usr/lib/python2.7/dist-packages/botocore/client.py", line 310, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/usr/lib/python2.7/dist-packages/botocore/client.py", line 395, in _make_api_call
raise ClientError(parsed_response, operation_name)botocore.exceptions.ClientError: An error occurred (PermanentRedirect) when calling the ListObjects operation: The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.
Coisas que tenteiConfigurando o parâmetro endpoint_url para o nó de extremidade do bucket especificado na resposta de exceção, comos3_resource = session.resource('s3', endpoint_url='my.test.bucket.s3.amazonaws.com')Especificando a região em que o bucket está localizados3_resource = session.resource('s3', region_name='eu-west-1')

Eu acredito que o problema é semelhante aoesta questão stackoverflow no boto, que corrige o problema, definindo o parâmetro call_format no construtor s3Connection. Infelizmente, não posso usar o boto (veja acima).

Atualizar

Aqui está o que acabou funcionando para mim. Não é a abordagem mais elegante, mas funciona =).

from boto3.session import Session

session = Session(aws_access_key_id=<ACCESS_KEY>,
                  aws_secret_access_key=<SECRET_KEY>,
                  aws_session_token=<TOKEN>)
s3_resource = session.resource('s3')

# First get all the bucket names
bucket_names = [bucket.name for bucket in s3_resource.buckets.all()]


for bucket_name in bucket_names:
    # Check each name for a "." and use a different resource if needed
    if "." in bucket_name:
        region = session.client('s3').get_bucket_location(Bucket=bucket_name)['LocationConstraint']
        resource = session.resource('s3', region_name=region)
    else:
        resource = s3_resource
    bucket = resource.Bucket(bucket_name)

    # Continue as usual using this resource
    for obj in bucket.objects.all():
        key = resource.Object(bucket.name, obj.key)
        # Do some stuff with the key...

questionAnswers(2)

yourAnswerToTheQuestion