conviso-ast 3.0.0__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 (128) hide show
  1. conviso_ast-3.0.0.data/scripts/flow_bash_completer.sh +21 -0
  2. conviso_ast-3.0.0.data/scripts/flow_fish_completer.fish +1 -0
  3. conviso_ast-3.0.0.data/scripts/flow_zsh_completer.sh +32 -0
  4. conviso_ast-3.0.0.dist-info/METADATA +37 -0
  5. conviso_ast-3.0.0.dist-info/RECORD +128 -0
  6. conviso_ast-3.0.0.dist-info/WHEEL +5 -0
  7. conviso_ast-3.0.0.dist-info/entry_points.txt +3 -0
  8. conviso_ast-3.0.0.dist-info/top_level.txt +1 -0
  9. convisoappsec/__init__.py +0 -0
  10. convisoappsec/common/__init__.py +5 -0
  11. convisoappsec/common/box.py +251 -0
  12. convisoappsec/common/cleaner.py +78 -0
  13. convisoappsec/common/docker.py +399 -0
  14. convisoappsec/common/exceptions.py +8 -0
  15. convisoappsec/common/git_data_parser.py +76 -0
  16. convisoappsec/common/graphql/__init__.py +0 -0
  17. convisoappsec/common/graphql/error_handlers.py +75 -0
  18. convisoappsec/common/graphql/errors.py +16 -0
  19. convisoappsec/common/graphql/low_client.py +51 -0
  20. convisoappsec/common/retry_handler.py +40 -0
  21. convisoappsec/common/strings.py +8 -0
  22. convisoappsec/flow/__init__.py +3 -0
  23. convisoappsec/flow/api.py +104 -0
  24. convisoappsec/flow/cleaner.py +118 -0
  25. convisoappsec/flow/graphql_api/__init__.py +0 -0
  26. convisoappsec/flow/graphql_api/beta/__init__.py +0 -0
  27. convisoappsec/flow/graphql_api/beta/client.py +18 -0
  28. convisoappsec/flow/graphql_api/beta/models/__init__.py +0 -0
  29. convisoappsec/flow/graphql_api/beta/models/issues/__init__.py +0 -0
  30. convisoappsec/flow/graphql_api/beta/models/issues/container.py +72 -0
  31. convisoappsec/flow/graphql_api/beta/models/issues/iac.py +6 -0
  32. convisoappsec/flow/graphql_api/beta/models/issues/normalize.py +13 -0
  33. convisoappsec/flow/graphql_api/beta/models/issues/sast.py +53 -0
  34. convisoappsec/flow/graphql_api/beta/models/issues/sca.py +78 -0
  35. convisoappsec/flow/graphql_api/beta/resources_api.py +142 -0
  36. convisoappsec/flow/graphql_api/beta/schemas/__init__.py +0 -0
  37. convisoappsec/flow/graphql_api/beta/schemas/mutations/__init__.py +61 -0
  38. convisoappsec/flow/graphql_api/beta/schemas/resolvers/__init__.py +0 -0
  39. convisoappsec/flow/graphql_api/v1/__init__.py +0 -0
  40. convisoappsec/flow/graphql_api/v1/client.py +46 -0
  41. convisoappsec/flow/graphql_api/v1/models/__init__.py +0 -0
  42. convisoappsec/flow/graphql_api/v1/models/asset.py +14 -0
  43. convisoappsec/flow/graphql_api/v1/models/issues.py +16 -0
  44. convisoappsec/flow/graphql_api/v1/models/project.py +35 -0
  45. convisoappsec/flow/graphql_api/v1/resources_api.py +489 -0
  46. convisoappsec/flow/graphql_api/v1/schemas/__init__.py +0 -0
  47. convisoappsec/flow/graphql_api/v1/schemas/mutations/__init__.py +212 -0
  48. convisoappsec/flow/graphql_api/v1/schemas/resolvers/__init__.py +180 -0
  49. convisoappsec/flow/source_code_scanner/__init__.py +9 -0
  50. convisoappsec/flow/source_code_scanner/exceptions.py +2 -0
  51. convisoappsec/flow/source_code_scanner/scc.py +68 -0
  52. convisoappsec/flow/source_code_scanner/source_code_scanner.py +177 -0
  53. convisoappsec/flow/util/__init__.py +7 -0
  54. convisoappsec/flow/util/ci_provider.py +99 -0
  55. convisoappsec/flow/util/metrics.py +16 -0
  56. convisoappsec/flow/util/source_code_compressor.py +22 -0
  57. convisoappsec/flow/version_control_system_adapter.py +528 -0
  58. convisoappsec/flow/version_searchers/__init__.py +9 -0
  59. convisoappsec/flow/version_searchers/sorted_by_versioning_style.py +85 -0
  60. convisoappsec/flow/version_searchers/timebased_version_seacher.py +39 -0
  61. convisoappsec/flow/version_searchers/version_searcher_result.py +33 -0
  62. convisoappsec/flow/versioning_style/__init__.py +0 -0
  63. convisoappsec/flow/versioning_style/semantic_versioning.py +44 -0
  64. convisoappsec/flowcli/__init__.py +3 -0
  65. convisoappsec/flowcli/__main__.py +4 -0
  66. convisoappsec/flowcli/assets/__init__.py +4 -0
  67. convisoappsec/flowcli/assets/create.py +88 -0
  68. convisoappsec/flowcli/assets/entrypoint.py +20 -0
  69. convisoappsec/flowcli/assets/ls.py +63 -0
  70. convisoappsec/flowcli/ast/__init__.py +3 -0
  71. convisoappsec/flowcli/ast/entrypoint.py +427 -0
  72. convisoappsec/flowcli/common.py +175 -0
  73. convisoappsec/flowcli/companies/__init__.py +0 -0
  74. convisoappsec/flowcli/companies/ls.py +25 -0
  75. convisoappsec/flowcli/container/__init__.py +3 -0
  76. convisoappsec/flowcli/container/entrypoint.py +17 -0
  77. convisoappsec/flowcli/container/run.py +306 -0
  78. convisoappsec/flowcli/context.py +49 -0
  79. convisoappsec/flowcli/deploy/__init__.py +0 -0
  80. convisoappsec/flowcli/deploy/create/__init__.py +4 -0
  81. convisoappsec/flowcli/deploy/create/context.py +12 -0
  82. convisoappsec/flowcli/deploy/create/entrypoint.py +31 -0
  83. convisoappsec/flowcli/deploy/create/with_/__init__.py +3 -0
  84. convisoappsec/flowcli/deploy/create/with_/entrypoint.py +20 -0
  85. convisoappsec/flowcli/deploy/create/with_/tag_tracker/__init__.py +4 -0
  86. convisoappsec/flowcli/deploy/create/with_/tag_tracker/context.py +11 -0
  87. convisoappsec/flowcli/deploy/create/with_/tag_tracker/entrypoint.py +30 -0
  88. convisoappsec/flowcli/deploy/create/with_/tag_tracker/sort_by/__init__.py +4 -0
  89. convisoappsec/flowcli/deploy/create/with_/tag_tracker/sort_by/entrypoint.py +21 -0
  90. convisoappsec/flowcli/deploy/create/with_/tag_tracker/sort_by/time_.py +84 -0
  91. convisoappsec/flowcli/deploy/create/with_/tag_tracker/sort_by/versioning_style.py +115 -0
  92. convisoappsec/flowcli/deploy/create/with_/values.py +133 -0
  93. convisoappsec/flowcli/entrypoint.py +103 -0
  94. convisoappsec/flowcli/environment_checker.py +45 -0
  95. convisoappsec/flowcli/findings/__init__.py +4 -0
  96. convisoappsec/flowcli/findings/create/__init__.py +4 -0
  97. convisoappsec/flowcli/findings/create/entrypoint.py +18 -0
  98. convisoappsec/flowcli/findings/create/with_/__init__.py +3 -0
  99. convisoappsec/flowcli/findings/create/with_/entrypoint.py +19 -0
  100. convisoappsec/flowcli/findings/create/with_/version_tracker.py +93 -0
  101. convisoappsec/flowcli/findings/entrypoint.py +19 -0
  102. convisoappsec/flowcli/findings/import_sarif/__init__.py +4 -0
  103. convisoappsec/flowcli/findings/import_sarif/entrypoint.py +430 -0
  104. convisoappsec/flowcli/help_option.py +18 -0
  105. convisoappsec/flowcli/iac/__init__.py +3 -0
  106. convisoappsec/flowcli/iac/entrypoint.py +17 -0
  107. convisoappsec/flowcli/iac/run.py +328 -0
  108. convisoappsec/flowcli/requirements_verifier.py +132 -0
  109. convisoappsec/flowcli/sast/__init__.py +3 -0
  110. convisoappsec/flowcli/sast/entrypoint.py +17 -0
  111. convisoappsec/flowcli/sast/run.py +485 -0
  112. convisoappsec/flowcli/sbom/__init__.py +3 -0
  113. convisoappsec/flowcli/sbom/entrypoint.py +17 -0
  114. convisoappsec/flowcli/sbom/generate.py +235 -0
  115. convisoappsec/flowcli/sca/__init__.py +3 -0
  116. convisoappsec/flowcli/sca/entrypoint.py +17 -0
  117. convisoappsec/flowcli/sca/run.py +479 -0
  118. convisoappsec/flowcli/vulnerability/__init__.py +3 -0
  119. convisoappsec/flowcli/vulnerability/assert_security_rules.py +201 -0
  120. convisoappsec/flowcli/vulnerability/container_vulnerability_manager.py +175 -0
  121. convisoappsec/flowcli/vulnerability/entrypoint.py +18 -0
  122. convisoappsec/flowcli/vulnerability/rules_schema.json +53 -0
  123. convisoappsec/flowcli/vulnerability/run.py +487 -0
  124. convisoappsec/logger.py +29 -0
  125. convisoappsec/sast/__init__.py +0 -0
  126. convisoappsec/sast/decision.py +45 -0
  127. convisoappsec/sast/sastbox.py +296 -0
  128. convisoappsec/version.py +1 -0
