> ## 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 Conan

> Learn how to configure Endor Labs to access private Conan registries 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'].filter(Boolean).join(' ')} style={btnStyle(selected)} onClick={() => setActiveIndex(index)}>
              <span className="bt-tab-title">{tab.title}</span>
              {tab.badgeText ? <span className={['bt-badge', badgeClass].join(' ')}>{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>URL</strong> of your private Conan registry.</li><li>Enter a <strong>Remote Name</strong>, the logical name for this registry in the Conan client configuration.</li><li>Enter your <strong>Username</strong>.</li><li>Enter your <strong>Password</strong>.</li></ul>

export const showScopeWarning_0 = undefined

export const showGarTab_0 = undefined

export const showPluginRepo_0 = undefined

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

Endor Labs supports the following private Conan registry providers:

* JFrog Artifactory
* AWS CodeArtifact
* Self-hosted Conan servers

This integration enables Endor Labs to:

* Access private Conan 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>This toggle applies to Maven builds only. To resolve Gradle plugins from a private registry, configure a Gradle package manager integration instead. See <a href="/integrations/package-managers/gradle-private-package-manager#resolve-gradle-plugins-from-a-private-maven-registry">Resolve Gradle plugins from a private Maven registry</a>.</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**.

## Configure a private Conan registry using API

Use endorctl to create a `PackageManager` resource for your private Conan registry. Endor Labs supports two authentication methods: basic authentication and AWS CodeArtifact.

### Basic authentication

Use basic authentication to connect to JFrog Artifactory or a self-hosted Conan server.

Replace the following placeholders before running the command:

* `<namespace>` with your Endor Labs namespace
* `<registry-url>` with the URL of your Conan registry (for example, `https://your-artifactory.example.com/artifactory/api/conan/conan-local`)
* `<remote-name>` with a logical name for this registry (for example, `artifactory`)
* `<username>` with your registry username
* `<password-or-token>` with your registry password or API token

```shell expandable theme={null}
endorctl api create -r PackageManager -n <namespace> -d '
{
    "meta": {
        "name": "conan-private-registry",
        "description": "Private Conan registry with basic authentication"
    },
    "spec": {
        "conan": {
            "priority": 1,
            "url": "<registry-url>",
            "remote_name": "<remote-name>",
            "basic_auth": {
                "username": "<username>",
                "password": "<password-or-token>"
            }
        }
    },
    "propagate": false
}'
```

### AWS CodeArtifact authentication

Use AWS CodeArtifact authentication to connect to a Conan repository hosted in AWS CodeArtifact. Endor Labs assumes the specified IAM role to obtain short-lived credentials before each scan.

Before configuring this integration, create an IAM role with the required trust policy. See [Configure package manager integrations with AWS](/integrations/package-managers/aws-codeartifact) for instructions.

Replace the following placeholders before running the command:

* `<namespace>` with your Endor Labs namespace
* `<registry-url>` with your AWS CodeArtifact endpoint URL (for example, `https://<domain>-<account-id>.d.codeartifact.<region>.amazonaws.com/conan/<repository>/`)
* `<remote-name>` with a logical name for this registry
* `<domain>` with your AWS CodeArtifact domain name
* `<account-id>` with your AWS account ID
* `<repository>` with your AWS CodeArtifact repository name
* `<region>` with the AWS region hosting your CodeArtifact repository
* `<role-arn>` with the ARN of the IAM role Endor Labs should assume
* `<audience>` with the allowed audience value configured in your trust policy

```shell expandable theme={null}
endorctl api create -r PackageManager -n <namespace> -d '
{
    "meta": {
        "name": "conan-codeartifact-registry",
        "description": "Private Conan registry with AWS CodeArtifact authentication"
    },
    "spec": {
        "conan": {
            "priority": 1,
            "url": "<registry-url>",
            "remote_name": "<remote-name>",
            "aws": {
                "domain": "<domain>",
                "domain_owner": "<account-id>",
                "repository": "<repository>",
                "region": "<region>",
                "target_role_arn": "<role-arn>",
                "allowed_audience": "<audience>"
            }
        }
    },
    "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>
```
