Posted in

OpenShift S3 (NooBa) – Implementing Secure, Short-Lived S3 Access in ODF 4.21

The Challenge

A common requirement for modern cloud applications is the ability to securely share private files (like reports or generated artifacts) with external systems or users without making the entire storage bucket public or sharing long-term credentials.

The Solution: ODF S3 Presigned URLs

Red Hat OpenShift Data Foundation provides a robust, S3-compatible API that supports presigned URLs. This allows an application to generate a temporary link (using standard S3 SDKs like Boto3) that grants time-limited access to a specific object.

Reference to AWS S3 documentation: https://docs.aws.amazon.com/boto3/latest/reference/services/s3/client/generate_presigned_url.html

Architecture Overview

ODF handles these requests through a multi-layered operator system:

  • Multicloud Object Gateway (MCG): Powered by the mcg-operator, this provides the S3 API endpoint.
  • Short-lived URLs: The MCG Object Browser includes a built-in feature specifically for generating presigned URLs.
  • NooBaa Endpoint: These requests are processed by the noobaa-endpoint pods, which provide the S3-compatible API layer for your storage.
  • Networking & Routes: The s3 route in the openshift-storage namespace serves as the external gateway for API calls.
  • Scalability: The system uses a Horizontal Pod Autoscaler (HPA) for MCG endpoints, ensuring that when your API generates high volumes of traffic for these URLs, the storage layer scales to meet the demand.

How to Implement (Python Example)

To generate these URLs from your own API or script, you point a standard S3 client at your ODF Route.

import boto3
from botocore.config import Config
from botocore.exceptions import ClientError

# Configuration - Replace with your actual credentials
S3_ENDPOINT = "https://s3-openshift-storage.apps.<fqdn>"
ACCESS_KEY = "XXX"
SECRET_KEY = "XXX"
BUCKET_NAME = "test-objectbucketclaim
OBJECT_NAME = "ocp-sno/clusterpolicy-1.yml"


def create_presigned_url(bucket_name, object_name, expiration=3600):
    """Generate a presigned URL to share an S3 object"""
    
    # Initialize the S3 client with your ODF endpoint
    s3_client = boto3.client(
        's3',
        endpoint_url=S3_ENDPOINT,
        aws_access_key_id=ACCESS_KEY,
        aws_secret_access_key=SECRET_KEY,
        # ODF often uses path-style addressing depending on configuration
        config=Config(s3={'addressing_style': 'path'}),
        verify=False # Set to True if you have valid CA certificates configured
    )

    try:
        response = s3_client.generate_presigned_url(
            'get_object',
            Params={'Bucket': bucket_name, 'Key': object_name},
            ExpiresIn=expiration
        )
    except ClientError as e:
        print(f"Error generating URL: {e}")
        return None

    return response

# Generate and print the URL
url = create_presigned_url(BUCKET_NAME, OBJECT_NAME)
if url:
    print(f"Successfully generated presigned URL:\n{url}")

Security Best Practices for ODF

  • Use Least Privilege: Use credentials from a specific Object Bucket Claim (OBC) rather than administrative keys.
  • SSL Verification: While verify=False is common for initial testing with self-signed OpenShift certificates, production environments should use the cluster’s CA bundle for secure communication.
  • Lifecycle Policies: ODF supports automatic object deletion, allowing you to set policies that clean up temporary files after their expiration, further reducing the security footprint.

Support for Automatic Deletion (Lifecycle)

Lifecycle Policies: NooBaa supports S3 Lifecycle Management, allowing you to define rules that automatically expire (delete) objects after a certain number of days.

  • Consistency: These policies work consistently regardless of whether your “backing store” is local (PV-based) or a public cloud provider like AWS S3 or Azure Blob.


Key Takeaway: ODF 4.21 isn’t just for internal container storage; its integrated S3 API (via NooBaa/MCG) allows it to function as a full-featured object store capable of supporting complex external integration patterns.

Leave a Reply

Your email address will not be published. Required fields are marked *