Skip to content

Commit 3f4bf2c

Browse files
committed
fix(operator): support private VPC S3 endpoints in Loki operator
This PR fixes the Loki operator's overly strict S3 endpoint validation that was rejecting private VPC S3 endpoints. The operator was only accepting the standard AWS S3 endpoint format and failing to reconcile when users configured private VPC endpoints in OpenShift environments. The fix updates the validateS3Endpoint function to accept VPC endpoint formats while preventing bucket-specific VPC endpoints that could cause folder creation issues: - Allows: https://vpce-*-region.s3.region.vpce.amazonaws.com (general VPC endpoint) - Rejects: https://bucket.vpce-*-region.s3.region.vpce.amazonaws.com (bucket-specific VPC endpoint) This maintains full backward compatibility with existing standard AWS S3 endpoints while adding support for VPC endpoints without the bucket name prefix that could lead to unwanted folder creation in S3 buckets. Fixes #19243 Signed-off-by: puretension <[email protected]>
1 parent 37eddab commit 3f4bf2c

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

operator/internal/handlers/internal/storage/secrets.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,10 +506,24 @@ func validateS3Endpoint(endpoint string, region string) error {
506506
return fmt.Errorf("%w: %s", errSecretMissingField, storage.KeyAWSRegion)
507507
}
508508

509+
// Check if it's a standard AWS S3 endpoint
509510
validEndpoint := fmt.Sprintf("https://s3.%s%s", region, awsEndpointSuffix)
510-
if endpoint != validEndpoint {
511-
return fmt.Errorf("%w: %s", errS3EndpointAWSInvalid, validEndpoint)
511+
if endpoint == validEndpoint {
512+
return nil
512513
}
514+
515+
// Check if it's a VPC endpoint format: https://vpce-*-region.s3.region.vpce.amazonaws.com
516+
// Reject bucket-specific VPC endpoints to avoid folder creation issues
517+
if strings.Contains(endpoint, ".vpce.amazonaws.com") && strings.Contains(endpoint, region) {
518+
// Ensure it's not a bucket-specific VPC endpoint (bucket.vpce-xxx format)
519+
hostname := parsedURL.Hostname()
520+
if strings.HasPrefix(hostname, "vpce-") {
521+
return nil
522+
}
523+
}
524+
525+
// If neither standard nor VPC endpoint format, return error
526+
return fmt.Errorf("%w: %s", errS3EndpointAWSInvalid, validEndpoint)
513527
}
514528
return nil
515529
}

operator/internal/handlers/internal/storage/secrets_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,39 @@ func TestS3Extract_ForcePathStyle(t *testing.T) {
719719
ForcePathStyle: true,
720720
},
721721
},
722+
{
723+
desc: "aws s3 vpc endpoint with bucket name should fail",
724+
secret: &corev1.Secret{
725+
ObjectMeta: metav1.ObjectMeta{Name: "test"},
726+
Data: map[string][]byte{
727+
"endpoint": []byte("https://bucket.vpce-1234567-us-east-1c.s3.us-east-1.vpce.amazonaws.com"),
728+
"region": []byte("us-east-1"),
729+
"bucketnames": []byte("this,that"),
730+
"access_key_id": []byte("id"),
731+
"access_key_secret": []byte("secret"),
732+
},
733+
},
734+
wantError: "endpoint for AWS S3 must include correct region: https://s3.us-east-1.amazonaws.com",
735+
},
736+
{
737+
desc: "aws s3 vpc endpoint without bucket prefix",
738+
secret: &corev1.Secret{
739+
ObjectMeta: metav1.ObjectMeta{Name: "test"},
740+
Data: map[string][]byte{
741+
"endpoint": []byte("https://vpce-1234567-us-east-1c.s3.us-east-1.vpce.amazonaws.com"),
742+
"region": []byte("us-east-1"),
743+
"bucketnames": []byte("this,that"),
744+
"access_key_id": []byte("id"),
745+
"access_key_secret": []byte("secret"),
746+
},
747+
},
748+
wantOptions: &storage.S3StorageConfig{
749+
Endpoint: "https://vpce-1234567-us-east-1c.s3.us-east-1.vpce.amazonaws.com",
750+
Region: "us-east-1",
751+
Buckets: "this,that",
752+
ForcePathStyle: false,
753+
},
754+
},
722755
{
723756
desc: "invalid forcepathstyle value",
724757
secret: &corev1.Secret{

0 commit comments

Comments
 (0)