Skip to content

Conversation

achdmbp
Copy link

@achdmbp achdmbp commented Aug 28, 2025

Add IRSA and Session Token Support to AWS Storage Service

Fixes #1316

Overview

This enhancement addresses the AWS credential limitations in OpenVSX by adding support for multiple authentication methods, enabling secure Kubernetes deployments and following AWS security best practices.

🔧 Changes Made

  • Enhanced credential support: Static credentials, session tokens, IRSA, and default provider chain
  • Automatic credential detection: Service intelligently selects the best available authentication method
  • Backward compatibility: Existing static credential configurations continue to work
  • Comprehensive testing: Integration tests covering all authentication scenarios
  • Updated documentation: Examples for all deployment scenarios

Supported Authentication Methods

  1. Static credentials with session token (temporary credentials from STS)
  2. Static credentials without session token (permanent IAM user credentials)
  3. IRSA credentials (IAM Roles for Service Accounts in Kubernetes)
  4. Default credential provider chain (instance profiles, credential files, etc.)

Testing Instructions

Prerequisites

  • AWS account with S3 bucket
  • Kubernetes cluster (for IRSA testing)
  • kubectl configured

Option A: Testing with IRSA (Recommended)

1. Set up IRSA in your Kubernetes cluster

Follow the AWS IRSA documentation to configure IAM Roles for Service Accounts.

2. Create IAM Role and Policy

# Create IAM policy for S3 access
aws iam create-policy \
 --policy-name openvsx-s3-policy \
 --policy-document '{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Effect": "Allow",
       "Action": [
         "s3:GetObject",
         "s3:PutObject",
         "s3:DeleteObject",
         "s3:ListBucket"
       ],
       "Resource": [
         "arn:aws:s3:::your-openvsx-bucket",
         "arn:aws:s3:::your-openvsx-bucket/*"
       ]
     }
   ]
 }'

Create IAM role for IRSA

eksctl create iamserviceaccount \
 --cluster=your-cluster-name \
 --namespace=openvsx \
 --name=openvsx-service-account \
 --attach-policy-arn=arn:aws:iam::YOUR-ACCOUNT:policy/openvsx-s3-policy \
 --approve

3. Deploy OpenVSX with IRSA

apiVersion: apps/v1
kind: Deployment
metadata:
 name: openvsx-server
 namespace: openvsx
spec:
 template:
   spec:
     serviceAccountName: openvsx-service-account  # IRSA service account
     containers:
      • name: server
       image: openvsx/server:latest # image built using this MR updates
       env:
       # Only configure S3 bucket - credentials auto-detected via IRSA
        • name: OVSX_STORAGE_AWS_BUCKET
         value: "your-openvsx-bucket"
        • name: OVSX_STORAGE_AWS_REGION
         value: "us-east-1"
       # No static credentials needed!

4. Verify IRSA Authentication

# Check pod logs for successful S3 authentication
kubectl logs -n openvsx deployment/openvsx-server | grep -i "aws\|s3"

# Test file upload via OpenVSX API
curl -X POST http://your-openvsx-url/api/-/publish \
 -H "Authorization: Bearer YOUR_TOKEN" \
 -F "[email protected]"

Option B: Testing with Manual Credentials (Fallback)

If IRSA setup is not available, use this manual configuration:

1. Create Kubernetes Secret

# Create secret with AWS credentials
kubectl create secret generic aws-credentials \
 --from-literal=access-key-id=YOUR_ACCESS_KEY \
 --from-literal=secret-access-key=YOUR_SECRET_KEY \
 --from-literal=session-token=YOUR_SESSION_TOKEN  # Optional for temporary creds

2. Deploy with Secret-based Credentials

apiVersion: apps/v1
kind: Deployment
metadata:
 name: openvsx-server
spec:
 template:
   spec:
     containers:
      • name: server
       image: openvsx/server:latest
       env:
        • name: OVSX_STORAGE_AWS_ACCESS_KEY_ID
         valueFrom:
           secretKeyRef:
             name: aws-credentials
             key: access-key-id
        • name: OVSX_STORAGE_AWS_SECRET_ACCESS_KEY
         valueFrom:
           secretKeyRef:
             name: aws-credentials
             key: secret-access-key
        • name: OVSX_STORAGE_AWS_SESSION_TOKEN  # Optional
         valueFrom:
           secretKeyRef:
             name: aws-credentials
             key: session-token
        • name: OVSX_STORAGE_AWS_BUCKET
         value: "your-openvsx-bucket"
        • name: OVSX_STORAGE_AWS_REGION
         value: "us-east-1"

