gitlabcis 1.3.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. gitlabcis/__init__.py +12 -0
  2. gitlabcis/__main__.py +7 -0
  3. gitlabcis/benchmarks/__init__.py +8 -0
  4. gitlabcis/benchmarks/artifacts_4/__init__.py +4 -0
  5. gitlabcis/benchmarks/artifacts_4/access_to_artifacts_4_2.py +139 -0
  6. gitlabcis/benchmarks/artifacts_4/origin_traceability_4_4.py +11 -0
  7. gitlabcis/benchmarks/artifacts_4/package_registries_4_3.py +105 -0
  8. gitlabcis/benchmarks/artifacts_4/verification_4_1.py +83 -0
  9. gitlabcis/benchmarks/build_pipelines_2/__init__.py +4 -0
  10. gitlabcis/benchmarks/build_pipelines_2/build_environment_2_1.py +268 -0
  11. gitlabcis/benchmarks/build_pipelines_2/build_worker_2_2.py +129 -0
  12. gitlabcis/benchmarks/build_pipelines_2/pipeline_instructions_2_3.py +444 -0
  13. gitlabcis/benchmarks/build_pipelines_2/pipeline_integrity_2_4.py +146 -0
  14. gitlabcis/benchmarks/dependencies_3/__init__.py +2 -0
  15. gitlabcis/benchmarks/dependencies_3/third_party_packages_3_1.py +171 -0
  16. gitlabcis/benchmarks/dependencies_3/validate_packages_3_2.py +182 -0
  17. gitlabcis/benchmarks/deployment_5/__init__.py +2 -0
  18. gitlabcis/benchmarks/deployment_5/deployment_configuration_5_1.py +165 -0
  19. gitlabcis/benchmarks/deployment_5/deployment_environment_5_2.py +66 -0
  20. gitlabcis/benchmarks/source_code_1/__init__.py +6 -0
  21. gitlabcis/benchmarks/source_code_1/code_changes_1_1.py +665 -0
  22. gitlabcis/benchmarks/source_code_1/code_risks_1_5.py +506 -0
  23. gitlabcis/benchmarks/source_code_1/contribution_access_1_3.py +334 -0
  24. gitlabcis/benchmarks/source_code_1/repository_management_1_2.py +168 -0
  25. gitlabcis/benchmarks/source_code_1/third_party_1_4.py +139 -0
  26. gitlabcis/cli/__init__.py +0 -0
  27. gitlabcis/cli/log.py +30 -0
  28. gitlabcis/cli/main.py +541 -0
  29. gitlabcis/cli/output.py +151 -0
  30. gitlabcis/recommendations/artifacts_4/access_to_artifacts_4_2/external_auth_server.yml +51 -0
  31. gitlabcis/recommendations/artifacts_4/access_to_artifacts_4_2/limit_artifact_uploaders.yml +57 -0
  32. gitlabcis/recommendations/artifacts_4/access_to_artifacts_4_2/limit_certifying_artifacts.yml +53 -0
  33. gitlabcis/recommendations/artifacts_4/access_to_artifacts_4_2/minimum_package_registry_admins.yml +54 -0
  34. gitlabcis/recommendations/artifacts_4/access_to_artifacts_4_2/readme.md +14 -0
  35. gitlabcis/recommendations/artifacts_4/access_to_artifacts_4_2/require_mfa_to_package_registry.yml +52 -0
  36. gitlabcis/recommendations/artifacts_4/access_to_artifacts_4_2/restrict_anonymous_access.yml +67 -0
  37. gitlabcis/recommendations/artifacts_4/origin_traceability_4_4/artifact_origin_info.yml +56 -0
  38. gitlabcis/recommendations/artifacts_4/origin_traceability_4_4/readme.md +7 -0
  39. gitlabcis/recommendations/artifacts_4/package_registries_4_3/all_artifact_versions_signed.yml +70 -0
  40. gitlabcis/recommendations/artifacts_4/package_registries_4_3/audit_package_registry_config.yml +46 -0
  41. gitlabcis/recommendations/artifacts_4/package_registries_4_3/readme.md +12 -0
  42. gitlabcis/recommendations/artifacts_4/package_registries_4_3/secure_repo_webhooks.yml +50 -0
  43. gitlabcis/recommendations/artifacts_4/package_registries_4_3/validate_signed_artifacts_on_upload.yml +72 -0
  44. gitlabcis/recommendations/artifacts_4/readme.md +12 -0
  45. gitlabcis/recommendations/artifacts_4/verification_4_1/encrypt_artifacts_before_distribution.yml +47 -0
  46. gitlabcis/recommendations/artifacts_4/verification_4_1/only_authorized_platforms_can_decrypt_artifacts.yml +59 -0
  47. gitlabcis/recommendations/artifacts_4/verification_4_1/readme.md +11 -0
  48. gitlabcis/recommendations/artifacts_4/verification_4_1/sign_artifacts_in_build_pipeline.yml +40 -0
  49. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/authenticate_build_access.yml +55 -0
  50. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/build_automation.yml +54 -0
  51. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/build_env_admins.yml +55 -0
  52. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/build_logging.yml +49 -0
  53. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/disable_build_tools_default_passwords.yml +54 -0
  54. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/immutable_pipeline_infrastructure.yml +60 -0
  55. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/limit_build_access.yml +64 -0
  56. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/limit_build_secrets_scope.yml +56 -0
  57. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/readme.md +19 -0
  58. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/secure_build_env_webhooks.yml +43 -0
  59. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/single_responsibility_pipeline.yml +58 -0
  60. gitlabcis/recommendations/build_pipelines_2/build_environment_2_1/vuln_scanning.yml +64 -0
  61. gitlabcis/recommendations/build_pipelines_2/build_worker_2_2/build_worker_vuln_scanning.yml +58 -0
  62. gitlabcis/recommendations/build_pipelines_2/build_worker_2_2/monitor_worker_resource_consumption.yml +59 -0
  63. gitlabcis/recommendations/build_pipelines_2/build_worker_2_2/pass_worker_envs_and_commands.yml +48 -0
  64. gitlabcis/recommendations/build_pipelines_2/build_worker_2_2/readme.md +16 -0
  65. gitlabcis/recommendations/build_pipelines_2/build_worker_2_2/restrict_worker_connectivity.yml +61 -0
  66. gitlabcis/recommendations/build_pipelines_2/build_worker_2_2/segregate_worker_duties.yml +78 -0
  67. gitlabcis/recommendations/build_pipelines_2/build_worker_2_2/single_use_workers.yml +47 -0
  68. gitlabcis/recommendations/build_pipelines_2/build_worker_2_2/store_worker_config.yml +62 -0
  69. gitlabcis/recommendations/build_pipelines_2/build_worker_2_2/worker_runtime_security.yml +37 -0
  70. gitlabcis/recommendations/build_pipelines_2/pipeline_instructions_2_3/build_stage_io.yml +49 -0
  71. gitlabcis/recommendations/build_pipelines_2/pipeline_instructions_2_3/build_steps_as_code.yml +42 -0
  72. gitlabcis/recommendations/build_pipelines_2/pipeline_instructions_2_3/limit_pipeline_triggers.yml +76 -0
  73. gitlabcis/recommendations/build_pipelines_2/pipeline_instructions_2_3/pipeline_misconfiguration_scanning.yml +48 -0
  74. gitlabcis/recommendations/build_pipelines_2/pipeline_instructions_2_3/pipeline_secret_scanning.yml +56 -0
  75. gitlabcis/recommendations/build_pipelines_2/pipeline_instructions_2_3/pipeline_vuln_scanning.yml +44 -0
  76. gitlabcis/recommendations/build_pipelines_2/pipeline_instructions_2_3/readme.md +16 -0
  77. gitlabcis/recommendations/build_pipelines_2/pipeline_instructions_2_3/secure_pipeline_output.yml +52 -0
  78. gitlabcis/recommendations/build_pipelines_2/pipeline_instructions_2_3/track_pipeline_files.yml +48 -0
  79. gitlabcis/recommendations/build_pipelines_2/pipeline_integrity_2_4/create_reproducible_artifacts.yml +52 -0
  80. gitlabcis/recommendations/build_pipelines_2/pipeline_integrity_2_4/lock_dependencies.yml +59 -0
  81. gitlabcis/recommendations/build_pipelines_2/pipeline_integrity_2_4/pipeline_produces_sbom.yml +81 -0
  82. gitlabcis/recommendations/build_pipelines_2/pipeline_integrity_2_4/pipeline_signs_sbom.yml +38 -0
  83. gitlabcis/recommendations/build_pipelines_2/pipeline_integrity_2_4/readme.md +14 -0
  84. gitlabcis/recommendations/build_pipelines_2/pipeline_integrity_2_4/sign_artifacts.yml +35 -0
  85. gitlabcis/recommendations/build_pipelines_2/pipeline_integrity_2_4/validate_dependencies.yml +63 -0
  86. gitlabcis/recommendations/build_pipelines_2/readme.md +12 -0
  87. gitlabcis/recommendations/dependencies_3/readme.md +10 -0
  88. gitlabcis/recommendations/dependencies_3/third_party_packages_3_1/define_package_managers.yml +84 -0
  89. gitlabcis/recommendations/dependencies_3/third_party_packages_3_1/dependency_sbom.yml +84 -0
  90. gitlabcis/recommendations/dependencies_3/third_party_packages_3_1/monitor_dependencies.yml +61 -0
  91. gitlabcis/recommendations/dependencies_3/third_party_packages_3_1/packages_over_60_days_old.yml +95 -0
  92. gitlabcis/recommendations/dependencies_3/third_party_packages_3_1/pin_dependency_version.yml +48 -0
  93. gitlabcis/recommendations/dependencies_3/third_party_packages_3_1/readme.md +14 -0
  94. gitlabcis/recommendations/dependencies_3/third_party_packages_3_1/third_party_sbom_required.yml +70 -0
  95. gitlabcis/recommendations/dependencies_3/third_party_packages_3_1/verify_artifacts.yml +45 -0
  96. gitlabcis/recommendations/dependencies_3/third_party_packages_3_1/verify_signed_metadata.yml +41 -0
  97. gitlabcis/recommendations/dependencies_3/validate_packages_3_2/org_wide_dependency_policy.yml +47 -0
  98. gitlabcis/recommendations/dependencies_3/validate_packages_3_2/package_license_scanning.yml +47 -0
  99. gitlabcis/recommendations/dependencies_3/validate_packages_3_2/package_ownership_change.yml +42 -0
  100. gitlabcis/recommendations/dependencies_3/validate_packages_3_2/package_vuln_scanning.yml +62 -0
  101. gitlabcis/recommendations/dependencies_3/validate_packages_3_2/readme.md +10 -0
  102. gitlabcis/recommendations/deployment_5/deployment_configuration_5_1/audit_deployment_config.yml +46 -0
  103. gitlabcis/recommendations/deployment_5/deployment_configuration_5_1/limit_deployment_config_access.yml +51 -0
  104. gitlabcis/recommendations/deployment_5/deployment_configuration_5_1/pin_deployment_config_manifests.yml +59 -0
  105. gitlabcis/recommendations/deployment_5/deployment_configuration_5_1/readme.md +13 -0
  106. gitlabcis/recommendations/deployment_5/deployment_configuration_5_1/scan_iac.yml +72 -0
  107. gitlabcis/recommendations/deployment_5/deployment_configuration_5_1/secret_scan_deployment_config.yml +45 -0
  108. gitlabcis/recommendations/deployment_5/deployment_configuration_5_1/separate_deployment_config.yml +50 -0
  109. gitlabcis/recommendations/deployment_5/deployment_configuration_5_1/verify_deployment_config.yml +49 -0
  110. gitlabcis/recommendations/deployment_5/deployment_environment_5_2/automate_deployment.yml +47 -0
  111. gitlabcis/recommendations/deployment_5/deployment_environment_5_2/disable_default_passwords.yml +63 -0
  112. gitlabcis/recommendations/deployment_5/deployment_environment_5_2/limit_prod_access.yml +45 -0
  113. gitlabcis/recommendations/deployment_5/deployment_environment_5_2/readme.md +12 -0
  114. gitlabcis/recommendations/deployment_5/deployment_environment_5_2/reproducible_deployment.yml +50 -0
  115. gitlabcis/recommendations/deployment_5/readme.md +10 -0
  116. gitlabcis/recommendations/readme.md +24 -0
  117. gitlabcis/recommendations/source_code_1/code_changes_1_1/audit_branch_protections.yml +56 -0
  118. gitlabcis/recommendations/source_code_1/code_changes_1_1/auto_risk_scan_merges.yml +62 -0
  119. gitlabcis/recommendations/source_code_1/code_changes_1_1/branch_protections_for_admins.yml +60 -0
  120. gitlabcis/recommendations/source_code_1/code_changes_1_1/branches_updated_before_merging.yml +56 -0
  121. gitlabcis/recommendations/source_code_1/code_changes_1_1/checks_pass_before_merging.yml +57 -0
  122. gitlabcis/recommendations/source_code_1/code_changes_1_1/code_approval_dismissals.yml +62 -0
  123. gitlabcis/recommendations/source_code_1/code_changes_1_1/code_approvals.yml +65 -0
  124. gitlabcis/recommendations/source_code_1/code_changes_1_1/code_changes_require_code_owners.yml +68 -0
  125. gitlabcis/recommendations/source_code_1/code_changes_1_1/code_dismissal_restrictions.yml +69 -0
  126. gitlabcis/recommendations/source_code_1/code_changes_1_1/code_owners.yml +61 -0
  127. gitlabcis/recommendations/source_code_1/code_changes_1_1/code_tracing.yml +52 -0
  128. gitlabcis/recommendations/source_code_1/code_changes_1_1/comments_resolved_before_merging.yml +59 -0
  129. gitlabcis/recommendations/source_code_1/code_changes_1_1/commits_must_be_signed_before_merging.yml +63 -0
  130. gitlabcis/recommendations/source_code_1/code_changes_1_1/default_branch_protected.yml +85 -0
  131. gitlabcis/recommendations/source_code_1/code_changes_1_1/deny_branch_deletions.yml +76 -0
  132. gitlabcis/recommendations/source_code_1/code_changes_1_1/ensure_force_push_is_denied.yml +59 -0
  133. gitlabcis/recommendations/source_code_1/code_changes_1_1/linear_history_required.yml +56 -0
  134. gitlabcis/recommendations/source_code_1/code_changes_1_1/merging_restrictions.yml +65 -0
  135. gitlabcis/recommendations/source_code_1/code_changes_1_1/readme.md +26 -0
  136. gitlabcis/recommendations/source_code_1/code_changes_1_1/stale_branch_reviews.yml +72 -0
  137. gitlabcis/recommendations/source_code_1/code_changes_1_1/version_control.yml +45 -0
  138. gitlabcis/recommendations/source_code_1/code_risks_1_5/dast_api_scanning.yml +50 -0
  139. gitlabcis/recommendations/source_code_1/code_risks_1_5/dast_web_scanning.yml +51 -0
  140. gitlabcis/recommendations/source_code_1/code_risks_1_5/dependency_scanning.yml +84 -0
  141. gitlabcis/recommendations/source_code_1/code_risks_1_5/enable_secret_detection.yml +45 -0
  142. gitlabcis/recommendations/source_code_1/code_risks_1_5/license_scanning.yml +47 -0
  143. gitlabcis/recommendations/source_code_1/code_risks_1_5/readme.md +14 -0
  144. gitlabcis/recommendations/source_code_1/code_risks_1_5/secure_iac_instructions.yml +81 -0
  145. gitlabcis/recommendations/source_code_1/code_risks_1_5/secure_pipeline_instructions.yml +62 -0
  146. gitlabcis/recommendations/source_code_1/code_risks_1_5/vulnerability_scanning.yml +48 -0
  147. gitlabcis/recommendations/source_code_1/contribution_access_1_3/domain_verification.yml +65 -0
  148. gitlabcis/recommendations/source_code_1/contribution_access_1_3/ensure_2_admins_per_repo.yml +56 -0
  149. gitlabcis/recommendations/source_code_1/contribution_access_1_3/limit_top_level_group_creation.yml +61 -0
  150. gitlabcis/recommendations/source_code_1/contribution_access_1_3/limit_user_registration_domain.yml +58 -0
  151. gitlabcis/recommendations/source_code_1/contribution_access_1_3/minimum_number_of_admins.yml +56 -0
  152. gitlabcis/recommendations/source_code_1/contribution_access_1_3/org_provided_ssh_certs.yml +70 -0
  153. gitlabcis/recommendations/source_code_1/contribution_access_1_3/readme.md +21 -0
  154. gitlabcis/recommendations/source_code_1/contribution_access_1_3/require_mfa_at_org_level.yml +89 -0
  155. gitlabcis/recommendations/source_code_1/contribution_access_1_3/require_mfa_for_contributors.yml +76 -0
  156. gitlabcis/recommendations/source_code_1/contribution_access_1_3/restrict_ip_addresses.yml +84 -0
  157. gitlabcis/recommendations/source_code_1/contribution_access_1_3/review_and_remove_inactive_users.yml +62 -0
  158. gitlabcis/recommendations/source_code_1/contribution_access_1_3/scm_notification_restriction.yml +46 -0
  159. gitlabcis/recommendations/source_code_1/contribution_access_1_3/strict_permissions_for_repo.yml +62 -0
  160. gitlabcis/recommendations/source_code_1/contribution_access_1_3/track_code_anomalies.yml +43 -0
  161. gitlabcis/recommendations/source_code_1/readme.md +13 -0
  162. gitlabcis/recommendations/source_code_1/repository_management_1_2/limit_issue_deletions.yml +57 -0
  163. gitlabcis/recommendations/source_code_1/repository_management_1_2/limit_repo_creations.yml +64 -0
  164. gitlabcis/recommendations/source_code_1/repository_management_1_2/limit_repo_deletions.yml +57 -0
  165. gitlabcis/recommendations/source_code_1/repository_management_1_2/public_repos_have_security_file.yml +59 -0
  166. gitlabcis/recommendations/source_code_1/repository_management_1_2/readme.md +15 -0
  167. gitlabcis/recommendations/source_code_1/repository_management_1_2/review_and_archive_stale_repos.yml +65 -0
  168. gitlabcis/recommendations/source_code_1/repository_management_1_2/track_forks.yml +74 -0
  169. gitlabcis/recommendations/source_code_1/repository_management_1_2/track_project_visibility_status.yml +74 -0
  170. gitlabcis/recommendations/source_code_1/third_party_1_4/README.md +12 -0
  171. gitlabcis/recommendations/source_code_1/third_party_1_4/admin_approval_for_app_installs.yml +83 -0
  172. gitlabcis/recommendations/source_code_1/third_party_1_4/least_privilge_app_permissions.yml +103 -0
  173. gitlabcis/recommendations/source_code_1/third_party_1_4/secure_webhooks.yml +73 -0
  174. gitlabcis/recommendations/source_code_1/third_party_1_4/stale_app_reviews.yml +66 -0
  175. gitlabcis/recommendations/template.yml +30 -0
  176. gitlabcis/tests/__init__.py +0 -0
  177. gitlabcis/tests/input/__init__.py +0 -0
  178. gitlabcis/tests/input/conftest.py +29 -0
  179. gitlabcis/tests/input/no_input_test.py +82 -0
  180. gitlabcis/tests/input/switch_test.py +19 -0
  181. gitlabcis/tests/input/version_test.py +7 -0
  182. gitlabcis/tests/unit/__init__.py +0 -0
  183. gitlabcis/tests/unit/benchmarks/artifacts_4/access_to_artifacts_4_2_test.py +131 -0
  184. gitlabcis/tests/unit/benchmarks/artifacts_4/origin_traceability_4_4_test.py +15 -0
  185. gitlabcis/tests/unit/benchmarks/artifacts_4/package_registries_4_3_test.py +102 -0
  186. gitlabcis/tests/unit/benchmarks/artifacts_4/verification_4_1_test.py +78 -0
  187. gitlabcis/tests/unit/benchmarks/build_pipelines_2/build_environment_2_1_test.py +239 -0
  188. gitlabcis/tests/unit/benchmarks/build_pipelines_2/build_worker_2_2_test.py +105 -0
  189. gitlabcis/tests/unit/benchmarks/build_pipelines_2/pipeline_instructions_2_3_test.py +340 -0
  190. gitlabcis/tests/unit/benchmarks/build_pipelines_2/pipeline_integrity_2_4_test.py +115 -0
  191. gitlabcis/tests/unit/benchmarks/conftest.py +47 -0
  192. gitlabcis/tests/unit/benchmarks/dependencies_3/third_party_packages_3_1_test.py +135 -0
  193. gitlabcis/tests/unit/benchmarks/dependencies_3/validate_packages_3_2_test.py +171 -0
  194. gitlabcis/tests/unit/benchmarks/deployment_5/deployment_configuration_5_1_test.py +140 -0
  195. gitlabcis/tests/unit/benchmarks/deployment_5/deployment_environment_5_2_test.py +60 -0
  196. gitlabcis/tests/unit/benchmarks/function_test.py +24 -0
  197. gitlabcis/tests/unit/benchmarks/source_code_1/code_changes_1_1_test.py +565 -0
  198. gitlabcis/tests/unit/benchmarks/source_code_1/code_risks_1_5_test.py +419 -0
  199. gitlabcis/tests/unit/benchmarks/source_code_1/contribution_access_1_3_test.py +265 -0
  200. gitlabcis/tests/unit/benchmarks/source_code_1/repository_management_1_2_test.py +142 -0
  201. gitlabcis/tests/unit/benchmarks/source_code_1/third_party_1_4_test.py +119 -0
  202. gitlabcis/tests/unit/conftest.py +94 -0
  203. gitlabcis/tests/unit/log/log_test.py +23 -0
  204. gitlabcis/tests/unit/utils/argfilters_test.py +9 -0
  205. gitlabcis/tests/unit/utils/ci_test.py +156 -0
  206. gitlabcis/tests/unit/utils/output_test.py +95 -0
  207. gitlabcis/tests/unit/utils/utils_general_test.py +149 -0
  208. gitlabcis/tests/unit/utils/version_test.py +11 -0
  209. gitlabcis/tests/unit/yaml/bad_file_test.py +15 -0
  210. gitlabcis/tests/unit/yaml/recommendation_test.py +123 -0
  211. gitlabcis/utils/__init__.py +146 -0
  212. gitlabcis/utils/ci.py +132 -0
  213. gitlabcis-1.3.2.dist-info/LICENSE +21 -0
  214. gitlabcis-1.3.2.dist-info/METADATA +241 -0
  215. gitlabcis-1.3.2.dist-info/RECORD +218 -0
  216. gitlabcis-1.3.2.dist-info/WHEEL +5 -0
  217. gitlabcis-1.3.2.dist-info/entry_points.txt +2 -0
  218. gitlabcis-1.3.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,142 @@
