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,334 @@
1
+ # -------------------------------------------------------------------------
2
+
3
+ def review_and_remove_inactive_users(glEntity, glObject, **kwargs):
4
+ """
5
+ id: 1.3.1
6
+ title: Ensure inactive users are reviewed and removed periodically
7
+ """
8
+
9
+ from gitlab.exceptions import GitlabGetError, GitlabHttpError
10
+ from gitlab.exceptions import GitlabAuthenticationError
11
+ from gitlab.exceptions import GitlabListError
12
+
13
+ from dateutil.relativedelta import relativedelta
14
+ from datetime import datetime, timezone
15
+
16
+ try:
17
+ ninetyDaysAgo = datetime.now(timezone.utc) - relativedelta(days=90)
18
+
19
+ users = glObject.users.list(per_page=100, iterator=True)
20
+
21
+ for user in users:
22
+
23
+ # a regular PAT is not going to return this value:
24
+ try:
25
+ if user.last_activity_on is None:
26
+ continue
27
+ except AttributeError:
28
+ return {None: 'Insufficient permissions'}
29
+
30
+ if datetime.strptime(
31
+ user.last_activity_on,
32
+ '%Y-%m-%d'
33
+ ).replace(tzinfo=timezone.utc) > ninetyDaysAgo:
34
+ return {
35
+ False: 'User found with last activity longer than 90 days'}
36
+
37
+ return {True: 'No users found with activity longer than 90 days'}
38
+
39
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError,
40
+ GitlabListError) as e:
41
+ if e.response_code in [401, 403]:
42
+ return {None: 'Insufficient permissions'}
43
+
44
+ # -------------------------------------------------------------------------
45
+
46
+
47
+ def limit_top_level_group_creation(glEntity, glObject, **kwargs):
48
+ """
49
+ id: 1.3.2
50
+ title: Ensure top-level group creation is limited to specific members
51
+ """
52
+
53
+ from gitlab.exceptions import GitlabGetError, GitlabHttpError
54
+ from gitlab.exceptions import GitlabAuthenticationError
55
+
56
+ try:
57
+ if glObject.settings.get().can_create_group is False:
58
+ return {True: 'Top-level group creation is limited'}
59
+
60
+ return {False: 'Top-level group creation is not limited'}
61
+
62
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError) as e:
63
+ if e.response_code in [401, 403, 404]:
64
+ return {None: 'Insufficient permissions'}
65
+
66
+ # -------------------------------------------------------------------------
67
+
68
+
69
+ def minimum_number_of_admins(glEntity, glObject, **kwargs):
70
+ """
71
+ id: 1.3.3
72
+ title: Ensure minimum number of administrators are set for the
73
+ organization
74
+ """
75
+
76
+ from gitlab.exceptions import GitlabGetError, GitlabHttpError
77
+ from gitlab.exceptions import GitlabAuthenticationError
78
+
79
+ try:
80
+ members = glEntity.members_all.list(get_all=True)
81
+
82
+ totalMembers = len(members)
83
+
84
+ if totalMembers == 1:
85
+ return {None: 'Only 1 member found'}
86
+
87
+ # Access levels:
88
+ # No access 0
89
+ # Minimal access 5
90
+ # Guest 10
91
+ # Reporter 20
92
+ # Developer 30
93
+ # Maintainer 40
94
+ # Owner 50
95
+
96
+ ownersOrMaintainers = []
97
+ for member in members:
98
+ if member.access_level >= 40:
99
+ ownersOrMaintainers.append(member)
100
+
101
+ if len(ownersOrMaintainers) < totalMembers:
102
+ return {True: 'Less owners/maintainers than members set'}
103
+
104
+ return {False: 'Access levels not restrictive for members'}
105
+
106
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError) as e:
107
+ if e.response_code in [401, 403, 404]:
108
+ return {None: 'Insufficient permissions'}
109
+
110
+ # -------------------------------------------------------------------------
111
+
112
+
113
+ def require_mfa_for_contributors(glEntity, glObject, **kwargs):
114
+ """
115
+ id: 1.3.4
116
+ title: Ensure Multi-Factor Authentication (MFA) is required for
117
+ contributors of new code
118
+ """
119
+
120
+ from gitlab.exceptions import GitlabGetError, GitlabHttpError
121
+ from gitlab.exceptions import GitlabAuthenticationError
122
+
123
+ try:
124
+ _settings = glObject.settings.get()
125
+
126
+ if _settings.require_two_factor_authentication is True:
127
+ return {True: 'Two Factor Authentication is required'}
128
+
129
+ return {False: 'Two Factor Authentication is not required'}
130
+
131
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError) as e:
132
+ if e.response_code in [401, 403, 404]:
133
+ return {None: 'Insufficient permissions'}
134
+
135
+ # -------------------------------------------------------------------------
136
+
137
+
138
+ def require_mfa_at_org_level(glEntity, glObject, **kwargs):
139
+ """
140
+ id: 1.3.5
141
+ title: Ensure the organization is requiring members to use
142
+ Multi-Factor Authentication (MFA)
143
+ """
144
+
145
+ from gitlab.exceptions import GitlabGetError, GitlabHttpError
146
+ from gitlab.exceptions import GitlabAuthenticationError
147
+
148
+ try:
149
+ _settings = glObject.settings.get()
150
+
151
+ if _settings.require_two_factor_authentication is True:
152
+ return {True: 'Two Factor Authentication is required'}
153
+
154
+ if _settings.two_factor_grace_period != 0:
155
+ return {True: 'Grace period is set for Two Factor Authentication'}
156
+
157
+ return {False: 'Two Factor Authentication is not required'}
158
+
159
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError) as e:
160
+ if e.response_code in [401, 403, 404]:
161
+ return {None: 'Insufficient permissions'}
162
+
163
+ # -------------------------------------------------------------------------
164
+
165
+
166
+ def limit_user_registration_domain(glEntity, glObject, **kwargs):
167
+ """
168
+ id: 1.3.6
169
+ title: Ensure new members are required to be invited using
170
+ company-approved email
171
+ """
172
+
173
+ # We cannot automatically answer this check, therefore we SKIP:
174
+ return {None: 'This check requires validation'}
175
+
176
+ # -------------------------------------------------------------------------
177
+
178
+
179
+ def ensure_2_admins_per_repo(glEntity, glObject, **kwargs):
180
+ """
181
+ id: 1.3.7
182
+ title: Ensure two administrators are set for each repository
183
+ """
184
+
185
+ from gitlab.exceptions import GitlabGetError, GitlabHttpError
186
+ from gitlab.exceptions import GitlabAuthenticationError
187
+
188
+ try:
189
+ owners = 0
190
+ members = glEntity.members_all.list(get_all=True)
191
+
192
+ for member in members:
193
+
194
+ if member.access_level == 50:
195
+ owners += 1
196
+
197
+ if owners == 2:
198
+ return {True: 'Two repository owners found'}
199
+
200
+ return {
201
+ True: 'No repository owners found'
202
+ if owners == 0
203
+ else f'Only found: {owners} owners'}
204
+
205
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError) as e:
206
+ if e.response_code in [401, 403]:
207
+ return {None: 'Insufficient permissions'}
208
+
209
+ # this throws an attr error if accessed anonymously (pytest no auth)
210
+ except AttributeError:
211
+ return {None: 'Insufficient permissions'}
212
+
213
+ # -------------------------------------------------------------------------
214
+
215
+
216
+ def strict_permissions_for_repo(glEntity, glObject, **kwargs):
217
+ """
218
+ id: 1.3.8
219
+ title: Ensure strict base permissions are set for repositories
220
+ """
221
+
222
+ from gitlab.exceptions import GitlabGetError, GitlabHttpError
223
+ from gitlab.exceptions import GitlabAuthenticationError
224
+ from gitlab.exceptions import GitlabListError
225
+
226
+ try:
227
+ members = glEntity.members_all.list(get_all=True)
228
+
229
+ totalMembers = len(members)
230
+
231
+ if totalMembers == 1:
232
+ return {None: 'Only 1 member found'}
233
+
234
+ # Access levels:
235
+ # No access 0
236
+ # Minimal access 5
237
+ # Guest 10
238
+ # Reporter 20
239
+ # Developer 30
240
+ # Maintainer 40
241
+ # Owner 50
242
+
243
+ ownersOrMaintainers = []
244
+ for member in members:
245
+ if member.access_level >= 40:
246
+ ownersOrMaintainers.append(member)
247
+
248
+ if len(ownersOrMaintainers) < totalMembers:
249
+ return {True: 'Less owners/maintainers than members set'}
250
+
251
+ return {False: 'Access levels not restrictive for members'}
252
+
253
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError,
254
+ GitlabListError) as e:
255
+ if e.response_code in [401, 403]:
256
+ return {None: 'Insufficient permissions'}
257
+
258
+ # -------------------------------------------------------------------------
259
+
260
+
261
+ def domain_verification(glEntity, glObject, **kwargs):
262
+ """
263
+ id: 1.3.9
264
+ title: Ensure an organization's identity is confirmed with a “Verified”
265
+ badge
266
+ """
267
+
268
+ return {None: 'This check requires validation'}
269
+
270
+ # -------------------------------------------------------------------------
271
+
272
+
273
+ def scm_notification_restriction(glEntity, glObject, **kwargs):
274
+ """
275
+ id: 1.3.10
276
+ title: Ensure Source Code Management (SCM) email notifications are
277
+ restricted to verified domains
278
+ """
279
+
280
+ return {None: 'This check requires validation'}
281
+
282
+ # -------------------------------------------------------------------------
283
+
284
+
285
+ def org_provided_ssh_certs(glEntity, glObject, **kwargs):
286
+ """
287
+ id: 1.3.11
288
+ title: Ensure an organization provides SSH certificates
289
+ """
290
+
291
+ from gitlab.exceptions import GitlabGetError, GitlabHttpError
292
+ from gitlab.exceptions import GitlabAuthenticationError
293
+
294
+ try:
295
+ keyRestrictions = [
296
+ 'ed25519_key_restriction', 'ecdsa_key_restriction',
297
+ 'dsa_key_restriction', 'rsa_key_restriction',
298
+ 'ecdsa_sk_key_restriction', 'ed25519_sk_key_restriction'
299
+ ]
300
+
301
+ settings = glObject.settings.get()
302
+
303
+ for restriction in keyRestrictions:
304
+
305
+ if getattr(settings, restriction) != 0:
306
+ return {True: f'{restriction} is enforced'}
307
+
308
+ return {False: 'No key restrictions set'}
309
+
310
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError) as e:
311
+ if e.response_code in [401, 403]:
312
+ return {None: 'Insufficient permissions'}
313
+
314
+ # -------------------------------------------------------------------------
315
+
316
+
317
+ def restrict_ip_addresses(glEntity, glObject, **kwargs):
318
+ """
319
+ id: 1.3.12
320
+ title: Ensure Git access is limited based on IP addresses
321
+ """
322
+
323
+ return {None: 'This check requires validation'}
324
+
325
+ # -------------------------------------------------------------------------
326
+
327
+
328
+ def track_code_anomalies(glEntity, glObject, **kwargs):
329
+ """
330
+ id: 1.3.13
331
+ title: Ensure anomalous code behavior is tracked
332
+ """
333
+
334
+ return {None: 'This check requires validation'}
@@ -0,0 +1,168 @@
1
+ # -------------------------------------------------------------------------
2
+
3
+
4
+ def public_repos_have_security_file(glEntity, glObject, **kwargs):
5
+ """
6
+ id: 1.2.1
7
+ title: Ensure all public repositories contain a SECURITY.md file
8
+ """
9
+
10
+ from gitlab.exceptions import (GitlabAuthenticationError, GitlabGetError,
11
+ GitlabHttpError)
12
+
13
+ try:
14
+ # SKIP private repos:
15
+ try:
16
+ if glEntity.visibility == 'private':
17
+ return {None: 'Project is private'}
18
+ except AttributeError:
19
+ return {None: 'Insufficient permissions'}
20
+
21
+ # PASS if the SECURITY.md file exists in the root dir of default
22
+ # branch
23
+ _rootFiles = glEntity.repository_tree(path='')
24
+
25
+ for _file in _rootFiles:
26
+ if _file.get('name').upper() == 'SECURITY.MD':
27
+ return {True: 'SECURITY.md file found'}
28
+
29
+ return {False: 'No SECURITY.md file found'}
30
+
31
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError) as e:
32
+ if e.response_code in [401, 403]:
33
+ return {None: 'Insufficient permissions'}
34
+
35
+ # -------------------------------------------------------------------------
36
+
37
+
38
+ def limit_repo_creations(glEntity, glObject, **kwargs):
39
+ """
40
+ id: 1.2.2
41
+ title: Ensure repository creation is limited to specific members
42
+ """
43
+
44
+ from gitlab.exceptions import (GitlabAuthenticationError, GitlabGetError,
45
+ GitlabHttpError)
46
+
47
+ try:
48
+ settings = glObject.settings.get()
49
+
50
+ if settings.signup_enabled is False:
51
+ return {True: 'Public signup is disabled'}
52
+
53
+ if settings.signup_enabled is True and \
54
+ settings.require_admin_approval_after_user_signup is True and \
55
+ settings.email_confirmation_setting == 'hard':
56
+ return {True: 'Requires approval after signup and email '
57
+ 'confirmation setting is "hard"'}
58
+
59
+ return {False: 'Either public signup enabled, admin approval after '
60
+ 'signup not set or email confirmation is set to '
61
+ '"hard"'}
62
+
63
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError) as e:
64
+ if e.response_code in [401, 403]:
65
+ return {None: 'Insufficient permissions'}
66
+
67
+ # -------------------------------------------------------------------------
68
+
69
+
70
+ def limit_repo_deletions(glEntity, glObject, **kwargs):
71
+ """
72
+ id: 1.2.3
73
+ title: Ensure repository deletion is limited to specific users
74
+ """
75
+
76
+ # attempting to paginate over 1,000 users in a project which
77
+ # recived their membership due to nested-group permissions...
78
+ # results in a large wait-time for this function to run.
79
+ # roughly it take 1.5 minutes for it to complete all of /gitlab-com.
80
+
81
+ return {None: 'This check requires validation'}
82
+
83
+ # -------------------------------------------------------------------------
84
+
85
+
86
+ def limit_issue_deletions(glEntity, glObject, **kwargs):
87
+ """
88
+ id: 1.2.4
89
+ title: Ensure issue deletion is limited to specific users
90
+ """
91
+
92
+ # attempting to paginate over 1,000 users in a project which
93
+ # recived their membership due to nested-group permissions...
94
+ # results in a large wait-time for this function to run.
95
+ # roughly it take 1.5 minutes for it to complete all of /gitlab-com.
96
+
97
+ return {None: 'This check requires validation'}
98
+
99
+ # -------------------------------------------------------------------------
100
+
101
+
102
+ def track_forks(glEntity, glObject, **kwargs):
103
+ """
104
+ id: 1.2.5
105
+ title: Ensure all copies (forks) of code are tracked and accounted for
106
+ """
107
+
108
+ from gitlab.exceptions import (GitlabAuthenticationError, GitlabGetError,
109
+ GitlabHttpError, GitlabListError)
110
+
111
+ try:
112
+ _forksFound = glEntity.forks.list(get_all=False)
113
+
114
+ if not _forksFound:
115
+ return {True: 'No forks found'}
116
+
117
+ # we can't track and account for forks, so SKIP if forks found
118
+ return {None: 'Cannot track and account for forks'}
119
+
120
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError,
121
+ GitlabListError) as e:
122
+ if e.response_code in [403, 404]:
123
+ return {None: 'Insufficient permissions'}
124
+
125
+ # -------------------------------------------------------------------------
126
+
127
+
128
+ def track_project_visibility_status(glEntity, glObject, **kwargs):
129
+ """
130
+ id: 1.2.6
131
+ title: Ensure all code projects are tracked for changes in visibility
132
+ status
133
+ """
134
+
135
+ # We cannot automatically answer this check, therefore we SKIP:
136
+ return {None: 'This check requires validation'}
137
+
138
+ # -------------------------------------------------------------------------
139
+
140
+
141
+ def review_and_archive_stale_repos(glEntity, glObject, **kwargs):
142
+ """
143
+ id: 1.2.7
144
+ title: Ensure inactive repositories are reviewed and archived
145
+ periodically
146
+ """
147
+
148
+ from datetime import datetime, timezone
149
+
150
+ from dateutil.relativedelta import relativedelta
151
+ from gitlab.exceptions import (GitlabAuthenticationError, GitlabGetError,
152
+ GitlabHttpError)
153
+
154
+ try:
155
+ lastActivity = datetime.strptime(
156
+ glEntity.last_activity_at, '%Y-%m-%dT%H:%M:%S.%fZ'
157
+ ).replace(tzinfo=timezone.utc)
158
+
159
+ sixMonthsAgo = datetime.now(timezone.utc) - relativedelta(months=6)
160
+
161
+ if lastActivity > sixMonthsAgo:
162
+ return {True: 'Repository is active'}
163
+
164
+ return {False: 'Repository is inactive'}
165
+
166
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError) as e:
167
+ if e.response_code in [401, 403]:
168
+ return {None: 'Insufficient permissions'}
@@ -0,0 +1,139 @@
1
+ # -------------------------------------------------------------------------
2
+
3
+
4
+ def admin_approval_for_app_installs(glEntity, glObject, **kwargs):
5
+ """
6
+ id: 1.4.1
7
+ title: Ensure administrator approval is required for every installed
8
+ application
9
+ """
10
+
11
+ return {True: 'You are compliant by default. Only maintainers and '
12
+ 'owners can integrate with external applications'}
13
+
14
+ # -------------------------------------------------------------------------
15
+
16
+
17
+ def stale_app_reviews(glEntity, glObject, **kwargs):
18
+ """
19
+ id: 1.4.2
20
+ title: Ensure stale applications are reviewed and inactive ones are
21
+ removed
22
+ """
23
+
24
+ from gitlab.exceptions import (GitlabAuthenticationError, GitlabGetError,
25
+ GitlabHttpError)
26
+ from gql import Client, gql
27
+ from gql.transport.exceptions import (TransportAlreadyConnected,
28
+ TransportServerError)
29
+ from gql.transport.requests import RequestsHTTPTransport
30
+ from graphql import GraphQLError
31
+
32
+ try:
33
+
34
+ variables = {
35
+ 'fullPath': glEntity.path_with_namespace
36
+ }
37
+
38
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError) as e:
39
+ if e.response_code in [401, 403]:
40
+ return {None: 'Insufficient permissions'}
41
+
42
+ client = Client(
43
+ transport=RequestsHTTPTransport(
44
+ url=kwargs.get('graphQLEndpoint'),
45
+ headers=kwargs.get('graphQLHeaders'),
46
+ use_json=True
47
+ ),
48
+ fetch_schema_from_transport=True
49
+ )
50
+
51
+ query = gql('''
52
+ query GetSecurityScanners($fullPath: ID!) {
53
+ project(fullPath: $fullPath) {
54
+ securityScanners {
55
+ enabled
56
+ }
57
+ }
58
+ }
59
+ ''')
60
+
61
+ try:
62
+
63
+ results = client.execute(query, variable_values=variables)
64
+
65
+ except (GraphQLError, TransportServerError, TransportAlreadyConnected):
66
+ return {None: 'Error: Issue with GraphQL Query'}
67
+
68
+ # pytest no auth:
69
+ except AttributeError:
70
+ return {None: 'Insufficient permissions'}
71
+
72
+ try:
73
+ # dependency scanning alerts when there are stale applications present:
74
+ if 'DEPENDENCY_SCANNING' in \
75
+ results['project']['securityScanners']['enabled']:
76
+ return {True: 'Dependency Scanning is enabled'}
77
+
78
+ else:
79
+ return {False: 'Dependency Scanning is not enabled'}
80
+
81
+ except KeyError:
82
+ return {False: 'Dependency Scanning is not enabled'}
83
+
84
+ # -------------------------------------------------------------------------
85
+
86
+
87
+ def least_privilge_app_permissions(glEntity, glObject, **kwargs):
88
+ """
89
+ id: 1.4.3
90
+ title: Ensure the access granted to each installed application is
91
+ limited to the least privilege needed
92
+ """
93
+
94
+ from gitlab.exceptions import (GitlabAuthenticationError, GitlabGetError,
95
+ GitlabHttpError, GitlabListError)
96
+
97
+ try:
98
+ integrations = glEntity.integrations.list(get_all=False)
99
+
100
+ if len(integrations) == 0:
101
+ return {True: 'No integrations found'}
102
+
103
+ return {None: 'This check requires validation'}
104
+
105
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError,
106
+ GitlabListError) as e:
107
+ if e.response_code in [401, 403]:
108
+ return {None: 'Insufficient permissions'}
109
+
110
+ # -------------------------------------------------------------------------
111
+
112
+
113
+ def secure_webhooks(glEntity, glObject, **kwargs):
114
+ """
115
+ id: 1.4.4
116
+ title: Ensure only secured webhooks are used
117
+ """
118
+
119
+ from gitlab.exceptions import (GitlabAuthenticationError, GitlabGetError,
120
+ GitlabHttpError, GitlabListError)
121
+
122
+ try:
123
+ webhooks = glEntity.hooks.list(get_all=True)
124
+
125
+ if len(webhooks) == 0:
126
+ return {None: 'No webhooks found'}
127
+
128
+ for hook in webhooks:
129
+
130
+ if hook.enable_ssl_verification is False or \
131
+ hook.url.startswith('http://'):
132
+ return {False: 'Insecure webhook found'}
133
+
134
+ return {True: 'All webhooks using HTTPS'}
135
+
136
+ except (GitlabHttpError, GitlabGetError, GitlabAuthenticationError,
137
+ GitlabListError) as e:
138
+ if e.response_code in [401, 403]:
139
+ return {None: 'Insufficient permissions'}
File without changes
gitlabcis/cli/log.py ADDED
@@ -0,0 +1,30 @@
1
+ # -----------------------------------------------------------------------------
2
+
3
+ import logging
4
+
5
+ # -----------------------------------------------------------------------------
6
+
7
+
8
+ class CustomLogFilter(logging.Filter):
9
+
10
+ # -------------------------------------------------------------------------
11
+
12
+ def __init__(self, token):
13
+
14
+ super().__init__()
15
+ self.token = token
16
+
17
+ # -------------------------------------------------------------------------
18
+
19
+ def filter(self, record):
20
+
21
+ # The connection is being discarded after the request is completed
22
+ # we want to suppress this as it affects the cosmetics of the progress
23
+ if ('Connection pool is full, discarding connection'
24
+ in record.getMessage()):
25
+ return False
26
+
27
+ # Suppress any logs containing the token
28
+ record.msg = record.getMessage().replace(self.token, '[REDACTED]')
29
+
30
+ return True