From 4cbcfb8cd755472ea54d3a6306747c3648108ace Mon Sep 17 00:00:00 2001 From: Paul Osinski Date: Mon, 12 May 2025 16:16:03 -0600 Subject: [PATCH 1/7] delete redundant articles --- .../archived_docs/integrations/_index.md | 13 - .../integrations/social-authentication.md | 519 ------------------ .../open_source/archived_docs/usage/models.md | 78 --- .../archived_docs/usage/permissions.md | 125 ----- .../archived_docs/usage/productgrading.md | 50 -- .../archived_docs/usage/workflows.md | 63 --- 6 files changed, 848 deletions(-) delete mode 100644 docs/content/en/open_source/archived_docs/integrations/_index.md delete mode 100644 docs/content/en/open_source/archived_docs/integrations/social-authentication.md delete mode 100644 docs/content/en/open_source/archived_docs/usage/models.md delete mode 100644 docs/content/en/open_source/archived_docs/usage/permissions.md delete mode 100644 docs/content/en/open_source/archived_docs/usage/productgrading.md delete mode 100644 docs/content/en/open_source/archived_docs/usage/workflows.md diff --git a/docs/content/en/open_source/archived_docs/integrations/_index.md b/docs/content/en/open_source/archived_docs/integrations/_index.md deleted file mode 100644 index 38a96445b03..00000000000 --- a/docs/content/en/open_source/archived_docs/integrations/_index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: "Integrations" -description: "A lot of integrations help to fit DefectDojo in your environment" -weight: 3 -toc: true -sidebar: - collapsed: true -seo: - title: "" # custom title (optional) - description: "" # custom description (recommended) - canonical: "" # custom canonical URL (optional) - robots: "" # custom robot tags (optional) ---- diff --git a/docs/content/en/open_source/archived_docs/integrations/social-authentication.md b/docs/content/en/open_source/archived_docs/integrations/social-authentication.md deleted file mode 100644 index 91ebd89d4e1..00000000000 --- a/docs/content/en/open_source/archived_docs/integrations/social-authentication.md +++ /dev/null @@ -1,519 +0,0 @@ ---- -title: "Authentication via OAuth2/SAML2" -description: "OAuth2/SAML2 let users authenticate against enterprise directories." -draft: false -weight: 3 -exclude_search: true ---- - -## Auth0 - -In the same way as with other identity providers, it's now possible to -leverage Auth0 to authenticate users on DefectDojo. - -1. Inside your Auth0 dashboard create a new application (Applications / - Create Application / Single Page Web Application). -2. On the new application set the following fields: - - Name: "Defectdojo" - - Allowed Callback URLs: - **https://the_hostname_you_have_dojo_deployed:your_server_port/complete/auth0/** -3. Copy the following info from the application: - - Domain - - Client ID - - Client Secret -4. Now, edit the settings (see [Configuration](../../open_source/installation/configuration)) with the following - information: - - {{< highlight python >}} - DD_SOCIAL_AUTH_AUTH0_OAUTH2_ENABLED=True - DD_SOCIAL_AUTH_AUTH0_KEY=(str, '**YOUR_CLIENT_ID_FROM_STEP_ABOVE**'), - DD_SOCIAL_AUTH_AUTH0_SECRET=(str,'**YOUR_CLIENT_SECRET_FROM_STEP_ABOVE**'), - DD_SOCIAL_AUTH_AUTH0_DOMAIN=(str, '**YOUR_AUTH0_DOMAIN_FROM_STEP_ABOVE**'), - {{< /highlight >}} - -5. Restart DefectDojo, and you should now see a **Login with Auth0** - button on the login page. - -## Google - -New to DefectDojo, a Google account can now be used for Authentication, -Authorization, and a DefectDojo user. Upon login with a Google account, -a new user will be created if one does not already exist. The criteria -for determining whether a user exists is based on the users username. In -the event a new user is created, the username is that of the Google -address without the domain. Once created, the user creation process will -not happen again as the user is recalled by its username, and logged in. -In order to make the magic happen, a Google authentication server needs -to be created. Closely follow the steps below to guarantee success. - -1. Navigate to the following address and either create a new account, - or login with an existing one: [Google Developers - Console](https://console.developers.google.com) -2. Once logged in, find the key shaped button labeled **Credentials** - on the left side of the screen. Click **Create Credentials**, and - choose **OAuth Client ID**: - - ![image](images/google_1.png) - -3. Select **Web Applications**, and provide a descriptive name for the - client. - - ![image](images/google_2.png) - -4. Add the pictured URLs in the **Authorized Redirect URLs** section. - This part is very important. If there are any mistakes here, the - authentication client will not authorize the request, and deny - access. -5. Once all URLs are added, finish by clicking **Create** - -6. Now with the authentication client created, the **Client ID** and - **Client Secret Key** need to be copied over to the settings. - Click the newly created client and copy the values: - - ![image](images/google_3.png) - -7. Edit the settings (see [Configuration](../../open_source/installation/configuration) with the following - information: - - {{< highlight python >}} - DD_SOCIAL_AUTH_GOOGLE_OAUTH2_ENABLED=True, - DD_SOCIAL_AUTH_GOOGLE_OAUTH2_KEY=(str, '**YOUR_CLIENT_ID_FROM_STEP_ABOVE**'), - DD_SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET=(str, '**YOUR_CLIENT_SECRET_FROM_STEP_ABOVE**'), - {{< /highlight >}} - - To authorize users you will need to set the following: - - {{< highlight python >}} - DD_SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = ['example.com', 'example.org'] - {{< /highlight >}} - - As an environment variable: - - {{< highlight python >}} - DD_SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = example.com,example.org - {{< /highlight >}} - - or - - {{< highlight python >}} - DD_SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_EMAILS = [''] - {{< /highlight >}} - - As an environment variable: - - {{< highlight python >}} - DD_SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_EMAILS = email@example.com,email2@example.com - {{< /highlight >}} - -## OKTA - -In a similar fashion to that of Google, using OKTA as a OAuth2 provider -carries the same attributes and a similar procedure. Follow along below. - -1. Navigate to the following address and either create a new account, - or login with an existing one: [OKTA Account - Creation](https://www.okta.com/developer/signup/) -2. Once logged in, enter the **Applications** and click **Add - Application**: - - ![image](images/okta_1.png) - -3. Select **Web Applications**. - - ![image](images/okta_2.png) - -4. Add the pictured URLs in the **Login Redirect URLs** section. This - part is very important. If there are any mistakes here, the - authentication client will not authorize the request, and deny - access. Check the **Implicit** box as well. - - ![image](images/okta_3.png) - -5. Once all URLs are added, finish by clicking **Done**. - -6. Return to the **Dashboard** to find the **Org-URL**. Note this value - as it will be important in the settings file. - - ![image](images/okta_4.png) - -7. Now, with the authentication client created, the **Client ID** and - **Client Secret** Key need to be copied over to the settings. - Click the newly created client and copy the values: - - ![image](images/okta_5.png) - -8. Edit the settings (see [Configuration](../../open_source/installation/configuration)) with the following - information: - - {{< highlight python >}} - DD_SOCIAL_AUTH_OKTA_OAUTH2_ENABLED=True, - DD_SOCIAL_AUTH_OKTA_OAUTH2_KEY=(str, '**YOUR_CLIENT_ID_FROM_STEP_ABOVE**'), - DD_SOCIAL_AUTH_OKTA_OAUTH2_SECRET=(str, '**YOUR_CLIENT_SECRET_FROM_STEP_ABOVE**'), - DD_SOCIAL_AUTH_OKTA_OAUTH2_API_URL=(str, 'https://{your-org-url}/oauth2'), - {{< /highlight >}} - -If during the login process you get the following error: *The -'redirect_uri' parameter must be an absolute URI that is whitelisted -in the client app settings.* and the `redirect_uri` HTTP -GET parameter starts with `http://` instead of -`https://` you need to add -`SOCIAL_AUTH_REDIRECT_IS_HTTPS = True` in the settings. - -## Azure Active Directory -### Azure AD Configuration -You can now use your corporate Azure Active Directory to authenticate -users to Defect Dojo. Users will be using your corporate Azure AD -account (A.K.A. Office 365 identity) to authenticate via OAuth, and all -the conditional access rules and benefits from Azure Active Directory -will also apply to the Defect Dojo Authentication. Once the user signs -in, it will try to match the UPN of the user to an existing e-mail from -a user in Defect Dojo, and if no match is found, a new user will be -created in Defect Dojo, associated with the unique id/value of the user -provided by your Azure AD tenant. Then, you can assign roles to this -user, such as 'superuser'. - -1. Navigate to the following address and follow instructions to create - a new app registration - - - - -2. Once you register an app, take note of the following information: - - - **Application (client) ID** - - **Directory (tenant) ID** - - Under Certificates & Secrets, create a new **Client Secret** - -3. Under Authentication > Redirect URIs, add a *WEB* type of uri where - the redirect points to - - - - - **OR** - - **https://the_hostname_you_have_dojo_deployed:your_server_port/complete/azuread-tenant-oauth2/** - -4. Edit the settings (see [Configuration](../../open_source/installation/configuration)) with the following - information: - - {{< highlight python >}} - DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY=(str, 'YOUR_APPLICATION_ID_FROM_STEP_ABOVE'), - DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET=(str, 'YOUR_CLIENT_SECRET_FROM_STEP_ABOVE'), - DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID=(str, 'YOUR_DIRECTORY_ID_FROM_STEP_ABOVE'), - DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_ENABLED = True - {{< /highlight >}} - -5. Restart your Dojo, and you should now see a **Login with Azure AD** - button on the login page which should *magically* work - -### Automatic Import of User-Groups -To import groups from Azure AD users, the following environment variable needs to be set: - - {{< highlight python >}} - DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_GET_GROUPS=True - {{< /highlight >}} - -This will ensure the user is added to all the groups found in the Azure AD Token. Any missing groups will be created in DefectDojo (unless filtered). This group synchronization allows for product access via groups to limit the products a user can interact with. - -The Azure AD token returned by Azure will also need to be configured to include group IDs. Without this step, the -token will not contain any notion of a group, and the mapping process will report that the current user is not a member of any -groups. To update the format of the token, add a group claim that applies to whatever group type you are using. -If unsure of what type that is, select `All Groups`. Do not activate `Emit groups as role claims` within the Azure AD -"Token configuration" page. - -Application API permissions need to be updated with the `Group.Read.All` permission so that groups can be read on behalf -of the user that has successfully signed in. - -To limit the amount of groups imported from Azure AD, a regular expression can be used as the following: - - {{< highlight python >}} - DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_GROUPS_FILTER='^team-.*' # or 'teamA|teamB|groupC' - {{< /highlight >}} - -### Automatic Cleanup of User-Groups - -To prevent authorization creep, old Azure AD groups a user is not having anymore can be deleted with the following environment parameter: - - {{< highlight python >}} - DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_CLEANUP_GROUPS=True - {{< /highlight >}} - -When a user is removed from a given group in Azure AD, they will also be removed from the corresponding group in DefectDojo. -If there is a group in DefectDojo, that no longer has any members, it will be left as is for record purposes. - -## Gitlab - -In a similar fashion to that of Google and OKTA, using Gitlab as a -OAuth2 provider carries the same attributes and a similar procedure. -Follow along below. - -1. Navigate to your Gitlab settings page and got to the Applications - section - - - - - **OR** - - **https://the_hostname_you_have_gitlab_deployed:your_gitlab_port/profile/applications** - -2. Choose a name for your application -3. For the Redirect URI, enter the DefectDojo URL with the following - format - - - **https://the_hostname_you_have_dojo_deployed:your_server_port/complete/gitlab/** - -4. Edit the settings (see [Configuration](../../open_source/installation/configuration)) with the following - information: - - {{< highlight python >}} - DD_SOCIAL_AUTH_GITLAB_KEY=(str, 'YOUR_APPLICATION_ID_FROM_STEP_ABOVE'), - DD_SOCIAL_AUTH_GITLAB_SECRET=(str, 'YOUR_SECRET_FROM_STEP_ABOVE'), - DD_SOCIAL_AUTH_GITLAB_API_URL=(str, 'https://gitlab.com'), - DD_SOCIAL_AUTH_GITLAB_OAUTH2_ENABLED = True - {{< /highlight >}} - - Additionally, if you want to import your Gitlab projects as DefectDojo - products, add the following line to your settings: - - {{< highlight python >}} - DD_SOCIAL_AUTH_GITLAB_PROJECT_AUTO_IMPORT = True - {{< /highlight >}} - - **Important:** if you enable this setting on already working instance with gitlab integrations, it will require new grant "read_repository" by user - -5. Restart DefectDojo, and you should now see a **Login with Gitlab** - button on the login page. - -## Keycloak -There is also an option to use Keycloak as OAuth2 provider in order to authenticate users to Defect Dojo, also by using -the social-auth plugin. - -Here are suggestion on how to configure Keycloak and DefectDojo: - -### Configure Keycloak -(assuming you already have an existing realm, otherwise create one) -1. Navigate to your keycloak realm and add a new client of type openid-connect. Choose a name for the client id and use this value below for DD_SOCIAL_AUTH_KEYCLOAK_KEY). -2. In the client settings: - * Set `access type` to `confidential` - * Under `valid Redirect URIs`, add the URI to your defect dojo installation, e.g. 'https:///*' - * Under `web origins`, add the same (or '+') - * Under `Fine grained openID connect configuration` -> `user info signed response algorithm`: set to `RS256` - * Under `Fine grained openID connect configuration` -> `request object signature algorithm`: set to `RS256` - * -> save these settings in keycloak (hit save button) -3. Under `Scope` -> `Full Scope Allowed` set to `off` -4. Under `mappers` -> add a custom mapper here: - * Name: `aud` - * Mapper type: `audience` - * Included audience: select your client/client-id here - * Add ID to token: `off` - * Add access to token: `on` -5. Under `credentials`: copy the secret (and use as DD_SOCIAL_AUTH_KEYCLOAK_SECRET below) -6. In your realm settings -> keys: copy the "Public key" (signing key) (use for DD_SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY below) -7. In your realm settings -> general -> endpoints: look into openId endpoint configuration - and look up your authorization and token endpoint (use them below) - -### Configure OIDC -Provides the option to authenticate users using a generic OIDC provider. - -The minimum configuration requires: - - {{< highlight python >}} - DD_SOCIAL_AUTH_OIDC_AUTH_ENABLED=True, - DD_SOCIAL_AUTH_OIDC_OIDC_ENDPOINT=(str, 'https://example.com'), - DD_SOCIAL_AUTH_OIDC_KEY=(str, 'YOUR_CLIENT_ID'), - DD_SOCIAL_AUTH_OIDC_SECRET=(str, 'YOUR_CLIENT_SECRET') - {{< /highlight >}} - -The rest of the OIDC configuration will be auto-detected by fetching data from: - - /.well-known/open-id-configuration/ - -You can also optionally set the following: - - {{< highlight python >}} - DD_SOCIAL_AUTH_OIDC_ID_KEY=(str, ''), #the key associated with the OIDC user IDs - DD_SOCIAL_AUTH_OIDC_USERNAME_KEY=(str, ''), #the key associated with the OIDC usernames - DD_SOCIAL_AUTH_OIDC_WHITELISTED_DOMAINS=(list, ['']), #list of domains allowed for login - DD_SOCIAL_AUTH_OIDC_JWT_ALGORITHMS=(list, ["RS256","HS256"]), - DD_SOCIAL_AUTH_OIDC_ID_TOKEN_ISSUER=(str, ''), - DD_SOCIAL_AUTH_OIDC_ACCESS_TOKEN_URL=(str, ''), - DD_SOCIAL_AUTH_OIDC_AUTHORIZATION_URL=(str, ''), - DD_SOCIAL_AUTH_OIDC_USERINFO_URL=(str, ''), - DD_SOCIAL_AUTH_OIDC_JWKS_URI=(str, ''), - {{< /highlight >}} - -### Configure Defect Dojo -Edit the settings (see [Configuration](../../open_source/installation/configuration)) with the following - information: - - {{< highlight python >}} - DD_SESSION_COOKIE_SECURE=True, - DD_CSRF_COOKIE_SECURE=True, - DD_SECURE_SSL_REDIRECT=True, - DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_ENABLED=True, - DD_SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY=(str, ''), - DD_SOCIAL_AUTH_KEYCLOAK_KEY=(str, ''), - DD_SOCIAL_AUTH_KEYCLOAK_SECRET=(str, ''), - DD_SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL=(str, ''), - DD_SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL=(str, '') - {{< /highlight >}} - -or, alternatively, for helm configuration, add this to the `extraConfig` section: - -```yaml -DD_SESSION_COOKIE_SECURE: 'True' -DD_CSRF_COOKIE_SECURE: 'True' -DD_SECURE_SSL_REDIRECT: 'True' -DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_ENABLED: 'True' -DD_SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY: '' -DD_SOCIAL_AUTH_KEYCLOAK_KEY: '' -DD_SOCIAL_AUTH_KEYCLOAK_SECRET: '' -DD_SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL: '' -DD_SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL: '' -``` - -Optionally, you *can* set `DD_SOCIAL_AUTH_KEYCLOAK_LOGIN_BUTTON_TEXT` in order to customize the login button's text caption. - -## GitHub Enterprise -1. Navigate to your GitHub Enterprise Server and follow instructions to create a new OAuth App [https://docs.github.com/en/enterprise-server/developers/apps/building-oauth-apps/creating-an-oauth-app](https://docs.github.com/en/enterprise-server/developers/apps/building-oauth-apps/creating-an-oauth-app) -2. Choose a name for your application -3. For the Redirect URI, enter the DefectDojo URL with the following - format - - **https://the_hostname_you_have_dojo_deployed:your_server_port/complete/github-enterprise/** -4. Edit the settings (see [Configuration](../../open_source/installation/configuration)) with the following - information: - {{< highlight python >}} - DD_SOCIAL_AUTH_GITHUB_ENTERPRISE_KEY=(str, 'GitHub Enterprise OAuth App Client ID'), - DD_SOCIAL_AUTH_GITHUB_ENTERPRISE_SECRET=(str, 'GitHub Enterprise OAuth App Client Secret'), - DD_SOCIAL_AUTH_GITHUB_ENTERPRISE_URL=(str, 'https://github..com/'), - DD_SOCIAL_AUTH_GITHUB_ENTERPRISE_API_URL=(str, 'https://github..com/api/v3/'), - DD_SOCIAL_AUTH_GITHUB_ENTERPRISE_OAUTH2_ENABLED = True, - {{< /highlight >}} -5. Restart DefectDojo, and you should now see a **Login with GitHub Enterprise** - button on the login page. - -## SAML 2.0 -In a similar direction to OAuth, this SAML addition provides a more secure -perogative to SSO. For definitions of terms used and more information, -see the plugin [plugin homepage](https://github.com/IdentityPython/djangosaml2). - -1. Navigate to your SAML IdP and find your metadata -2. Edit the settings (see [Configuration](../../open_source/installation/configuration)) with the following - information: - - {{< highlight python >}} - DD_SAML2_ENABLED=(bool, **True**), - # SAML Login Button Text - DD_SAML2_LOGIN_BUTTON_TEXT=(str, 'Login with SAML'), - # If the metadata can be accessed from a url, try the - DD_SAML2_METADATA_AUTO_CONF_URL=(str, ''), - # Otherwise, downlaod a copy of the metadata into an xml file, and - # list the path in DD_SAML2_METADATA_LOCAL_FILE_PATH - DD_SAML2_METADATA_LOCAL_FILE_PATH=(str, '/path/to/your/metadata.xml'), - # Fill in DD_SAML2_ATTRIBUTES_MAP to corresponding SAML2 userprofile attributes provided by your IdP - DD_SAML2_ATTRIBUTES_MAP=(dict, { - # format: SAML attrib:django_user_model - 'Email': 'email', - 'UserName': 'username', - 'Firstname': 'first_name', - 'Lastname': 'last_name' - }), - # May configure the optional fields - {{< /highlight >}} - -NOTE: *DD_SAML2_ATTRIBUTES_MAP* in k8s can be referenced as extraConfig (e.g. `DD_SAML2_ATTRIBUTES_MAP: 'Email'='email', 'Username'='username'...`) - -NOTE: *DD_SITE_URL* might also need to be set depending on the choices you make with the metadata.xml provider. (File versus URL). - -4. Checkout the SAML section in dojo/`dojo/settings/settings.dist.py` and verfiy if it fits your requirement. If you need help, take a look at the [plugin -documentation](https://djangosaml2.readthedocs.io/contents/setup.html#configuration). - -5. Restart DefectDojo, and you should now see a **Login with SAML** button (default setting of DD_SAML2_LOGIN_BUTTON_TEXT) on the login page. - -NOTE: In the case when IDP is configured to use self signed (private) certificate, -than CA needs to be specified by define environments variable -REQUESTS_CA_BUNDLE that points to the path of private CA certificate. - -### Advanced Configuration -The [https://github.com/IdentityPython/djangosaml2](djangosaml2) plugin has a lot of options. For details take a look at the [plugin -documentation](https://djangosaml2.readthedocs.io/contents/setup.html#configuration). All default options in DefectDojo can overwritten in the local_settings.py. If you want to change the organization name, you can add the following lines: - -{{< highlight python >}} -if SAML2_ENABLED: - SAML_CONFIG['contact_person'] = [{ - 'given_name': 'Extra', - 'sur_name': 'Example', - 'company': 'DefectDojo', - 'email_address': 'dummy@defectdojo.com', - 'contact_type': 'technical' - }] - SAML_CONFIG['organization'] = { - 'name': [('DefectDojo', 'en')], - 'display_name': [('DefectDojo', 'en')], - }, -{{< /highlight >}} - -### Migration from django-saml2-auth -Up to relase 1.15.0 the SAML integration was based on [https://github.com/fangli/django-saml2-auth](django-saml2-auth). Which the switch to djangosaml2 some parameters has changed: - -* DD_SAML2_ASSERTION_URL: not necessary any more - automatically generated -* DD_SAML2_DEFAULT_NEXT_URL: not necessary any more - default forwarding from defectdojo is used -* DD_SAML2_NEW_USER_PROFILE: not possible any more - default profile is used, see User Permissions -* DD_SAML2_ATTRIBUTES_MAP: Syntax has changed -* DD_SAML2_CREATE_USER: Default value changed to False, to avoid security breaches - -## RemoteUser - -This implementation is suitable if the DefectDojo instance is placed behind HTTP Authentication Proxy. -Dojo expects that the proxy will perform authentication and pass HTTP requests to the Dojo instance with filled HTTP headers. -The proxy should check if an attacker is not trying to add a malicious HTTP header and bypass authentication. - -Values which need to be set: - -* `DD_AUTH_REMOTEUSER_ENABLED` - Needs to be set to `True` -* `DD_AUTH_REMOTEUSER_USERNAME_HEADER` - Name of the header which contains the username -* `DD_AUTH_REMOTEUSER_EMAIL_HEADER`(optional) - Name of the header which contains the email -* `DD_AUTH_REMOTEUSER_FIRSTNAME_HEADER`(optional) - Name of the header which contains the first name -* `DD_AUTH_REMOTEUSER_LASTNAME_HEADER`(optional) - Name of the header which contains the last name -* `DD_AUTH_REMOTEUSER_GROUPS_HEADER`(optional) - Name of the header which contains the comma-separated list of groups; user will be assigned to these groups (missing groups will be created) -* `DD_AUTH_REMOTEUSER_GROUPS_CLEANUP`(optional) - Same as [#automatic-import-of-user-groups](AzureAD implementation) -* `DD_AUTH_REMOTEUSER_TRUSTED_PROXY` - Comma separated list of proxies; Simple IP and CIDR formats are supported -* `DD_AUTH_REMOTEUSER_LOGIN_ONLY`(optional) - Check [Django documentation](https://docs.djangoproject.com/en/3.2/howto/auth-remote-user/#using-remote-user-on-login-pages-only) - -*WARNING:* There is possible spoofing of headers (for all `DD_AUTH_REMOTEUSER_xxx_HEADER` values). Read Warning in [Django documentation](https://docs.djangoproject.com/en/3.2/howto/auth-remote-user/#configuration) - -## User Permissions - -When a new user is created via the social-auth, only the default permissions are active. This means that the newly created user does not have access to add, edit, nor delete anything within DefectDojo. There are two parameters in the System Settings to influence the permissions for newly created users: - -### Default group - -When both the parameters `Default group` and `Default group role` are set, the new user will be a member of the given group with the given role, which will give him the respective permissions. - -### Groups from Identity Providers - -Some Identity Providers are able to send list of groups to which should user belongs. This functionality is implemented only for Identity Providers mentioned below. For all others, we will be more than happy for contribution (hint: functions `assign_user_to_groups` and `cleanup_old_groups_for_user` from [`dojo/pipeline.py`](https://github.com/DefectDojo/django-DefectDojo/blob/master/dojo/pipeline.py) might be useful). - -- [Azure](#automatic-import-of-user-groups): Check `DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_GET_GROUPS` and `DD_SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_CLEANUP_GROUPS` -- [RemoteUser](#remoteuser): Check `DD_AUTH_REMOTEUSER_GROUPS_HEADER` and `DD_AUTH_REMOTEUSER_GROUPS_CLEANUP` - -## Login speed-up - -You can bypass the login form if you are only using SSO/Social authentication for login in by enabling these two environment variables: - -```yaml -DD_SOCIAL_LOGIN_AUTO_REDIRECT: "true" -DD_SOCIAL_AUTH_SHOW_LOGIN_FORM: "false" -``` - -### Login form fallback - -If you are using "login speed-up", it can be useful to be able to login by the standard way, for example when an admin -user needs to log in because of a change of some settings or permissions. This feature is accessible by a visiting the URL -`/login?force_login_form`. - - -## Other Providers - -In an effort to accommodate as much generality as possible, it was -decided to implement OAuth2 with the -[social-auth](https://github.com/python-social-auth/social-core/tree/master/social_core/backends) -ecosystem as it has a library of compatible providers with documentation -of implementation. Conveniently, each provider has an identical -procedure of managing the authenticated responses and authorizing access -within a given application. The only difficulty is creating a new -authentication client with a given OAuth2 provider. diff --git a/docs/content/en/open_source/archived_docs/usage/models.md b/docs/content/en/open_source/archived_docs/usage/models.md deleted file mode 100644 index f08996d96dc..00000000000 --- a/docs/content/en/open_source/archived_docs/usage/models.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: "Core data classes" -description: "DefectDojo is made to be flexible to conform to your program, rather than making your team conform to the tool." -draft: false -weight: 1 -exclude_search: true ---- - -![image](images/dd-hierarchy.png) - -## Product Type - -Product types represent the top level model, these can be business unit -divisions, different offices or locations, development teams, or any -other logical way of distinguishing "types" of products. - -Examples: -: - IAM Team - - Internal / 3rd Party - - Main company / Acquisition - - San Francisco / New York offices - -## Product - -This is the name of any project, program, or product that you are -currently testing. - -Examples: -: - Wordpress - - Internal wiki - - Slack - -## Engagement - -Engagements are moments in time when testing is taking place. They are -associated with a name for easy reference, a time line, a lead (the user -account of the main person conducting the testing), a test strategy, and -a status. Engagement consists of two types: Interactive and CI/CD. An -interactive engagement is typically an engagement conducted by an -engineer, where findings are usually uploaded by the engineer. A CI/CD -engagement, as it's name suggests, is for automated integration with a -CI/CD pipeline. - -Examples: -: - Beta - - Quarterly PCI Scan - - Release Version X - -## Test - -Tests are a grouping of activities conducted by engineers to attempt to -discover flaws in a product. Tests are bundled within engagements, have a -start and end date and are defined by a test type. - -Examples: -: - Burp Scan from Oct. 29, 2015 to Oct. 29, 2015 - - Nessus Scan from Oct. 31, 2015 to Oct. 31, 2015 - - API Test from Oct. 15, 2015 to Oct. 20, 2015 - -## Finding - -A finding represents a flaw discovered while testing. It can be -categorized with severities of Critical, High, Medium, Low, and -Informational (Info). - -Examples: -: - OpenSSL 'ChangeCipherSpec' MiTM Potential Vulnerability - - Web Application Potentially Vulnerable to Clickjacking - - Web Browser XSS Protection Not Enabled - -## Endpoint - -Endpoints represent testable systems defined by their IP address or Fully Qualified Domain Name. - -Examples: -: - https://www.example.com - - https://www.example.com:8080/products - - 192.168.0.36 diff --git a/docs/content/en/open_source/archived_docs/usage/permissions.md b/docs/content/en/open_source/archived_docs/usage/permissions.md deleted file mode 100644 index 4430ad01b2a..00000000000 --- a/docs/content/en/open_source/archived_docs/usage/permissions.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -title: "Permissions" -description: "Users have different functionality available to them, depending on their system-wide permissions and on the role they have as a member of a particular Product or Product Type." -weight: 3 -draft: false ---- - -## System-wide permissions - -* Administrators (aka superusers) have no limitations in the system. They can change all settings, manage users and have read / write access to all data. -* Staff users can add Product Types, and have access to data according to their role in a Product or Product Type. -* Regular users have limited functionality available. They cannot add Product Types but have access to data according to their role in a Product or Product Type - -## Product and Product Type permissions - -Users can be assigned as members to Products and Product Types, giving them one out of five predefined roles. The role defines what kind of access a user has to functions for interacting with data of that Product or Product Type: - -**Product / Product Type roles:** - -| | Reader | Writer | Maintainer | Owner | API Importer | -|-----------------------------|:------:|:------:|:----------:|:-----:|:------------:| -| Add Product Type | | | 1) |1) | | -| View Product Type | x | x | x | x | x | -| Remove yourself as a member | x | x | x | x | | -| Manage Product Type members | | | x | x | | -| Edit Product Type | | | x | x | | -| Add Product | | | x | x | | -| Add Product Type member as Owner | | | | x | | -| Delete Product Type | | | | x | | -| | | | | | | -| View Product | x | x | x | x | x | -| Remove yourself as a member | x | x | x | x | | -| Manage Product members | | | x | x | | -| Edit Product | | | x | x | | -| Add Product member as Owner | | | | x | | -| Delete Product | | | | x | | -| | | | | | | -| View Engagement | x | x | x | x | x | -| Add Engagement | | x | x | x | x | -| Edit Engagement | | x | x | x | x | -| Risk Acceptance | | x | x | x | | -| Delete Engagement | | | x | x | | -| | | | | | | -| View Test | x | x | x | x | x | -| Add Test | | x | x | x | | -| Edit Test | | x | x | x | x | -| Delete Test | | | x | x | | -| | | | | | | -| View Finding | x | x | x | x | x | -| Add Finding | | x | x | x | | -| Edit Finding | | x | x | x | | -| (Re-)Import Scan Result | | x | x | x | x | -| Delete Finding | | | x | x | | -| | | | | | | -| View Finding Group | x | x | x | x | x | -| Add Finding Group | | x | x | x | | -| Edit Finding Group | | x | x | x | | -| Delete Finding Group | | x | x | x | | -| | | | | | | -| View Endpoint | x | x | x | x | x | -| Add Endpoint | | x | x | x | | -| Edit Endpoint | | x | x | x | | -| Delete Endpoint | | | x | x | | -| | | | | | | -| Edit Benchmark | | x | x | x | | -| Delete Benchmark | | | x | x | | -| | | | | | | -| View Components | x | x | x | x | x | -| | | | | | | -| View Note History | x | x | x | x | | -| Add Note | x | x | x | x | | -| Edit Note | (x) 2) | x | x | x | | -| Delete Note | (x) 2) | (x) 2) | x | x | | - - -1) Every superuser can add Product Types. Regular users are not allowed to add Product Types, unless they are a Global Owner or Maintainer. - -2) Every user is allowed to edit and delete his own notes. - -The role of a user within a Product Type is inherited by all Products of that Product Type, unless the user is explicitly defined as a member of a Product with a different role. In that case, if a user doesn't have a certain right for the Product Type, it is then checked if he has the right for the Product. - -A Product Type needs to have at least one owner. The last owner cannot be removed. - -## Global permissions - -Users can be assigned a global role in the *Edit User* dialog. A global role gives a user access to all Product Types and Products, including the underlying data, with permissions according to the respective role. - -A use case for a global role could be the Chief Information Security Officer of a company who needs an overview of all systems. If he gets the global role `Reader`, he can see the findings for all products and also all metrics. - -Since global roles give users access to all data, only superusers are allowed to edit it. - -## Groups ## - -If you have a number of users who should all have the same permissions for some Products or Product Types, you can put them together in a group. The group defines the roles for Products and Product Types that are applied to all members of the group. - -The membership of a group itself has a role that determines what permissions the member has to manage the group: - -| | Reader | Maintainer | Owner | -|-----------------------------|:------:|:----------:|:-----:| -| Add Group 1) | | | | -| View Group | x | x | x | -| Remove yourself as a member | x | x | x | -| Manage Group members | | x | x | -| Edit Group | | x | x | -| Add Group member as Owner | | | x | -| Delete Group | | | x | - -1) Every superuser can add groups. Regular users are not allowed to add groups. - -The permissions to manage the roles of Products and Product types for a group is defined by the role of the user in the respective Product or Product Type. - -Groups can have a global role too. This global role gives all members of the group access to all Product Types and Products, including the underlying data, with permissions according to the respective role. - -## Configuration permissions - -Many configuration dialogues and API endpoints can be enabled for users or groups of users, regardless of their **superuser** status: - -![Configuration permissions](images/configuration_permissions.png) - -3 configurations can still only be changed by superusers: -* System settings -* Notifications on system level -* Configuration permissions for users and groups - -These configuration settings are a powerful tool and should be used with great care. diff --git a/docs/content/en/open_source/archived_docs/usage/productgrading.md b/docs/content/en/open_source/archived_docs/usage/productgrading.md deleted file mode 100644 index 3ead06d24f4..00000000000 --- a/docs/content/en/open_source/archived_docs/usage/productgrading.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Product Health Grading" -description: "Products are graded based on their health." -draft: false -weight: 2 ---- - -## Product Health Grading - -Within DefectDojo's system settings, you have the opportunity to enable a grading system for your products. For that you have to enable ("Enable Product Grading"). Then, the products are graded with the following possible grades: -- Grade A -- Grade B -- Grade C -- Grade D -- Grade F - -The best grade is A going down to the worst grade F. By default the grades stick to the achieved percentage mentioned in grade converation [here](https://en.wikipedia.org/wiki/Academic_grading_in_the_United_States). - -### Calculation of the grades -The code that performs the grade calculations can be found [here](https://github.com/DefectDojo/django-DefectDojo/blob/76e11c21e88fb84b67b6da27c78fbbe1899e7e78/dojo/management/commands/system_settings.py#L8). - -The highest health score is 100 and it decreases based on the number of findings for each severity (critical, high, medium, low) within the product. In the following code snippet you can see the rules. -Note that the following abbreviations were used: - -- crit: amount of critical findings within the product -- high: amount of high findings within the product -- med: amount of medium findings within the product -- low: amount of low findings within the product - -```python -health=100 -if crit > 0: - health = 40 - health = health - ((crit - 1) * 5) -if high > 0: - if health == 100: - health = 60 - health = health - ((high - 1) * 3) -if med > 0: - if health == 100: - health = 80 - health = health - ((med - 1) * 2) -if low > 0: - if health == 100: - health = 95 - health = health - low -if health < 5: - health = 5 -return health -``` \ No newline at end of file diff --git a/docs/content/en/open_source/archived_docs/usage/workflows.md b/docs/content/en/open_source/archived_docs/usage/workflows.md deleted file mode 100644 index 62882ba8352..00000000000 --- a/docs/content/en/open_source/archived_docs/usage/workflows.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "Example workflows" -description: "Two examples how DefectDojo can be used in day-to-day operations." -draft: false -weight: 4 ---- - - -Example 1 - Bill the security engineer --------------------------------------- - -Bill wants a place to keep track of what he\'s worked on, so that he can -show his boss exactly what issues he reports, and statistics about how -long it takes to close them. - -When he is asked to audit an application, Bill registers a new Product -in DefectDojo, and creates a new Engagement. Here he sets some basic -information, like how long he expects the Engagement will take, who will -be leading the testing (himself), what Product he will be working on, -and what tests he will be doing. - -Next, he can add a Test to the Engagement, or upload a Nessus scan and -start picking out the real vulnerabilities from the false positives -(Nessus scan Findings are imported as inactive by default). - -Within the Test section, Bill can add Findings for any issues that he -has uncovered during his audit. He can assign a severity to the -Findings, describe replication steps, mitigation strategies, and impact -on the system. This will come in handy when he wants to generate a -report to send to the development team responsible for this Product, or -his manager. - -Once Bill has completed his Engagement, he can close the Engagement on -the main Engagement page. He can then view the results of his Tests, and -generate a report to send to the development team. - -If Bill hears back from the development team that they won\'t be able to -fix the issue for a while, he can make a note of this on the Engagement -page. Bill will also receive Alerts for any bugs that persist longer -than they are supposed to based on their severity. - -Example 2 - John the QE manager -------------------------------- - -John wants to keep tabs on what his team members are up to, and find -issues that are taking a long time to get fixed. He creates his own -DefectDojo account with superuser privileges so that he can view other -team members\' metrics. - -To get a better idea of what his team members are currently working on, -he can start by checking the Calendar. This will show him any active -Engagements that his team is involved in, based on the dates assigned to -those Engagements. - -He can view metrics for a Product Type, such as \"Third Party Apps\" to -track his team\'s activity and follow up with Product teams who have -long-lived bugs. He can also look at all the Findings for which there is -a Risk Acceptance associated, and ensure that the proper documentation -or timeline has been provided for the Findings in question. - -If he wants to check on a particular team member\'s progress, he can -look at the Engineer Metrics dashboard under \"Additional Metrics\" for -that user. From 2ad779f25de7a8437206043d32a7bcdae0bc3d64 Mon Sep 17 00:00:00 2001 From: Paul Osinski Date: Mon, 12 May 2025 16:16:32 -0600 Subject: [PATCH 2/7] mv source-code article to new directory --- .../source-code-repositories.md | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) rename docs/content/en/{open_source/archived_docs/integrations => working_with_findings/organizing_engagements_tests}/source-code-repositories.md (59%) diff --git a/docs/content/en/open_source/archived_docs/integrations/source-code-repositories.md b/docs/content/en/working_with_findings/organizing_engagements_tests/source-code-repositories.md similarity index 59% rename from docs/content/en/open_source/archived_docs/integrations/source-code-repositories.md rename to docs/content/en/working_with_findings/organizing_engagements_tests/source-code-repositories.md index c6f3b333a98..0bb47f6dc33 100644 --- a/docs/content/en/open_source/archived_docs/integrations/source-code-repositories.md +++ b/docs/content/en/working_with_findings/organizing_engagements_tests/source-code-repositories.md @@ -1,17 +1,18 @@ --- -title: "Source code repositories" +title: "Link Findings to source code" description: "Integration of repositories to navigate to the locaction of findings in the source code." draft: false weight: 5 --- -Findings can have a filepath and a line number as the location of the vulnerability. This is typically set when scanning an application with a Static Application Security Test (SAST) tool. If the repository of the source code is specified in the Engagement, DefectDojo will present the filepath as a link and the user can navigate directly to the location of the vulnerability. +Certain tools (particularly SAST tools) will include the associated file name and line number in vulnerability data. If the repository of the source code is specified in the Engagement, DefectDojo will present the filepath as a link and the user can navigate directly to the location of the vulnerability. ## Setting the repository in the Engagement and Test ### Engagement While editing the Engagement, users can set the URL of the specific SCM repo. -For Interactive Engagement it needs to be the URL including the branch: + +For an Interactive Engagement, it needs to be a URL that specifies the branch: - for GitHub - like https://github.com/DefectDojo/django-DefectDojo/tree/dev ![Edit Engagement (GitHub)](images/source-code-repositories_1.png) - for GitLab - like https://gitlab.com/gitlab-org/gitlab/-/tree/master @@ -21,13 +22,13 @@ For Interactive Engagement it needs to be the URL including the branch: - for standalone/onpremise BitBucket https://bb.example.com/scm/some-project/some-repo.git or https://bb.example.com/scm/some-user-name/some-repo.git for user public repo (like git clone url) ![Edit Engagement (Bitbucket standalone)](images/source-code-repositories-bitbucket-onpremise_1.png) -For CI/CD Engagement, where user could set commit hash, branch/tag and code line it should look like examples below: -- for GitHub - like https://github.com/DefectDojo/django-DefectDojo -- for GitLab - like https://gitlab.com/gitlab-org/gitlab -- for public BitBucket, Gitea and Codeberg - like https://bitbucket.org/some-user/some-project.git (like git clone url) -- for standalone/onpremise BitBucket https://bb.example.com/scm/some-project.git or https://bb.example.com/scm/some-user-name/some-repo.git for user public repo (like git clone url) +For CI/CD Engagements, the commit hash, branch/tag and code line can vary, so you only need to include the URL of the repository. +- for GitHub - like `https://github.com/DefectDojo/django-DefectDojo` +- for GitLab - like `https://gitlab.com/gitlab-org/gitlab` +- for public BitBucket, Gitea and Codeberg - like `https://bitbucket.org/some-user/some-project.git` (like git clone url) +- for standalone/onpremise BitBucket `https://bb.example.com/scm/some-project.git` or `https://bb.example.com/scm/some-user-name/some-repo.git` for user public repo (like git clone url) -If user does not set commit hash or branch/tag in appropriate fields of CI/CD Engagement edit form, the URL should look like in Interactive Engagement edit form. +In a CI/CD Engagement, you can specify a commit hash or branch/tag in the **Edit Engagement** form, which will be appended to any links rendered by DefectDojo. If these are not set, the SCM URL will need to contain a complete link which includes the code branch. SCM navigation URL is composed from Repo URL using SCM Type. A specific SCM type can be set in Product custom field "scm-type". If no "scm-type" is set and the URL contains "https://github.com", a "github" SCM type is assumed. @@ -42,7 +43,7 @@ Product SCM type add: Possible SCM types could be 'github', 'gitlab', 'bitbucket', 'bitbucket-standalone', 'gitea', 'codeberg' or nothing (for default github). -## Link in Finding +## Source code Links in Findings When viewing a finding, the location will be presented as a link, if the repository of the source code has been set in the Engagement: From 326831879ae1b87582eed69be4d6186b4124af83 Mon Sep 17 00:00:00 2001 From: Paul Osinski Date: Mon, 12 May 2025 16:17:07 -0600 Subject: [PATCH 3/7] Add triageless info to import-scan article --- .../import_scan_files/import_scan_ui.md | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/content/en/connecting_your_tools/import_scan_files/import_scan_ui.md b/docs/content/en/connecting_your_tools/import_scan_files/import_scan_ui.md index 342d1dcc2c6..0e5fc440017 100644 --- a/docs/content/en/connecting_your_tools/import_scan_files/import_scan_ui.md +++ b/docs/content/en/connecting_your_tools/import_scan_files/import_scan_ui.md @@ -65,9 +65,27 @@ This option is especially relevant when using the API to import data. If uploadi * **Source Code Management URI** can also be specified. This form option must be a valid URI. * **Group By:** if you want to create Finding Groups out of this File, you can specify the grouping method here. -### Next Steps +### Triage-less scanners: "Do Not Reactivate" -Once your upload has completed, you should be redirected to the Test Page which contains the Findings found in the scan file. You can start working with those results right away, but feel free to consult the following articles: +Some scanners might not include triage information in their reports (e.g. tfsec). They simply scan code or dependencies, flag issues, and return everything, regardless of whether a vulnerability has already been triaged or not. -* Learn how to organize your Product Hierarchy to manage different contexts for your Findings and Tests: [Product Hierarchy Overview](/en/working_with_findings/organizing_engagements_tests/product_hierarchy/). -* Learn how to extend a Test with additional Findings and reports: [Reimport Guide](../using_reimport/) \ No newline at end of file +To handle this case, DefectDojo also includes a "Do not reactivate" checkbox in uploading reports (also in the reimport API), so you can use DefectDojo as the source of truth for triage, instead of reactivating your triaged Findings on each import / reimport. + +### Using the Scan Completion Date (API: `scan_date`) field + +DefectDojo offers a plethora of supported scanner reports, but not all of them contain the +information most important to a user. The `scan_date` field is a flexible smart feature that +allows users to set the completion date of the a given scan report, and have it propagate +down to all the findings imported. This field is **not** mandatory, but the default value for +this field is the date of import (whenever the request is processed and a successful response is returned). + +Here are the following use cases for using this field: + +1. The report **does not** set the date, and `scan_date` is **not** set at import + - Finding date will be the default value of `scan_date` +2. The report **sets** the date, and the `scan_date` is **not** set at import + - Finding date will be whatever the report sets +3. The report **does not** set the date, and the `scan_date` is **set** at import + - Finding date will be whatever the user set for `scan_date` +4. The report **sets** the date, and the `scan_date` is **set** at import + - Finding date will be whatever the user set for `scan_date` From 6ad3ad5b6b96be0f58b6bc511a44b81f3a1fa21f Mon Sep 17 00:00:00 2001 From: Paul Osinski Date: Mon, 12 May 2025 16:20:55 -0600 Subject: [PATCH 4/7] add SSO whitelist info to docs --- docs/content/en/customize_dojo/user_management/configure_sso.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/content/en/customize_dojo/user_management/configure_sso.md b/docs/content/en/customize_dojo/user_management/configure_sso.md index c0a830e6f6f..ac07ac1e069 100644 --- a/docs/content/en/customize_dojo/user_management/configure_sso.md +++ b/docs/content/en/customize_dojo/user_management/configure_sso.md @@ -16,6 +16,8 @@ Users can connect to DefectDojo with a Username and Password, but if you prefer, All of these methods can only be configured by a Superuser in DefectDojo. DefectDojo Pro users can quickly set up SSO through their system settings, while Open Source users will need to configure these settings on the back-end by setting an environment variable within Docker. This article covers both methods of configuration. +**NOTE: DefectDojo Pro users will all need to add the IP addresses of SAML or SSO services to their Firewall whitelist. See [Firewall Rules](/en/cloud_management/using-cloud-manager/#changing-your-firewall-settings) for more information.** + ## Disable username / password use You may wish to disable traditional username/password login on your instance. From 712f3b2ed760646c9f64973687429ed006ea1759 Mon Sep 17 00:00:00 2001 From: Paul Osinski Date: Thu, 15 May 2025 08:49:33 -0600 Subject: [PATCH 5/7] remove reference to deprecated async import --- docs/content/en/open_source/performance.md | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/docs/content/en/open_source/performance.md b/docs/content/en/open_source/performance.md index 70dfa44b421..4504e4a3158 100644 --- a/docs/content/en/open_source/performance.md +++ b/docs/content/en/open_source/performance.md @@ -1,5 +1,5 @@ --- -title: "Performance Enhancements" +title: "Performance Enhancements (Open Source)" description: "Settings to configure to enhance performance in DefectDojo" draft: false weight: 4 @@ -15,17 +15,6 @@ change many filters to only search on names, rather than the objects themselves. This change will save many large queries, and will improve the performance of UI based interactions. -## Asynchronous Import - -DefectDojo offers an experimental feature to aynschronously import security reports. -This feature works in most use cases, but struggles when doing things such as pushing -to Jira during the import process. Because Endpoints are still being processed and -created even after the import procedure is completed, pushing Findings to Jira can -result in incomplete Jira tickets. It is advised to wait until after import has been -completed (reaches 100%). - -To enable this feature, set `ASYNC_FINDING_IMPORT` to True in `local_settings.py` - ## Asynchronous Delete For larger instances, deleting an object can take minutes for all related objects to be From 74232e25fdcc9e352b0ee3c9466211596f28e1a0 Mon Sep 17 00:00:00 2001 From: Paul Osinski <42211303+paulOsinski@users.noreply.github.com> Date: Thu, 15 May 2025 10:13:28 -0600 Subject: [PATCH 6/7] Update import_scan_ui.md --- .../connecting_your_tools/import_scan_files/import_scan_ui.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/connecting_your_tools/import_scan_files/import_scan_ui.md b/docs/content/en/connecting_your_tools/import_scan_files/import_scan_ui.md index 0e5fc440017..dac6195a6d3 100644 --- a/docs/content/en/connecting_your_tools/import_scan_files/import_scan_ui.md +++ b/docs/content/en/connecting_your_tools/import_scan_files/import_scan_ui.md @@ -65,7 +65,7 @@ This option is especially relevant when using the API to import data. If uploadi * **Source Code Management URI** can also be specified. This form option must be a valid URI. * **Group By:** if you want to create Finding Groups out of this File, you can specify the grouping method here. -### Triage-less scanners: "Do Not Reactivate" +### Triage-less scanners: Do Not Reactivate field Some scanners might not include triage information in their reports (e.g. tfsec). They simply scan code or dependencies, flag issues, and return everything, regardless of whether a vulnerability has already been triaged or not. From 625b6a73c5bf7c232d3d2be13bb4307e7f319233 Mon Sep 17 00:00:00 2001 From: Paul Osinski Date: Thu, 15 May 2025 15:25:55 -0600 Subject: [PATCH 7/7] add OIDC to docs --- docs/assets/images/oidc_pro.png | Bin 0 -> 47833 bytes .../user_management/configure_sso.md | 53 ++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 docs/assets/images/oidc_pro.png diff --git a/docs/assets/images/oidc_pro.png b/docs/assets/images/oidc_pro.png new file mode 100644 index 0000000000000000000000000000000000000000..80a2dfdba09d6244368f438533f68fa08c781fd9 GIT binary patch literal 47833 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 literal 0 HcmV?d00001 diff --git a/docs/content/en/customize_dojo/user_management/configure_sso.md b/docs/content/en/customize_dojo/user_management/configure_sso.md index ac07ac1e069..45bd70c3279 100644 --- a/docs/content/en/customize_dojo/user_management/configure_sso.md +++ b/docs/content/en/customize_dojo/user_management/configure_sso.md @@ -515,6 +515,59 @@ GET parameter starts with `http://` instead of 2. Restart DefectDojo, and 'Login With Okta' should appear on the login screen. +## OIDC (OpenID Connect) + +Adding OIDC gives you the option to authenticate users using a generic OIDC provider. + +### Pro Configuration + +In DefectDojo Pro, OIDC can be configured from the OIDC settings page: + +![image](images/oidc_pro.png) + +Fill out the form as follows + +1. Enter your OIDC endpoint in the Endpoint field. This is the base URL of your OIDC instance (you do not need to include `/.well-known/open-id-configuration/`) + +2. Enter your OIDC Client ID in the Client ID field. + +3. Enter the OIDC Client Secret in the Client Secret field. + +4. Check the box for Enable OIDC. + +Once the form has been submitted, Log In With OIDC should be added as an option to the DefectDojo login page. + + +### Open-Source + +The minimum configuration requires you to set the following environment variables: + + {{< highlight python >}} + DD_SOCIAL_AUTH_OIDC_AUTH_ENABLED=True, + DD_SOCIAL_AUTH_OIDC_OIDC_ENDPOINT=(str, 'https://example.com'), + DD_SOCIAL_AUTH_OIDC_KEY=(str, 'YOUR_CLIENT_ID'), + DD_SOCIAL_AUTH_OIDC_SECRET=(str, 'YOUR_CLIENT_SECRET') + {{< /highlight >}} + +The rest of the OIDC configuration will be auto-detected by fetching data from: + - /.well-known/open-id-configuration/ + +You can also optionally set the following variables: + + {{< highlight python >}} + DD_SOCIAL_AUTH_OIDC_ID_KEY=(str, ''), #the key associated with the OIDC user IDs + DD_SOCIAL_AUTH_OIDC_USERNAME_KEY=(str, ''), #the key associated with the OIDC usernames + DD_SOCIAL_AUTH_OIDC_WHITELISTED_DOMAINS=(list, ['']), #list of domains allowed for login + DD_SOCIAL_AUTH_OIDC_JWT_ALGORITHMS=(list, ["RS256","HS256"]), + DD_SOCIAL_AUTH_OIDC_ID_TOKEN_ISSUER=(str, ''), + DD_SOCIAL_AUTH_OIDC_ACCESS_TOKEN_URL=(str, ''), + DD_SOCIAL_AUTH_OIDC_AUTHORIZATION_URL=(str, ''), + DD_SOCIAL_AUTH_OIDC_USERINFO_URL=(str, ''), + DD_SOCIAL_AUTH_OIDC_JWKS_URI=(str, ''), + {{< /highlight >}} + +Once these variables have been set, restart DefectDojo. Log In With OIDC should now be added to the DefectDojo login page. + ## SAML Configuration DefectDojo Pro users can follow this guide to set up a SAML configuration using the DefectDojo UI. Open-Source users can set up SAML via environment variables, using the following [guide](./#open-source-saml).