🔍 Verification Steps

  1. Check authentication method detection:
  kubectl logs deployment/openvsx-server | grep "AWS authentication"
  1. Test S3 operations:

    • Upload an extension via the API
    • Verify files appear in S3 bucket
    • Download extension files
    • Check namespace logo uploads
  2. Verify credential rotation (for temporary credentials):

    • Wait for credentials to expire
    • Confirm automatic credential refresh

Unit Test Coverage

Run the comprehensive test suite:

# Run all AWS storage tests
./gradlew test --tests "*AwsStorageService*"

Run integration tests with LocalStack

DOCKER_HOST=unix:///path/to/docker.sock \
TESTCONTAINERS_RYUK_DISABLED=true \
./gradlew test --tests "*AwsStorageServiceIntegrationTest*"

Documentation

🔒 Security Benefits

  • ✅ Eliminates long-lived static credentials in Kubernetes
  • ✅ Supports automatic credential rotation
  • ✅ Follows AWS security best practices
  • ✅ Enables least-privilege access via IAM roles
  • ✅ Maintains backward compatibility

Breaking Changes

None - this is a backward-compatible enhancement.

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Unit tests added/updated
  • Integration tests added
  • Documentation updated
  • Backward compatibility maintained
  • Security best practices followed

return UrlUtil.createApiUrl("", namespace.getName(), "logo", namespace.getLogoName()).substring(1);
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no new line

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no new line

done

assertFalse((Boolean) ReflectionTestUtils.invokeMethod(storageService, "hasStaticCredentials"));
assertFalse((Boolean) ReflectionTestUtils.invokeMethod(storageService, "hasSessionToken"));
}
} No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no new line

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no new line

done

@achdmbp achdmbp force-pushed the feature/aws-irsa-support branch from 12ee2d6 to ff10815 Compare September 2, 2025 17:49
@ibuziuk
Copy link
Member

ibuziuk commented Sep 3, 2025

@svor @amvanbaren folks, could you please review? It would be great to include the change in the next release.

@svor
Copy link
Contributor

svor commented Sep 12, 2025

@achdmbp Hello, I've tried to follow steps from the description Option A: Testing with IRSA (Recommended). When I deployed openvsx-server to EKS cluster:
kubectl apply -f deployement.yaml

deployement.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: openvsx-server
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: openvsx-server
  template:
    metadata:
      labels:
        app: openvsx-server
    spec:
      serviceAccountName: openvsx-service-account  # IRSA service account
      containers:
       - name: server
         image: quay.io/vsvydenk/openvsx:pr-check # image built using this PR
         env:
          # Only configure S3 bucket - credentials auto-detected via IRSA
           - name: OVSX_STORAGE_AWS_BUCKET
             value: "vsvydenk-openvsx"
           - name: OVSX_STORAGE_AWS_REGION
             value: "us-east-1"
          # No static credentials needed!

openvsx-server pod failed:

