diff --git a/charts/openhands/README.md b/charts/openhands/README.md index f8984d0e..29fa6880 100644 --- a/charts/openhands/README.md +++ b/charts/openhands/README.md @@ -243,6 +243,36 @@ authentication as well. enabled: true ``` +#### Azure DevOps + +1. Create an Azure AD App Registration: + + - Go to the Azure Portal > Azure Active Directory > App registrations > New registration + - Set the "Redirect URI" to `https://auth.openhands.example.com/realms/allhands/broker/azuredevops/endpoint` + - Under "Certificates & secrets", create a new client secret + - Under "API permissions", add the following permissions for Azure DevOps (if using delegated permissions): vso.code_write, vso.work_write, vso.identity, vso.profile, vso.project + - Note the Application (client) ID, Directory (tenant) ID, and Client Secret + +2. Create an Azure DevOps App secret: + + ```bash + kubectl create secret generic azuredevops-app -n openhands \ + --from-literal=client-id= \ + --from-literal=client-secret= + ``` + +3. Update site-values.yaml file: + + ```yaml + azureDevOps: + enabled: true + # For single-tenant apps, set your Azure AD tenant ID + # For multi-tenant apps, leave empty or set to "common" + tenantId: "" + auth: + existingSecret: azuredevops-app + ``` + When the chart is deployed, a job will run to configure the Keycloak realm with the identity provider credentials you provided. #### Bitbucket Data Center diff --git a/charts/openhands/templates/_env.yaml b/charts/openhands/templates/_env.yaml index 75e8c861..a679b962 100644 --- a/charts/openhands/templates/_env.yaml +++ b/charts/openhands/templates/_env.yaml @@ -193,6 +193,20 @@ name: {{ .Values.bitbucket.auth.existingSecret }} key: client-secret {{- end }} +{{- if .Values.azureDevOps.enabled }} +- name: AZURE_DEVOPS_APP_CLIENT_ID + valueFrom: + secretKeyRef: + name: {{ .Values.azureDevOps.auth.existingSecret }} + key: client-id +- name: AZURE_DEVOPS_APP_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.azureDevOps.auth.existingSecret }} + key: client-secret +- name: AZURE_DEVOPS_TENANT_ID + value: {{ .Values.azureDevOps.tenantId | quote }} +{{- end }} {{- if .Values.bitbucketDataCenter.enabled }} - name: BITBUCKET_DATA_CENTER_HOST value: {{ .Values.bitbucketDataCenter.host }} diff --git a/charts/openhands/templates/ingress-integrations.yaml b/charts/openhands/templates/ingress-integrations.yaml index 830c1c86..ce527ffc 100644 --- a/charts/openhands/templates/ingress-integrations.yaml +++ b/charts/openhands/templates/ingress-integrations.yaml @@ -43,6 +43,13 @@ spec: name: openhands-integrations-service port: number: 3000 + - path: /integration/azure-devops/events + pathType: Exact + backend: + service: + name: openhands-integrations-service + port: + number: 3000 - path: /integration/jira/events pathType: Exact backend: diff --git a/charts/openhands/templates/keycloak-config-script.yaml b/charts/openhands/templates/keycloak-config-script.yaml index 09a5de58..a550683a 100644 --- a/charts/openhands/templates/keycloak-config-script.yaml +++ b/charts/openhands/templates/keycloak-config-script.yaml @@ -94,7 +94,7 @@ data: # the OAuth2 provider creation fails with an invalid host. export BITBUCKET_DATA_CENTER_HOST=${BITBUCKET_DATA_CENTER_HOST:-"placeholder.invalid"} export GITLAB_HOST=${GITLAB_HOST:-"gitlab.com"} - envsubst '$WEB_HOST,$AUTH_WEB_HOST,$KEYCLOAK_REALM_NAME,$KEYCLOAK_CLIENT_ID,$KEYCLOAK_CLIENT_SECRET,$GITHUB_APP_CLIENT_ID,$GITHUB_APP_CLIENT_SECRET,$GITLAB_APP_CLIENT_ID,$GITLAB_APP_CLIENT_SECRET,$GITLAB_HOST,$BITBUCKET_APP_CLIENT_ID,$BITBUCKET_APP_CLIENT_SECRET,$GITHUB_BASE_URL,$KEYCLOAK_SMTP_PASSWORD,$BITBUCKET_DATA_CENTER_HOST,$BITBUCKET_DATA_CENTER_CLIENT_ID,$BITBUCKET_DATA_CENTER_CLIENT_SECRET'< /realm-template/allhands-realm-github-provider.json.tmpl > /tmp/allhands-realm-github-provider.json + envsubst '$WEB_HOST,$AUTH_WEB_HOST,$KEYCLOAK_REALM_NAME,$KEYCLOAK_CLIENT_ID,$KEYCLOAK_CLIENT_SECRET,$GITHUB_APP_CLIENT_ID,$GITHUB_APP_CLIENT_SECRET,$GITLAB_APP_CLIENT_ID,$GITLAB_APP_CLIENT_SECRET,$GITLAB_HOST,$BITBUCKET_APP_CLIENT_ID,$BITBUCKET_APP_CLIENT_SECRET,$AZURE_DEVOPS_APP_CLIENT_ID,$AZURE_DEVOPS_APP_CLIENT_SECRET,$GITHUB_BASE_URL,$KEYCLOAK_SMTP_PASSWORD,$BITBUCKET_DATA_CENTER_HOST,$BITBUCKET_DATA_CENTER_CLIENT_ID,$BITBUCKET_DATA_CENTER_CLIENT_SECRET'< /realm-template/allhands-realm-github-provider.json.tmpl > /tmp/allhands-realm-github-provider.json REALM_JSON=/tmp/allhands-realm-github-provider.json if [ "$ERROR_MESSAGE" = "Realm not found." ]; then diff --git a/charts/openhands/values.yaml b/charts/openhands/values.yaml index b7a249b4..738765d7 100644 --- a/charts/openhands/values.yaml +++ b/charts/openhands/values.yaml @@ -13,6 +13,7 @@ appConfig: OPENHANDS_GITHUB_SERVICE_CLS: "integrations.github.github_service.SaaSGitHubService" OPENHANDS_GITLAB_SERVICE_CLS: "integrations.gitlab.gitlab_service.SaaSGitLabService" OPENHANDS_BITBUCKET_SERVICE_CLS: "integrations.bitbucket.bitbucket_service.SaaSBitBucketService" + OPENHANDS_AZURE_DEVOPS_SERVICE_CLS: "integrations.azure_devops.azure_devops_service.SaaSAzureDevOpsService" OPENHANDS_BITBUCKET_DATA_CENTER_SERVICE_CLS: "integrations.bitbucket_data_center.bitbucket_dc_service.SaaSBitbucketDCService" OPENHANDS_MCP_CONFIG_CLS: "server.mcp.mcp_config.SaaSOpenHandsMCPConfig" OPENHANDS_EXPERIMENT_MANAGER_CLS: "experiments.experiment_manager.SaaSExperimentManager" @@ -639,6 +640,14 @@ jiraDc: linear: enabled: false +azureDevOps: + enabled: false + # Azure AD tenant ID for single-tenant app authentication + # Leave empty or set to "common" for multi-tenant apps + tenantId: "" + auth: + existingSecret: azuredevops-app + # Plugin Directory subchart configuration # When enabled, deploys the plugin directory marketplace as a subchart # The plugin directory allows users to discover, browse, and review agent plugins