Using Server-Side Encryption with Linode Object Storage

Updated by Linode Written by Ben Bigger

Contribute on GitHub

Report an Issue | View File | Edit File

Note
Linode Object Storage is now available to the general public in the Newark, Frankfurt, and Singapore data centers! For billing information on Object Storage, see our Object Storage Pricing and Limitations guide.
Caution
Object Storage is similar to a subscription service. Once enabled, you will be billed at the flat rate regardless of whether or not there are active buckets on your account. You must Cancel Object Storage to stop billing for this service.

Server-side encryption secures data on Linode Object Storage. Using your own encryption key, Linode will encrypt your data at the object level prior to storing it to disk. Once encrypted, Linode will only decrypt data if that same encryption key is provided with the retrieval request. This enables you to use Linode Object Storage to confidently handle sensitive data like Terraform configurations that contain passwords and SSH keys.

In this guide, you will write an example Python script that will upload a simple file containing the text “Hello World!” to Linode Object Storage, encrypt the file with server-side encryption using a provided encryption key (SSE-C), decrypt and retrieve the contents of the file, then delete the file. Once completed, the components of this script can be adapted to implement server side encryption for your own specific use case.

Before You Begin

  • Familiarize yourself with Linode Object Storage by reading the How to Use Object Storage guide.
  • Create an Object Storage bucket. For demonstration purposes, you can create an Object Storage bucket and delete it after completing this guide.

Python Example Script

  1. This section requires that Python 2.7, 3.4 or above is installed on your machine. Check your version of Python with the following command:

    python --version
    
  2. Install Boto3, the AWS SDK for Python:

    pip install boto3
    
  3. Generate an Object Storage key pair, saving the access key and secret key for use in your script.

  4. Choose a 32 character encryption key for use in your script. You can use OpenSSL to randomly generate 32 hexadecimal characters to use as your encryption key with the following command:

    openssl rand -hex 16
    
    Caution
    Linode destroys encryption keys immediately after your data is encrypted. Object Storage data that is encrypted with SSE-C is unrecoverable without your encryption key.
  5. Using a code editor, open a new file labeled example.py for your Python script and enter the following:

    example.py
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    
    #!/usr/bin/env python
    import boto3
    
    cfg = {
        "aws_access_key_id": "example-access-key",
        "aws_secret_access_key": "example-secret-access-key",
        "endpoint_url": "https://example-cluster-url",
    }
    
    # Your encryption key must be 32 characters
    ENCRYPTION_KEY = "example-encryption-key-987654321"
    ALGO = "AES256"
    BUCKET = "example-bucket-name"
    FILE = "sse-c-test"
    BODY = "Hello World!"
    
    client = boto3.client("s3", **cfg)
    
    print("Uploading file to Object Storage and encrypting with SSE-C.")
    
    r1 = client.put_object(
        SSECustomerKey=ENCRYPTION_KEY,
        SSECustomerAlgorithm=ALGO,
        Bucket=BUCKET,
        Key=FILE,
        Body=BODY
    )
    
    if r1["ResponseMetadata"]["HTTPStatusCode"] == 200:
        print("Upload and encryption successful.")
    
    print("Downloading encrypted Object Storage file.")
    
    r2 = client.get_object(
        SSECustomerKey=ENCRYPTION_KEY,
        SSECustomerAlgorithm=ALGO,
        Bucket=BUCKET,
        Key=FILE
    )
    
    print("Decrypted object body:", r2["Body"].read())
    
    print("Deleting encrypted Object Storage file.")
    
    r3 = client.delete_object(
        Bucket=BUCKET,
        Key=FILE
    )
    
    if r3["ResponseMetadata"]["HTTPStatusCode"] == 204:
        print("Deletion successful.")
        
  6. In your script file, example.py, replace the following example values with your own unique values created in previous steps and save your changes:

    Example Unique Value
    example-access-key Your Object Storage access key.
    example-secret-access-key Your Object Storage secret key.
    example-cluster-url The URL of your Object Storage bucket’s cluster.
    example-encryption-key-987654321 Your 32-character encryption key.
    example-bucket-name The name of your Object Storage bucket.
    Note
    A cluster is defined as all buckets hosted by a unique URL; for example: us-east-1.linodeobjects.com, ap-south-1.linodeobjects.com, or eu-central-1.linodeobjects.com.
  7. From your machine’s terminal, make your script file executable:

    chmod +x example.py
    
  8. Run your script:

    ./example.py
    

    The following output shows that you successfully uploaded, downloaded, and deleted an SSE-C encrypted Linode Object Storage file:

      
    Uploading file to Object Storage and encrypting with SSE-C.
    Upload and encryption successful.
    Downloading encrypted Object Storage file.
    Decrypted object body: b'Hello World!'
    Deleting encrypted Object Storage file.
    Deletion successful.
        
    

Join our Community

Find answers, ask questions, and help others.

This guide is published under a CC BY-ND 4.0 license.