logs
ionExtensionSupport : Spring Data Reactive Elasticsearch - Could not safely identify store assignment for repository candidate interface org.eclipse.openvsx.repositories.PersistedLogRepository; If you want this repository to be a Reactive Elasticsearch repository, consider annotating your entities with one of these annotations: org.springframework.data.elasticsearch.annotations.Document (preferred), or consider extending one of the following types with your repository: org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository
2025-09-12T09:04:50.159Z  INFO 1 --- [           main] [                                                 ] .RepositoryConfigurationExtensionSupport : Spring Data Reactive Elasticsearch - Could not safely identify store assignment for repository candidate interface org.eclipse.openvsx.repositories.PersonalAccessTokenRepository; If you want this repository to be a Reactive Elasticsearch repository, consider annotating your entities with one of these annotations: org.springframework.data.elasticsearch.annotations.Document (preferred), or consider extending one of the following types with your repository: org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository
2025-09-12T09:04:50.160Z  INFO 1 --- [           main] [                                                 ] .RepositoryConfigurationExtensionSupport : Spring Data Reactive Elasticsearch - Could not safely identify store assignment for repository candidate interface org.eclipse.openvsx.repositories.SignatureKeyPairRepository; If you want this repository to be a Reactive Elasticsearch repository, consider annotating your entities with one of these annotations: org.springframework.data.elasticsearch.annotations.Document (preferred), or consider extending one of the following types with your repository: org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository
2025-09-12T09:04:50.160Z  INFO 1 --- [           main] [                                                 ] .RepositoryConfigurationExtensionSupport : Spring Data Reactive Elasticsearch - Could not safely identify store assignment for repository candidate interface org.eclipse.openvsx.repositories.UserDataRepository; If you want this repository to be a Reactive Elasticsearch repository, consider annotating your entities with one of these annotations: org.springframework.data.elasticsearch.annotations.Document (preferred), or consider extending one of the following types with your repository: org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository
2025-09-12T09:04:50.161Z  INFO 1 --- [           main] [                                                 ] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 36 ms. Found 0 Reactive Elasticsearch repository interfaces.
2025-09-12T09:04:50.174Z  INFO 1 --- [           main] [                                                 ] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode
2025-09-12T09:04:50.175Z  INFO 1 --- [           main] [                                                 ] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2025-09-12T09:04:50.405Z  INFO 1 --- [           main] [                                                 ] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 223 ms. Found 13 JPA repository interfaces.
2025-09-12T09:04:52.485Z  INFO 1 --- [           main] [                                                 ] o.s.b.w.e.j.JettyServletWebServerFactory : Server initialized with port: 8080
2025-09-12T09:04:52.496Z  INFO 1 --- [           main] [                                                 ] org.eclipse.jetty.server.Server          : jetty-12.0.22; built: 2025-06-02T15:25:31.946Z; git: 335c9ab44a5591f0ea941bf350e139b8c4f5537c; jvm 17.0.7+7
2025-09-12T09:04:52.544Z  INFO 1 --- [           main] [                                                 ] o.e.j.s.h.ContextHandler.application     : Initializing Spring embedded WebApplicationContext
2025-09-12T09:04:52.549Z  INFO 1 --- [           main] [                                                 ] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 5772 ms
Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts
2025-09-12T09:04:53.745Z  INFO 1 --- [           main] [                                                 ] o.e.j.session.DefaultSessionIdManager    : Session workerName=node0
2025-09-12T09:04:53.755Z  INFO 1 --- [           main] [                                                 ] o.e.jetty.server.handler.ContextHandler  : Started osbwej.JettyEmbeddedWebAppContext@261b6c8c{application,/,b=[file:/tmp/jetty-docbase.8080.10915226778919228570/, jar:file:///home/openvsx/server/BOOT-INF/lib/swagger-ui-5.17.14.jar!/META-INF/resources/],a=AVAILABLE,h=oeje10s.SessionHandler@3516f436{STARTED}}
2025-09-12T09:04:53.757Z  INFO 1 --- [           main] [                                                 ] o.e.j.e.servlet.ServletContextHandler    : Started osbwej.JettyEmbeddedWebAppContext@261b6c8c{application,/,b=[file:/tmp/jetty-docbase.8080.10915226778919228570/, jar:file:///home/openvsx/server/BOOT-INF/lib/swagger-ui-5.17.14.jar!/META-INF/resources/],a=AVAILABLE,h=oeje10s.SessionHandler@3516f436{STARTED}}
2025-09-12T09:04:53.760Z  INFO 1 --- [           main] [                                                 ] org.eclipse.jetty.server.Server          : Started oejs.Server@729d6ee2{STARTING}[12.0.22,sto=0] @8736ms
2025-09-12T09:04:54.085Z  WARN 1 --- [           main] [                                                 ] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Failed to initialize dependency 'flyway' of LoadTimeWeaverAware bean 'entityManagerFactory': Error creating bean with name 'flyway' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Failed to instantiate [org.flywaydb.core.Flyway]: Factory method 'flyway' threw exception with message: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception with message: Failed to determine a suitable driver class
2025-09-12T09:04:54.106Z  INFO 1 --- [           main] [                                                 ] i.o.sdk.logs.SdkLoggerProvider           : Calling shutdown() multiple times.
2025-09-12T09:04:54.106Z  INFO 1 --- [           main] [                                                 ] i.o.sdk.trace.SdkTracerProvider          : Calling shutdown() multiple times.
2025-09-12T09:04:54.107Z  INFO 1 --- [           main] [                                                 ] i.o.exporter.zipkin.ZipkinSpanExporter   : Calling shutdown() multiple times.
2025-09-12T09:04:54.116Z  INFO 1 --- [           main] [                                                 ] org.eclipse.jetty.server.Server          : Stopped oejs.Server@729d6ee2{STOPPING}[12.0.22,sto=0]
2025-09-12T09:04:54.121Z  INFO 1 --- [           main] [                                                 ] o.e.j.e.servlet.ServletContextHandler    : Stopped osbwej.JettyEmbeddedWebAppContext@261b6c8c{application,/,b=[file:/tmp/jetty-docbase.8080.10915226778919228570/, jar:file:///home/openvsx/server/BOOT-INF/lib/swagger-ui-5.17.14.jar!/META-INF/resources/],a=AVAILABLE,h=oeje10s.SessionHandler@3516f436{STOPPED}}
2025-09-12T09:04:54.162Z  INFO 1 --- [           main] [                                                 ] .s.b.a.l.ConditionEvaluationReportLogger : 

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2025-09-12T09:04:54.188Z ERROR 1 --- [           main] [                                                 ] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class


Action:

Consider the following:
        If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
        If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

could you please provide more details how openvsx should be deployed, did you add any additional configuration into application.yaml ?

This enhancement addresses the AWS credential limitations in OpenVSX by adding
support for multiple authentication methods:

1. Static credentials with session token (temporary credentials)
2. Static credentials without session token (permanent credentials)
3. IRSA credentials (IAM Roles for Service Accounts)
4. Default credential provider chain (fallback)

Key improvements:
- Enables secure Kubernetes deployments using IRSA
- Supports temporary credentials from AWS STS
- Maintains backward compatibility with existing configurations
- Follows AWS security best practices
- Eliminates need for long-lived static credentials in containers

The service automatically detects available credential types and uses
appropriate AWS SDK credential providers based on configuration.

Updated documentation includes examples for all authentication methods
and deployment scenarios.

Fixes: eclipse#1316
Signed-off-by: Adnan Al <[email protected]>
- Enables Web Identity Token authentication for S3 storage
- Fixes 'sts service module must be on the class path' error
- Required for IAM Roles for Service Accounts (IRSA) integration
@achdmbp achdmbp force-pushed the feature/aws-irsa-support branch from 02c35e5 to a85c501 Compare October 12, 2025 03:30
@achdmbp
Copy link
Author

achdmbp commented Oct 13, 2025

OpenVSX IRSA Integration - PR Testing Instructions

Overview

This PR adds AWS IRSA (IAM Roles for Service Accounts) support to OpenVSX, allowing it to authenticate with AWS S3 using OpenShift service account tokens instead of static credentials.

Prerequisites

  • OpenShift cluster with access to AWS
  • AWS CLI configured with appropriate permissions
  • podman for container builds
  • ovsx CLI tool (npm install -g ovsx)
  • jq for JSON processing

Step-by-Step Testing

1. Create AWS Infra

Create S3 Bucket:

export AWS_REGION="your-aws-region"
export BUCKET_NAME="your-openvsx-test-bucket-$(date +%s)"

aws s3 mb s3://$BUCKET_NAME --region $AWS_REGION

Create IAM Role for IRSA:

export ROLE_NAME="your-openvsx-irsa-role"
export OIDC_PROVIDER="your-openshift-oidc-provider-url"
export NAMESPACE="your-test-namespace"

# Create trust policy
cat > trust-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):oidc-provider/$OIDC_PROVIDER"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "$OIDC_PROVIDER:sub": "system:serviceaccount:$NAMESPACE:openvsx-service-account"
        }
      }
    }
  ]
}
EOF

