> ## Documentation Index
> Fetch the complete documentation index at: https://docs.endorlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Private package manager integration for Swift

> Learn how to configure Endor Labs to access private Swift package repositories for dependency resolution and security scanning.

export const BadgeTabs = ({children}) => {
  const DEFAULT_BADGE_COLOR = 'gray';
  const FALLBACK_TAB_PREFIX = 'Tab ';
  const ARIA_ID_PREFIX = 'bt-tab-';
  const ACCENT_GREEN = '#26D07C';
  const BADGE_COLOR_CLASS = {
    green: 'bt-badge--green',
    blue: 'bt-badge--blue',
    orange: 'bt-badge--orange',
    red: 'bt-badge--red',
    purple: 'bt-badge--purple',
    yellow: 'bt-badge--yellow',
    gray: 'bt-badge--gray'
  };
  const readDataAttr = (props, kebabName) => {
    if (!props || typeof props !== 'object') return undefined;
    const direct = props[kebabName];
    if (direct !== undefined && direct !== null) return String(direct);
    return undefined;
  };
  const normalizeBadgeColor = raw => {
    if (!raw) return DEFAULT_BADGE_COLOR;
    const c = String(raw).toLowerCase().trim();
    return BADGE_COLOR_CLASS[c] ? c : DEFAULT_BADGE_COLOR;
  };
  const flattenChildren = (node, out) => {
    if (node === null || node === undefined) return;
    if (Array.isArray(node)) {
      for (const item of node) flattenChildren(item, out);
      return;
    }
    out.push(node);
  };
  const childToTabItem = (child, index, itemCount) => {
    if (child === null || child === undefined) return null;
    if (typeof child === 'string' || typeof child === 'number') {
      const text = String(child).trim();
      if (!text) return null;
      return {
        key: `text-${index}`,
        title: `${FALLBACK_TAB_PREFIX}${itemCount + 1}`,
        badgeText: '',
        badgeColor: DEFAULT_BADGE_COLOR,
        node: <span>{child}</span>
      };
    }
    if (typeof child !== 'object' || !child.props) return null;
    const p = child.props;
    const title = readDataAttr(p, 'data-title')?.trim() || `${FALLBACK_TAB_PREFIX}${itemCount + 1}`;
    const badgeText = readDataAttr(p, 'data-badge')?.trim() || '';
    const badgeColor = normalizeBadgeColor(readDataAttr(p, 'data-badge-color'));
    return {
      key: child.key == null ? `tab-${index}` : String(child.key),
      title,
      badgeText,
      badgeColor,
      node: child
    };
  };
  const tabItems = useMemo(() => {
    const arr = [];
    flattenChildren(children, arr);
    const items = [];
    for (const [i, child] of arr.entries()) {
      const item = childToTabItem(child, i, items.length);
      if (item) items.push(item);
    }
    return items;
  }, [children]);
  const [activeIndex, setActiveIndex] = useState(0);
  const [isDark, setIsDark] = useState(false);
  const [baseId] = useState(() => `${ARIA_ID_PREFIX}${Math.random().toString(36).slice(2, 11)}`);
  useEffect(() => {
    const check = () => {
      const r = document.documentElement;
      setIsDark(r.dataset.theme === 'dark' || r.classList.contains('dark'));
    };
    check();
    const obs = new MutationObserver(check);
    obs.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['data-theme', 'class']
    });
    return () => obs.disconnect();
  }, []);
  useEffect(() => {
    if (activeIndex >= tabItems.length && tabItems.length > 0) setActiveIndex(0);
  }, [activeIndex, tabItems.length]);
  const safeIndex = tabItems.length === 0 ? 0 : Math.min(activeIndex, tabItems.length - 1);
  const focusTabAt = nextIndex => {
    if (tabItems.length === 0) return;
    const wrapped = (nextIndex % tabItems.length + tabItems.length) % tabItems.length;
    setActiveIndex(wrapped);
    const btn = document.getElementById(`${baseId}-tab-${wrapped}`);
    if (btn && typeof btn.focus === 'function') btn.focus();
  };
  const onKeyDownTabList = event => {
    if (tabItems.length === 0) return;
    const key = event.key;
    if (key === 'ArrowRight' || key === 'ArrowDown') {
      event.preventDefault();
      focusTabAt(safeIndex + 1);
    } else if (key === 'ArrowLeft' || key === 'ArrowUp') {
      event.preventDefault();
      focusTabAt(safeIndex - 1);
    } else if (key === 'Home') {
      event.preventDefault();
      focusTabAt(0);
    } else if (key === 'End') {
      event.preventDefault();
      focusTabAt(tabItems.length - 1);
    }
  };
  if (tabItems.length === 0) return null;
  const containerStyle = {
    borderRadius: '0.5rem',
    overflow: 'hidden',
    border: isDark ? '1px solid rgba(38,208,124,0.2)' : '1px solid #a7e8c8',
    margin: '1rem 0'
  };
  const navStyle = {
    display: 'flex',
    flexWrap: 'wrap',
    gap: 0,
    background: isDark ? 'rgba(38,208,124,0.1)' : '#e6f9f0',
    borderBottom: isDark ? '1px solid rgba(38,208,124,0.2)' : '1px solid #a7e8c8',
    padding: '0 0.75rem'
  };
  const btnStyle = selected => ({
    display: 'inline-flex',
    alignItems: 'center',
    gap: '0.35rem',
    padding: '0.6rem 0.75rem',
    border: 'none',
    borderBottom: selected ? `2px solid ${ACCENT_GREEN}` : '2px solid transparent',
    background: 'transparent',
    color: isDark ? selected ? '#e6edf3' : 'rgba(255,255,255,0.6)' : selected ? '#111827' : '#4b5563',
    cursor: 'pointer',
    fontSize: '0.85rem',
    fontWeight: selected ? 600 : 400
  });
  const panelStyle = {
    padding: '1rem 1.25rem'
  };
  return <div className="bt-root" style={containerStyle}>
      <div className="not-prose bt-tablist" role="tablist" aria-orientation="horizontal" tabIndex={-1} onKeyDown={onKeyDownTabList} style={navStyle}>
        {tabItems.map((tab, index) => {
    const selected = index === safeIndex;
    const tabId = `${baseId}-tab-${index}`;
    const panelId = `${baseId}-panel-${index}`;
    const badgeClass = BADGE_COLOR_CLASS[tab.badgeColor] || BADGE_COLOR_CLASS.gray;
    return <button key={tab.key} type="button" id={tabId} role="tab" aria-selected={selected} aria-controls={panelId} tabIndex={selected ? 0 : -1} className={`bt-tab-btn${selected ? ' bt-tab-btn--active' : ''}`} style={btnStyle(selected)} onClick={() => setActiveIndex(index)}>
              <span className="bt-tab-title">{tab.title}</span>
              {tab.badgeText ? <span className={`bt-badge ${badgeClass}`}>{tab.badgeText}</span> : null}
            </button>;
  })}
      </div>
      {tabItems.map((tab, index) => {
    const panelId = `${baseId}-panel-${index}`;
    const tabId = `${baseId}-tab-${index}`;
    const hidden = index !== safeIndex;
    return <div key={`${tab.key}-panel`} id={panelId} role="tabpanel" aria-labelledby={tabId} hidden={hidden} className="bt-tabpanel" style={{
      display: hidden ? 'none' : 'block',
      ...panelStyle
    }}>
            {tab.node}
          </div>;
  })}
    </div>;
};

