diff --git a/.gitbook/assets/01-app-registrations.png b/.gitbook/assets/01-app-registrations.png new file mode 100644 index 0000000..5aa8404 Binary files /dev/null and b/.gitbook/assets/01-app-registrations.png differ diff --git a/.gitbook/assets/02-register-app-form.png b/.gitbook/assets/02-register-app-form.png new file mode 100644 index 0000000..397ee4e Binary files /dev/null and b/.gitbook/assets/02-register-app-form.png differ diff --git a/.gitbook/assets/03-register-app-filled.png b/.gitbook/assets/03-register-app-filled.png new file mode 100644 index 0000000..d4f14b7 Binary files /dev/null and b/.gitbook/assets/03-register-app-filled.png differ diff --git a/.gitbook/assets/04-app-registered-overview.png b/.gitbook/assets/04-app-registered-overview.png new file mode 100644 index 0000000..f024250 Binary files /dev/null and b/.gitbook/assets/04-app-registered-overview.png differ diff --git a/.gitbook/assets/05-certificates-secrets-page.png b/.gitbook/assets/05-certificates-secrets-page.png new file mode 100644 index 0000000..3812fda Binary files /dev/null and b/.gitbook/assets/05-certificates-secrets-page.png differ diff --git a/.gitbook/assets/06-add-client-secret.png b/.gitbook/assets/06-add-client-secret.png new file mode 100644 index 0000000..fda7420 Binary files /dev/null and b/.gitbook/assets/06-add-client-secret.png differ diff --git a/.gitbook/assets/07-client-secret-created.png b/.gitbook/assets/07-client-secret-created.png new file mode 100644 index 0000000..6460a78 Binary files /dev/null and b/.gitbook/assets/07-client-secret-created.png differ diff --git a/.gitbook/assets/08-ado-org-users.png b/.gitbook/assets/08-ado-org-users.png new file mode 100644 index 0000000..38e8600 Binary files /dev/null and b/.gitbook/assets/08-ado-org-users.png differ diff --git a/SUMMARY.md b/SUMMARY.md index 2eb854a..02840d1 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -179,6 +179,11 @@ * [Project](collaborate/project.md) * [Integrations](collaborate/integrations.md) + +## Integrations + +* [Overview](integrations/README.md) + * [Azure DevOps](integrations/azure-devops.md) *** * [API Reference](api-reference/README.md) diff --git a/integrations/README.md b/integrations/README.md new file mode 100644 index 0000000..9752600 --- /dev/null +++ b/integrations/README.md @@ -0,0 +1,32 @@ +--- +icon: puzzle-piece +--- + +# Integrations + +Integrations connect sfp to external services for source control, work item tracking, artifact management, and notifications. Credentials are encrypted at rest using AES-256 and can be scoped globally or per project. + +## Supported Providers + +| Provider | Auth Types | Use Case | +| ------------------------------------ | ----------------------- | ---------------------------------- | +| [Azure DevOps](azure-devops.md) | Service Principal, PAT | Source control, builds, work items | +| GitHub | PAT, OAuth, GitHub App | Source control, PRs, status checks | +| GitLab | PAT | Source control, merge requests | +| Jira | Basic Auth, OAuth | Work item tracking | +| JFrog | API Key | Artifact registry | +| Slack | Webhook | Notifications | + +## Credential Management + +Integrations support two scoping models: + +* **Global** (`isGlobal: true`): A single set of credentials shared across all projects. Suitable when one service account covers the entire organization. +* **Project-scoped** (`projects: [...]`): Credentials assigned to specific repositories. Use when teams require isolated access or different service accounts per project. + +During operations, sfp resolves credentials by checking project-scoped integrations first, then falling back to global integrations. + +## Further Reading + +* [Integrations API Reference](../api-reference/integrations.md) — REST endpoints for managing integrations programmatically. +* [Azure DevOps Setup Guide](azure-devops.md) — Step-by-step Service Principal and PAT configuration. diff --git a/integrations/azure-devops.md b/integrations/azure-devops.md new file mode 100644 index 0000000..4798d31 --- /dev/null +++ b/integrations/azure-devops.md @@ -0,0 +1,183 @@ +--- +icon: cloud +--- + +# Azure DevOps + +## Overview + +Azure DevOps integration enables sfp to connect to your Azure DevOps (ADO) repositories. This supports automated build triggering on pushes and pull requests, work item creation and updates, and release candidate management across environments. + +sfp resolves credentials dynamically during operations, supporting both project-scoped and global configurations. + +## Authentication Methods + +### Service Principal (Recommended) + +Service Principals use Azure Entra ID (formerly Azure AD) application registration with the client credentials OAuth flow. + +Advantages include: +- No manual token rotation; secrets have configurable expiry (up to 24 months). +- Scoped permissions via ADO access levels and project roles. +- Centralized audit trail through Entra ID logs. +- Suitable for CI/CD and shared team access. + +### Personal Access Token (PAT) + +PATs are user-scoped tokens generated in ADO. Setup is simpler but tokens expire (default 90 days, max 1 year) and are tied to individual accounts. + +Use PATs for personal testing or when Service Principal setup is not feasible. + +## Setting Up a Service Principal + +### Prerequisites + +- Access to Azure Portal with Entra ID permissions to register applications. +- Azure DevOps organization administrator access to add the Service Principal as a user. + +### Step 1: Register an Application in Azure Entra ID + +1. Sign in to the [Azure Portal](https://portal.azure.com). +2. Navigate to **Microsoft Entra ID** > **App registrations**. +3. Select **New registration**. + +
+Entra ID App registrations page +

