diff --git a/.gitlab/ci/qa-common/main.gitlab-ci.yml b/.gitlab/ci/qa-common/main.gitlab-ci.yml index e2e4bc55cb5..85f0142c77d 100644 --- a/.gitlab/ci/qa-common/main.gitlab-ci.yml +++ b/.gitlab/ci/qa-common/main.gitlab-ci.yml @@ -63,14 +63,7 @@ stages: .update-script: script: - !reference [.bundle-prefix] - - export QA_COMMAND="$BUNDLE_PREFIX gitlab-qa Test::Omnibus::UpdateFromPrevious $RELEASE $GITLAB_SEMVER_VERSION $UPDATE_TYPE $UPDATE_FROM_EDITION -- $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS" - - echo "Running - '$QA_COMMAND'" - - eval "$QA_COMMAND" - -.update-with-ai-components-script: - script: - - !reference [.bundle-prefix] - - export QA_COMMAND="$BUNDLE_PREFIX gitlab-qa Test::Omnibus::UpdateFromPreviousAi $RELEASE $GITLAB_SEMVER_VERSION $UPDATE_TYPE $UPDATE_FROM_EDITION -- $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS" + - export QA_COMMAND="$BUNDLE_PREFIX gitlab-qa ${QA_SCENARIO:-Test::Omnibus::UpdateFromPrevious} $RELEASE $GITLAB_SEMVER_VERSION $UPDATE_TYPE $UPDATE_FROM_EDITION -- $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS" - echo "Running - '$QA_COMMAND'" - eval "$QA_COMMAND" diff --git a/.gitlab/ci/qa-common/rules.gitlab-ci.yml b/.gitlab/ci/qa-common/rules.gitlab-ci.yml index 6624d4548fd..82d21a1a3f1 100644 --- a/.gitlab/ci/qa-common/rules.gitlab-ci.yml +++ b/.gitlab/ci/qa-common/rules.gitlab-ci.yml @@ -91,6 +91,17 @@ include: - !reference [.qa:rules:code-merge-request, rules] - *default-branch +.rules:test:update-patch: + rules: + # skip upgrade jobs if gitlab version is not in semver compatible format + # these jobs need gitlab version because we can't reliably detect it from just the image + - if: $GITLAB_SEMVER_VERSION !~ /^\d+\.\d+\.\d+/ + when: never + # update jobs are only relevant in testing app updates that can be affected by code changes only + # by checking code patterns, skip running job on changes that can't affect the outcome + # subset of update jobs only applicable for backport MRs to verify patch upgrade paths + - !reference [.qa:rules:code-merge-request-targeting-stable-branch, rules] + .rules:test:never-schedule-pipeline: rules: - <<: *if-schedule-pipeline diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 507a27768a7..e6381383a66 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -1669,6 +1669,11 @@ - <<: *if-merge-request changes: *code-patterns +.qa:rules:code-merge-request-targeting-stable-branch: + rules: + - <<: *if-merge-request-targeting-stable-branch + changes: *code-patterns + .qa:rules:code-merge-request-allowed-to-fail: rules: - <<: *if-merge-request diff --git a/.gitlab/ci/test-on-omnibus-nightly/main.gitlab-ci.yml b/.gitlab/ci/test-on-omnibus-nightly/main.gitlab-ci.yml index 7ee700b1ab0..8e34ea35d47 100644 --- a/.gitlab/ci/test-on-omnibus-nightly/main.gitlab-ci.yml +++ b/.gitlab/ci/test-on-omnibus-nightly/main.gitlab-ci.yml @@ -187,9 +187,10 @@ gitlab-pages: update-minor-ee-ai-components: extends: - .qa - - .update-with-ai-components-script + - .update-script - .with-ignored-runtime-data variables: + QA_SCENARIO: Test::Omnibus::UpdateFromPreviousAi UPDATE_TYPE: minor UPDATE_FROM_EDITION: ee QA_RSPEC_TAGS: --tag ai_gateway diff --git a/.gitlab/ci/test-on-omnibus/main.gitlab-ci.yml b/.gitlab/ci/test-on-omnibus/main.gitlab-ci.yml index c7a1c4100fe..5e7e173ab3d 100644 --- a/.gitlab/ci/test-on-omnibus/main.gitlab-ci.yml +++ b/.gitlab/ci/test-on-omnibus/main.gitlab-ci.yml @@ -400,6 +400,28 @@ update-major: - !reference [.rules:test:dependency-update-never, rules] - !reference [.rules:test:update, rules] +update-patch: + extends: + - .qa + - .update-script + variables: + UPDATE_TYPE: patch + QA_RSPEC_TAGS: --tag health_check + rules: + - !reference [.rules:test:dependency-update-never, rules] + - !reference [.rules:test:update-patch, rules] + +update-from-patch-to-stable: + extends: + - .qa + - .update-script + variables: + QA_RSPEC_TAGS: --tag health_check + QA_SCENARIO: Test::Omnibus::UpdateToNext + rules: + - !reference [.rules:test:dependency-update-never, rules] + - !reference [.rules:test:update-patch, rules] + update-ee-to-ce: extends: - .qa diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md index 5f7b4d3d7d5..69569fff0b6 100644 --- a/.gitlab/issue_templates/Feature Flag Roll Out.md +++ b/.gitlab/issue_templates/Feature Flag Roll Out.md @@ -41,7 +41,7 @@ Note: Please make sure to run the chatops commands in the Slack channel that get - test kicked off: `Feature flag has been set to true on **gstg**` - test result: `This pipeline was triggered due to toggling of feature flag` -For assistance with end-to-end test failures, please reach out via the [`#test-platform` Slack channel](https://gitlab.slack.com/archives/C3JJET4Q6). Note that end-to-end test failures on `staging-ref` [don't block deployments](https://about.gitlab.com/handbook/engineering/infrastructure/environments/staging-ref/#how-to-use-staging-ref). +For assistance with end-to-end test failures, please reach out via the [`#s_developer_experience` Slack channel](https://gitlab.enterprise.slack.com/archives/C07TWBRER7H). Note that end-to-end test failures on `staging-ref` [don't block deployments](https://about.gitlab.com/handbook/engineering/infrastructure/environments/staging-ref/#how-to-use-staging-ref). ### Specific rollout on production diff --git a/.rubocop_todo/style/if_unless_modifier.yml b/.rubocop_todo/style/if_unless_modifier.yml index 2af7e0f209a..abc7b70753e 100644 --- a/.rubocop_todo/style/if_unless_modifier.yml +++ b/.rubocop_todo/style/if_unless_modifier.yml @@ -196,7 +196,6 @@ Style/IfUnlessModifier: - 'config/initializers/direct_upload_support.rb' - 'config/initializers/doorkeeper.rb' - 'config/initializers/google_api_client.rb' - - 'config/initializers/jira.rb' - 'config/initializers/kaminari_active_record_relation_methods_with_limit.rb' - 'config/initializers/remove_active_job_execute_callback.rb' - 'config/initializers/stackprof.rb' diff --git a/app/assets/javascripts/content_editor/components/suggestions_dropdown.vue b/app/assets/javascripts/content_editor/components/suggestions_dropdown.vue index c3be24f0f07..bcbcf27ad72 100644 --- a/app/assets/javascripts/content_editor/components/suggestions_dropdown.vue +++ b/app/assets/javascripts/content_editor/components/suggestions_dropdown.vue @@ -373,7 +373,7 @@ export default {
diff --git a/app/assets/javascripts/content_editor/components/wrappers/html_comment.vue b/app/assets/javascripts/content_editor/components/wrappers/html_comment.vue index e109458c40a..35ebff183d3 100644 --- a/app/assets/javascripts/content_editor/components/wrappers/html_comment.vue +++ b/app/assets/javascripts/content_editor/components/wrappers/html_comment.vue @@ -28,7 +28,7 @@ export default { 'gl-border-dashed gl-border-default': !selected, }" > - {{ + {{ node.attrs.description }} diff --git a/app/assets/javascripts/content_editor/components/wrappers/image.vue b/app/assets/javascripts/content_editor/components/wrappers/image.vue index 355da809f19..dcced1fea04 100644 --- a/app/assets/javascripts/content_editor/components/wrappers/image.vue +++ b/app/assets/javascripts/content_editor/components/wrappers/image.vue @@ -116,7 +116,7 @@ export default { > @@ -43,7 +43,7 @@ export default { :href="node.attrs.src" class="with-attachment-icon" target="_blank" - draggable="true" + :draggable="true" data-drag-handle="" > {{ node.attrs.title || node.attrs.alt }} diff --git a/config/events/click_delete_package_button.yml b/config/events/click_delete_package_button.yml new file mode 100644 index 00000000000..0c54bae4d96 --- /dev/null +++ b/config/events/click_delete_package_button.yml @@ -0,0 +1,20 @@ +--- +description: Tracks the delete button clicked in the error packages alert +internal_events: true +action: click_delete_package_button +identifiers: +- project +- namespace +- user +additional_properties: + label: + description: package_errors_alert +product_group: package_registry +product_categories: +- package_registry +milestone: '17.6' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/170748 +tiers: +- free +- premium +- ultimate diff --git a/config/events/click_show_packages_with_errors_link.yml b/config/events/click_show_packages_with_errors_link.yml new file mode 100644 index 00000000000..6297ee608f6 --- /dev/null +++ b/config/events/click_show_packages_with_errors_link.yml @@ -0,0 +1,20 @@ +--- +description: Tracks the number of times the link was clicked in the error packages alert +internal_events: true +action: click_show_packages_with_errors_link +identifiers: +- project +- namespace +- user +additional_properties: + label: + description: package_errors_alert +product_group: package_registry +product_categories: +- package_registry +milestone: '17.10' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/170748 +tiers: +- free +- premium +- ultimate diff --git a/config/feature_flags/ops/zoekt_reduced_pull_frequency.yml b/config/feature_flags/ops/zoekt_reduced_pull_frequency.yml index 9802770e8c2..f1be3940ccd 100644 --- a/config/feature_flags/ops/zoekt_reduced_pull_frequency.yml +++ b/config/feature_flags/ops/zoekt_reduced_pull_frequency.yml @@ -6,4 +6,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/474248 milestone: '17.3' group: group::global search type: ops -default_enabled: false +default_enabled: true diff --git a/config/initializers/jira.rb b/config/initializers/jira.rb deleted file mode 100644 index 664f9c87808..00000000000 --- a/config/initializers/jira.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -# Changes Jira DVCS user agent requests in order to be successfully handled -# by our API. -# -# Gitlab::Jira::Middleware is only defined on EE -# -# Use safe_constantize because the class may exist but has not been loaded yet -if "Gitlab::Jira::Middleware".safe_constantize - Rails.application.config.middleware.use(Gitlab::Jira::Middleware) -end diff --git a/config/metrics/counts_all/count_distinct_user_id_from_click_delete_package_button.yml b/config/metrics/counts_all/count_distinct_user_id_from_click_delete_package_button.yml new file mode 100644 index 00000000000..b2b7cf5f826 --- /dev/null +++ b/config/metrics/counts_all/count_distinct_user_id_from_click_delete_package_button.yml @@ -0,0 +1,23 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_delete_package_button +description: Count of unique users who attempted to delete the package from error packages alert. +product_group: package_registry +product_categories: +- package_registry +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.10' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/170748 +time_frame: +- 28d +- 7d +data_source: internal_events +data_category: optional +tiers: +- free +- premium +- ultimate +events: +- name: click_delete_package_button + unique: user.id diff --git a/config/metrics/counts_all/count_distinct_user_id_from_click_show_packages_with_errors_link.yml b/config/metrics/counts_all/count_distinct_user_id_from_click_show_packages_with_errors_link.yml new file mode 100644 index 00000000000..636d56d6041 --- /dev/null +++ b/config/metrics/counts_all/count_distinct_user_id_from_click_show_packages_with_errors_link.yml @@ -0,0 +1,23 @@ +--- +key_path: redis_hll_counters.count_distinct_user_id_from_click_show_packages_with_errors_link +description: Count of unique users who viewed the package list page with error status applied. +product_group: package_registry +product_categories: +- package_registry +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.10' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/170748 +time_frame: +- 28d +- 7d +data_source: internal_events +data_category: optional +tiers: +- free +- premium +- ultimate +events: +- name: click_show_packages_with_errors_link + unique: user.id diff --git a/danger/stable_branch_patch/Dangerfile b/danger/stable_branch_patch/Dangerfile index 1810fb98141..b97184173d1 100644 --- a/danger/stable_branch_patch/Dangerfile +++ b/danger/stable_branch_patch/Dangerfile @@ -6,8 +6,8 @@ if stable_branch.encourage_package_and_qa_execution? **@#{helper.mr_author}, the `e2e:test-on-omnibus` job must complete before merging this merge request.*** - If there are failures on the `e2e:test-on-omnibus` pipeline, ping your team's associated Software Engineer in Test (SET) to confirm - the failures are unrelated to the merge request. If there's no SET assigned, ask for assistance on the `#test-platform` Slack channel. + If there are failures on the `e2e:test-on-omnibus` pipeline, ask for assistance from a Software Engineer in Test (SET) + on the `#s_developer_experience` Slack channel to confirm the failures are unrelated to the merge request. MARKDOWN end diff --git a/doc/development/ai_features/duo_chat.md b/doc/development/ai_features/duo_chat.md index f7f6fd6d70b..63249be0c92 100644 --- a/doc/development/ai_features/duo_chat.md +++ b/doc/development/ai_features/duo_chat.md @@ -448,7 +448,7 @@ and, as an Admin, easily create licensed groups for testing. Duo Chat end-to-end tests run continuously against [Staging](https://staging.gitlab.com/users/sign_in) and [Production](https://gitlab.com/) GitLab environments. These tests run in scheduled pipelines and ensure the end-to-end user experiences are functioning correctly. -Results can be viewed in the `#e2e-run-staging` and `#e2e-run-production` Slack channels. The pipelines can be found below, access can be requested in `#test-platform`: +Results can be viewed in the `#e2e-run-staging` and `#e2e-run-production` Slack channels. The pipelines can be found below, access can be requested in `#s_developer_experience`: - [Staging-canary pipelines](https://ops.gitlab.net/gitlab-org/quality/staging-canary/-/pipelines) - [Staging pipelines](https://ops.gitlab.net/gitlab-org/quality/staging/-/pipelines) diff --git a/doc/development/testing_guide/end_to_end/_index.md b/doc/development/testing_guide/end_to_end/_index.md index aef2ae9a005..0258ae174ff 100644 --- a/doc/development/testing_guide/end_to_end/_index.md +++ b/doc/development/testing_guide/end_to_end/_index.md @@ -63,7 +63,7 @@ The [existing scenarios](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/doc that run in the downstream `gitlab-qa-mirror` pipeline include many tests, but there are times when you might want to run a test or a group of tests that are different than the groups in any of the existing scenarios. -For example, when we [dequarantine](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/debugging-qa-test-failures/#dequarantining-tests) a flaky test we first want to make sure that it's no longer flaky. We can do that by running `_ee:quarantine` manual job. When selecting the name (not the play icon) of manual job, you are prompted to enter variables. You can use any of [the variables that can be used with `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables) as well as these: +For example, when we [dequarantine](https://handbook.gitlab.com/handbook/engineering/infrastructure-platforms/developer-experience/pipeline-triage/#dequarantining-tests) a flaky test we first want to make sure that it's no longer flaky. We can do that by running `_ee:quarantine` manual job. When selecting the name (not the play icon) of manual job, you are prompted to enter variables. You can use any of [the variables that can be used with `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables) as well as these: | Variable | Description | | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -175,7 +175,7 @@ When these tests are executed in the scope of merge requests, the `Allure` repor ##### Scheduled pipelines -Scheduled pipelines for these tests contain a `generate-allure-report` job under the `Report` stage. They also output a link to the current test report. Each type of scheduled pipeline generates a static link for the latest test report according to its stage. You can find a list of this in the [GitLab handbook](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/pipeline-monitoring/#allure-report). +Scheduled pipelines for these tests contain a `generate-allure-report` job under the `Report` stage. They also output a link to the current test report. Each type of scheduled pipeline generates a static link for the latest test report according to its stage. You can find a list of this in the [GitLab handbook](https://handbook.gitlab.com/handbook/engineering/infrastructure-platforms/developer-experience/end-to-end-pipeline-monitoring/#allure-report). ### Provisioning @@ -249,10 +249,10 @@ We should follow these best practices for end-to-end tests: ### Miscellaneous -- [Test Platform Sub-Department handbook](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/): Topics related to our vision, monitoring practices, failure triage processes, etc +- [Developer Experience Sub-Department handbook](https://handbook.gitlab.com/handbook/engineering/infrastructure-platforms/developer-experience/): Topics related to our vision, monitoring practices, failure triage processes, etc - [`gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/master/docs): For information regarding the use of the GitLab QA orchestrator - [`customers-gitlab-com`](https://gitlab.com/gitlab-org/customers-gitlab-com/-/tree/main/qa/doc) (internal only): For guides that are specific to the CustomersDot platform ## Where can you ask for help? -You can ask question in the `#test-platform` channel on Slack (GitLab internal) or you can find an issue you would like to work on in [the `gitlab` issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name%5B%5D=QA&label_name%5B%5D=test). +You can ask question in the `#s_developer_experience` channel on Slack (GitLab internal) or you can find an issue you would like to work on in [the `gitlab` issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name%5B%5D=QA&label_name%5B%5D=test). diff --git a/doc/development/testing_guide/end_to_end/beginners_guide/page_objects.md b/doc/development/testing_guide/end_to_end/beginners_guide/page_objects.md index 12b7ceb2902..c2826dfae77 100644 --- a/doc/development/testing_guide/end_to_end/beginners_guide/page_objects.md +++ b/doc/development/testing_guide/end_to_end/beginners_guide/page_objects.md @@ -300,8 +300,8 @@ from within the `qa` directory. ## Where to ask for help? -If you need more information, ask for help on `#test-platform` channel on Slack +If you need more information, ask for help on `#s_developer_experience` channel on Slack (internal, GitLab Team only). If you are not a Team Member, and you still need help to contribute, -open an issue in GitLab CE issue tracker with the `~QA` label. +open an issue in GitLab issue tracker with the `~QA` label. diff --git a/doc/development/testing_guide/end_to_end/beginners_guide/resources.md b/doc/development/testing_guide/end_to_end/beginners_guide/resources.md index f46e665357e..148d030737f 100644 --- a/doc/development/testing_guide/end_to_end/beginners_guide/resources.md +++ b/doc/development/testing_guide/end_to_end/beginners_guide/resources.md @@ -491,7 +491,7 @@ end We have a mechanism to [collect](https://gitlab.com/gitlab-org/gitlab/-/blob/44345381e89d6bbd440f7b4c680d03e8b75b86de/qa/qa/tools/test_resource_data_processor.rb#L32) all resources created during test executions, and another to [handle](https://gitlab.com/gitlab-org/gitlab/-/blob/44345381e89d6bbd440f7b4c680d03e8b75b86de/qa/qa/tools/test_resources_handler.rb#L44) -these resources. On [dotcom environments](https://handbook.gitlab.com/handbook/engineering/infrastructure/environments/#environments), after a test suite finishes in the [QA pipelines](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/debugging-qa-test-failures/#qa-test-pipelines), resources from all passing test are +these resources. On [dotcom environments](https://handbook.gitlab.com/handbook/engineering/infrastructure/environments/#environments), after a test suite finishes in the [E2E pipelines](https://handbook.gitlab.com/handbook/engineering/infrastructure-platforms/developer-experience/debugging-end-to-end-test-failures/), resources from all passing test are automatically deleted in the same pipeline run. Resources from all failed tests are reserved for investigation, and won't be deleted until the following Saturday by a scheduled pipeline. When introducing new resources, also make sure to add any resource that cannot be deleted to the [IGNORED_RESOURCES](https://gitlab.com/gitlab-org/gitlab/-/blob/44345381e89d6bbd440f7b4c680d03e8b75b86de/qa/qa/tools/test_resources_handler.rb#L29) @@ -499,8 +499,8 @@ list. ## Where to ask for help? -If you need more information, ask for help on `#test-platform` channel on Slack +If you need more information, ask for help on `#s_developer_experience` channel on Slack (internal, GitLab Team only). If you are not a Team Member, and you still need help to contribute, -open an issue in GitLab CE issue tracker with the `~QA` label. +open an issue in GitLab issue tracker with the `~QA` label. diff --git a/doc/user/application_security/dast/browser/configuration/authentication.md b/doc/user/application_security/dast/browser/configuration/authentication.md index 21c2ede004c..aeb9e769d7a 100644 --- a/doc/user/application_security/dast/browser/configuration/authentication.md +++ b/doc/user/application_security/dast/browser/configuration/authentication.md @@ -69,25 +69,9 @@ To run a DAST authenticated scan: ### Available CI/CD variables -| CI/CD variable | Type | Description | -|:-------------------------------------|:--------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `DAST_AUTH_AFTER_LOGIN_ACTIONS` | string | A comma-separated list of actions to be run after login but before login verification. Currently supports "click" actions. Example: `click(on=id:change_to_bar_graph),click(on=css:input[name=username])`. | -| `DAST_AUTH_BEFORE_LOGIN_ACTIONS` | [selector](#finding-an-elements-selector) | A comma-separated list of selectors representing elements to click on prior to entering the `DAST_AUTH_USERNAME` and `DAST_AUTH_PASSWORD` into the login form. Example: `"css:.navigation-menu,css:.login-menu-item"`. | -| `DAST_AUTH_CLEAR_INPUT_FIELDS` | boolean | Disables clearing of username and password fields before attempting manual login. Set to `false` by default. | -| `DAST_AUTH_COOKIE_NAMES` | string | Set to a comma-separated list of cookie names to specify which cookies are used for authentication. | -| `DAST_AUTH_FIRST_SUBMIT_FIELD` | [selector](#finding-an-elements-selector) | A selector describing the element that is clicked on to submit the username form of a multi-page login process. Example, `css:button[type='user-submit']`. | -| `DAST_AUTH_PASSWORD_FIELD` | [selector](#finding-an-elements-selector) | A selector describing the element used to enter the password on the login form. Example: `id:password` | -| `DAST_AUTH_PASSWORD` | string | The password to authenticate to in the website. Example: `P@55w0rd!`. | -| `DAST_AUTH_REPORT` | boolean | Set to `true` to generate a report detailing steps taken during the authentication process. You must also define `gl-dast-debug-auth-report.html` as a CI job artifact to be able to access the generated report. The report's content aids when debugging authentication failures. | -| `DAST_AUTH_SUBMIT_FIELD` | [selector](#finding-an-elements-selector) | A selector describing the element clicked on to submit the login form for a single-page login form, or the password form for a multi-page login form. Example: `css:button[type='submit']`. | -| `DAST_AUTH_SUCCESS_IF_AT_URL` | URL | A URL that is compared to the URL in the browser to determine if authentication has succeeded after the login form is submitted. Example: `"https://example.com/loggedin_page"`. | -| `DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND` | [selector](#finding-an-elements-selector) | A selector describing an element whose presence is used to determine if authentication has succeeded after the login form is submitted. Example: `css:.user-photo`. | -| `DAST_AUTH_SUCCESS_IF_NO_LOGIN_FORM` | boolean | Verifies successful authentication by checking for the absence of a login form after the login form has been submitted. | -| `DAST_AUTH_TYPE` | string | The authentication type to use. Example: `basic-digest`. | -| `DAST_AUTH_URL` | URL | The URL of the page containing the login form on the target website. `DAST_AUTH_USERNAME` and `DAST_AUTH_PASSWORD` are submitted with the login form to create an authenticated scan. Example: `https://login.example.com`. | -| `DAST_AUTH_USERNAME_FIELD` | [selector](#finding-an-elements-selector) | A selector describing the element used to enter the username on the login form. Example: `name:username`. | -| `DAST_AUTH_USERNAME` | string | The username to authenticate to in the website. Example: `admin`. | -| `DAST_SCOPE_EXCLUDE_URLS` | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. | +For a list of DAST Authentication CI/CD variables, see [Authentication variables](variables.md#authentication). + +The DAST CI/CD variable table is generated by the Rake task `bundle exec rake gitlab:dast_variables:compile_docs`. It uses variable metadata defined in [`lib/gitlab/security/dast_variables.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/security/dast_variables.rb). ### Update the target website diff --git a/doc/user/application_security/dast/browser/configuration/variables.md b/doc/user/application_security/dast/browser/configuration/variables.md index 3850bc9e240..b0f59b1abf6 100644 --- a/doc/user/application_security/dast/browser/configuration/variables.md +++ b/doc/user/application_security/dast/browser/configuration/variables.md @@ -6,70 +6,96 @@ info: To determine the technical writer assigned to the Stage/Group associated w title: Available CI/CD variables --- + + These CI/CD variables are specific to the browser-based DAST analyzer. They can be used to customize the behavior of DAST to your requirements. -For authentication CI/CD variables, see [Authentication](authentication.md). -| CI/CD variable | Type | Example | Description | -|:-------------------------------------------|:-----------------------------------------------------------|----------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `DAST_ACTIVE_SCAN_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `3h` | The maximum amount of time to wait for the active scan phase of the scan to complete. Defaults to `3h`. | -| `DAST_ACTIVE_SCAN_WORKER_COUNT` | number | `3` | The number of active checks to run in parallel. Defaults to `3`. | -| `DAST_AUTH_AFTER_LOGIN_ACTIONS` | string | `click(on=id:remember-me),click(on=css:.continue)` | A comma-separated list of actions to be run after login but before login verification. Currently supports "click" actions. | -| `DAST_AUTH_BEFORE_LOGIN_ACTIONS` | [selector](authentication.md#finding-an-elements-selector) | `css:.user,id:show-login-form` | A comma-separated list of selectors representing elements to click on prior to entering the `DAST_AUTH_USERNAME` and `DAST_AUTH_PASSWORD` into the login form. | -| `DAST_AUTH_CLEAR_INPUT_FIELDS` | boolean | `true` | Disables clearing of username and password fields before attempting manual login. Set to `false` by default. | -| `DAST_AUTH_COOKIE_NAMES` | string | `sessionID,groupName` | Set to a comma-separated list of cookie names to specify which cookies are used for authentication. | -| `DAST_AUTH_FIRST_SUBMIT_FIELD` | [selector](authentication.md#finding-an-elements-selector) | `css:input[type=submit]` | A selector describing the element that is clicked on to submit the username form of a multi-page login process. | -| `DAST_AUTH_PASSWORD_FIELD` | [selector](authentication.md#finding-an-elements-selector) | `name:password` | A selector describing the element used to enter the password on the login form. | -| `DAST_AUTH_NEGOTIATE_DELEGATION` | string | `*.example.com,example.com,*.EXAMPLE.COM,EXAMPLE.COM` | Which servers should be allowed for integrated authentication and delegation. This property sets two Chromium policies: [AuthServerAllowlist](https://chromeenterprise.google/policies/#AuthServerAllowlist) and [AuthNegotiateDelegateAllowlist.](https://chromeenterprise.google/policies/#AuthNegotiateDelegateAllowlist) [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/502476) in GitLab 17.6. | -| `DAST_AUTH_PASSWORD` | string | `P@55w0rd!` | The password to authenticate to in the website. | -| `DAST_AUTH_REPORT` | boolean | `true` | Set to `true` to generate a report detailing steps taken during the authentication process. You must also define `gl-dast-debug-auth-report.html` as a CI job artifact to be able to access the generated report. The report's content aids when debugging authentication failures. Defaults to `false`. | -| `DAST_AUTH_SUBMIT_FIELD` | [selector](authentication.md#finding-an-elements-selector) | `css:input[type=submit]` | A selector describing the element clicked on to submit the login form for a single-page login form, or the password form for a multi-page login form. | -| `DAST_AUTH_SUCCESS_IF_AT_URL` | URL | `https://www.site.com/welcome` | A URL that is compared to the URL in the browser to determine if authentication has succeeded after the login form is submitted. | -| `DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND` | [selector](authentication.md#finding-an-elements-selector) | `css:.user-avatar` | A selector describing an element whose presence is used to determine if authentication has succeeded after the login form is submitted. | -| `DAST_AUTH_SUCCESS_IF_NO_LOGIN_FORM` | boolean | `true` | Verifies successful authentication by checking for the absence of a login form after the login form has been submitted. This success check is enabled by default. | -| `DAST_AUTH_TYPE` | string | `basic-digest` | The authentication type to use. | -| `DAST_AUTH_URL` | URL | `https://site.com/login` | The URL of the page containing the login form on the target website. `DAST_AUTH_USERNAME` and `DAST_AUTH_PASSWORD` are submitted with the login form to create an authenticated scan. | -| `DAST_AUTH_USERNAME_FIELD` | [selector](authentication.md#finding-an-elements-selector) | `name:username` | A selector describing the element used to enter the username on the login form. | -| `DAST_AUTH_USERNAME` | string | `user@email.com` | The username to authenticate to in the website. | -| `DAST_BROWSER_SCAN` | boolean | `true` | Required to be `true` to run a browser-based scan. | -| `DAST_CHECKS_TO_EXCLUDE` | string | `552.2,78.1` | Comma-separated list of check identifiers to exclude from the scan. For identifiers, see [vulnerability checks](../checks/_index.md). | -| `DAST_CHECKS_TO_RUN` | List of strings | `16.1,16.2,16.3` | Comma-separated list of check identifiers to use for the scan. For identifiers, see [vulnerability checks](../checks/_index.md). | -| `DAST_CRAWL_EXTRACT_ELEMENT_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `5s` | The maximum amount of time to allow the browser to extract newly found elements or navigations. Defaults to `5s`. | -| `DAST_CRAWL_GRAPH` | boolean | `true` | Set to `true` to generate an SVG graph of navigation paths visited during crawl phase of the scan. You must also define `gl-dast-crawl-graph.svg` as a CI job artifact to be able to access the generated graph. Defaults to `false`. | -| `DAST_CRAWL_MAX_ACTIONS` | number | `10000` | The maximum number of actions that the crawler performs. Example actions include selecting a link, or filling a form. Defaults to `10000`. | -| `DAST_CRAWL_MAX_DEPTH` | number | `10` | The maximum number of chained actions that the crawler takes. For example, `Click -> Form Fill -> Click` is a depth of three. Defaults to `10`. | -| `DAST_CRAWL_SEARCH_ELEMENT_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `3s` | The maximum amount of time to allow the browser to search for new elements or user actions. Defaults to `3s`. | -| `DAST_CRAWL_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `5m` | The maximum amount of time to wait for the crawl phase of the scan to complete. Defaults to `24h`. | -| `DAST_CRAWL_WORKER_COUNT` | number | `3` | The maximum number of concurrent browser instances to use. For instance runners on GitLab.com, we recommended a maximum of three. Private runners with more resources may benefit from a higher number, but are likely to produce little benefit after five to seven instances. The default value is dynamic, equal to the number of usable logical CPUs. | -| `DAST_FULL_SCAN` | boolean | `true` | Set to `true` to run both passive and active checks. Default: `false` | -| `DAST_LOG_BROWSER_OUTPUT` | boolean | `true` | Set to `true` to log Chromium `STDOUT` and `STDERR`. | -| `DAST_LOG_CONFIG` | List of strings | `brows:debug,auth:debug` | A list of modules and their intended logging level for use in the console log. | -| `DAST_LOG_DEVTOOLS_CONFIG` | string | `Default:messageAndBody,truncate:2000` | Set to log protocol messages between DAST and the Chromium browser. | -| `DAST_LOG_FILE_CONFIG` | List of strings | `brows:debug,auth:debug` | A list of modules and their intended logging level for use in the file log. | -| `DAST_LOG_FILE_PATH` | string | `/output/browserker.log` | Set to the path of the file log. Default is `gl-dast-scan.log` | -| `DAST_PAGE_DOM_READY_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis after a navigation completes. Defaults to `6s`. | -| `DAST_PAGE_DOM_STABLE_WAIT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `200ms` | Define how long to wait for updates to the DOM before checking a page is stable. Defaults to `500ms`. | -| `DAST_PAGE_ELEMENT_READY_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `600ms` | The maximum amount of time to wait for an element before determining it is ready for analysis. Defaults to `300ms`. | -| `DAST_PAGE_IS_LOADING_ELEMENT` | selector | `css:#page-is-loading` | Selector that when is no longer visible on the page, indicates to the analyzer that the page has finished loading and the scan can continue. Cannot be used with `DAST_PAGE_IS_READY_ELEMENT`. | -| `DAST_PAGE_IS_READY_ELEMENT` | selector | `css:#page-is-ready` | Selector that when detected as visible on the page, indicates to the analyzer that the page has finished loading and the scan can continue. Cannot be used with `DAST_PAGE_IS_LOADING_ELEMENT`. | -| `DAST_PAGE_MAX_RESPONSE_SIZE_MB` | number | `15` | The maximum size of a HTTP response body. Responses with bodies larger than this are blocked by the browser. Defaults to `10` MB. | -| `DAST_PAGE_READY_AFTER_ACTION_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis. Defaults to `7s`. | -| `DAST_PAGE_READY_AFTER_NAVIGATION_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `15s` | The maximum amount of time to wait for a browser to navigate from one page to another. Defaults to `15s`. | -| `DAST_PASSIVE_SCAN_WORKER_COUNT` | int | `5` | Number of workers that passive scan in parallel. Defaults to the number of available CPUs. | -| `DAST_PKCS12_CERTIFICATE_BASE64` | string | `ZGZkZ2p5NGd...` | The PKCS12 certificate used for sites that require Mutual TLS. Must be encoded as base64 text. | -| `DAST_PKCS12_PASSWORD` | string | `password` | The password of the certificate used in `DAST_PKCS12_CERTIFICATE_BASE64`. Create sensitive [custom CI/CI variables](../../../../../ci/variables/_index.md#define-a-cicd-variable-in-the-ui) using the GitLab UI. | -| `DAST_REQUEST_ADVERTISE_SCAN` | boolean | `true` | Set to `true` to add a `Via: GitLab DAST ` header to every request sent, advertising that the request was sent as part of a GitLab DAST scan. Default: `false`. | -| `DAST_REQUEST_COOKIES` | dictionary | `abtesting_group:3,region:locked` | A cookie name and value to be added to every request. | -| `DAST_REQUEST_HEADERS` | string | `Cache-control:no-cache` | Set to a comma-separated list of request header names and values. The following headers are not supported: `content-length`, `cookie2`, `keep-alive`, `hosts`, `trailer`, `transfer-encoding`, and all headers with a `proxy-` prefix. | -| `DAST_SCOPE_ALLOW_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered in scope when crawled. By default the `DAST_TARGET_URL` hostname is included in the allowed hosts list. Headers set using `DAST_REQUEST_HEADERS` are added to every request made to these hostnames. | -| `DAST_SCOPE_EXCLUDE_ELEMENTS` | selector | `a[href='2.html'],css:.no-follow` | Comma-separated list of selectors that are ignored when scanning. | -| `DAST_SCOPE_EXCLUDE_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered excluded and connections are forcibly dropped. | -| `DAST_SCOPE_EXCLUDE_URLS` | URLs | `https://site.com/.*/sign-out` | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. | -| `DAST_SCOPE_IGNORE_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are accessed, not attacked, and not reported against. | -| `DAST_TARGET_CHECK_SKIP` | boolean | `true` | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. | -| `DAST_TARGET_CHECK_TIMEOUT` | number | `60` | Time limit in seconds to wait for target availability. Default: `60s`. | -| `DAST_TARGET_PATHS_FILE` | string | `/builds/project/urls.txt` | Ensures that the provided paths are always scanned. Set to a file path containing a list of URL paths relative to `DAST_TARGET_URL`. The file must be plain text with one path per line. | -| `DAST_TARGET_PATHS` | string | `/page1.html,/category1/page3.html` | Ensures that the provided paths are always scanned. Set to a comma-separated list of URL paths relative to `DAST_TARGET_URL`. | -| `DAST_TARGET_URL` | URL | `https://site.com` | The URL of the website to scan. | -| `DAST_USE_CACHE` | boolean | `true` | Set to `false` to disable caching. Default: `true`. **Note:** Disabling cache can cause OOM events or DAST job timeouts. | -| `SECURE_ANALYZERS_PREFIX` | URL | `registry.organization.com` | Set the Docker registry base address from which to download the analyzer. | +## Scanner behavior + +These variables control how the scan is conducted and where its results are stored. + +| CI/CD variable | Type | Example | Description | +| :------------- | :--- | ------- | :---------- | +| `DAST_CHECKS_TO_EXCLUDE` | string | `552.2,78.1` | Comma-separated list of check identifiers to exclude from the scan. For identifiers, see [vulnerability checks](../checks/_index.md). | +| `DAST_CHECKS_TO_RUN` | List of strings | `16.1,16.2,16.3` | Comma-separated list of check identifiers to use for the scan. For identifiers, see [vulnerability checks](../checks/_index.md). | +| `DAST_CRAWL_GRAPH` | boolean | `true` | Set to `true` to generate an SVG graph of navigation paths visited during crawl phase of the scan. You must also define `gl-dast-crawl-graph.svg` as a CI job artifact to be able to access the generated graph. Defaults to `false`. | +| `DAST_FULL_SCAN` | boolean | `true` | Set to `true` to run both passive and active checks. Default is `false`. | +| `DAST_LOG_BROWSER_OUTPUT` | boolean | `true` | Set to `true` to log Chromium `STDOUT` and `STDERR`. | +| `DAST_LOG_CONFIG` | List of strings | `brows:debug,auth:debug` | A list of modules and their intended logging level for use in the console log. | +| `DAST_LOG_DEVTOOLS_CONFIG` | string | `Default:messageAndBody,truncate:2000` | Set to log protocol messages between DAST and the Chromium browser. | +| `DAST_LOG_FILE_CONFIG` | List of strings | `brows:debug,auth:debug` | A list of modules and their intended logging level for use in the file log. | +| `DAST_LOG_FILE_PATH` | string | `/output/browserker.log` | Set to the path of the file log. Default is `gl-dast-scan.log`. | +| `SECURE_ANALYZERS_PREFIX` | URL | `registry.organization.com` | Set the Docker registry base address from which to download the analyzer. | + +## Elements, actions, and timeouts + +These variables tell the scanner where to look for certain elements, which actions to take, and how long to wait for operations to complete. + +| CI/CD variable | Type | Example | Description | +| :------------- | :--- | ------- | :---------- | +| `DAST_ACTIVE_SCAN_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `3h` | The maximum amount of time to wait for the active scan phase of the scan to complete. Defaults to 3h. | +| `DAST_ACTIVE_SCAN_WORKER_COUNT` | number | `3` | The number of active checks to run in parallel. Defaults to 3. | +| `DAST_CRAWL_EXTRACT_ELEMENT_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `5s` | The maximum amount of time to allow the browser to extract newly found elements or navigations. Defaults to `5s`. | +| `DAST_CRAWL_MAX_ACTIONS` | number | `10000` | The maximum number of actions that the crawler performs. Example actions include selecting a link, or filling out a form. Defaults to `10000`. | +| `DAST_CRAWL_MAX_DEPTH` | number | `10` | The maximum number of chained actions that the crawler takes. For example, `Click, Form Fill, Click` is a depth of three. Defaults to `10`. | +| `DAST_CRAWL_SEARCH_ELEMENT_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `3s` | The maximum amount of time to allow the browser to search for new elements or user actions. Defaults to `3s`. | +| `DAST_CRAWL_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `5m` | The maximum amount of time to wait for the crawl phase of the scan to complete. Defaults to `24h`. | +| `DAST_CRAWL_WORKER_COUNT` | number | `3` | The maximum number of concurrent browser instances to use. For instance runners on GitLab.com, we recommended a maximum of three. Private runners with more resources may benefit from a higher number, but are likely to produce little benefit after five to seven instances. The default value is dynamic, equal to the number of usable logical CPUs. | +| `DAST_PAGE_DOM_READY_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis after a navigation completes. Defaults to `6s`. | +| `DAST_PAGE_DOM_STABLE_WAIT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `200ms` | Define how long to wait for updates to the DOM before checking a page is stable. Defaults to `500ms`. | +| `DAST_PAGE_ELEMENT_READY_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `600ms` | The maximum amount of time to wait for an element before determining it is ready for analysis. Defaults to `300ms`. | +| `DAST_PAGE_IS_LOADING_ELEMENT` | [selector](authentication.md#finding-an-elements-selector) | `css:#page-is-loading` | Selector that, when no longer visible on the page, indicates to the analyzer that the page has finished loading and the scan can continue. Cannot be used with `DAST_PAGE_IS_READY_ELEMENT`. | +| `DAST_PAGE_IS_READY_ELEMENT` | [selector](authentication.md#finding-an-elements-selector) | `css:#page-is-ready` | Selector that when detected as visible on the page, indicates to the analyzer that the page has finished loading and the scan can continue. Cannot be used with `DAST_PAGE_IS_LOADING_ELEMENT`. | +| `DAST_PAGE_MAX_RESPONSE_SIZE_MB` | number | `15` | The maximum size of a HTTP response body. Responses with bodies larger than this are blocked by the browser. Defaults to `10` MB. | +| `DAST_PAGE_READY_AFTER_ACTION_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis. Defaults to `7s`. | +| `DAST_PAGE_READY_AFTER_NAVIGATION_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `15s` | The maximum amount of time to wait for a browser to navigate from one page to another. Defaults to `15s`. | +| `DAST_PASSIVE_SCAN_WORKER_COUNT` | int | `5` | Number of workers that passive scan in parallel. Defaults to the number of available CPUs. | +| `DAST_PKCS12_CERTIFICATE_BASE64` | string | `ZGZkZ2p5NGd...` | The PKCS12 certificate used for sites that require Mutual TLS. Must be encoded as base64 text. | +| `DAST_PKCS12_PASSWORD` | string | `password` | The password of the certificate used in `DAST_PKCS12_CERTIFICATE_BASE64`. Create sensitive [custom CI/CI variables](../../../../../ci/variables/_index.md#define-a-cicd-variable-in-the-ui) using the GitLab UI. | +| `DAST_REQUEST_ADVERTISE_SCAN` | boolean | `true` | Set to `true` to add a `Via: GitLab DAST ` header to every request sent, advertising that the request was sent as part of a GitLab DAST scan. Default: `false`. | +| `DAST_REQUEST_COOKIES` | dictionary | `abtesting_group:3,region:locked` | A cookie name and value to be added to every request. | +| `DAST_REQUEST_HEADERS` | String | `Cache-control:no-cache` | Set to a comma-separated list of request header names and values. The following headers are not supported: `content-length`, `cookie2`, `keep-alive`, `hosts`, `trailer`, `transfer-encoding`, and all headers with a `proxy-` prefix. | +| `DAST_SCOPE_ALLOW_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered in scope when crawled. By default the `DAST_TARGET_URL` hostname is included in the allowed hosts list. Headers set using `DAST_REQUEST_HEADERS` are added to every request made to these hostnames. | +| `DAST_SCOPE_EXCLUDE_ELEMENTS` | [selector](authentication.md#finding-an-elements-selector) | `a[href='2.html'],css:.no-follow` | Comma-separated list of selectors that are ignored when scanning. | +| `DAST_SCOPE_EXCLUDE_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered excluded and connections are forcibly dropped. | +| `DAST_SCOPE_IGNORE_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are accessed, not attacked, and not reported against. | +| `DAST_TARGET_CHECK_SKIP` | boolean | `true` | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. | +| `DAST_TARGET_CHECK_TIMEOUT` | number | `60` | Time limit in seconds to wait for target availability. Default: `60s`. | +| `DAST_TARGET_PATHS_FILE` | string | `/builds/project/urls.txt` | Ensures that the provided paths are always scanned. Set to a file path containing a list of URL paths relative to `DAST_TARGET_URL`. The file must be plain text with one path per line. | +| `DAST_TARGET_PATHS` | string | `/page1.html,/category1/page3.html` | Ensures that the provided paths are always scanned. Set to a comma-separated list of URL paths relative to `DAST_TARGET_URL`. | +| `DAST_TARGET_URL` | URL | `https://site.com` | The URL of the website to scan. | +| `DAST_USE_CACHE` | boolean | `true` | Set to `false` to disable caching. Default: `true`. **Note:** Disabling cache can cause OOM events or DAST job timeouts. | + +### Authentication + +These variables tell the scanner how to authenticate with your application. + +| CI/CD variable | Type | Example | Description | +| :------------- | :--- | ------- | :---------- | +| `DAST_AUTH_AFTER_LOGIN_ACTIONS` | string | `click(on=id:remember-me),click(on=css:.continue)` | A comma-separated list of actions to be run after login but before login verification. Currently supports `click` actions. | +| `DAST_AUTH_BEFORE_LOGIN_ACTIONS` | [selector](authentication.md#finding-an-elements-selector) | `css:.user,id:show-login-form` | A comma-separated list of selectors representing elements to click on prior to entering the DAST_AUTH_USERNAME and DAST_AUTH_PASSWORD into the login form. | +| `DAST_AUTH_CLEAR_INPUT_FIELDS` | boolean | `true` | Disables clearing of username and password fields before attempting manual login. Set to false by default. | +| `DAST_AUTH_COOKIE_NAMES` | string | `sessionID,groupName` | Set to a comma-separated list of cookie names to specify which cookies are used for authentication. | +| `DAST_AUTH_FIRST_SUBMIT_FIELD` | [selector](authentication.md#finding-an-elements-selector) | `css:input[type=submit]` | A selector describing the element that is clicked on to submit the username form of a multi-page login process. | +| `DAST_AUTH_NEGOTIATE_DELEGATION` | string | `*.example.com,example.com,*.EXAMPLE.COM,EXAMPLE.COM` | Which servers should be allowed for integrated authentication and delegation. This property sets two Chromium policies: [AuthServerAllowlist](https://chromeenterprise.google/policies/#AuthServerAllowlist) and [AuthNegotiateDelegateAllowlist](https://chromeenterprise.google/policies/#AuthNegotiateDelegateAllowlist). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/502476) in GitLab 17.6. | +| `DAST_AUTH_PASSWORD` | String | `P@55w0rd!` | The password to authenticate to in the website. | +| `DAST_AUTH_PASSWORD_FIELD` | [selector](authentication.md#finding-an-elements-selector) | `name:password` | A selector describing the element used to enter the password on the login form. | +| `DAST_AUTH_SUBMIT_FIELD` | [selector](authentication.md#finding-an-elements-selector) | `css:input[type=submit]` | A selector describing the element clicked on to submit the login form for a single-page login form, or the password form for a multi-page login form. | +| `DAST_AUTH_SUCCESS_IF_AT_URL` | URL | `https://www.site.com/welcome` | A URL that is compared to the URL in the browser to determine if authentication has succeeded after the login form is submitted. | +| `DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND` | [selector](authentication.md#finding-an-elements-selector) | `css:.user-avatar` | A selector describing an element whose presence is used to determine if authentication has succeeded after the login form is submitted. | +| `DAST_AUTH_SUCCESS_IF_NO_LOGIN_FORM` | boolean | `true` | Verifies successful authentication by checking for the absence of a login form after the login form has been submitted. This success check is enabled by default. | +| `DAST_AUTH_TYPE` | string | `basic-digest` | The authentication type to use. | +| `DAST_AUTH_URL` | URL | `https://www.site.com/login` | The URL of the page containing the login form on the target website. DAST_AUTH_USERNAME and DAST_AUTH_PASSWORD are submitted with the login form to create an authenticated scan. | +| `DAST_AUTH_USERNAME` | string | `user@email.com` | The username to authenticate to in the website. | +| `DAST_AUTH_USERNAME_FIELD` | [selector](authentication.md#finding-an-elements-selector) | `name:username` | A selector describing the element used to enter the username on the login form. | +| `DAST_SCOPE_EXCLUDE_URLS` | URLs | `https://site.com/.*/sign-out` | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. | +| `DAST_AUTH_REPORT` | boolean | `true` | Set to `true` to generate a report detailing steps taken during the authentication process. You must also define `gl-dast-debug-auth-report.html` as a CI job artifact to be able to access the generated report. The report's content aids when debugging authentication failures. Defaults to `false`. | diff --git a/lib/gitlab/security/dast_variables.rb b/lib/gitlab/security/dast_variables.rb new file mode 100644 index 00000000000..b6fc3e0ead5 --- /dev/null +++ b/lib/gitlab/security/dast_variables.rb @@ -0,0 +1,615 @@ +# frozen_string_literal: true + +module Gitlab + module Security + class DastVariables + def self.ci_variables_documentation_link + Gitlab::Routing.url_helpers.help_page_path('ci/variables/_index.md', anchor: 'define-a-cicd-variable-in-the-ui') + end + + # rubocop: disable Metrics/AbcSize -- Generate dynamic translation as per + # https://docs.gitlab.com/ee/development/i18n/externalization.html#keep-translations-dynamic + def self.data + { + site: { + DAST_ACTIVE_SCAN_TIMEOUT: { + additional: true, + type: "Duration string", + example: "3h", + name: s_("DastProfiles|Active scan timeout"), + description: s_( + "DastProfiles|The maximum amount of time to wait for the active scan phase of the scan to complete. " \ + "Defaults to 3h." + ) + }, + DAST_ACTIVE_SCAN_WORKER_COUNT: { + additional: true, + type: "number", + example: 3, + name: s_("DastProfiles|Active scan worker count"), + description: s_("DastProfiles|The number of active checks to run in parallel. Defaults to 3.") + }, + DAST_AUTH_AFTER_LOGIN_ACTIONS: { + additional: true, + auth: true, + type: "string", + example: "click(on=id:remember-me),click(on=css:.continue)", + name: s_("DastProfiles|After-login actions"), + description: s_( + "DastProfiles|A comma-separated list of actions to be run after login but before login " \ + "verification. Currently supports `click` actions." + ) + }, + DAST_AUTH_BEFORE_LOGIN_ACTIONS: { + additional: true, + auth: true, + type: "selector", + example: "css:.user,id:show-login-form", + name: s_("DastProfiles|Before-login actions"), + description: s_( + "DastProfiles|A comma-separated list of selectors representing elements to click on " \ + "prior to entering the DAST_AUTH_USERNAME and DAST_AUTH_PASSWORD into the login form." + ) + }, + DAST_AUTH_CLEAR_INPUT_FIELDS: { + additional: true, + auth: true, + type: "boolean", + example: true, + name: s_("DastProfiles|Clear input fields"), + description: s_( + "DastProfiles|Disables clearing of username and password fields before attempting manual login. " \ + "Set to false by default." + ) + }, + DAST_AUTH_COOKIE_NAMES: { + additional: true, + auth: true, + type: "string", + example: "sessionID,groupName", + name: s_("DastProfiles|Cookie names"), + description: s_( + "DastProfiles|Set to a comma-separated list of cookie names to specify which cookies " \ + "are used for authentication." + ) + }, + DAST_AUTH_FIRST_SUBMIT_FIELD: { + additional: true, + auth: true, + type: "selector", + example: "css:input[type=submit]", + name: s_("DastProfiles|First submit field"), + description: s_( + "DastProfiles|A selector describing the element that is clicked on to submit the username form " \ + "of a multi-page login process." + ) + }, + DAST_AUTH_NEGOTIATE_DELEGATION: { + additional: true, + auth: true, + type: "string", + example: "*.example.com,example.com,*.EXAMPLE.COM,EXAMPLE.COM", + name: s_("DastProfiles|Authentication delegation servers"), + description: s_( + "DastProfiles|Which servers should be allowed for integrated authentication and delegation. " \ + "This property sets two Chromium policies: " \ + "[AuthServerAllowlist](https://chromeenterprise.google/policies/#AuthServerAllowlist) and " \ + "[AuthNegotiateDelegateAllowlist]" \ + "(https://chromeenterprise.google/policies/#AuthNegotiateDelegateAllowlist). " \ + "[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/502476) in GitLab 17.6." + ) + }, + DAST_AUTH_PASSWORD: { + additional: false, + auth: true, + type: "String", + example: "P@55w0rd!", + name: s_("DastProfiles|Password"), + description: s_("DastProfiles|The password to authenticate to in the website.") + }, + DAST_AUTH_PASSWORD_FIELD: { + additional: false, + auth: true, + type: "selector", + example: "name:password", + name: s_("DastProfiles|Password field"), + description: s_( + "DastProfiles|A selector describing the element used to enter the password on the login form." + ) + }, + DAST_AUTH_SUBMIT_FIELD: { + additional: false, + auth: true, + type: "selector", + example: "css:input[type=submit]", + name: s_("DastProfiles|Submit field"), + description: s_( + "DastProfiles|A selector describing the element clicked on to submit the login form " \ + "for a single-page login form, or the password form for a multi-page login form." + ) + }, + DAST_AUTH_SUCCESS_IF_AT_URL: { + additional: true, + auth: true, + type: "URL", + example: "https://www.site.com/welcome", + name: s_("DastProfiles|Success URL"), + description: s_( + "DastProfiles|A URL that is compared to the URL in the browser to determine if authentication " \ + "has succeeded after the login form is submitted." + ) + }, + DAST_AUTH_SUCCESS_IF_ELEMENT_FOUND: { + additional: true, + auth: true, + type: "selector", + example: "css:.user-avatar", + name: s_("DastProfiles|Success element"), + description: s_( + "DastProfiles|A selector describing an element whose presence is used to determine if " \ + "authentication has succeeded after the login form is submitted." + ) + }, + DAST_AUTH_SUCCESS_IF_NO_LOGIN_FORM: { + additional: true, + auth: true, + type: "boolean", + example: true, + name: s_("DastProfiles|Success without login form"), + description: s_( + "DastProfiles|Verifies successful authentication by checking for the absence of a login form " \ + "after the login form has been submitted. This success check is enabled by default." + ) + }, + DAST_AUTH_TYPE: { + additional: true, + auth: true, + type: "string", + example: "basic-digest", + name: s_("DastProfiles|Authentication type"), + description: s_("DastProfiles|The authentication type to use.") + }, + DAST_AUTH_URL: { + additional: false, + auth: true, + type: "URL", + example: "https://www.site.com/login", + name: s_("DastProfiles|Authentication URL"), + description: s_( + "DastProfiles|The URL of the page containing the login form on the target website. " \ + "DAST_AUTH_USERNAME and DAST_AUTH_PASSWORD are submitted with the login form to create " \ + "an authenticated scan." + ) + }, + DAST_AUTH_USERNAME: { + additional: false, + auth: true, + type: "string", + example: "user@email.com", + name: s_("DastProfiles|Username"), + description: s_("DastProfiles|The username to authenticate to in the website.") + }, + DAST_AUTH_USERNAME_FIELD: { + additional: false, + auth: true, + type: "selector", + example: "name:username", + name: s_("DastProfiles|Username field"), + description: s_( + "DastProfiles|A selector describing the element used to enter the username on the login form." + ) + }, + DAST_CRAWL_EXTRACT_ELEMENT_TIMEOUT: { + additional: true, + type: "Duration string", + example: "5s", + name: s_("DastProfiles|Extract element timeout"), + description: s_( + "DastProfiles|The maximum amount of time to allow the browser to extract newly found elements " \ + "or navigations. Defaults to `5s`." + ) + }, + DAST_CRAWL_MAX_ACTIONS: { + additional: true, + type: "number", + example: "10000", + name: s_("DastProfiles|Maximum action count"), + description: s_( + "DastProfiles|The maximum number of actions that the crawler performs. " \ + "Example actions include selecting a link, or filling out a form. " \ + "Defaults to `10000`." + ) + }, + DAST_CRAWL_MAX_DEPTH: { + additional: true, + type: "number", + example: "10", + name: s_("DastProfiles|Maximum action depth"), + description: s_( + "DastProfiles|The maximum number of chained actions that the crawler takes. " \ + "For example, `Click, Form Fill, Click` is a depth of three. " \ + "Defaults to `10`." + ) + }, + DAST_CRAWL_SEARCH_ELEMENT_TIMEOUT: { + additional: true, + type: "Duration string", + example: "3s", + name: s_("DastProfiles|Element search timeout"), + description: s_( + "DastProfiles|The maximum amount of time to allow the browser to search for new elements " \ + "or user actions. Defaults to `3s`." + ) + }, + DAST_CRAWL_TIMEOUT: { + additional: true, + type: "Duration string", + example: "5m", + name: s_("DastProfiles|Timeout"), + description: s_( + "DastProfiles|The maximum amount of time to wait for the crawl phase of the scan to complete. " \ + "Defaults to `24h`." + ) + }, + DAST_CRAWL_WORKER_COUNT: { + additional: true, + type: "number", + example: "3", + name: s_("DastProfiles|Worker count"), + description: s_( + "DastProfiles|The maximum number of concurrent browser instances to use. " \ + "For instance runners on GitLab.com, we recommended a maximum of three. " \ + "Private runners with more resources may benefit from a higher number, " \ + "but are likely to produce little benefit after five to seven instances. " \ + "The default value is dynamic, equal to the number of usable logical CPUs." + ) + }, + DAST_PAGE_DOM_READY_TIMEOUT: { + additional: true, + type: "Duration string", + example: "7s", + name: s_("DastProfiles|DOM ready timeout"), + description: s_( + "DastProfiles|The maximum amount of time to wait for a browser to consider a page loaded " \ + "and ready for analysis after a navigation completes. Defaults to `6s`." + ) + }, + DAST_PAGE_DOM_STABLE_WAIT: { + additional: true, + type: "Duration string", + example: "200ms", + name: s_("DastProfiles|DOM stable timeout"), + description: s_( + "DastProfiles|Define how long to wait for updates to the DOM before checking a page is stable. " \ + "Defaults to `500ms`." + ) + }, + DAST_PAGE_ELEMENT_READY_TIMEOUT: { + additional: true, + type: "Duration string", + example: "600ms", + name: s_("DastProfiles|Page ready timeout"), + description: s_( + "DastProfiles|The maximum amount of time to wait for an element before determining it is " \ + "ready for analysis. Defaults to `300ms`." + ) + }, + DAST_PAGE_IS_LOADING_ELEMENT: { + additional: true, + type: "selector", + example: "css:#page-is-loading", + name: s_("DastProfiles|Loading element"), + description: s_( + "DastProfiles|Selector that, when no longer visible on the page, indicates to the analyzer " \ + "that the page has finished loading and the scan can continue. " \ + "Cannot be used with `DAST_PAGE_IS_READY_ELEMENT`." + ) + }, + DAST_PAGE_IS_READY_ELEMENT: { + additional: true, + type: "selector", + example: "css:#page-is-ready", + name: s_("DastProfiles|Ready element"), + description: s_( + "DastProfiles|Selector that when detected as visible on the page, indicates to the analyzer " \ + "that the page has finished loading and the scan can continue. " \ + "Cannot be used with `DAST_PAGE_IS_LOADING_ELEMENT`." + ) + }, + DAST_PAGE_MAX_RESPONSE_SIZE_MB: { + additional: true, + type: "number", + example: "15", + name: s_("DastProfiles|Maximum response size (MB)"), + description: s_( + "DastProfiles|The maximum size of a HTTP response body. " \ + "Responses with bodies larger than this are blocked by the browser. " \ + "Defaults to `10` MB." + ) + }, + DAST_PAGE_READY_AFTER_ACTION_TIMEOUT: { + additional: true, + type: "Duration string", + example: "7s", + name: s_("DastProfiles|Page ready timeout (after action)"), + description: s_( + "DastProfiles|The maximum amount of time to wait for a browser to consider a page loaded " \ + "and ready for analysis. Defaults to `7s`." + ) + }, + DAST_PAGE_READY_AFTER_NAVIGATION_TIMEOUT: { + additional: true, + type: "Duration string", + example: "15s", + name: s_("DastProfiles|Page ready timeout (after navigation)"), + description: s_( + "DastProfiles|The maximum amount of time to wait for a browser to navigate from one page " \ + "to another. Defaults to `15s`." + ) + }, + DAST_PASSIVE_SCAN_WORKER_COUNT: { + additional: true, + type: "int", + example: "5", + name: s_("DastProfiles|Passive scan worker count"), + description: s_( + "DastProfiles|Number of workers that passive scan in parallel. " \ + "Defaults to the number of available CPUs." + ) + }, + DAST_PKCS12_CERTIFICATE_BASE64: { + additional: true, + type: "string", + example: "ZGZkZ2p5NGd...", + name: s_("DastProfiles|PKCS12 certificate"), + description: s_( + "DastProfiles|The PKCS12 certificate used for sites that require Mutual TLS. " \ + "Must be encoded as base64 text." + ) + }, + DAST_PKCS12_PASSWORD: { + additional: true, + type: "string", + example: "password", + name: s_("DastProfiles|PKCS12 password"), + description: format(s_( + "DastProfiles|The password of the certificate used in `DAST_PKCS12_CERTIFICATE_BASE64`. " \ + "Create sensitive [custom CI/CI variables](%{documentation_link}) using the GitLab UI."), + documentation_link: ci_variables_documentation_link + ) + }, + DAST_REQUEST_ADVERTISE_SCAN: { + additional: true, + type: "boolean", + example: true, + name: s_("DastProfiles|Advertise scan"), + description: format(s_( + "DastProfiles|Set to `true` to add a `Via: GitLab DAST %{version}` header to every request sent, " \ + "advertising that the request was sent as part of a GitLab DAST scan. Default: `false`." + ), version: "") + }, + DAST_REQUEST_COOKIES: { + additional: true, + type: "dictionary", + example: "abtesting_group:3,region:locked", + name: s_("DastProfiles|Request cookies"), + description: s_("DastProfiles|A cookie name and value to be added to every request.") + }, + DAST_REQUEST_HEADERS: { + additional: false, + type: "String", + example: "Cache-control:no-cache", + name: s_("DastProfiles|Request headers"), + description: s_( + "DastProfiles|Set to a comma-separated list of request header names and values. " \ + "The following headers are not supported: `content-length`, `cookie2`, `keep-alive`, `hosts`, " \ + "`trailer`, `transfer-encoding`, and all headers with a `proxy-` prefix." + ) + }, + DAST_SCOPE_ALLOW_HOSTS: { + additional: true, + type: "List of strings", + example: "site.com,another.com", + name: s_("DastProfiles|Allowed hosts"), + description: s_( + "DastProfiles|Hostnames included in this variable are considered in scope when crawled. " \ + "By default the `DAST_TARGET_URL` hostname is included in the allowed hosts list. " \ + "Headers set using `DAST_REQUEST_HEADERS` are added to every request made to these hostnames." + ) + }, + DAST_SCOPE_EXCLUDE_ELEMENTS: { + additional: true, + type: "selector", + example: "a[href='2.html'],css:.no-follow", + name: s_("DastProfiles|Excluded elements"), + description: s_("DastProfiles|Comma-separated list of selectors that are ignored when scanning.") + }, + DAST_SCOPE_EXCLUDE_HOSTS: { + additional: true, + type: "List of strings", + example: "site.com,another.com", + name: s_("DastProfiles|Excluded hosts"), + description: s_( + "DastProfiles|Hostnames included in this variable are considered excluded and connections " \ + "are forcibly dropped." + ) + }, + DAST_SCOPE_EXCLUDE_URLS: { + auth: true, + additional: false, + type: "URLs", + example: "https://site.com/.*/sign-out", + name: s_("DastProfiles|Excluded URLs"), + description: s_( + "DastProfiles|The URLs to skip during the authenticated scan; comma-separated. " \ + "Regular expression syntax can be used to match multiple URLs. " \ + "For example, `.*` matches an arbitrary character sequence." + ) + }, + DAST_SCOPE_IGNORE_HOSTS: { + additional: true, + type: "List of strings", + example: "site.com,another.com", + name: s_("DastProfiles|Ignored hosts"), + description: s_( + "DastProfiles|Hostnames included in this variable are accessed, not attacked, " \ + "and not reported against." + ) + }, + DAST_TARGET_CHECK_SKIP: { + additional: true, + type: "boolean", + example: true, + name: s_("DastProfiles|Skip target check"), + description: s_( + "DastProfiles|Set to `true` to prevent DAST from checking that the target is available " \ + "before scanning. Default: `false`." + ) + }, + DAST_TARGET_CHECK_TIMEOUT: { + additional: true, + type: "number", + example: "60", + name: s_("DastProfiles|Target check timeout"), + description: s_("DastProfiles|Time limit in seconds to wait for target availability. Default: `60s`.") + }, + DAST_TARGET_PATHS_FILE: { + additional: true, + type: "string", + example: "/builds/project/urls.txt", + name: s_("DastProfiles|Target paths file"), + description: s_( + "DastProfiles|Ensures that the provided paths are always scanned. " \ + "Set to a file path containing a list of URL paths relative to `DAST_TARGET_URL`. " \ + "The file must be plain text with one path per line." + ) + }, + DAST_TARGET_PATHS: { + additional: true, + type: "string", + example: "/page1.html,/category1/page3.html", + name: s_("DastProfiles|Target paths"), + description: s_( + "DastProfiles|Ensures that the provided paths are always scanned. " \ + "Set to a comma-separated list of URL paths relative to `DAST_TARGET_URL`." + ) + }, + DAST_TARGET_URL: { + additional: false, + type: "URL", + example: "https://site.com", + name: s_("DastProfiles|Target URL"), + description: s_("DastProfiles|The URL of the website to scan.") + }, + DAST_USE_CACHE: { + additional: true, + type: "boolean", + example: true, + name: s_("DastProfiles|Use cache"), + description: s_( + "DastProfiles|Set to `false` to disable caching. " \ + "Default: `true`. " \ + "**Note:** Disabling cache can cause OOM events or DAST job timeouts." + ) + } + }, + scanner: { + DAST_AUTH_REPORT: { + auth: true, + type: "boolean", + example: true, + name: s_("DastProfiles|Generate authentication report"), + description: s_( + "DastProfiles|Set to `true` to generate a report detailing steps taken during the " \ + "authentication process. You must also define `gl-dast-debug-auth-report.html` as a " \ + "CI job artifact to be able to access the generated report. " \ + "The report's content aids when debugging authentication failures. Defaults to `false`." + ) + }, + DAST_CHECKS_TO_EXCLUDE: { + type: "string", + example: "552.2,78.1", + name: s_("DastProfiles|Excluded checks"), + description: s_( + "DastProfiles|Comma-separated list of check identifiers to exclude from the scan. " \ + "For identifiers, see [vulnerability checks](../checks/_index.md)." + ) + }, + DAST_CHECKS_TO_RUN: { + type: "List of strings", + example: "16.1,16.2,16.3", + name: s_("DastProfiles|Included checks"), + description: s_( + "DastProfiles|Comma-separated list of check identifiers to use for the scan. " \ + "For identifiers, see [vulnerability checks](../checks/_index.md)." + ) + }, + DAST_CRAWL_GRAPH: { + type: "boolean", + example: true, + name: s_("DastProfiles|Generate graph"), + description: s_( + "DastProfiles|Set to `true` to generate an SVG graph of navigation paths visited during crawl phase " \ + "of the scan. You must also define `gl-dast-crawl-graph.svg` as a CI job artifact to be able to " \ + "access the generated graph. Defaults to `false`." + ) + }, + DAST_FULL_SCAN: { + type: "boolean", + example: true, + name: s_("DastProfiles|Full scan"), + description: s_("DastProfiles|Set to `true` to run both passive and active checks. Default is `false`.") + }, + DAST_LOG_BROWSER_OUTPUT: { + type: "boolean", + example: true, + name: s_("DastProfiles|Log browser output"), + description: s_("DastProfiles|Set to `true` to log Chromium `STDOUT` and `STDERR`.") + }, + DAST_LOG_CONFIG: { + type: "List of strings", + example: "brows:debug,auth:debug", + name: s_("DastProfiles|Log levels"), + description: s_( + "DastProfiles|A list of modules and their intended logging level for use in the console log.") + }, + DAST_LOG_DEVTOOLS_CONFIG: { + type: "string", + example: "Default:messageAndBody,truncate:2000", + name: s_("DastProfiles|Log messages"), + description: s_("DastProfiles|Set to log protocol messages between DAST and the Chromium browser.") + }, + DAST_LOG_FILE_CONFIG: { + type: "List of strings", + example: "brows:debug,auth:debug", + name: s_("DastProfiles|Log file levels"), + description: s_( + "DastProfiles|A list of modules and their intended logging level for use in the file log.") + }, + DAST_LOG_FILE_PATH: { + type: "string", + example: "/output/browserker.log", + name: s_("DastProfiles|Log file path"), + description: s_("DastProfiles|Set to the path of the file log. Default is `gl-dast-scan.log`.") + }, + SECURE_ANALYZERS_PREFIX: { + type: "URL", + example: "registry.organization.com", + name: s_("DastProfiles|Docker registry"), + description: s_("DastProfiles|Set the Docker registry base address from which to download the analyzer.") + } + } + }.freeze + end + # rubocop: enable Metrics/AbcSize + + def self.additional_site_variables + data[:site].filter { |_, variable| variable[:additional] } + end + + def self.auth_variables + data[:site].merge(data[:scanner]).filter { |_, variable| variable[:auth] } + end + end + end +end diff --git a/lib/tasks/gitlab/dast_variables.rake b/lib/tasks/gitlab/dast_variables.rake new file mode 100644 index 00000000000..ede5f09d718 --- /dev/null +++ b/lib/tasks/gitlab/dast_variables.rake @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +return if Rails.env.production? + +namespace :gitlab do + namespace :dast_variables do + desc 'GitLab | DAST variables | Generate docs' + task compile_docs: [:environment] do + require_relative '../../../tooling/dast_variables/docs/renderer' + + renderer = Tooling::DastVariables::Docs::Renderer.new(**dast_variables_render_options) + + renderer.write + + puts "Documentation compiled." + end + + desc 'GitLab | DAST variables | Check if docs are up to date' + task check_docs: [:environment] do + require_relative '../../../tooling/dast_variables/docs/renderer' + + renderer = Tooling::DastVariables::Docs::Renderer.new(**dast_variables_render_options) + + doc = File.read(dast_variables_render_options[:output_file]) + + unless doc == renderer.contents + raise <<~ERROR_MESSAGE.strip + DAST variables documentation is outdated! + Please update it by running `bundle exec rake gitlab:dast_variables:compile_docs`. + ERROR_MESSAGE + end + + puts "DAST variables documentation is up to date" + end + + def dast_variables_render_options + { + output_file: Rails.root.join("doc/user/application_security/dast/browser/configuration/variables.md"), + template: Rails.root.join("tooling/dast_variables/docs/templates/default.md.haml") + } + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 85fbdbb4d21..55a774bce3b 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -6878,6 +6878,9 @@ msgstr "" msgid "Analytics settings" msgstr "" +msgid "AnalyticsDashboards|Failed to load namespace metadata." +msgstr "" + msgid "Analytics| Last updated: %{recordedAt}" msgstr "" @@ -18453,6 +18456,12 @@ msgstr "" msgid "DastProfiles|A cookie name and value to be added to every request." msgstr "" +msgid "DastProfiles|A list of modules and their intended logging level for use in the console log." +msgstr "" + +msgid "DastProfiles|A list of modules and their intended logging level for use in the file log." +msgstr "" + msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities." msgstr "" @@ -18462,9 +18471,18 @@ msgstr "" msgid "DastProfiles|A selector describing an element whose presence is used to determine if authentication has succeeded after the login form is submitted." msgstr "" +msgid "DastProfiles|A selector describing the element clicked on to submit the login form for a single-page login form, or the password form for a multi-page login form." +msgstr "" + msgid "DastProfiles|A selector describing the element that is clicked on to submit the username form of a multi-page login process." msgstr "" +msgid "DastProfiles|A selector describing the element used to enter the password on the login form." +msgstr "" + +msgid "DastProfiles|A selector describing the element used to enter the username on the login form." +msgstr "" + msgid "DastProfiles|A site profile defines the attributes and configuration details of your deployed application, website, or API. %{linkStart}Learn more%{linkEnd}." msgstr "" @@ -18537,6 +18555,12 @@ msgstr "" msgid "DastProfiles|Clear input fields" msgstr "" +msgid "DastProfiles|Comma-separated list of check identifiers to exclude from the scan. For identifiers, see [vulnerability checks](../checks/_index.md)." +msgstr "" + +msgid "DastProfiles|Comma-separated list of check identifiers to use for the scan. For identifiers, see [vulnerability checks](../checks/_index.md)." +msgstr "" + msgid "DastProfiles|Comma-separated list of selectors that are ignored when scanning." msgstr "" @@ -18600,6 +18624,9 @@ msgstr "" msgid "DastProfiles|Disables clearing of username and password fields before attempting manual login. Set to false by default." msgstr "" +msgid "DastProfiles|Docker registry" +msgstr "" + msgid "DastProfiles|Edit DAST variable" msgstr "" @@ -18642,6 +18669,9 @@ msgstr "" msgid "DastProfiles|Excluded URLs (optional)" msgstr "" +msgid "DastProfiles|Excluded checks" +msgstr "" + msgid "DastProfiles|Excluded elements" msgstr "" @@ -18663,6 +18693,15 @@ msgstr "" msgid "DastProfiles|First submit field" msgstr "" +msgid "DastProfiles|Full scan" +msgstr "" + +msgid "DastProfiles|Generate authentication report" +msgstr "" + +msgid "DastProfiles|Generate graph" +msgstr "" + msgid "DastProfiles|Hide debug messages" msgstr "" @@ -18681,9 +18720,27 @@ msgstr "" msgid "DastProfiles|Include debug messages in the DAST console output." msgstr "" +msgid "DastProfiles|Included checks" +msgstr "" + msgid "DastProfiles|Loading element" msgstr "" +msgid "DastProfiles|Log browser output" +msgstr "" + +msgid "DastProfiles|Log file levels" +msgstr "" + +msgid "DastProfiles|Log file path" +msgstr "" + +msgid "DastProfiles|Log levels" +msgstr "" + +msgid "DastProfiles|Log messages" +msgstr "" + msgid "DastProfiles|Manage %{profileType} profiles" msgstr "" @@ -18765,6 +18822,9 @@ msgstr "" msgid "DastProfiles|Password" msgstr "" +msgid "DastProfiles|Password field" +msgstr "" + msgid "DastProfiles|Password form field" msgstr "" @@ -18840,18 +18900,42 @@ msgstr "" msgid "DastProfiles|Selector that, when no longer visible on the page, indicates to the analyzer that the page has finished loading and the scan can continue. Cannot be used with `DAST_PAGE_IS_READY_ELEMENT`." msgstr "" +msgid "DastProfiles|Set the Docker registry base address from which to download the analyzer." +msgstr "" + msgid "DastProfiles|Set to `false` to disable caching. Default: `true`. **Note:** Disabling cache can cause OOM events or DAST job timeouts." msgstr "" -msgid "DastProfiles|Set to `true` to add a `Via` header to every request sent, advertising that the request was sent as part of a GitLab DAST scan. Default: `false`." +msgid "DastProfiles|Set to `true` to add a `Via: GitLab DAST %{version}` header to every request sent, advertising that the request was sent as part of a GitLab DAST scan. Default: `false`." +msgstr "" + +msgid "DastProfiles|Set to `true` to generate a report detailing steps taken during the authentication process. You must also define `gl-dast-debug-auth-report.html` as a CI job artifact to be able to access the generated report. The report's content aids when debugging authentication failures. Defaults to `false`." +msgstr "" + +msgid "DastProfiles|Set to `true` to generate an SVG graph of navigation paths visited during crawl phase of the scan. You must also define `gl-dast-crawl-graph.svg` as a CI job artifact to be able to access the generated graph. Defaults to `false`." +msgstr "" + +msgid "DastProfiles|Set to `true` to log Chromium `STDOUT` and `STDERR`." msgstr "" msgid "DastProfiles|Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`." msgstr "" +msgid "DastProfiles|Set to `true` to run both passive and active checks. Default is `false`." +msgstr "" + msgid "DastProfiles|Set to a comma-separated list of cookie names to specify which cookies are used for authentication." msgstr "" +msgid "DastProfiles|Set to a comma-separated list of request header names and values. The following headers are not supported: `content-length`, `cookie2`, `keep-alive`, `hosts`, `trailer`, `transfer-encoding`, and all headers with a `proxy-` prefix." +msgstr "" + +msgid "DastProfiles|Set to log protocol messages between DAST and the Chromium browser." +msgstr "" + +msgid "DastProfiles|Set to the path of the file log. Default is `gl-dast-scan.log`." +msgstr "" + msgid "DastProfiles|Show debug messages" msgstr "" @@ -18876,6 +18960,9 @@ msgstr "" msgid "DastProfiles|Submit button (optional)" msgstr "" +msgid "DastProfiles|Submit field" +msgstr "" + msgid "DastProfiles|Success URL" msgstr "" @@ -18903,6 +18990,15 @@ msgstr "" msgid "DastProfiles|The PKCS12 certificate used for sites that require Mutual TLS. Must be encoded as base64 text." msgstr "" +msgid "DastProfiles|The URL of the page containing the login form on the target website. DAST_AUTH_USERNAME and DAST_AUTH_PASSWORD are submitted with the login form to create an authenticated scan." +msgstr "" + +msgid "DastProfiles|The URL of the website to scan." +msgstr "" + +msgid "DastProfiles|The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence." +msgstr "" + msgid "DastProfiles|The authentication type to use." msgstr "" @@ -18951,7 +19047,13 @@ msgstr "" msgid "DastProfiles|The number of active checks to run in parallel. Defaults to 3." msgstr "" -msgid "DastProfiles|The password of the certificate used in `DAST_PKCS12_CERTIFICATE_BASE64`. Create sensitive %{linkStart}custom CI/CI variables%{linkEnd} using the GitLab UI." +msgid "DastProfiles|The password of the certificate used in `DAST_PKCS12_CERTIFICATE_BASE64`. Create sensitive [custom CI/CI variables](%{documentation_link}) using the GitLab UI." +msgstr "" + +msgid "DastProfiles|The password to authenticate to in the website." +msgstr "" + +msgid "DastProfiles|The username to authenticate to in the website." msgstr "" msgid "DastProfiles|This profile is currently being used in a policy." @@ -18984,6 +19086,9 @@ msgstr "" msgid "DastProfiles|Username" msgstr "" +msgid "DastProfiles|Username field" +msgstr "" + msgid "DastProfiles|Username form field" msgstr "" @@ -19014,7 +19119,7 @@ msgstr "" msgid "DastProfiles|What does each method do?" msgstr "" -msgid "DastProfiles|Which servers should be allowed for integrated authentication and delegation." +msgid "DastProfiles|Which servers should be allowed for integrated authentication and delegation. This property sets two Chromium policies: [AuthServerAllowlist](https://chromeenterprise.google/policies/#AuthServerAllowlist) and [AuthNegotiateDelegateAllowlist](https://chromeenterprise.google/policies/#AuthNegotiateDelegateAllowlist). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/502476) in GitLab 17.6." msgstr "" msgid "DastProfiles|Worker count" diff --git a/qa/qa/scenario/test/sanity/selectors.rb b/qa/qa/scenario/test/sanity/selectors.rb index ad84f99128b..4b8f3c16d34 100644 --- a/qa/qa/scenario/test/sanity/selectors.rb +++ b/qa/qa/scenario/test/sanity/selectors.rb @@ -35,8 +35,8 @@ module QA current changes in this merge request. For more help see documentation in - https://docs.gitlab.com/ee/development/testing_guide/end_to_end/page_objects.html - or ask for help on #test-platform channel on Slack (GitLab Team only). + https://docs.gitlab.com/development/testing_guide/end_to_end/beginners_guide/page_objects/ + or ask for help on #s_developer_experience channel on Slack (GitLab Team only). If you are not a Team Member, and you still need help to contribute, please open an issue in GitLab QA issue tracker. diff --git a/scripts/frontend/quarantined_vue3_specs.txt b/scripts/frontend/quarantined_vue3_specs.txt index 214ef23f75f..8ab738bca53 100644 --- a/scripts/frontend/quarantined_vue3_specs.txt +++ b/scripts/frontend/quarantined_vue3_specs.txt @@ -125,12 +125,8 @@ spec/frontend/clusters/components/new_cluster_spec.js spec/frontend/clusters/components/remove_cluster_confirmation_spec.js spec/frontend/clusters_list/components/delete_agent_button_spec.js spec/frontend/content_editor/components/bubble_menus/media_bubble_menu_spec.js -spec/frontend/content_editor/components/toolbar_button_spec.js spec/frontend/content_editor/components/wrappers/code_block_spec.js -spec/frontend/content_editor/components/wrappers/html_comment_spec.js -spec/frontend/content_editor/components/wrappers/image_spec.js spec/frontend/content_editor/components/wrappers/paragraph_spec.js -spec/frontend/content_editor/components/wrappers/playable_spec.js spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js spec/frontend/custom_emoji/components/list_spec.js spec/frontend/design_management/components/design_notes/design_reply_form_spec.js @@ -147,10 +143,8 @@ spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js spec/frontend/feature_flags/components/strategy_spec.js spec/frontend/gitlab_version_check/index_spec.js spec/frontend/glql/components/common/facade_spec.js -spec/frontend/glql/components/presenters/link_spec.js spec/frontend/glql/components/presenters/list_spec.js spec/frontend/glql/components/presenters/table_spec.js -spec/frontend/glql/components/presenters/text_spec.js spec/frontend/glql/core/presenter_spec.js spec/frontend/groups/components/transfer_group_form_spec.js spec/frontend/helpers/init_simple_app_helper_spec.js diff --git a/scripts/generate-failed-test-on-omnibus-mr-message.rb b/scripts/generate-failed-test-on-omnibus-mr-message.rb index b15851e5c1a..aa5997db222 100755 --- a/scripts/generate-failed-test-on-omnibus-mr-message.rb +++ b/scripts/generate-failed-test-on-omnibus-mr-message.rb @@ -53,8 +53,8 @@ class GenerateFailedTestOnOmnibusMrMessage `e2e:test-on-omnibus-ee` pipeline is allowed to fail due its [flakiness](#{package_and_test_link}). Failures should be investigated to guarantee this backport complies with the Quality standards. - Ping your team's associated Software Engineer in Test (SET) to confirm the failures are unrelated to the merge request. - If there's no SET assigned, ask for assistance on the `#test-platform` Slack channel. + Ask for assistance from a Software Engineer in Test (SET) on the `#s_developer_experience` Slack channel to confirm + the failures are unrelated to the merge request. MARKDOWN end @@ -63,7 +63,7 @@ class GenerateFailedTestOnOmnibusMrMessage end def package_and_test_link - "https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/dashboards" + "https://handbook.gitlab.com/handbook/engineering/infrastructure-platforms/developer-experience/dashboards/" end end diff --git a/scripts/generate-message-to-run-e2e-pipeline.rb b/scripts/generate-message-to-run-e2e-pipeline.rb index 53dcc403583..536477b56b6 100755 --- a/scripts/generate-message-to-run-e2e-pipeline.rb +++ b/scripts/generate-message-to-run-e2e-pipeline.rb @@ -81,12 +81,12 @@ class GenerateMessageToRunE2ePipeline To run all E2E tests, apply the ~"pipeline:run-all-e2e" label and run a new pipeline. - E2E test jobs are allowed to fail due to [flakiness](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/dashboards). + E2E test jobs are allowed to fail due to [flakiness](https://handbook.gitlab.com/handbook/engineering/infrastructure-platforms/developer-experience/dashboards/). See current failures at the latest [pipeline triage issue](https://gitlab.com/gitlab-org/quality/pipeline-triage/-/issues). Once done, apply the ✅ emoji on this comment. - **Team members only:** for any questions or help, reach out on the internal `#test-platform` Slack channel. + **Team members only:** for any questions or help, reach out on the internal `#s_developer_experience` Slack channel. MARKDOWN end diff --git a/spec/frontend/content_editor/components/toolbar_button_spec.js b/spec/frontend/content_editor/components/toolbar_button_spec.js index b9cf631fb40..b8dab0d8bd1 100644 --- a/spec/frontend/content_editor/components/toolbar_button_spec.js +++ b/spec/frontend/content_editor/components/toolbar_button_spec.js @@ -93,7 +93,7 @@ describe('content_editor/components/toolbar_button', () => { buildWrapper({ editorCommand }); - await findButton().trigger('click'); + await findButton().vm.$emit('click'); expect(mockCommands[editorCommand]).toHaveBeenCalled(); expect(mockCommands.focus).toHaveBeenCalled(); @@ -107,7 +107,7 @@ describe('content_editor/components/toolbar_button', () => { buildWrapper(); - await findButton().trigger('click'); + await findButton().vm.$emit('click'); expect(mockCommands[editorCommand]).not.toHaveBeenCalled(); expect(wrapper.emitted().execute).toHaveLength(1); diff --git a/spec/frontend/content_editor/components/wrappers/image_spec.js b/spec/frontend/content_editor/components/wrappers/image_spec.js index 44905ef397f..c3e467cfe8c 100644 --- a/spec/frontend/content_editor/components/wrappers/image_spec.js +++ b/spec/frontend/content_editor/components/wrappers/image_spec.js @@ -37,8 +37,8 @@ describe('content/components/wrappers/image_spec', () => { attrs: { src: 'image.png', alt: 'My Image', width: 200, height: 200 }, }); + expect(findImage().element.src).toBe('image.png'); expect(findImage().attributes()).toMatchObject({ - src: 'image.png', alt: 'My Image', height: '200', width: '200', @@ -57,8 +57,8 @@ describe('content/components/wrappers/image_spec', () => { it('sets width and height to auto if not provided', () => { createWrapper({ type: { name: 'image' }, attrs: { src: 'image.png', alt: 'My Image' } }); + expect(findImage().element.src).toBe('image.png'); expect(findImage().attributes()).toMatchObject({ - src: 'image.png', alt: 'My Image', height: 'auto', width: 'auto', diff --git a/spec/frontend/glql/components/presenters/link_spec.js b/spec/frontend/glql/components/presenters/link_spec.js index 5feb9de1c74..25cb52c29dc 100644 --- a/spec/frontend/glql/components/presenters/link_spec.js +++ b/spec/frontend/glql/components/presenters/link_spec.js @@ -14,39 +14,4 @@ describe('LinkPresenter', () => { expect(wrapper.text()).toBe(linkText); expect(wrapper.attributes('href')).toBe(linkHref); }); - - it.each` - scenario | data - ${'for data without a webUrl'} | ${{ title: 'Issue 1' }} - ${'for data without a title'} | ${{ webUrl: 'https://gitlab.com' }} - `('$scenario, it shows a warning in console', ({ data }) => { - jest.spyOn(console, 'error').mockImplementation(() => {}); - - shallowMountExtended(LinkPresenter, { propsData: { data } }); - - // eslint-disable-next-line no-console - expect(console.error.mock.calls[0][0]).toContain( - '[Vue warn]: Invalid prop: custom validator check failed for prop "data"', - ); - }); - - describe.each` - dataType | data - ${'String'} | ${'Hello, world!'} - ${'Number'} | ${100} - ${'Array'} | ${[1, 2, 3]} - `('for data type $dataType', ({ dataType, data }) => { - beforeEach(() => { - jest.spyOn(console, 'error').mockImplementation(() => {}); - }); - - it('shows a warning in console for mismatched propType', () => { - shallowMountExtended(LinkPresenter, { propsData: { data } }); - - // eslint-disable-next-line no-console - expect(console.error.mock.calls[0][0]).toContain( - `[Vue warn]: Invalid prop: type check failed for prop "data". Expected Object, got ${dataType}`, - ); - }); - }); }); diff --git a/spec/frontend/glql/components/presenters/text_spec.js b/spec/frontend/glql/components/presenters/text_spec.js index 62038204fd8..def7e07f310 100644 --- a/spec/frontend/glql/components/presenters/text_spec.js +++ b/spec/frontend/glql/components/presenters/text_spec.js @@ -11,25 +11,4 @@ describe('TextPresenter', () => { expect(wrapper.text()).toBe(data.toString()); }); - - describe.each` - dataType | data - ${'Null'} | ${null} - ${'Undefined'} | ${undefined} - ${'Object'} | ${{ some: 'object' }} - ${'Array'} | ${[1, 2, 3]} - `('for data type $dataType', ({ dataType, data }) => { - beforeEach(() => { - jest.spyOn(console, 'error').mockImplementation(() => {}); - }); - - it('shows a warning in console for mismatched propType', () => { - shallowMountExtended(TextPresenter, { propsData: { data } }); - - // eslint-disable-next-line no-console - expect(console.error.mock.calls[0][0]).toContain( - `[Vue warn]: Invalid prop: type check failed for prop "data". Expected String, Number, got ${dataType}`, - ); - }); - }); }); diff --git a/spec/lib/gitlab/security/dast_variables_spec.rb b/spec/lib/gitlab/security/dast_variables_spec.rb new file mode 100644 index 00000000000..dc33b7df262 --- /dev/null +++ b/spec/lib/gitlab/security/dast_variables_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ::Gitlab::Security::DastVariables, feature_category: :dynamic_application_security_testing do + let(:dast_variables) { described_class } + + describe '#additional_site_variables' do + it 'contains only additional variables' do + described_class.additional_site_variables.each_value do |variable| + expect(variable[:additional]).to be(true) + end + end + end + + describe '#auth_variables' do + it 'contains only authentication variables' do + described_class.auth_variables.each_value do |variable| + expect(variable[:auth]).to be(true) + end + end + end +end diff --git a/spec/scripts/generate_message_to_run_e2e_pipeline_spec.rb b/spec/scripts/generate_message_to_run_e2e_pipeline_spec.rb index 25b1fe14807..bcb89ab487f 100644 --- a/spec/scripts/generate_message_to_run_e2e_pipeline_spec.rb +++ b/spec/scripts/generate_message_to_run_e2e_pipeline_spec.rb @@ -230,12 +230,12 @@ RSpec.describe GenerateMessageToRunE2ePipeline, feature_category: :tooling do To run all E2E tests, apply the ~"pipeline:run-all-e2e" label and run a new pipeline. - E2E test jobs are allowed to fail due to [flakiness](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/dashboards). + E2E test jobs are allowed to fail due to [flakiness](https://handbook.gitlab.com/handbook/engineering/infrastructure-platforms/developer-experience/dashboards/). See current failures at the latest [pipeline triage issue](https://gitlab.com/gitlab-org/quality/pipeline-triage/-/issues). Once done, apply the ✅ emoji on this comment. - **Team members only:** for any questions or help, reach out on the internal `#test-platform` Slack channel. + **Team members only:** for any questions or help, reach out on the internal `#s_developer_experience` Slack channel. MARKDOWN end diff --git a/spec/tooling/dast_variables/docs/renderer_spec.rb b/spec/tooling/dast_variables/docs/renderer_spec.rb new file mode 100644 index 00000000000..434caeb75be --- /dev/null +++ b/spec/tooling/dast_variables/docs/renderer_spec.rb @@ -0,0 +1,130 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'tmpdir' +require_relative '../../../../tooling/dast_variables/docs/renderer' + +RSpec.describe Tooling::DastVariables::Docs::Renderer, feature_category: :dynamic_application_security_testing do + let(:template) { Rails.root.join('tooling/dast_variables/docs/templates/default.md.haml') } + + describe '#contents' do + subject(:contents) do + described_class.new( + output_file: nil, + template: template + ).contents + end + + describe 'scanner variables table' do + let(:expectation) do + <<~DOC + ## Scanner behavior + + These variables control how the scan is conducted and where its results are stored. + + | CI/CD variable | Type | Example | Description | + | :------------- | :--- | ------- | :---------- | + DOC + end + + it 'renders scanner variables' do + expect(contents).to include(expectation) + end + end + + describe 'site variables table' do + let(:expectation) do + <<~DOC + ## Elements, actions, and timeouts + + These variables tell the scanner where to look for certain elements, which actions to take, and how long to wait for operations to complete. + + | CI/CD variable | Type | Example | Description | + | :------------- | :--- | ------- | :---------- | + DOC + end + + it 'renders site variables' do + expect(contents).to include(expectation) + end + end + + describe 'authentication variables table' do + let(:expectation) do + <<~DOC + ### Authentication + + These variables tell the scanner how to authenticate with your application. + + | CI/CD variable | Type | Example | Description | + | :------------- | :--- | ------- | :---------- | + DOC + end + + it 'renders authentication variables' do + expect(contents).to include(expectation) + end + end + + describe 'links' do + describe 'CI/CD variables' do + let(:expectation) do + <<~DOC + | `DAST_PKCS12_PASSWORD` | string | `password` | The password of the certificate used in `DAST_PKCS12_CERTIFICATE_BASE64`. Create sensitive [custom CI/CI variables](../../../../../ci/variables/_index.md#define-a-cicd-variable-in-the-ui) using the GitLab UI. | + DOC + end + + it 'links to the type definition' do + expect(contents).to include(expectation) + end + end + + describe 'Duration string' do + let(:expectation) do + <<~DOC + | `DAST_ACTIVE_SCAN_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `3h` | The maximum amount of time to wait for the active scan phase of the scan to complete. Defaults to 3h. | + DOC + end + + it 'links to the type definition' do + expect(contents).to include(expectation) + end + end + + describe 'selector' do + let(:expectation) do + <<~DOC + | `DAST_AUTH_BEFORE_LOGIN_ACTIONS` | [selector](authentication.md#finding-an-elements-selector) | `css:.user,id:show-login-form` | A comma-separated list of selectors representing elements to click on prior to entering the DAST_AUTH_USERNAME and DAST_AUTH_PASSWORD into the login form. | + DOC + end + + it 'links to the type definition' do + expect(contents).to include(expectation) + end + end + end + end + + describe '#write' do + let(:output_dir) { Dir.mktmpdir } + let(:output_file) { File.join(output_dir, 'variables.md') } + + after do + FileUtils.remove_entry(output_dir) + end + + it 'writes contents to file' do + renderer = described_class.new( + output_file: output_file, + template: template + ) + + expect(File).to receive(:write).with(output_file, renderer.contents).and_call_original + + renderer.write + + expect(File.exist?(output_file)).to be true + expect(File.read(output_file)).to eq(renderer.contents) + end + end +end diff --git a/tooling/dast_variables/docs/helper.rb b/tooling/dast_variables/docs/helper.rb new file mode 100644 index 00000000000..b354475f079 --- /dev/null +++ b/tooling/dast_variables/docs/helper.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require 'gitlab/utils/strong_memoize' + +module Tooling + module DastVariables + module Docs + module Helper + TABLE_HEADER = <<~MD + | CI/CD variable | Type | Example | Description | + | :------------- | :--- | ------- | :---------- | + MD + + def render_variables_table(filter) + case filter + when 'site' + variables = Gitlab::Security::DastVariables.data[:site].filter { |_, variable| !variable[:auth] } + when 'scanner' + variables = Gitlab::Security::DastVariables.data[:scanner].filter { |_, variable| !variable[:auth] } + when 'auth' + variables = Gitlab::Security::DastVariables.auth_variables + end + + rendered_variables = variables.map { |key, variable| render_variable(key, variable) }.join("\n") + + "#{TABLE_HEADER}#{rendered_variables}\n" + end + + def render_variable(key, variable) + render_row( + "`#{key}`", + render_type(variable[:type]), + "`#{variable[:example]}`", + render_description(variable[:description]) + ) + end + + def render_type(type) + case type + when 'Duration string' then '[Duration string](https://pkg.go.dev/time#ParseDuration)' + when 'selector' then '[selector](authentication.md#finding-an-elements-selector)' + else type + end + end + + def render_description(description) + # replace help_page_path-generated documentation link + # with relative path to documentation file + description.sub( + Gitlab::Security::DastVariables.ci_variables_documentation_link, + '../../../../../ci/variables/_index.md#define-a-cicd-variable-in-the-ui' + ) + end + + def render_row(*values) + "| #{values.map { |val| val.to_s.squish }.join(' | ')} |" + end + end + end + end +end diff --git a/tooling/dast_variables/docs/renderer.rb b/tooling/dast_variables/docs/renderer.rb new file mode 100644 index 00000000000..7c5fbb05f3f --- /dev/null +++ b/tooling/dast_variables/docs/renderer.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require_relative 'helper' + +module Tooling + module DastVariables + module Docs + class Renderer + include Tooling::DastVariables::Docs::Helper + + attr_reader :schema + + def initialize(output_file:, template:) + @output_file = output_file + @template = template + @layout = Haml::Engine.new(File.read(template)) + end + + def contents + # Render and remove an extra trailing new line + @contents ||= @layout.render(self).sub!(/\n(?=\Z)/, '') + end + + def write + File.write(@output_file, contents) + end + end + end + end +end diff --git a/tooling/dast_variables/docs/templates/default.md.haml b/tooling/dast_variables/docs/templates/default.md.haml new file mode 100644 index 00000000000..0b33e2780f7 --- /dev/null +++ b/tooling/dast_variables/docs/templates/default.md.haml @@ -0,0 +1,44 @@ +:plain + --- + type: reference, howto + stage: Application Security Testing + group: Dynamic Analysis + info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments + title: Available CI/CD variables + --- + + + + These CI/CD variables are specific to the browser-based DAST analyzer. They can be used to customize the behavior of + DAST to your requirements. + + ## Scanner behavior + + These variables control how the scan is conducted and where its results are stored. +\ + += render_variables_table('scanner') + +:plain + ## Elements, actions, and timeouts + + These variables tell the scanner where to look for certain elements, which actions to take, and how long to wait for operations to complete. +\ + += render_variables_table('site') + +:plain + ### Authentication + + These variables tell the scanner how to authenticate with your application. +\ + += render_variables_table('auth')