# Create IAM role
aws iam create-role --role-name $ROLE_NAME --assume-role-policy-document file://trust-policy.json

# Create S3 access policy
cat > s3-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::$BUCKET_NAME",
        "arn:aws:s3:::$BUCKET_NAME/*"
      ]
    }
  ]
}
EOF

# Attach policy to role
aws iam put-role-policy --role-name $ROLE_NAME --policy-name S3Access --policy-document file://s3-policy.json

export ROLE_ARN="arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/$ROLE_NAME"

2. Create OpenShift Project and Service Account

oc new-project $NAMESPACE

# Create service account with IRSA annotation
cat << EOF | oc apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: openvsx-service-account
  namespace: $NAMESPACE
  annotations:
    eks.amazonaws.com/role-arn: $ROLE_ARN
EOF

3. Deploy PostgreSQL Database

cat << EOF | oc apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
  namespace: $NAMESPACE
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgresql
  namespace: $NAMESPACE
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgresql
  template:
    metadata:
      labels:
        app: postgresql
    spec:
      containers:
      - name: postgresql
        image: postgres:13
        env:
        - name: POSTGRES_DB
          value: openvsx
        - name: POSTGRES_USER
          value: openvsx
        - name: POSTGRES_PASSWORD
          value: openvsx
        ports:
        - containerPort: 5432
        volumeMounts:
        - name: postgres-storage
          mountPath: /var/lib/postgresql/data
      volumes:
      - name: postgres-storage
        persistentVolumeClaim:
          claimName: postgres-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: postgresql
  namespace: $NAMESPACE