export const basicFields_0 = <ul><li>Enter the <strong>Package manager URL</strong>.</li><li>Enter a <strong>Scope</strong> to restrict this registry to a specific package scope.</li><li>Under <strong>Authentication Method</strong>, choose <strong>Authentication Token</strong> or <strong>Basic Auth</strong>.</li><li>Enter the <strong>Authentication</strong> value for the selected method.</li></ul>

export const showScopeWarning_0 = undefined

export const showGarTab_0 = undefined

export const showPluginRepo_0 = undefined

Configure Endor Labs to integrate with private Swift package repositories to access proprietary dependencies during security scanning and analysis. When your Swift projects depend on packages hosted in private or corporate repositories, Endor Labs requires authentication credentials to resolve these dependencies and generate a complete bill of materials.

This integration enables Endor Labs to:

* Access private Swift packages during dependency resolution
* Generate comprehensive security analysis including private dependencies
* Maintain complete visibility into your software supply chain

Endor Labs generally respects package authentication and configuration settings and a package manager integration is usually not required to scan private packages successfully.

* Use package manager integrations to simplify scanning when authentication to private repositories is not part of standard manifest or settings files.
* Package manager integrations allow you to set custom repositories for each package ecosystem and the priority of each repository for scanning.

To set up a package manager integration:

