Aws::Errors::InvalidRegionError: Invalid :region option — add early validation and clear error message for missing S3 region configuration

Summary

GitLab.com is raising Aws::Errors::InvalidRegionError: Invalid ':region' option was provided. when attempting to stream audit events to an AWS S3 destination. This error originates from the AWS SDK for Ruby and indicates that the :region configuration option passed to the S3 client is either missing, nil, or set to an invalid/empty string.

Error

Aws::Errors::InvalidRegionError
Invalid `:region` option was provided. (Aws::Errors::InvalidRegionError)

* Not every service is available in every region.

* Never suffix region names with availability zones.
  Use "us-east-1", not "us-east-1a"

Known AWS regions include (not specific to this service):

af-south-1, ap-east-1, ap-northeast-1, ap-northeast-2, ap-northeast-3,
ap-south-1, ap-south-2, ap-southeast-1, ap-southeast-2, ap-southeast-3,
ap-southeast-4, ap-southeast-5, aws-global, ca-central-1, ca-west-1,
eu-central-1, eu-central-2, eu-north-1, eu-south-1, eu-south-2,
eu-west-1, eu-west-2, eu-west-3, il-central-1, me-central-1, me-south-1,
sa-east-1, us-east-1, us-east-2, us-west-1, us-west-2, ...

            raise Errors::InvalidRegionError
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^

Context

This error is specific to audit event streaming to AWS S3, not GitLab's general object storage (e.g. artifacts, LFS, uploads). GitLab supports streaming audit events to external destinations, including AWS S3 buckets, via the AuditEvents::Streaming feature. The S3 client used for this feature is initialised as follows:

class S3Client
  def initialize(access_key_id, secret_access_key, aws_region)
    credentials = Aws::Credentials.new(access_key_id, secret_access_key)
    @s3_client = Aws::S3::Client.new(
      region: aws_region,
      credentials: credentials,
      # Default value is 1, which will send a 1xx, but GitLab rejects all 1xx responses by default
      ...
    )
  end
end

When a user configures an audit event streaming destination with a missing or invalid AWS region, aws_region is nil or an empty string, causing the AWS SDK to raise InvalidRegionError at runtime during an actual streaming operation.

Root Cause

The AWS SDK for Ruby raises Aws::Errors::InvalidRegionError when:

  1. The :region option is nil or an empty string ("").
  2. The region string does not match the expected format (e.g. us-east-1).
  3. The region is not resolved from any of the SDK's fallback sources (environment variable AWS_REGION / AWS_DEFAULT_REGION, instance metadata, config file).

In this case, the aws_region value originates from the audit event streaming destination configuration supplied by the user/administrator. There is currently no early validation of this field before the S3 client is constructed.

Steps to Reproduce

  1. Navigate to Admin Area → Monitoring → Audit Events → Streams (or the group-level equivalent).
  2. Add a new streaming destination of type AWS S3, providing valid credentials but omitting or leaving blank the AWS Region field.
  3. Trigger an audit event (e.g. sign in, change a setting).
  4. Observe Aws::Errors::InvalidRegionError in the application logs or Sentry.

Impact

  • Audit event streaming to the affected S3 destination silently fails or raises an unhandled error.
  • Administrators may not receive a clear error message explaining the misconfiguration.

Classification

This is a user/configuration error — consistent with how similar AWS SDK errors have been handled in the past. The region is a required field for AWS SDK clients and must be explicitly provided by the user when configuring an S3 streaming destination.

Possible Fix

GitLab should validate the aws_region field before constructing the Aws::S3::Client, and surface a clear, actionable error to the user at configuration time rather than letting the AWS SDK raise at runtime.

Option 1 — Validate at destination save time

Add a presence and format validation on the aws_region attribute when a user saves an S3 audit event streaming destination:

validates :aws_region, presence: true, format: { with: /\A[a-z]{2}-[a-z]+-\d+\z|aws-global|aws-cn-global|aws-us-gov-global/, message: "must be a valid AWS region (e.g. us-east-1)" }, if: :s3_destination?

Option 2 — Raise a descriptive error in S3Client#initialize

Guard the constructor so that a missing region produces a clear ConfigurationError rather than an opaque AWS SDK exception:

def initialize(access_key_id, secret_access_key, aws_region)
  raise ConfigurationError, "AWS region must be provided for audit event S3 streaming." if aws_region.blank?

  credentials = Aws::Credentials.new(access_key_id, secret_access_key)
  @s3_client = Aws::S3::Client.new(region: aws_region, credentials: credentials)
end

Both options can be combined: validate at save time for the best UX, and add the guard in S3Client as a defensive fallback.

References

Edited by 🤖 GitLab Bot 🤖