1
+ # -----------------------------------------------------------------------------
2
+
3
+ from unittest.mock import Mock
4
+
5
+ from gitlabcis.benchmarks.source_code_1 import repository_management_1_2
6
+ from conftest import run
7
+
8
+ # -----------------------------------------------------------------------------
9
+
10
+
11
+ def test_public_repos_have_security_file(glEntity, glObject, unauthorised):
12
+
13
+ from gitlab.exceptions import GitlabGetError
14
+
15
+ test = repository_management_1_2.public_repos_have_security_file
16
+
17
+ unauthorised.visibility.side_effect \
18
+ = GitlabGetError(response_code=401)
19
+ unauthorised.repository_tree.side_effect \
20
+ = GitlabGetError(response_code=401)
21
+ run(unauthorised, glObject, test, None)
22
+
23
+ del unauthorised.visibility
24
+ run(unauthorised, glObject, test, None)
25
+
26
+ unauthorised.visibility = 'private'
27
+ unauthorised.repository_tree.side_effect = (
28
+ GitlabGetError(response_code=401))
29
+ run(unauthorised, glObject, test, None)
30
+
31
+ visibility = Mock()
32
+ visibility.visibility = 'private'
33
+ run(visibility, glObject, test, None)
34
+
35
+ visibility = Mock()
36
+ del visibility.visibility
37
+ run(visibility, glObject, test, None)
38
+
39
+ files = [
40
+ {'name': 'security.md'}
41
+ ]
42
+ glEntity.repository_tree.return_value = files
43
+ run(glEntity, glObject, test, True)
44
+
45
+ files = [
46
+ {'name': 'not-security.md'}
47
+ ]
48
+ glEntity.repository_tree.return_value = files
49
+ run(glEntity, glObject, test, False)
50
+
51
+ # -----------------------------------------------------------------------------
52
+
53
+
54
+ def test_limit_repo_creations(glEntity, glObject, unauthorised):
55
+
56
+ from gitlab.exceptions import GitlabGetError
57
+
58
+ test = repository_management_1_2.limit_repo_creations
59
+
60
+ unauthorised.settings.get.side_effect \
61
+ = GitlabGetError(response_code=401)
62
+ run(unauthorised, unauthorised, test, None)
63
+
64
+ settings = Mock()
65
+ settings.signup_enabled = False
66
+ glObject.settings.get.return_value = settings
67
+ run(glEntity, glObject, test, True)
68
+
69
+ settings.signup_enabled = True
70
+ settings.require_admin_approval_after_user_signup = True
71
+ settings.email_confirmation_setting = 'hard'
72
+ run(glEntity, glObject, test, True)
73
+
74
+ settings.require_admin_approval_after_user_signup = False
75
+ settings.email_confirmation_setting = 'no'
76
+ run(glEntity, glObject, test, False)
77
+
78
+ # -----------------------------------------------------------------------------
79
+
80
+
81
+ def test_limit_repo_deletions(glEntity, glObject, unauthorised):
82
+
83
+ test = repository_management_1_2.limit_repo_deletions
84
+
85
+ run(unauthorised, unauthorised, test, None)
86
+
87
+ run(glEntity, glObject, test, None)
88
+
89
+ # -----------------------------------------------------------------------------
90
+
91
+
92
+ def test_limit_issue_deletions(glEntity, glObject, unauthorised):
93
+
94
+ test = repository_management_1_2.limit_issue_deletions
95
+
96
+ run(unauthorised, unauthorised, test, None)
97
+
98
+ run(glEntity, glObject, test, None)
99
+
100
+ # -----------------------------------------------------------------------------
101
+
102
+
103
+ def test_track_forks(glEntity, glObject):
104
+
105
+ test = repository_management_1_2.track_forks
106
+
107
+ glEntity.forks.list.return_value = []
108
+ run(glEntity, glObject, test, True)
109
+
110
+ glEntity.forks.list.return_value = ['yes']
111
+ run(glEntity, glObject, test, None)
112
+
113
+ # -----------------------------------------------------------------------------
114
+
115
+
116
+ def test_track_project_visibility_status(glEntity, glObject):
117
+
118
+ test = repository_management_1_2.track_project_visibility_status
119
+
120
+ run(glEntity, glObject, test, None)
121
+
122
+ # -----------------------------------------------------------------------------
123
+
124
+
125
+ def test_review_and_archive_stale_repos(glEntity, glObject):
126
+
127
+ from datetime import datetime, timezone
128
+ from dateutil.relativedelta import relativedelta
129
+
130
+ test = repository_management_1_2.review_and_archive_stale_repos
131
+
132
+ threeMonthsAgo = datetime.strftime(
133
+ datetime.now(timezone.utc) - relativedelta(months=3),
134
+ '%Y-%m-%dT%H:%M:%S.%fZ')
135
+ glEntity.last_activity_at = threeMonthsAgo
136
+ run(glEntity, glObject, test, True)
137
+
138
+ sevenMonthsAgo = datetime.strftime(
139
+ datetime.now(timezone.utc) - relativedelta(months=7),
140
+ '%Y-%m-%dT%H:%M:%S.%fZ')
141
+ glEntity.last_activity_at = sevenMonthsAgo
142
+ run(glEntity, glObject, test, False)
@@ -0,0 +1,119 @@
1
+ # -----------------------------------------------------------------------------
2
+
3
+ from unittest.mock import Mock
4
+
5
+ from conftest import run
6
+
7
+ from gitlabcis.benchmarks.source_code_1 import third_party_1_4
8
+
9
+ # -----------------------------------------------------------------------------
10
+
11
+
12
+ def test_admin_approval_for_app_installs(glEntity, glObject):
13
+
14
+ test = third_party_1_4.admin_approval_for_app_installs
15
+
16
+ run(glEntity, glObject, test, True)
17
+
18
+ # -----------------------------------------------------------------------------
19
+
20
+
21
+ def test_stale_app_reviews(glEntity, glObject, gqlClient):
22
+
23
+ from gql.transport.exceptions import TransportServerError
24
+
25
+ test = third_party_1_4.stale_app_reviews
26
+
27
+ kwargs = {
28
+ 'graphQLEndpoint': 'https://example.com/graphql',
29
+ 'graphQLHeaders': {'Authorization': 'Bearer token'}
30
+ }
31
+ run(glEntity, glObject, test, False, **kwargs)
32
+
33
+ glEntity.path_with_namespace = 'test/project'
34
+ gqlClient.return_value.execute.return_value = {
35
+ "project": {
36
+ "securityScanners": {
37
+ "enabled": ["DEPENDENCY_SCANNING", "CONTAINER_SCANNING"]
38
+ }
39
+ }
40
+ }
41
+ run(glEntity, glObject, test, True, **kwargs)
42
+
43
+ glEntity.path_with_namespace = 'test/project'
44
+ gqlClient.return_value.execute.return_value = {
45
+ "project": {
46
+ "securityScanners": {
47
+ "enabled": ["CONTAINER_SCANNING"]
48
+ }
49
+ }
50
+ }
51
+ run(glEntity, glObject, test, False, **kwargs)
52
+
53
+ glEntity.path_with_namespace = 'test/project'
54
+ gqlClient.return_value.execute.return_value = {
55
+ "project": {
56
+ "securityScanners": {
57
+ "enabled": []
58
+ }
59
+ }
60
+ }
61
+ run(glEntity, glObject, test, False, **kwargs)
62
+
63
+ glEntity.path_with_namespace = 'test/project'
64
+ gqlClient.return_value.execute.return_value = {
65
+ "project": {}
66
+ }
67
+ run(glEntity, glObject, test, False, **kwargs)
68
+
69
+ gqlClient.return_value.execute.side_effect = \
70
+ TransportServerError('GraphQL Error')
71
+ run(glEntity, glObject, test, None, **kwargs)
72
+
73
+ gqlClient.return_value.execute.side_effect = \
74
+ AttributeError()
75
+ run(glEntity, glObject, test, None, **kwargs)
76
+
77
+ # -----------------------------------------------------------------------------
78
+
79
+
80
+ def test_least_privilge_app_permissions(glEntity, glObject, unauthorised):
81
+ from gitlab.exceptions import GitlabGetError
82
+
83
+ test = third_party_1_4.least_privilge_app_permissions
84
+
85
+ unauthorised.integrations.list.side_effect \
86
+ = GitlabGetError(response_code=401)
87
+ run(unauthorised, glObject, test, None)
88
+
89
+ glEntity.integrations.list.return_value = ['one']
90
+ run(glEntity, glObject, test, None)
91
+
92
+ glEntity.integrations.list.return_value = []
93
+ run(glEntity, glObject, test, True)
94
+
95
+ # -----------------------------------------------------------------------------
96
+
97
+
98
+ def test_secure_webhooks(glEntity, glObject, unauthorised):
99
+ from gitlab.exceptions import GitlabGetError
100
+
101
+ test = third_party_1_4.secure_webhooks
102
+
103
+ unauthorised.hooks.list.side_effect \
104
+ = GitlabGetError(response_code=401)
105
+ run(unauthorised, glObject, test, None)
106
+
107
+ hook = Mock()
108
+ hook.enable_ssl_verification = False
109
+ hook.url = 'http://example.com'
110
+ glEntity.hooks.list.return_value = [hook]
111
+ run(glEntity, glObject, test, False)
112
+
113
+ hook.enable_ssl_verification = True
114
+ hook.url = 'https://example.com'
115
+ glEntity.hooks.list.return_value = [hook]
116
+ run(glEntity, glObject, test, True)
117
+
118
+ glEntity.hooks.list.return_value = []
119
+ run(glEntity, glObject, test, None)
@@ -0,0 +1,94 @@
1
+ # -----------------------------------------------------------------------------
2
+
3
+ from pathlib import Path
4
+ from unittest.mock import Mock
5
+
6
+ import pytest
7
+ import yaml
8
+
9
+ # -----------------------------------------------------------------------------
10
+
11
+
12
+ @pytest.fixture
13
+ def projectRoot(scope='function'):
14
+ try:
15
+ return next(
16
+ p for p in Path(__file__).parents if (p / 'gitlabcis').exists())
17
+ except StopIteration:
18
+ pytest.skip('Parent directory containing "gitlabcis" not found.')
19
+
20
+ # -----------------------------------------------------------------------------
21
+
22
+
23
+ @pytest.fixture
24
+ def recommendationFiles(projectRoot, scope='function'):
25
+ return list(filter(
26
+ lambda pathObj: pathObj.name != 'template.yml',
27
+ Path(f'{projectRoot}/gitlabcis/recommendations').rglob('*.yml')))
28
+
29
+ # -----------------------------------------------------------------------------
30
+
31
+
32
+ @pytest.fixture
33
+ def recommendationDirs(projectRoot, scope='function'):
34
+
35
+ dirNames = set()
36
+
37
+ for entry in filter(
38
+ lambda pathObj: pathObj.is_dir() is True,
39
+ Path(f'{projectRoot}/gitlabcis/recommendations').rglob('*')
40
+ ):
41
+
42
+ dirNames.update(entry.parts)
43
+
44
+ return dirNames
45
+
46
+ # -----------------------------------------------------------------------------
47
+
48
+
49
+ @pytest.fixture
50
+ def recommendations(recommendationFiles, scope='module'):
51
+ _recommendations = {}
52
+
53
+ for rec in recommendationFiles:
54
+
55
+ with open(rec, 'r') as f:
56
+ _data = yaml.safe_load(f)
57
+
58
+ _recommendations[_data.get('name')] = _data
59
+
60
+ return _recommendations
61
+
62
+ # -----------------------------------------------------------------------------
63
+
64
+
65
+ @pytest.fixture
66
+ def benchmarkFunctions(projectRoot, scope='module'):
67
+
68
+ from gitlabcis import benchmarks
69
+
70
+ return [
71
+ getattr(getattr(getattr(benchmarks, catFile), subCatFile), func)
72
+ for catFile in dir(benchmarks)
73
+ if not catFile.startswith('__')
74
+ for subCatFile in dir(getattr(benchmarks, catFile))
75
+ if not subCatFile.startswith('__')
76
+ for func in dir(getattr(getattr(benchmarks, catFile), subCatFile))
77
+ if not func.startswith('__')
78
+ ]
79
+
80
+ # -----------------------------------------------------------------------------
81
+
82
+
83
+ @pytest.fixture(scope="function")
84
+ def glEntity():
85
+ # mock a project:
86
+ return Mock()
87
+
88
+ # -----------------------------------------------------------------------------
89
+
90
+
91
+ @pytest.fixture(scope="function")
92
+ def glObject(glEntity):
93
+ # mock a gitlab object:
94
+ return Mock()
@@ -0,0 +1,23 @@
1
+ # -----------------------------------------------------------------------------
2
+
3
+ from unittest.mock import Mock
4
+
5
+ # -----------------------------------------------------------------------------
6
+
7
+
8
+ def test_log():
9
+
10
+ from gitlabcis.cli import log
11
+
12
+ token = 'a real token'
13
+ logFilter = log.CustomLogFilter(token)
14
+ mockLog = Mock()
15
+
16
+ mockLog.getMessage.return_value = (
17
+ 'Connection pool is full, discarding connection')
18
+ logFilter = log.CustomLogFilter(token)
19
+ assert logFilter.filter(mockLog) is False
20
+
21
+ mockLog.getMessage.return_value = f'oh look its my: {token}'
22
+ logFilter = log.CustomLogFilter(token)
23
+ assert logFilter.filter(mockLog) is True
@@ -0,0 +1,9 @@
1
+ # -------------------------------------------------------------------------
2
+
3
+ from gitlabcis.utils.__init__ import readRecommendations
4
+
5
+ # -------------------------------------------------------------------------
6
+
7
+
8
+ def test_none_argfilters():
9
+ assert readRecommendations(argFilters=None) is not None
@@ -0,0 +1,156 @@
1
+ # -----------------------------------------------------------------------------
2
+
3
+ from unittest.mock import MagicMock, Mock, patch
4
+
5
+ import pytest # noqa: F401
6
+ from gitlab.exceptions import GitlabAuthenticationError, GitlabGetError
7
+ from gitlab.v4.objects.files import ProjectFile
8
+
9
+ from gitlabcis.utils.ci import getConfig, searchConfig
10
+
11
+ # -----------------------------------------------------------------------------
12
+
13
+ mock_project_file = Mock(spec=ProjectFile)
14
+
15
+ # -----------------------------------------------------------------------------
16
+
17
+
18
+ def test_getConfig_remote_ci_file(glEntity, glObject):
19
+ glEntity.ci_config_path = 'https://example.com/.gitlab-ci.yml'
20
+ result = getConfig(glEntity, glObject)
21
+ assert result == {
22
+ None: 'Remote CI file: '
23
+ 'https://example.com/.gitlab-ci.yml not supported'}
24
+
25
+
26
+ def test_getConfig_default_path(glEntity, glObject):
27
+ glEntity.ci_config_path = ''
28
+ glEntity.default_branch = 'main'
29
+ glEntity.files.get.return_value = mock_project_file
30
+ result = getConfig(glEntity, glObject)
31
+ assert isinstance(next(iter(result)), ProjectFile)
32
+
33
+
34
+ def test_getConfig_file_not_found(glEntity, glObject):
35
+ glEntity.ci_config_path = '.gitlab-ci.yml'
36
+ glEntity.default_branch = 'main'
37
+ glEntity.files.get.side_effect = GitlabGetError(response_code=404)
38
+ result = getConfig(glEntity, glObject)
39
+ assert result == {
40
+ False: f'Pipeline config file not found: {glEntity.ci_config_path}'}
41
+
42
+
43
+ @patch('gitlabcis.utils.ci.getConfig')
44
+ def test_searchConfig_string_found(mock_get_config, glEntity, glObject):
45
+ mock_get_config.return_value = {mock_project_file: None}
46
+ mock_project_file.content = 'SGVsbG8gV29ybGQ='
47
+ result = searchConfig(glEntity, glObject, 'Hello')
48
+ assert result == {True: 'Hello was found in CI config file'}
49
+
50
+
51
+ @patch('gitlabcis.utils.ci.getConfig')
52
+ def test_searchConfig_string_not_found(mock_get_config, glEntity, glObject):
53
+ mock_get_config.return_value = {mock_project_file: None}
54
+ mock_project_file.content = 'SGVsbG8gV29ybGQ='
55
+ result = searchConfig(glEntity, glObject, 'Python')
56
+ assert result == {False: 'Python was not found in CI config file'}
57
+
58
+
59
+ @patch('gitlabcis.utils.ci.getConfig')
60
+ def test_searchConfig_skip_condition(mock_get_config, glEntity, glObject):
61
+ mock_get_config.return_value = {None: 'Some skip reason'}
62
+ result = searchConfig(glEntity, glObject, 'Hello')
63
+ assert result == {None: 'Some skip reason'}
64
+
65
+
66
+ @patch('gitlabcis.utils.ci.getConfig')
67
+ def test_searchConfig_file_not_found(mock_get_config, glEntity, glObject):
68
+ mock_get_config.return_value = {
69
+ False: 'Pipeline config file not found: .gitlab-ci.yml'}
70
+ result = searchConfig(glEntity, glObject, 'Hello')
71
+ assert result == {False: 'Pipeline config file not found: .gitlab-ci.yml'}
72
+
73
+
74
+ def test_searchConfig_insufficient_permissions(glEntity, glObject):
75
+ glEntity.ci_config_path = '.gitlab-ci.yml'
76
+ glEntity.default_branch = 'main'
77
+ glEntity.files.get.side_effect = GitlabAuthenticationError(
78
+ response_code=401)
79
+ result = searchConfig(glEntity, glObject, 'Hello')
80
+ assert result == {None: 'Insufficient permissions'}
81
+
82
+
83
+ def test_getConfig_insufficient_permissions(glEntity, glObject):
84
+ glEntity.ci_config_path = '.gitlab-ci.yml'
85
+ glEntity.default_branch = 'main'
86
+ glEntity.files.get.side_effect = GitlabGetError(response_code=418)
87
+ result = getConfig(glEntity, glObject)
88
+ assert result == {
89
+ False: f'Pipeline config file not found: {glEntity.ci_config_path}'}
90
+
91
+
92
+ @patch('re.match')
93
+ def test_nonetype_getConfig(reMatch, glEntity, glObject):
94
+ mockRemote = MagicMock()
95
+ mockRemote.group.side_effect = lambda name: {
96
+ 'refName': 'main',
97
+ 'namespace': 'stuff/things',
98
+ 'filePath': 'some/path'
99
+ }[name]
100
+
101
+ reMatch.return_value = mockRemote
102
+ glEntity.ci_config_path = b'12345'
103
+ glObject.projects.get.return_value = 'meh'
104
+ glEntity.files.get.side_effect = GitlabGetError(response_code=404)
105
+ result = getConfig(glEntity, glObject)
106
+ assert result == {None: 'Insufficient permissions'}
107
+
108
+
109
+ @patch('gitlabcis.utils.ci.getConfig')
110
+ def test_searchConfig_handles_type_error(getConfig, glEntity, glObject):
111
+ typeErrorMock = MagicMock()
112
+ typeErrorMock.return_value = {None: 'lel'}
113
+ getConfig.return_value = typeErrorMock
114
+ getConfig.return_value.__iter__.side_effect = TypeError
115
+ result = searchConfig(glEntity, glObject, 'search_string')
116
+ assert next(iter(result)) is None
117
+
118
+
119
+ @patch('gitlabcis.utils.ci.getConfig')
120
+ def test_searchConfig_teapot(getConfig, glEntity, glObject):
121
+ glEntity.ci_config_path = '.gitlab-ci.yml'
122
+ glEntity.default_branch = 'main'
123
+ getConfig.side_effect = GitlabAuthenticationError(response_code=418)
124
+ glEntity.files.get.side_effect = GitlabAuthenticationError(
125
+ response_code=418)
126
+ result = searchConfig(glEntity, glObject, 'Hello')
127
+ assert result is None
128
+
129
+
130
+ @patch('gitlabcis.utils.ci.getConfig')
131
+ def test_searchConfig_unauth(getConfig, glEntity, glObject):
132
+ glEntity.ci_config_path = '.gitlab-ci.yml'
133
+ glEntity.default_branch = 'main'
134
+ getConfig.side_effect = GitlabAuthenticationError(response_code=401)
135
+ glEntity.files.get.side_effect = GitlabAuthenticationError(
136
+ response_code=401)
137
+ result = searchConfig(glEntity, glObject, 'Hello')
138
+ assert result == {None: 'Insufficient permissions'}
139
+
140
+
141
+ @patch('re.match')
142
+ def test_nonetype_getConfig_teapot(reMatch, glEntity, glObject):
143
+ mockRemote = MagicMock()
144
+ mockRemote.group.side_effect = lambda name: {
145
+ 'refName': 'main',
146
+ 'namespace': 'stuff/things',
147
+ 'filePath': 'some/path'
148
+ }[name]
149
+
150
+ reMatch.return_value = mockRemote
151
+ glEntity.ci_config_path = b'12345'
152
+ glObject.projects.get.return_value = 'meh'
153
+ glEntity.files.get.side_effect = GitlabAuthenticationError(
154
+ response_code=418)
155
+ result = getConfig(glEntity, glObject)
156
+ assert result == {None: 'Insufficient permissions'}
@@ -0,0 +1,95 @@
1
+ # -----------------------------------------------------------------------------
2
+
3
+ from gitlabcis import output
4
+
5
+ # -----------------------------------------------------------------------------
6
+
7
+ stats = {
8
+ 'PASSED': 1,
9
+ 'FAILED': 1,
10
+ 'SKIPPED': 1,
11
+ 'TOTAL': 3
12
+ }
13
+
14
+ results = [
15
+ {
16
+ 'id': '1.1.1',
17
+ 'title': 'Something',
18
+ 'reason': 'Yes',
19
+ 'result': 'PASS'
20
+ },
21
+ {
22
+ 'id': '1.1.2',
23
+ 'title': 'Something else',
24
+ 'reason': 'No',
25
+ 'result': 'FAIL'
26
+ },
27
+ {
28
+ 'id': '1.1.3',
29
+ 'title': 'Something even more else',
30
+ 'reason': 'No',
31
+ 'result': 'SKIP'
32
+ }
33
+ ]
34
+
35
+ # -----------------------------------------------------------------------------
36
+
37
+
38
+ def test_terminal_output():
39
+ output(results, stats, 'terminal', None)
40
+
41
+ # -----------------------------------------------------------------------------
42
+
43
+
44
+ def test_xml_output():
45
+ with open('results.xml', 'w') as f:
46
+ output(results, stats, 'xml', f)
47
+
48
+ # -----------------------------------------------------------------------------
49
+
50
+
51
+ def test_json_output():
52
+ with open('results.json', 'w') as f:
53
+ output(results, stats, 'json', f)
54
+
55
+ # -----------------------------------------------------------------------------
56
+
57
+
58
+ def test_txt_output():
59
+ with open('results.txt', 'w') as f:
60
+ output(results, stats, 'txt', f)
61
+
62
+ # -----------------------------------------------------------------------------
63
+
64
+
65
+ def test_csv_output():
66
+ with open('results.csv', 'w') as f:
67
+ output(results, stats, 'csv', f)
68
+
69
+ # -----------------------------------------------------------------------------
70
+
71
+
72
+ def test_yaml_output():
73
+ with open('results.yaml', 'w') as f:
74
+ output(results, stats, 'yaml', f)
75
+
76
+ # -----------------------------------------------------------------------------
77
+
78
+
79
+ def test_no_results():
80
+ stats = {"PASSED": 5, "TOTAL": 10, "SKIPPED": 10, "FAILED": 0}
81
+ output([], stats, 'terminal', None)
82
+
83
+ # -----------------------------------------------------------------------------
84
+
85
+
86
+ def test_high_score_csv_results():
87
+ stats = {"PASSED": 9001, "TOTAL": 9001, "SKIPPED": 0, "FAILED": 0}
88
+ output([], stats, 'csv', None)
89
+
90
+ # -----------------------------------------------------------------------------
91
+
92
+
93
+ def test_zero_division_error():
94
+ stats = {"PASSED": 10, "TOTAL": 10, "SKIPPED": 10, "FAILED": 1}
95
+ output([], stats, 'csv', None)