1. Select **User menu** > **Integrations** from the left sidebar.
2. Select **Add** next to the package manager configuration you want to add.
3. Select **Add Package Manager**.
4. Enter a **Name** for the integration.
5. Choose an authentication type and complete the required fields.

   <BadgeTabs>
     <div data-title="Basic">
       Enter your registry URL and static credentials.

       {basicFields_0 || <ul><li>Enter the <strong>URL</strong> of your private package registry.</li><li>Enter your <strong>Username</strong>.</li><li>Enter your <strong>Password</strong>.</li></ul>}

       {showScopeWarning_0 && <Warning>If you do not enter a scope, all dependency downloads are routed to this registry and the public npm registry is not attempted as a fallback. This may cause scans to fail if your private registry does not host all required packages.</Warning>}
     </div>

     <div data-title="AWS CodeArtifact"><p>AWS CodeArtifact authentication uses OIDC token federation. No static credentials are stored. Enter the following fields:</p><ul><li><strong>Domain</strong>: Name of your AWS CodeArtifact domain.</li><li><strong>Domain Owner</strong>: AWS account ID that owns the domain.</li><li><strong>Repository</strong>: Name of the CodeArtifact repository.</li><li><strong>Target Role ARN</strong>: ARN of the IAM role Endor Labs assumes.</li><li><strong>Allowed Audience</strong>: Audience value specified when you created the OIDC provider.</li><li><strong>Region</strong>: AWS region of the repository.</li></ul><p>See <a href="/integrations/package-managers/aws-codeartifact">Configure integration with AWS CodeArtifact</a> for setup instructions.</p></div>

     {showGarTab_0 && <div data-title="Google Artifact Registry"><p>Google Artifact Registry authentication uses short-lived OAuth2 tokens minted from a service account key. No static registry credentials are stored. Enter the following fields:</p><ul><li><strong>GCP Project ID</strong>: ID of the GCP project that hosts the Artifact Registry repository.</li><li><strong>Location</strong>: GCP region of the repository, for example <code>us-central1</code>.</li><li><strong>Repository</strong>: Name of the GAR repository.</li><li><strong>Service Account Key</strong>: Full JSON contents of a GCP service account key.</li></ul><p>See <a href="/integrations/package-managers/google-artifact-registry">Configure integration with Google Artifact Registry</a> for setup instructions.</p></div>}
   </BadgeTabs>

<ol start="6">
  <li>Optionally, under <strong>Advanced</strong>, select <strong>Propagate this package manager to all child namespaces</strong> to share this integration with child namespaces.</li>

  {showPluginRepo_0 && <li>Optionally, under <strong>Advanced</strong>, select <strong>Use this package manager as a plugin repository</strong> if this registry hosts build plugins rather than library dependencies.<Note><p>When enabled, the registry is added to <code>{"<pluginRepositories>"}</code> for build plugin resolution only and not for library dependency resolution. To use a registry for both purposes, create two separate Maven package manager integrations.</p><p>Enabling <strong>Use this package manager as a plugin repository</strong> also enables plugin resolution for Gradle builds that use Maven-compatible plugin registries.</p></Note></li>}

  <li>Click <strong>Add Package Manager</strong>.</li>
</ol>

### Test package manager integration

You can test the connection to a configured package manager to verify that Endor Labs can reach the repository. To test the connection:

1. Select **User menu** > **Integrations** from the left sidebar.
2. Click **Manage** in the package manager configuration you want to customize.
3. Click the vertical three dots of the package manager configured and select **Test Connection**.

<Note>
  The integration does not perform authentication or authorization checks on the package manager repository.
</Note>

### Edit package manager integration

You can edit an existing package manager integration to update the name, repository URL, or authentication credentials. To edit a package manager integration:

1. Select **User menu** > **Integrations** from the left sidebar.
2. Click **Manage** next to the package manager you want to edit.
3. Click the vertical three dots on the configured integration you want to edit and select **Edit**.
4. You can modify the name, package manager URL, and credentials.
5. Click **Save Changes**.

## Package manager integration for SwiftPM using API

Use endorctl to create a package manager resource for your private swift registry and authenticate using one of the following methods:

* Basic authentication using username and password
* Authentication token

### Basic authentication using username and password

Run the following command to create a package manager resource and authenticate to Swift registry using basic authentication credentials with scope.

Replace:

* `namespace` with your namespace.
* `username` with your username
* `xxxx` with your password.
* `scope` with your scope. For example, `"scope":"abc-corp"`.

```shell expandable theme={null}
endorctl api create -r PackageManager -n <namespace> -d '
{
    "meta": {
        "name": "test swift",
        "description": "setup swift registry with basic auth"
    },
    "spec": {
        "swift": {
            "priority": 1,
            "url": "package manager url",
            "basic_auth": {
                "username": "username",
                "password": "xxxx"
            },
            "scope": "scope"
        }
    },
    "propagate": false
}'

```

### Authentication token

Run the following command to create a package manager resource and authenticate to Swift registry using authentication token with scope.

Replace:

* `namespace` with your namespace
* `token` with your Swift registry authentication token.
* `scope` with your scope. For example, `"scope":"abc-corp"`.

```shell theme={null}
endorctl api create -r PackageManager -n <namespace> -d '
{
   "meta": {
       "name": "test swift",
       "description": "setup swift registry with token"
   },
   "spec": {
       "swift": {
           "priority": 1,
           "url": "package manager url",
           "token": "authentication token",
           "scope": "scope"
       }
   },
   "propagate": false
} '
```

### Fetch package manager using API

Run the following command to fetch the package manager using the UUID.

```bash theme={null}
endorctl api get -r packageManager -n <your namespace>  --uuid <package-manager-uuid>
```

### Delete package manager using API

Run the following command to delete the package manager using the UUID.

```bash theme={null}
endorctl api delete -r packageManager -n <your namespace>  --uuid <package-manager-uuid>
```
