# SonarQube

{% hint style="info" %}
Cortex connects to many third-party vendors whose system interfaces frequently change. As a result, integration behavior or configuration steps may shift without notice. If you encounter unexpected issues, check with your system administrator or refer to the vendor's documentation for the most current information. Additionally, integration sync times vary and are subject to scheduling overrides and timing variance.
{% endhint %}

[SonarQube](https://www.sonarsource.com/products/sonarqube/) is an open-source platform that empowers developers to write clean and safe code by continuously inspecting code quality and reviewing for bugs, vulnerabilities, and code duplication.

Integrating SonarQube with Cortex allows you to:

* Pull in code smells, bugs, code coverage, vulnerabilities, and custom metrics on [entity details pages](/ingesting-data-into-cortex/entities-overview/entities/details.md)
* Create [Scorecards](/standardize/scorecards.md) that track progress and drive alignment on projects involving your SonarQube projects

This integration is supported for both SonarQube Server and SonarQube Cloud.

## How to configure SonarQube with Cortex

### Self-hosted prerequisites

If you’re using a self-hosted instance of SonarQube, you’ll need to verify that your Cortex instance is able to reach the SonarQube instance.

If you're unable to directly allowlist our static IP, you can route requests through a secondary proxy in your network that has this IP allowlisted and have that proxy route traffic to your SonarQube instance.

### Configure the integration

There are two options for integrating SonarQube: the default configuration method and Cortex Axon Relay, a relay broker allows you to securely connect your on-premises SonarQube data.

To modify the integration configuration, see [Modifying an existing integration configuration](/ingesting-data-into-cortex/integrations.md#modifying-an-existing-integration-configuration).

{% tabs %}
{% tab title="Default" %}
**Configure SonarQube with the default method**

**Prerequisites**

Before getting started, create a SonarQube user token:

* [SonarQube Server token instructions](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/managing-tokens/)
* [SonarQube Cloud token instructions](https://docs.sonarsource.com/sonarqube-cloud/managing-your-account/managing-tokens/)

**Configuration**

1. In Cortex, navigate to the [SonarQube settings page](https://app.getcortexapp.com/admin/integrations/sonarqube).
   * Click **Integrations** from the main nav. Search for and select **SonarQube**.
2. Click **Add configuration**.
3. Configure the SonarQube integration form:
   * **Account alias**: Enter the alias you will use to tie entity registrations to different configuration accounts.
   * **Token**: Enter your user token from SonarQube.
   * **SonarQube URL**: Enter the URL for your SonarQube instance.
     * For example, `https://sonarcloud.io` if you are on SonarQube Cloud, or `https://sonarqube.mycompany.com` if your organization has their own instance.
4. Click **Save**.
   {% endtab %}

{% tab title="Relay broker" %}
**Configure SonarQube with Cortex Axon Relay**

See [Internally hosted integrations](/ingesting-data-into-cortex/integrations/axon-relay.md) for instructions. Make sure to follow the SonarQube-specific instructions for the docker-compose.yml file.
{% endtab %}
{% endtabs %}

#### Integrate via custom webhook

If you’re unable to expose your SonarQube instance to be reachable by Cortex, you can set up a [custom integration webhook](/ingesting-data-into-cortex/integrations/webhook.md). To learn more about SonarQube webhooks, visit their [webhook documentation](https://docs.sonarqube.org/latest/project-administration/webhooks/).

## How to connect Cortex entities to SonarQube projects

### Discovery

By default, Cortex will use the [Cortex tag](/ingesting-data-into-cortex/entities-overview/entities.md#cortex-tag) (e.g. `my-entity`) as the "best guess" for SonarQube component key. For example, if your Cortex tag is `my-entity`, then the corresponding component key in SonarQube should also be `my-entity`.

If your SonarQube component key doesn't cleanly match the Cortex tag, you can override this in the Cortex entity descriptor.

{% hint style="warning" %}
If you’re using build-system tooling to push analysis to SonarQube, the plugin (e.g. Gradle, Maven) may be automatically generating a project key that’s different from the repo name.
{% endhint %}

### Connect entities via YAML or the Cortex UI

{% tabs %}
{% tab title="Cortex UI" %}
**Connect SonarQube entities via the Cortex UI**

1. Navigate to an [entity's details page](/ingesting-data-into-cortex/entities-overview/entities/details.md) in Cortex.
2. In the upper right corner, click **Configure entity**.

   <div align="left"><figure><img src="/files/fEmHBrIb2mtAqwGC1cAq" alt="In the upper right side of an entity, click &#x22;Configure entity.&#x22;"><figcaption></figcaption></figure></div>
3. Click the **Code quality** link in the sidebar. \\

   <div align="left"><figure><img src="/files/BzjB8qNjyWtMmjN5IVqL" alt="Click Code quality, then enter your SonarQube project details." width="563"><figcaption></figcaption></figure></div>
4. In the center of the page, configure the details for your SonarQube project:
   * **Alias**: If you have multiple configurations, select the one that this project is associated with.
   * **Project**: Enter the project's name.
5. Click **Save changes**.
   {% endtab %}

{% tab title="Entity YAML" %}
**Editing the entity descriptor**

When managing entities via the [YAML entity descriptor](/ingesting-data-into-cortex/entities-overview/entities.md#defining-entities-via-yaml-file), you can configure SonarQube projects under the `x-cortex-static-analysis` block:

```yaml
x-cortex-static-analysis:
  sonarqube:
    project: sonar-project-key
    alias: sonarqube-alias
```

| Field         | Description                                                                                      | Required |
| ------------- | ------------------------------------------------------------------------------------------------ | :------: |
| `project`     | Project key defined in Sonarqube                                                                 |   **✓**  |
| `alias`       | Alias for the configuration in Cortex (only needed if you have opted into multi-account support) |          |
| {% endtab %}  |                                                                                                  |          |
| {% endtabs %} |                                                                                                  |          |

{% hint style="warning" %}
Cortex only supports one SonarQube project per entity.
{% endhint %}

## Using the SonarQube integration

### View SonarQube data on entity pages

Once the integration is established, data from SonarQube will be available in the **Code & security** page in an [entity's sidebar,](/ingesting-data-into-cortex/entities-overview/entities/details.md#entity-details-sidebar) as well as under the Overview tab. You can pull in data on **code smells, bugs, code coverage, vulnerabilities, and any custom metrics** available through Sonar. You can read more about metric definitions in Sonar's [documentation](https://docs.sonarsource.com/sonarqube/latest/user-guide/metric-definitions/).

* Metrics
  * Complexity
  * Duplications
  * Issues
  * Maintainability
  * Quality gates
  * Reliability
  * Security
  * Size
  * Tests
* Code freshness
* Code coverage

### Scorecards and CQL

With the SonarQube integration, you can create Scorecard rules and write CQL queries based on SonarQube projects.

See more examples in the [CQL Explorer](https://app.getcortexapp.com/admin/cql-explorer) in Cortex.

<details>

<summary>Analysis freshness</summary>

Duration since the last analysis was uploaded to SonarQube for a given project (with granularity of days).

**Definition:** `sonarqube.freshness()`

**Example**

For a Scorecard focused on operational readiness, you can use this expression to evaluate the freshness of static analysis metrics from SonarQube.

```
sonarqube.freshness() <= duration("P7D")
```

This rule checks that an analysis has been uploaded to SonarQube within the past week, which developers can use to make sure the metrics being pulled aren't stale.

This same rule would work in a security Scorecard - by making sure a SonarQube analysis has been uploaded within the last seven days, you make sure teams are monitoring for compliance to coding rules.

</details>

<details>

<summary>Metric</summary>

Query metrics generated by static analysis of your projects and sent to SonarQube:

* Alert status
* Bugs
* Code smells
* Coverage
* Duplicated lines
* Duplicated lines density
* Lines of code
* New blocker violations
* New bugs
* New code smells
* New coverage
* New security hotspots
* New violations
* Reliability rating
* Security hotspots
* Security rating
* Security review rating
* SQALE rating
* Vulnerabilities

**Definition:** `sonarqube.metric("<metric>")`

**Examples**

**Development maturity Scorecard**

**Code coverage**

For a Scorecard focused on development maturity, you can set a rule to make sure entities have greater than 80% code coverage.

```
sonarqube.metric("coverage") > 0.80
```

Developers can then immediately identify entities that are falling behind to make improvements to testing effectiveness. This Scorecard can also give users a more comprehensive sense of how well code is being tested, and where gaps exist.

This rule also serves as a secondary check that a given entity is hooked up to SonarQube and reporting frequently.

**Security Scorecard**

**Vulnerabilities**

You can also use the `sonarqube.metric("<metric>")` expression to write a rule for a security Scorecard, making sure production entities aren't deployed with a high number of security vulnerabilities. In an initial level of a Scorecard, you might write a rule to enforce 2 or less vulnerabilities:

```
sonarqube.metric("vulnerabilities") <= 2
```

Sonar recommends 0 vulnerabilities to achieve an A rating for Security, so a higher level in your Scorecard could enforce 0 vulnerabilities:

```
sonarqube.metric("vulnerabilities") = 0
```

**Code coverage**

In a security Scorecard, you could also use the following expression to evaluate code coverage. The [Sonar way quality gate](https://docs.sonarsource.com/sonarqube-server/quality-standards-administration/managing-quality-gates/introduction-to-quality-gates) requires code coverage to be at 80% or higher:

```
sonarqube.metric("coverage") > 80
```

Entities with low code coverage scores are more likely to be vulnerable to attack, so a lower threshold might make sense for certain security Scorecards.

**Security hotspots**

Rules focused on [security hotspots](https://docs.sonarsource.com/sonarqube/9.8/user-guide/security-hotspots/#what-is-a-security-hotspot) can also make sure entities are operating with minimal security issues. Hotspots highlight a security-sensitive piece of code where the overall application security may not be impacted; Sonar recommends reviewing 100% of hotspots. In the following rule example, you can aim for less than 2 hotspots that need review:

```
sonarqube.metric("security_hotspots") < 2
```

</details>

<details>

<summary>Project existence</summary>

SonarQube project exists for an entity.

**Definition:** `sonarqube != null`

**Example**

For a Scorecard focused on operational readiness, you can write a rule to make sure an entity has an associated SonarQube project.

```
sonarqube != null
```

Because having a SonarQube project set would be key for an entity to be evaluated via other SonarQube-related expressions, this rule would make sense in a Scorecard's initial level.

</details>

<details>

<summary>Issues</summary>

Query issues identified by static analysis of your projects and sent to SonarQube, including bugs, vulnerabilities, code smells, and more. If the statuses are not filled in, they will default to "OPEN" and "REOPENED" statuses to prevent fetching of resolved issues.

Sonar recommends targeting 0 new issues.

**Definition:** `sonarqube.issues("<types>", "<rules>", "<severities>", "<statuses>", "<lookback>"): List<SonarqubeIssue>`

**Example**

You can write a rule to check that an entity has fewer than 3 major java:S2142 bugs:

```
sonarqube.issues(types = ["bug"], rules = ["java:S2142"], severities = ["major"]).length <= 3
```

**Code smells**

In an initial level of a Scorecard, you could write a rule to check that an entity has fewer than 5 minor code smells:

```
sonarqube.issues(types = ["code_smell"], severities = ["minor"]).length < 5
```

In higher levels of the Scorecard, you could verify that the entity has 0 code smells, per Sonar's recommended best practices:

```
sonarqube.issues(types = ["code_smell"]).length < 1
```

</details>

### View integration logs <a href="#still-need-help" id="still-need-help"></a>

## FAQs and troubleshooting

#### **Does Cortex support SonarCloud?**

Yes. You can integrate with SonarCloud by following the same steps as integrating with SonarQube. In the URL field, use your `https://sonarcloud.io/` URL. You can also use multi-account support to add a self-hosted or SonarCloud instance by adding the URL for that instance during configuration.

#### **I’m seeing “Socket timed out when trying to connect to SonarQube” for all of my entities in Scorecards.**

This means that Cortex is unable to talk to your SonarQube instance. Make sure that your instance is running and accessible to Cortex.

#### **I’m using Gradle and I’ve verified that my project is in SonarQube, but Cortex is still showing me an error.**

Gradle automatically generates a project key which is equal to `[$:]$`. As a result, automatic discovery won’t work. You’ll need to override the project key in your Cortex [entity descriptor](#entity-descriptor).

#### **My project is in Sonar and Cortex is able to talk to SonarQube, but my score isn’t showing up.**

Try the following troubleshooting steps:

1. Make sure the project key in your YAML is exactly the same as the key in SonarQube.
2. Verify that the scores are in the “default branch” in SonarQube. If your scores are showing up in a `branch-a` in SonarQube, but your SonarQube default branch is `main`, Cortex will not be able to retrieve the scores.
3. Run the following curl command and verify there are metrics showing up in the response:

```bash
    curl -v -u : "https://[SONARQUBE HOST]/api/measures/
    component_tree?component=[SONARQUBE PROJECT KEY]&metricKeys=ncloc,coverage"
```

#### **What if I want to send custom data, but I don't have control over the integration touchpoint?**

If you don't have control of or access to the integration touchpoint (for example, if you're using a SonarQube notification webhook) you'll want to use the API to send custom data. You can find information on sending data to a custom data webhook [here](https://docs.cortex.io/api#tag/Custom-Data).

#### **Why might I see the SonarQube connection error `Component key not found`?**[**​**](https://docs.cortex.io/docs/reference/integrations/sonarqube#why-might-i-see-the-sonarqube-connection-error-component-key-not-found)

For SonarQube (and all integrations), Cortex will map the Cortex tag defined in the cortex.yaml for a given entity. For SonarQube specifically, the tag must **exactly match** the project ID in SonarQube. If these are not one-to-one, we recommend using the override detailed above to define the proper mapping for project ID and entity name.

#### **Why might I see the error `Sonarqube: Fail to request url` on my integration page or a `validity check failed` error while creating a Workflow?**[**​**](https://docs.cortex.io/docs/reference/integrations/sonarqube#why-might-i-see-the-error-sonarqube-fail-to-request-url-on-my-integration-page-or-a-validity-check-failed-error-while-creating-a-workflow)

This can happen if your external DNS certificate expired. Ensure that any certificates you're using are valid.

## Still need help?[​](https://docs.cortex.io/docs/reference/integrations/aws#still-need-help) <a href="#still-need-help" id="still-need-help"></a>

The following options are available to get assistance from the Cortex Customer Engineering team:

* **Email**: <help@cortex.io>, or open a support ticket in the in app Resource Center
* **Slack**: Users with a connected Slack channel will have a workflow added to their account. From here, you can either @CortexTechnicalSupport or add a `:ticket:` reaction to a question in Slack, and the team will respond directly.

Don’t have a Slack channel? Talk with your Customer Success Manager.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.cortex.io/ingesting-data-into-cortex/integrations/sonarqube.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