spec:
  selector:
    app: postgresql
  ports:
  - port: 5432
    targetPort: 5432
EOF

# Wait for PostgreSQL to be ready
oc rollout status deployment/postgresql -n $NAMESPACE

4. Deploy Elasticsearch

cat << EOF | oc apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: elasticsearch
  namespace: $NAMESPACE
spec:
  replicas: 1
  selector:
    matchLabels:
      app: elasticsearch
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
      - name: elasticsearch
        image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
        env:
        - name: discovery.type
          value: single-node
        - name: ES_JAVA_OPTS
          value: "-Xms512m -Xmx512m"
        ports:
        - containerPort: 9200
---
apiVersion: v1
kind: Service
metadata:
  name: elasticsearch
  namespace: $NAMESPACE
spec:
  selector:
    app: elasticsearch
  ports:
  - port: 9200
    targetPort: 9200
EOF

# Wait for Elasticsearch to be ready
oc rollout status deployment/elasticsearch -n $NAMESPACE

5. Build and Deploy OpenVSX Server with PR changes

Build and push image:

cd server/  # Navigate to OpenVSX server directory
export IMAGE_NAME="image-registry.openshift-image-registry.svc:5000/$NAMESPACE/openvsx-server:latest"

# build and push the container image
podman build -t $IMAGE_NAME .
podman push $IMAGE_NAME

Deploy OpenVSX Server:

note: below are the env variables that worked to test the s3 integration using IRSA without creating application.yaml

cat << EOF | oc apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: openvsx-server
  namespace: $NAMESPACE
spec:
  replicas: 1
  selector:
    matchLabels:
      app: openvsx-server
  template:
    metadata:
      labels:
        app: openvsx-server
    spec:
      serviceAccountName: openvsx-service-account
      containers:
      - name: server
        image: $IMAGE_NAME
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_DATASOURCE_URL
          value: "jdbc:postgresql://postgresql:5432/openvsx"
        - name: SPRING_DATASOURCE_USERNAME
          value: "openvsx"
        - name: SPRING_DATASOURCE_PASSWORD
          value: "openvsx"
        - name: OVSX_ELASTICSEARCH_HOST
          value: "elasticsearch:9200"
        - name: OVSX_INTEGRITY_KEY_PAIR
          value: "create"
        - name: BUCKET4J_ENABLED
          value: "false"
        - name: OVSX_REDIS_ENABLED
          value: "false"
        - name: SPRING_AUTOCONFIGURE_EXCLUDE
          value: "org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration"
        - name: SPRING_FLYWAY_BASELINE_ON_MIGRATE
          value: "true"
        # S3 configuration for IRSA
        - name: OVSX_STORAGE_AWS_BUCKET
          value: "$BUCKET_NAME"
        - name: OVSX_STORAGE_AWS_REGION
          value: "$AWS_REGION"
---
apiVersion: v1
kind: Service
metadata:
  name: openvsx-server
  namespace: $NAMESPACE
spec:
  selector:
    app: openvsx-server
  ports:
  - port: 8080
    targetPort: 8080
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: openvsx-server
  namespace: $NAMESPACE
spec:
  to:
    kind: Service
    name: openvsx-server
  port:
    targetPort: 8080
  tls:
    termination: edge
EOF