@@ -0,0 +1,212 @@
1
+ CREATE_ASSET = """
2
+ mutation (
3
+ $companyId: Int!,
4
+ $name: String!,
5
+ $scanType: AssetScan!
6
+ ) {
7
+ createAsset(
8
+ input: {
9
+ companyId: $companyId,
10
+ name: $name,
11
+ scanType: $scanType
12
+ }
13
+ ) {
14
+ asset {
15
+ id
16
+ name
17
+ createdAt
18
+ }
19
+ errors
20
+ }
21
+ }
22
+ """
23
+
24
+ UPDATE_ASSET = """
25
+ mutation (
26
+ $id: ID!,
27
+ $companyId: Int!,
28
+ $name: String!,
29
+ $tecnologyList: [String!],
30
+ $repoUrl: String
31
+ ) {
32
+ updateAsset(
33
+ input: {
34
+ id: $id,
35
+ companyId: $companyId,
36
+ name: $name,
37
+ tecnologyList: $tecnologyList,
38
+ repoUrl: $repoUrl
39
+ }
40
+ ) {
41
+ asset {
42
+ id
43
+ }
44
+ }
45
+ }
46
+ """
47
+
48
+ IMPORT_SBOM = """
49
+ mutation (
50
+ $file: Upload!,
51
+ $assetId: ID!,
52
+ $companyId: ID!
53
+ ) {
54
+ importSbom(
55
+ input: {
56
+ file: $file,
57
+ assetId: $assetId,
58
+ companyId: $companyId
59
+ }
60
+ ) {
61
+ success
62
+ }
63
+ }
64
+ """
65
+
66
+ IMPORT_CONTAINER = """
67
+ mutation (
68
+ $file: Upload!,
69
+ $assetId: ID!,
70
+ $companyId: ID!
71
+ ) {
72
+ importContainerFindingsFile(
73
+ input: {
74
+ file: $file,
75
+ assetId: $assetId,
76
+ companyId: $companyId
77
+ }
78
+ ) {
79
+ success
80
+ }
81
+ }
82
+ """
83
+
84
+ LOG_AST_ERROR = """
85
+ mutation (
86
+ $companyId: ID!,
87
+ $assetId: ID!,
88
+ $log: String!
89
+ ) {
90
+ logAstError(
91
+ input: {
92
+ companyId: $companyId,
93
+ assetId: $assetId,
94
+ log: $log
95
+ }
96
+ ) {
97
+ success
98
+ }
99
+ }
100
+ """
101
+
102
+ CREATE_DEPLOY = """
103
+ mutation (
104
+ $assetId: ID!,
105
+ $previousCommit: String!,
106
+ $currentCommit: String!,
107
+ $branchName: String,
108
+ $diffContent: Upload!,
109
+ $commitHistory: Upload!
110
+ ) {
111
+ createDeploy(
112
+ input: {
113
+ assetId: $assetId,
114
+ previousCommit: $previousCommit,
115
+ currentCommit: $currentCommit,
116
+ branchName: $branchName,
117
+ diffContent: $diffContent,
118
+ commitHistory: $commitHistory
119
+ }
120
+ ) {
121
+ deploy {
122
+ id
123
+ }
124
+ }
125
+ }
126
+ """
127
+
128
+ IMPORT_FINDINGS = """
129
+ mutation (
130
+ $file: Upload!,
131
+ $assetId: ID!,
132
+ $companyId: ID!
133
+ $vulnerabilityTypes: [Issue!]!
134
+ $deployId: ID
135
+ $commitRef: String
136
+ $controlSyncStatusId: ID
137
+ ) {
138
+ importAstFindingsFile(
139
+ input: {
140
+ file: $file,
141
+ assetId: $assetId,
142
+ companyId: $companyId,
143
+ vulnerabilityTypes: $vulnerabilityTypes,
144
+ deployId: $deployId,
145
+ commitRef: $commitRef
146
+ controlSyncStatusId: $controlSyncStatusId
147
+ }
148
+ ) {
149
+ success
150
+ }
151
+ }
152
+ """
153
+
154
+ CREATE_CONTROL_SYNC_STATUS = """
155
+ mutation ($assetId: ID!) {
156
+ createControlSyncStatus(
157
+ input: {
158
+ assetId: $assetId,
159
+ integration: CONVISO_AST,
160
+ externalVulnerabilityCount: 0
161
+ }
162
+ ) {
163
+ controlSyncStatus {
164
+ id
165
+ }
166
+ success
167
+ }
168
+ }
169
+ """
170
+
171
+ UPDATE_CONTROL_SYNC_STATUS = """
172
+ mutation (
173
+ $id: ID!
174
+ $externalVulnerabilityCount: Int!
175
+ ) {
176
+ updateControlSyncStatus(
177
+ input: {
178
+ id: $id
179
+ externalVulnerabilityCount: $externalVulnerabilityCount
180
+ }
181
+ ) {
182
+ controlSyncStatus {
183
+ id
184
+ }
185
+ }
186
+ }
187
+ """
188
+
189
+ INCREASE_ISSUE_SCAN_COUNT = """
190
+ mutation (
191
+ $controlSyncStatusId: ID!
192
+ $assetId: ID!
193
+ $successCount: Int
194
+ $failureCount: Int
195
+ $failureReason: String
196
+ ) {
197
+ increaseIssueScanCount(
198
+ input: {
199
+ controlSyncStatusId: $controlSyncStatusId
200
+ assetId: $assetId
201
+ successCount: $successCount
202
+ failureCount: $failureCount
203
+ failureReason: $failureReason
204
+ integration: CONVISO_AST
205
+ }
206
+ ) {
207
+ controlSyncStatus {
208
+ id
209
+ }
210
+ }
211
+ }
212
+ """
@@ -0,0 +1,180 @@
1
+ GET_ASSETS = """
2
+ query (
3
+ $id: ID!,
4
+ $name: String!,
5
+ $page: Int,
6
+ $limit: Int
7
+ ) {
8
+ assets(
9
+ companyId: $id
10
+ page: $page
11
+ limit: $limit
12
+ search: {
13
+ name: $name
14
+ }
15
+ ) {
16
+ collection {
17
+ id
18
+ name
19
+ createdAt
20
+ projects(includeAst: true) {
21
+ type
22
+ apiCode
23
+ label
24
+ }
25
+ }
26
+
27
+ metadata {
28
+ currentPage
29
+ limitValue
30
+ totalCount
31
+ totalPages
32
+ }
33
+ }
34
+ }
35
+ """
36
+
37
+ GET_ISSUES_STATS = """
38
+ query (
39
+ $asset_id: [ID!],
40
+ $company_id: ID!,
41
+ $statuses: [IssueStatusLabel!],
42
+ $end_date: ISO8601DateTime
43
+ ) {
44
+ issuesStats(
45
+ companyId: $company_id
46
+ filters: {
47
+ assetIds: $asset_id
48
+ statuses: $statuses
49
+ createdAtRange: {
50
+ endDate: $end_date
51
+ }
52
+ }
53
+ ) {
54
+ severities {
55
+ value
56
+ count
57
+ }
58
+ }
59
+ }
60
+ """
61
+
62
+ GET_PROJECTS = """
63
+ query (
64
+ $project_code: String!,
65
+ $project_label: String!,
66
+ $company_id: ID!,
67
+ $page: Int,
68
+ $limit: Int
69
+ ) {
70
+ projects(
71
+ page: $page
72
+ limit: $limit
73
+ params: {
74
+ apiCodeEq: $project_code
75
+ labelEq: $project_label
76
+ scopeIdEq: $company_id
77
+ showHidden: true
78
+ projectTypeLabelEq: "ast"
79
+ }
80
+ ) {
81
+ collection {
82
+ id
83
+ apiCode
84
+ assets {
85
+ id
86
+ name
87
+ }
88
+ company {
89
+ id
90
+ customFeatures
91
+ }
92
+ }
93
+ metadata {
94
+ currentPage
95
+ limitValue
96
+ totalCount
97
+ totalPages
98
+ }
99
+ }
100
+ }
101
+ """
102
+
103
+ GET_COMPANY = """
104
+ query get_company($company_id: ID!) {
105
+ company(id: $company_id) {
106
+ id
107
+ label
108
+ customFeatures
109
+ }
110
+ }
111
+ """
112
+
113
+ GET_COMPANIES = """
114
+ query Companies {
115
+ companies (
116
+ limit: 50,
117
+ order: label,
118
+ orderType: ASC
119
+ ) {
120
+ collection {
121
+ id
122
+ label
123
+ customFeatures
124
+ }
125
+ }
126
+ }
127
+ """
128
+
129
+ GET_ISSUES_FINGERPRINT = """
130
+ query GetIssuesFingerprint(
131
+ $company_id: ID!,
132
+ $page: Int,
133
+ $per_page: Int,
134
+ $asset_id: [ID!],
135
+ $statuses: [IssueStatusLabel!]
136
+ $failure_types: [Issue!]
137
+ ) {
138
+ issues(
139
+ companyId: $company_id,
140
+ pagination: {
141
+ page: $page,
142
+ perPage: $per_page
143
+ },
144
+ filters: {
145
+ assetIds: $asset_id,
146
+ statuses: $statuses,
147
+ failureTypes: $failure_types
148
+ }
149
+ ) {
150
+ collection {
151
+ id
152
+ type
153
+ ... on FindingInterface {
154
+ originalIssueIdFromTool
155
+ scanSource
156
+ }
157
+ status
158
+ }
159
+ metadata {
160
+ totalCount
161
+ totalPages
162
+ }
163
+ }
164
+ }
165
+ """
166
+
167
+ GET_DEPLOYS_BY_ASSET = """
168
+ query GetDeploysByAsset(
169
+ $asset_id: ID!
170
+ ) {
171
+ deploysByAsset(
172
+ assetId: $asset_id
173
+ ) {
174
+ collection {
175
+ currentCommit
176
+ previousCommit
177
+ }
178
+ }
179
+ }
180
+ """
@@ -0,0 +1,9 @@
1
+ from .source_code_scanner import SourceCodeScanner # noqa
2
+ from .exceptions import SourceCodeScannerException # noqa
3
+ from .scc import SCC # noqa
4
+
5
+ __all_ = [
6
+ 'SourceCodeScanner',
7
+ 'SourceCodeScannerException',
8
+ 'SCC'
9
+ ]
@@ -0,0 +1,2 @@
1
+ class SourceCodeScannerException(RuntimeError):
2
+ pass
@@ -0,0 +1,68 @@
1
+ import yaml
2
+ import tempfile
3
+
4
+ from .source_code_scanner import SourceCodeScanner
5
+ from .exceptions import SourceCodeScannerException
6
+
7
+
8
+ class SCC(SourceCodeScanner):
9
+
10
+ def __init__(
11
+ self,
12
+ source_code_dir,
13
+ container_source_dir = '/code',
14
+ create_source_code_volume = True
15
+ ):
16
+ super().__init__(
17
+ source_code_dir,
18
+ create_source_code_volume=create_source_code_volume
19
+ )
20
+ self.__scan_result = {}
21
+ self.__container_source_dir = container_source_dir
22
+
23
+ @property
24
+ def repository(self):
25
+ return 'convisoappsec/scc'
26
+
27
+ @property
28
+ def tag(self):
29
+ return 'latest'
30
+
31
+ @property
32
+ def container_source_dir(self):
33
+ return self.__container_source_dir
34
+
35
+ def _read_scan_stdout(self, stdout_generator):
36
+ with tempfile.TemporaryFile() as yaml_output:
37
+ for chunk in stdout_generator:
38
+ yaml_output.write(chunk)
39
+
40
+ yaml_output.seek(0)
41
+
42
+ self.__scan_result = yaml.load(
43
+ yaml_output,
44
+ Loader=yaml.FullLoader
45
+ )
46
+
47
+ @property
48
+ def summary(self):
49
+ summary = self.__scan_result.get('SUM')
50
+ if not summary:
51
+ raise SourceCodeScannerException(
52
+ 'Unexpected error retrienving source code summary metrics'
53
+ )
54
+
55
+ return summary
56
+
57
+ @property
58
+ def total_source_code_lines(self):
59
+ return self.summary.get('code')
60
+
61
+ @property
62
+ def command(self):
63
+ return [
64
+ '--no-cocomo',
65
+ '--no-complexity',
66
+ '--format',
67
+ 'cloc-yaml'
68
+ ]
@@ -0,0 +1,177 @@
1
+ import docker
2
+ from contextlib import suppress
3
+ import tempfile
4
+ from uuid import uuid4
5
+
6
+ from convisoappsec.flow.util import SourceCodeCompressor
7
+ from .exceptions import SourceCodeScannerException
8
+
9
+
10
+ class SourceCodeScanner(object):
11
+ SUCCESS_EXIT_CODE = 0
12
+ '''
13
+ hooks:
14
+ def _pre_pull(self):
15
+ :return: void
16
+
17
+ def _capture_stdout(self, stdout_bytes)
18
+ :param stdout_bytes: chunks generated by stdout
19
+ :paramtype stdout_bytes: bytes
20
+ :return: void
21
+ _pre_scan
22
+ _scan_stdout
23
+ _post_scan
24
+ '''
25
+
26
+ def __init__(self, source_code_dir, create_source_code_volume = True):
27
+ uuid = str(uuid4())
28
+ self.docker = docker.from_env(version="auto")
29
+ self.__container_name = "source_code_scanner_{0}".format(
30
+ uuid
31
+ )
32
+ self.__source_code_dir = source_code_dir
33
+ self.__create_source_code_volume = create_source_code_volume
34
+
35
+ if self.__create_source_code_volume:
36
+ self.__source_code_volume_name = "source_code_scanner_src_{0}".format(
37
+ uuid
38
+ )
39
+ else:
40
+ self.__source_code_volume_name = None
41
+
42
+ @property
43
+ def repository(self):
44
+ raise Exception('Not implemented yet!')
45
+
46
+ @property
47
+ def tag(self):
48
+ raise Exception('Not implemented yet!')
49
+
50
+ @property
51
+ def command(self):
52
+ raise Exception('Not implemented yet!')
53
+
54
+ @property
55
+ def container_source_dir(self):
56
+ raise Exception('Not implemented yet!')
57
+
58
+ @property
59
+ def image(self):
60
+ return "{repository}:{tag}".format(
61
+ repository=self.repository,
62
+ tag=self.tag,
63
+ )
64
+
65
+ @property
66
+ def volumes(self):
67
+ if not self.__create_source_code_volume:
68
+ return {}
69
+
70
+ return {
71
+ self.__source_code_volume_name: {
72
+ 'bind': self.container_source_dir,
73
+ 'mode': 'rw',
74
+ }
75
+ }
76
+
77
+ def __get_container(self):
78
+ return self.docker.containers.get(
79
+ self.__container_name
80
+ )
81
+
82
+ def __get_source_code_volume(self):
83
+ return self.docker.volumes.get(
84
+ self.__source_code_volume_name
85
+ )
86
+
87
+ @property
88
+ def __container(self):
89
+ try:
90
+ return self.__get_container()
91
+ except docker.errors.NotFound:
92
+ return self.__create_container()
93
+
94
+ def __create_container(self):
95
+ return self.docker.containers.create(
96
+ self.image,
97
+ name=self.__container_name,
98
+ volumes=self.volumes,
99
+ detach=True,
100
+ command=self.command,
101
+ working_dir=self.container_source_dir if self.container_source_dir != '/code' else '/code'
102
+ )
103
+
104
+ def __pull_image(self):
105
+ if self.has_pre_pull:
106
+ self._pre_pull()
107
+
108
+ self.docker.images.pull(self.repository, self.tag)
109
+
110
+ def __load_source_code(self):
111
+ container = self.__container
112
+
113
+ with tempfile.TemporaryFile() as fileobj:
114
+ compressor = SourceCodeCompressor(
115
+ self.__source_code_dir
116
+ )
117
+
118
+ compressor.write_to(fileobj)
119
+ fileobj.seek(0)
120
+
121
+ container.put_archive(
122
+ self.container_source_dir,
123
+ fileobj
124
+ )
125
+
126
+ def scan(self):
127
+ self.__pull_image()
128
+ self.__load_source_code()
129
+ container = self.__container
130
+
131
+ container.start()
132
+
133
+ if self.has_read_scan_stderr:
134
+ self._read_scan_stderr(
135
+ container.logs(
136
+ stream=True, stdout=False, stderr=True
137
+ )
138
+ )
139
+
140
+ if self.has_read_scan_stdout:
141
+ self._read_scan_stdout(
142
+ container.logs(
143
+ stream=True, stdout=True, stderr=False
144
+ )
145
+ )
146
+
147
+ wait_result = container.wait()
148
+ status_code = wait_result.get('StatusCode')
149
+
150
+ if not status_code == self.SUCCESS_EXIT_CODE:
151
+ raise SourceCodeScannerException(
152
+ 'Source code scanning fail'
153
+ )
154
+
155
+ def __has_method(self, method_name):
156
+ return hasattr(self, method_name)
157
+
158
+ @property
159
+ def has_read_scan_stdout(self):
160
+ return self.__has_method('_read_scan_stdout')
161
+
162
+ @property
163
+ def has_read_scan_stderr(self):
164
+ return self.__has_method('_read_scan_stderr')
165
+
166
+ @property
167
+ def has_pre_pull(self):
168
+ return self.__has_method('_pre_pull')
169
+
170
+ def __del__(self):
171
+ with suppress(Exception):
172
+ container = self.__get_container()
173
+ container.remove()
174
+
175
+ with suppress(Exception):
176
+ source_code_volume = self.__get_source_code_volume()
177
+ source_code_volume.remove()
@@ -0,0 +1,7 @@
1
+ from .source_code_compressor import SourceCodeCompressor
2
+ from .metrics import project_metrics
3
+
4
+ __all__ = [
5
+ 'SourceCodeCompressor',
6
+ 'project_metrics',
7
+ ]