Entra ID App registrations page

+
+ +4. Complete the registration form with a descriptive name (e.g., `sfp-service-principal`). + +
+New app registration form +

New app registration form

+
+ +
+App registration form with name filled +

App registration form completed

+
+ +5. Select **Register**. + +### Step 2: Note Application Credentials + +From the app overview page, copy the **Application (client) ID** and **Directory (tenant) ID**. + +
+App overview showing client ID and tenant ID +

Application credentials from overview page

+
+ +### Step 3: Create a Client Secret + +1. In the app, navigate to **Certificates & secrets** > **Client secrets** > **New client secret**. + +
+Certificates and secrets page +

Certificates & secrets navigation

+
+ +2. Add a description, set an expiry (recommend 12-24 months), and select **Add**. + +
+New client secret dialog +

New client secret configuration

+
+ +3. **Immediately copy the secret Value**. It is shown only once. + +
+Client secret value visible +

Client secret value (copy immediately)

+
+ +### Step 4: Add Service Principal to Azure DevOps + +1. Sign in to your Azure DevOps organization. +2. Navigate to **Organization settings** > **Users** > **Add users**. + +
+ADO organization users page +

ADO organization users management

+
+ +3. Enter the **Application (client) ID** as the user identifier. +4. Assign at least **Basic** access level. +5. Grant project permissions as needed (e.g., Contributor for builds and work items). + +## Registering the Integration in sfp + +### Via codev Desktop App + +1. Open codev and navigate to **Settings** > **Integrations**. +2. Click **Add Integration** and select **Azure DevOps**. +3. Choose **Service Principal** authentication. +4. Enter **Application ID**, **Tenant ID**, and **Client Secret**. +5. Select scope: project-specific (enter repository identifier) or global. +6. Save the integration. + +### Via API + +```bash +curl -X POST 'https://your-sfp-server/sfp/api/integrations' \ + -H 'Authorization: Bearer $YOUR_JWT_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{ + "provider": "azuredevops", + "authType": "service_principal", + "credentials": { + "app_id": "your-application-client-id", + "password": "your-client-secret", + "tenant": "your-directory-tenant-id" + }, + "isGlobal": true, + "project": "your-ado-project" // Omit for global + }' +``` + +Replace `$YOUR_JWT_TOKEN` with a valid sfp server JWT. + +## How Credential Resolution Works + +sfp resolves credentials during operations via this chain: + +1. **Project-scoped**: Checks `sfp_integrations` for entries matching the target project/repository. +2. **Global/default**: Falls back to `isGlobal: true` integrations. +3. **Failure**: Returns 404 if no matching credentials found. + +This ensures project-specific credentials take precedence while providing safe defaults. + +## Setting Up a Personal Access Token + +1. In Azure DevOps, navigate to **User settings** > **Personal access tokens** > **New Token**. +2. Set a description and expiry. +3. Select scopes: **Code (Read & Write)**, **Work Items (Read & Write)**, **Build (Read & Execute)**. +4. Copy the generated token. +5. Register via codev UI (select **PAT** auth type) or API: + +```bash +curl -X POST 'https://your-sfp-server/sfp/api/integrations' \ + -H 'Authorization: Bearer $YOUR_JWT_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{ + "provider": "azuredevops", + "authType": "pat", + "credentials": { + "token": "your-pat-token" + }, + "isGlobal": true + }' +``` + +## Troubleshooting + +| Issue | Cause | Resolution | +|-------|-------|------------| +| `Invalid client credentials` | Mismatched ID/secret/tenant or expired secret | Verify values in Entra ID; regenerate secret if expired | +| `Insufficient privileges to complete operation` | Service Principal lacks ADO access | Confirm SP added as user with Basic+ access and project roles | +| `No integration found for project` | Missing or mis-scoped integration | Add project-scoped entry or fallback global integration | +| `401 Unauthorized` (PAT) | Expired or insufficient scopes | Regenerate PAT with required scopes (Code R/W, Work Items R/W, Build R/E) | +| Token expiry | Client secret or PAT reached end-of-life | Rotate before expiry; set calendar reminders for secrets up to 24 months | + +For API errors, check server logs via `docker logs sfp-pro-server-1`. Contact support with request ID if issues persist. \ No newline at end of file