# Wait for OpenVSX server to be ready
oc rollout status deployment/openvsx-server -n $NAMESPACE

6. Configure Database and Test

Setup test user and token:

# Add test user
oc exec deployment/postgresql -n $NAMESPACE -- \
  psql -U openvsx -d openvsx -c \
  "INSERT INTO user_data (id, login_name, full_name, email, provider_url, provider, created) 
   VALUES (1001, 'test-user', 'Test User', '[email protected]', 'github', 'github', NOW()) 
   ON CONFLICT (id) DO NOTHING;"

# Add personal access token
oc exec deployment/postgresql -n $NAMESPACE -- \
  psql -U openvsx -d openvsx -c \
  "INSERT INTO personal_access_token (id, user_data, value, active, created, accessed, description) 
   VALUES (1001, 1001, 'test_token_123', true, NOW(), NOW(), 'test publisher') 
   ON CONFLICT (id) DO NOTHING;"

Wait for server health and test publishing:

export OPENVSX_URL="https://$(oc get route openvsx-server -n $NAMESPACE -o jsonpath='{.spec.host}')"

# Wait for server to be healthy
echo "Waiting for OpenVSX server to be healthy..."
for i in {1..30}; do
    if curl -s -f "$OPENVSX_URL/actuator/health" >/dev/null 2>&1; then
        echo "✅ OpenVSX server is healthy"
        break
    fi
    if [ $i -eq 30 ]; then
        echo "❌ Health check timeout"
        exit 1
    fi
    echo "Attempt $i/30 - waiting 10 seconds..."
    sleep 10
done

# Create namespace and publish extension
ovsx create-namespace ms-python -r "$OPENVSX_URL" -p test_token_123

# Download and publish a test extension
curl -L -o redhat-vscode-yaml-test.vsix "https://open-vsx.org/api/redhat/vscode-yaml/1.20.2025100808/file/redhat.vscode-yaml-1.20.2025100808.vsix"
ovsx publish redhat-vscode-yaml-test.vsix -r "$OPENVSX_URL" -p test_token_123

7. Verify S3 Storage and Download

# Check S3 bucket contents
echo "Checking S3 bucket contents..."
aws s3 ls s3://$BUCKET_NAME --recursive --region $AWS_REGION

# Test extension download
echo "Testing extension download..."
DOWNLOAD_URL=$(curl -s "$OPENVSX_URL/api/redhat/vscode-yaml" | jq -r '.files.download')
curl -L -o test-download.vsix "$DOWNLOAD_URL"

if [ -f test-download.vsix ] && [ -s test-download.vsix ]; then
    FILE_SIZE=$(ls -lh test-download.vsix | awk '{print $5}')
    echo "✅ Extension downloaded successfully - Size: $FILE_SIZE"
    rm -f test-download.vsix
else
    echo "❌ Download failed"
fi

Expected Results

Success Indicators:

  • All deployments reach "Ready" status
  • OpenVSX server health check passes
  • Extension publishes without credential errors
  • Extension files appear in S3 bucket
  • Extension downloads work correctly

Cleanup

# Delete OpenShift resources
oc delete project $NAMESPACE

# Delete AWS resources
aws iam delete-role-policy --role-name $ROLE_NAME --policy-name S3Access
aws iam delete-role --role-name $ROLE_NAME
aws s3 rm s3://$BUCKET_NAME --recursive
aws s3 rb s3://$BUCKET_NAME

# Clean up local files
rm -f trust-policy.json s3-policy.json

Key Changes Tested

  1. IRSA Authentication: OpenVSX uses service account tokens instead of static AWS credentials
  2. S3 Storage: Extensions stored in S3 bucket with proper IRSA permissions
  3. Container Build: Fixed Dockerfile works in air-gapped environments
  4. Redis Disabled: Proper configuration to avoid Redis dependency issues

@achdmbp
Copy link
Author

achdmbp commented Oct 13, 2025

hi @svor sorry for the delay. I added steps I followed to test my changes here #1327 (comment) . let me know if you have any questions

Copy link
Contributor

@svor svor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested with IRSA credentials. Works for me!
Also configred Eclipse Che to use OpenVSX instance with AWS storage:
Screenshot 2025-10-16 at 14 48 50

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AWS Storage Service lacks support for temporary credentials and IRSA (IAM Roles for Service Accounts)

3 participants