From d7a1508b8e9ee3e9d6c2d1c4c8f68968ac7a9529 Mon Sep 17 00:00:00 2001 From: abhisek Date: Fri, 27 Sep 2024 08:15:21 +0530 Subject: [PATCH 01/28] refactor: Remove OpenAPI specs for deprecated control API and use gRPC report sync client --- Makefile | 6 - api/cp-v1-trials.yml | 123 ----- api/cp-v1.yml | 113 ----- api/sync-v1.yml | 1015 ----------------------------------------- auth.go | 2 +- go.mod | 14 +- go.sum | 130 ++---- internal/auth/auth.go | 26 +- pkg/reporter/sync.go | 391 +++------------- scan.go | 10 +- 10 files changed, 155 insertions(+), 1675 deletions(-) delete mode 100644 api/cp-v1-trials.yml delete mode 100644 api/cp-v1.yml delete mode 100644 api/sync-v1.yml diff --git a/Makefile b/Makefile index 2c7e9fe..a8fca75 100644 --- a/Makefile +++ b/Makefile @@ -18,12 +18,6 @@ dev-setup: linter-install oapi-codegen-install protoc-install oapi-codegen: oapi-codegen -package insightapi -generate types ./api/insights-v1.yml > ./gen/insightapi/insights.types.go oapi-codegen -package insightapi -generate client ./api/insights-v1.yml > ./gen/insightapi/insights.client.go - oapi-codegen -package cpv1trials -generate types ./api/cp-v1-trials.yml > ./gen/cpv1trials/trials.types.go - oapi-codegen -package cpv1trials -generate client ./api/cp-v1-trials.yml > ./gen/cpv1trials/trials.client.go - oapi-codegen -package cpv1 -generate types ./api/cp-v1.yml > ./gen/cpv1/cp.types.go - oapi-codegen -package cpv1 -generate client ./api/cp-v1.yml > ./gen/cpv1/cp.client.go - oapi-codegen -package syncv1 -generate types ./api/sync-v1.yml > ./gen/syncv1/sync.types.go - oapi-codegen -package syncv1 -generate client ./api/sync-v1.yml > ./gen/syncv1/sync.client.go protoc-codegen: protoc -I ./api \ diff --git a/api/cp-v1-trials.yml b/api/cp-v1-trials.yml deleted file mode 100644 index 7890dab..0000000 --- a/api/cp-v1-trials.yml +++ /dev/null @@ -1,123 +0,0 @@ -openapi: 3.0.2 -info: - title: SafeDep Control Plane API for Trials Registration - contact: - name: SafeDep API - url: 'https://safedep.io' - description: | - Trials API provide a way for obtaining an API Key for data plane service access - using an Email Address. Trials is different from Registrations as the later - allows full access to the control plane while Trials is meant to allow access - only to a time bounded (expirable) API key for quick evaluation of tools. - version: 0.0.1 -servers: - - url: 'https://{apiHost}/{apiBase}' - variables: - apiHost: - default: api.safedep.io - apiBase: - default: control-plane/v1 -tags: - - name: Control Plane - description: Control Plane API -paths: - /trials: - post: - description: | - Register a trial user to obtain an expirable API Key. The API key will - be generated and sent to the user over Email to ensure validity and access - to the email by the requester. System defined limits will be applied to - maximum number of trial API keys that can be generated for an email. - operationId: registerTrialUser - tags: - - Control Plane - requestBody: - description: Trial registration request - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/TrialRequest' - responses: - '201': - description: Successfully created an API key request - content: - application/json: - schema: - $ref: '#/components/schemas/TrialResponse' - '403': - description: Access to the API is denied - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '429': - description: Rate limit block - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '500': - description: Failed due to internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' -components: - schemas: - ApiError: - type: object - properties: - message: - type: string - description: A descriptive message about the error meant for developer consumption - type: - type: string - description: An optional service or domain specific error group - enum: - - invalid_request - - operation_failed - - internal_error - code: - type: string - description: An error code identifying the error - enum: - - api_guard_invalid_credentials - - api_guard_rate_limit_exceeded - - api_guard_unauthorized - - api_guard_error - - app_generic_error - - app_security_error - - app_insufficient_parameters - - app_feature_not_enabled - - app_package_version_not_found - params: - type: object - description: Optional error specific attributes - additionalProperties: - type: object - properties: - key: - type: string - value: - type: string - TrialRequest: - type: object - properties: - email: - type: string - format: email - required: - - email - TrialResponse: - type: object - properties: - id: - type: string - minLength: 6 - maxLength: 512 - description: The ID of the trial registration request created in the system - expires_at: - type: string - format: date-time - description: The expiry time of the API key diff --git a/api/cp-v1.yml b/api/cp-v1.yml deleted file mode 100644 index ccff190..0000000 --- a/api/cp-v1.yml +++ /dev/null @@ -1,113 +0,0 @@ -openapi: 3.0.2 -info: - title: SafeDep Control Plane API - contact: - name: SafeDep API - url: 'https://safedep.io' - description: | - The SafeDep Control Plane API provides configuration and management plane - access to clients for the SafeDep platform - version: 0.0.1 -servers: - - url: 'https://{apiHost}/{apiBase}' - variables: - apiHost: - default: api.safedep.io - apiBase: - default: control-plane/v1 -tags: - - name: Control Plane - description: Control Plane API -paths: - /auths/me: - get: - description: | - Introspection API for getting configuration information associated - with the supplied API credentials - operationId: getApiCredentialIntrospection - tags: - - Control Plane - responses: - '200': - description: API credentials introspection information - content: - application/json: - schema: - $ref: '#/components/schemas/CredentialIntrospectionResponse' - '403': - description: Access to the API is denied - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '429': - description: Rate limit block - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '500': - description: Failed due to internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' -components: - securitySchemes: - api_key: - type: apiKey - name: Authorization - in: header - schemas: - ApiError: - type: object - properties: - message: - type: string - description: A descriptive message about the error meant for developer consumption - type: - type: string - description: An optional service or domain specific error group - enum: - - invalid_request - - operation_failed - - internal_error - code: - type: string - description: An error code identifying the error - enum: - - api_guard_invalid_credentials - - api_guard_rate_limit_exceeded - - api_guard_unauthorized - - api_guard_error - - app_generic_error - - app_security_error - - app_insufficient_parameters - - app_feature_not_enabled - - app_package_version_not_found - params: - type: object - description: Optional error specific attributes - additionalProperties: - type: object - properties: - key: - type: string - value: - type: string - CredentialIntrospectionResponse: - type: object - properties: - type: - type: string - description: The entity type to which this credential belongs to - enum: - - TrialUser - - Organization - - Team - - User - expiry: - type: string - description: Expiry timestamp in RFC3399 format if expirable - required: - - type diff --git a/api/sync-v1.yml b/api/sync-v1.yml deleted file mode 100644 index aae60b1..0000000 --- a/api/sync-v1.yml +++ /dev/null @@ -1,1015 +0,0 @@ -openapi: 3.0.2 -info: - title: SafeDep Tool Data Synchronizations API - contact: - name: SafeDep API - url: 'https://safedep.io' - description: | - Synchronizations API can be used to sync tool (e.g. vet) generated - data to SafeDep cloud for platform users. - version: 0.0.1 -servers: - - url: 'https://{apiHost}/{apiBase}' - variables: - apiHost: - default: api.safedep.io - apiBase: - default: sync/v1 -tags: - - name: Data Plane - description: Synchronizations API -paths: - /jobs: - post: - description: | - Create a new data sync (upload) job with context information. - This API is intended for scanners like `vet` to upload scan - reports to SafeDep platform. - operationId: createSyncJob - tags: - - Data Plane - requestBody: - description: Job parameters - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateJobRequest' - responses: - '201': - description: Job is created - content: - application/json: - schema: - $ref: '#/components/schemas/AnyJobResponse' - '403': - description: Access to the API is denied - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '429': - description: Rate limit block - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '500': - description: Failed due to internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '/jobs/{job_id}': - put: - description: | - Update a Job status - operationId: updateSyncJob - tags: - - Data Plane - parameters: - - in: path - name: job_id - schema: - type: string - required: true - description: Job ID to update - requestBody: - description: Job parameters - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateJobRequest' - responses: - '200': - description: Job is updated - content: - application/json: - schema: - $ref: '#/components/schemas/AnyJobResponse' - '403': - description: Access to the API is denied - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '429': - description: Rate limit block - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '500': - description: Failed due to internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '/jobs/{job_id}/issues': - post: - description: Create and associate an Issue with this Job - operationId: createJobIssue - tags: - - Data Plane - parameters: - - in: path - name: job_id - schema: - type: string - required: true - description: Job ID to link the issue - requestBody: - description: Job parameters - required: true - content: - application/json: - schema: - oneOf: - - $ref: '#/components/schemas/IssuePackageVulnerability' - - $ref: '#/components/schemas/IssuePackageDependency' - - $ref: '#/components/schemas/IssuePackageLicense' - - $ref: '#/components/schemas/IssuePackageSource' - - $ref: '#/components/schemas/IssuePackageScorecard' - discriminator: - propertyName: issue_type - responses: - '201': - description: Issue is created for a job - content: - application/json: - schema: - $ref: '#/components/schemas/CreateIssueResponse' - '403': - description: Access to the API is denied - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '429': - description: Rate limit block - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' - '500': - description: Failed due to internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/ApiError' -components: - securitySchemes: - api_key: - type: apiKey - name: Authorization - in: header - schemas: - ApiError: - type: object - properties: - message: - type: string - description: A descriptive message about the error meant for developer consumption - type: - type: string - description: An optional service or domain specific error group - enum: - - invalid_request - - operation_failed - - internal_error - code: - type: string - description: An error code identifying the error - enum: - - api_guard_invalid_credentials - - api_guard_rate_limit_exceeded - - api_guard_unauthorized - - api_guard_error - - app_generic_error - - app_security_error - - app_insufficient_parameters - - app_feature_not_enabled - - app_package_version_not_found - params: - type: object - description: Optional error specific attributes - additionalProperties: - type: object - properties: - key: - type: string - value: - type: string - CreateJobRequest: - type: object - properties: - tool_type: - type: string - description: The type of tool creating this job - enum: - - oss_vet - tool_name: - type: string - tool_version: - type: string - trigger_event: - type: string - description: The event that triggered the tool - enum: - - git_scm_push - - git_scm_pull_request - - git_scm_tag_release - - manual - - scheduled - - other - project_name: - type: string - description: The name of the project to associate the job - project_source: - type: string - description: The source of this project - enum: - - github - - gitlab - - bitbucket - - generic_ci - - other - stream_name: - type: string - description: The stream name against which is job and its issues to attach - git_ref: - type: string - description: Git reference path (e.g. refs/heads/main) - git_ref_name: - type: string - description: The based name of a git ref such as `branchName` or `tagName` - git_ref_type: - type: string - description: Git ref type that triggered the scan - enum: - - git_branch - - git_tag - git_sha: - type: string - required: - - project_name - - project_source - - stream_name - - tool_type - - tool_name - - tool_version - - trigger_event - Job: - type: object - properties: - status: - type: string - enum: - - new - - running - - paused - - complete - - error - - timeout - UpdateJobRequest: - allOf: - - $ref: '#/components/schemas/Job' - - type: object - properties: - policy_status: - type: string - enum: - - unknown - - fail - - pass - - error - AnyJobResponse: - allOf: - - $ref: '#/components/schemas/Job' - - type: object - properties: - id: - type: string - description: The Job ID to use for all subsequent job operation - CreateIssueResponse: - type: object - properties: - id: - type: string - required: - - id - Issue: - type: object - properties: - issue_type: - type: string - enum: - - package_vulnerability - - package_dependency - - package_source_info - - package_license - - package_openssf_scorecard - required: - - issue_type - discriminator: - propertyName: issue_type - PackageIssue: - allOf: - - $ref: '#/components/schemas/Issue' - - type: object - description: Represents an issue affecting a package - properties: - manifest_path: - type: string - manifest_ecosystem: - type: string - description: Case insensitive ecosystem name - enum: - - Maven - - RubyGems - - Go - - npm - - PyPI - - Cargo - - NuGet - - Linux - - Debian - - Github Actions - package_name: - type: string - package_version: - type: string - IssuePackageCommonVulnerability: - type: object - description: | - Subset of OSV schema required to perform policy - decision by various tools - properties: - id: - type: string - description: Vulnerability identifier - summary: - type: string - description: Short summary of vulnerability - aliases: - type: array - items: - type: string - description: | - Alias identifiers of the same vulnerability in - other databases - related: - type: array - items: - type: string - description: | - Related vulnerability identifiers for similar issues - severities: - type: array - items: - type: object - properties: - type: - type: string - enum: - - UNSPECIFIED - - CVSS_V3 - - CVSS_V2 - score: - type: string - description: Type specific vulnerability score - risk: - type: string - enum: - - CRITICAL - - HIGH - - MEDIUM - - LOW - - UNKNOWN - description: Normalized risk rating computed from score - IssuePackageVulnerability: - allOf: - - $ref: '#/components/schemas/PackageIssue' - - type: object - properties: - vulnerability: - $ref: '#/components/schemas/IssuePackageCommonVulnerability' - IssuePackageDependency: - allOf: - - $ref: '#/components/schemas/PackageIssue' - - type: object - properties: - parent_package_name: - type: string - parent_package_version: - type: string - IssuePackageSource: - allOf: - - $ref: '#/components/schemas/PackageIssue' - - type: object - properties: - source_type: - type: string - enum: - - github - - gitlab - - bitbucket - - private - - other - source_url: - type: string - source_stars: - type: integer - source_forks: - type: integer - source_name: - type: string - source_display_name: - type: string - IssuePackageLicense: - allOf: - - $ref: '#/components/schemas/PackageIssue' - - type: object - properties: - license_id: - type: string - description: License SPDX code - enum: - - 0BSD - - AAL - - Abstyles - - Adobe-2006 - - Adobe-Glyph - - ADSL - - AFL-1.1 - - AFL-1.2 - - AFL-2.0 - - AFL-2.1 - - AFL-3.0 - - Afmparse - - AGPL-1.0 - - AGPL-1.0-only - - AGPL-1.0-or-later - - AGPL-3.0 - - AGPL-3.0-only - - AGPL-3.0-or-later - - Aladdin - - AMDPLPA - - AML - - AMPAS - - ANTLR-PD - - ANTLR-PD-fallback - - Apache-1.0 - - Apache-1.1 - - Apache-2.0 - - APAFML - - APL-1.0 - - App-s2p - - APSL-1.0 - - APSL-1.1 - - APSL-1.2 - - APSL-2.0 - - Arphic-1999 - - Artistic-1.0 - - Artistic-1.0-cl8 - - Artistic-1.0-Perl - - Artistic-2.0 - - Baekmuk - - Bahyph - - Barr - - Beerware - - Bitstream-Vera - - BitTorrent-1.0 - - BitTorrent-1.1 - - blessing - - BlueOak-1.0.0 - - Borceux - - BSD-1-Clause - - BSD-2-Clause - - BSD-2-Clause-FreeBSD - - BSD-2-Clause-NetBSD - - BSD-2-Clause-Patent - - BSD-2-Clause-Views - - BSD-3-Clause - - BSD-3-Clause-Attribution - - BSD-3-Clause-Clear - - BSD-3-Clause-LBNL - - BSD-3-Clause-Modification - - BSD-3-Clause-No-Military-License - - BSD-3-Clause-No-Nuclear-License - - BSD-3-Clause-No-Nuclear-License-2014 - - BSD-3-Clause-No-Nuclear-Warranty - - BSD-3-Clause-Open-MPI - - BSD-4-Clause - - BSD-4-Clause-Shortened - - BSD-4-Clause-UC - - BSD-Protection - - BSD-Source-Code - - BSL-1.0 - - BUSL-1.1 - - bzip2-1.0.5 - - bzip2-1.0.6 - - C-UDA-1.0 - - CAL-1.0 - - CAL-1.0-Combined-Work-Exception - - Caldera - - CATOSL-1.1 - - CC-BY-1.0 - - CC-BY-2.0 - - CC-BY-2.5 - - CC-BY-2.5-AU - - CC-BY-3.0 - - CC-BY-3.0-AT - - CC-BY-3.0-DE - - CC-BY-3.0-IGO - - CC-BY-3.0-NL - - CC-BY-3.0-US - - CC-BY-4.0 - - CC-BY-NC-1.0 - - CC-BY-NC-2.0 - - CC-BY-NC-2.5 - - CC-BY-NC-3.0 - - CC-BY-NC-3.0-DE - - CC-BY-NC-4.0 - - CC-BY-NC-ND-1.0 - - CC-BY-NC-ND-2.0 - - CC-BY-NC-ND-2.5 - - CC-BY-NC-ND-3.0 - - CC-BY-NC-ND-3.0-DE - - CC-BY-NC-ND-3.0-IGO - - CC-BY-NC-ND-4.0 - - CC-BY-NC-SA-1.0 - - CC-BY-NC-SA-2.0 - - CC-BY-NC-SA-2.0-FR - - CC-BY-NC-SA-2.0-UK - - CC-BY-NC-SA-2.5 - - CC-BY-NC-SA-3.0 - - CC-BY-NC-SA-3.0-DE - - CC-BY-NC-SA-3.0-IGO - - CC-BY-NC-SA-4.0 - - CC-BY-ND-1.0 - - CC-BY-ND-2.0 - - CC-BY-ND-2.5 - - CC-BY-ND-3.0 - - CC-BY-ND-3.0-DE - - CC-BY-ND-4.0 - - CC-BY-SA-1.0 - - CC-BY-SA-2.0 - - CC-BY-SA-2.0-UK - - CC-BY-SA-2.1-JP - - CC-BY-SA-2.5 - - CC-BY-SA-3.0 - - CC-BY-SA-3.0-AT - - CC-BY-SA-3.0-DE - - CC-BY-SA-4.0 - - CC-PDDC - - CC0-1.0 - - CDDL-1.0 - - CDDL-1.1 - - CDL-1.0 - - CDLA-Permissive-1.0 - - CDLA-Permissive-2.0 - - CDLA-Sharing-1.0 - - CECILL-1.0 - - CECILL-1.1 - - CECILL-2.0 - - CECILL-2.1 - - CECILL-B - - CECILL-C - - CERN-OHL-1.1 - - CERN-OHL-1.2 - - CERN-OHL-P-2.0 - - CERN-OHL-S-2.0 - - CERN-OHL-W-2.0 - - checkmk - - ClArtistic - - CNRI-Jython - - CNRI-Python - - CNRI-Python-GPL-Compatible - - COIL-1.0 - - Community-Spec-1.0 - - Condor-1.1 - - copyleft-next-0.3.0 - - copyleft-next-0.3.1 - - CPAL-1.0 - - CPL-1.0 - - CPOL-1.02 - - Crossword - - CrystalStacker - - CUA-OPL-1.0 - - Cube - - curl - - D-FSL-1.0 - - diffmark - - DL-DE-BY-2.0 - - DOC - - Dotseqn - - DRL-1.0 - - DSDP - - dvipdfm - - ECL-1.0 - - ECL-2.0 - - eCos-2.0 - - EFL-1.0 - - EFL-2.0 - - eGenix - - Elastic-2.0 - - Entessa - - EPICS - - EPL-1.0 - - EPL-2.0 - - ErlPL-1.1 - - etalab-2.0 - - EUDatagrid - - EUPL-1.0 - - EUPL-1.1 - - EUPL-1.2 - - Eurosym - - Fair - - FDK-AAC - - Frameworx-1.0 - - FreeBSD-DOC - - FreeImage - - FSFAP - - FSFUL - - FSFULLR - - FSFULLRWD - - FTL - - GD - - GFDL-1.1 - - GFDL-1.1-invariants-only - - GFDL-1.1-invariants-or-later - - GFDL-1.1-no-invariants-only - - GFDL-1.1-no-invariants-or-later - - GFDL-1.1-only - - GFDL-1.1-or-later - - GFDL-1.2 - - GFDL-1.2-invariants-only - - GFDL-1.2-invariants-or-later - - GFDL-1.2-no-invariants-only - - GFDL-1.2-no-invariants-or-later - - GFDL-1.2-only - - GFDL-1.2-or-later - - GFDL-1.3 - - GFDL-1.3-invariants-only - - GFDL-1.3-invariants-or-later - - GFDL-1.3-no-invariants-only - - GFDL-1.3-no-invariants-or-later - - GFDL-1.3-only - - GFDL-1.3-or-later - - Giftware - - GL2PS - - Glide - - Glulxe - - GLWTPL - - gnuplot - - GPL-1.0 - - GPL-1.0+ - - GPL-1.0-only - - GPL-1.0-or-later - - GPL-2.0 - - GPL-2.0+ - - GPL-2.0-only - - GPL-2.0-or-later - - GPL-2.0-with-autoconf-exception - - GPL-2.0-with-bison-exception - - GPL-2.0-with-classpath-exception - - GPL-2.0-with-font-exception - - GPL-2.0-with-GCC-exception - - GPL-3.0 - - GPL-3.0+ - - GPL-3.0-only - - GPL-3.0-or-later - - GPL-3.0-with-autoconf-exception - - GPL-3.0-with-GCC-exception - - gSOAP-1.3b - - HaskellReport - - Hippocratic-2.1 - - HPND - - HPND-sell-variant - - HTMLTIDY - - IBM-pibs - - ICU - - IJG - - ImageMagick - - iMatix - - Imlib2 - - Info-ZIP - - Intel - - Intel-ACPI - - Interbase-1.0 - - IPA - - IPL-1.0 - - ISC - - Jam - - JasPer-2.0 - - JPNIC - - JSON - - Knuth-CTAN - - LAL-1.2 - - LAL-1.3 - - Latex2e - - Leptonica - - LGPL-2.0 - - LGPL-2.0+ - - LGPL-2.0-only - - LGPL-2.0-or-later - - LGPL-2.1 - - LGPL-2.1+ - - LGPL-2.1-only - - LGPL-2.1-or-later - - LGPL-3.0 - - LGPL-3.0+ - - LGPL-3.0-only - - LGPL-3.0-or-later - - LGPLLR - - Libpng - - libpng-2.0 - - libselinux-1.0 - - libtiff - - libutil-David-Nugent - - LiLiQ-P-1.1 - - LiLiQ-R-1.1 - - LiLiQ-Rplus-1.1 - - Linux-man-pages-copyleft - - Linux-OpenIB - - LOOP - - LPL-1.0 - - LPL-1.02 - - LPPL-1.0 - - LPPL-1.1 - - LPPL-1.2 - - LPPL-1.3a - - LPPL-1.3c - - LZMA-SDK-9.11-to-9.20 - - LZMA-SDK-9.22 - - MakeIndex - - Minpack - - MirOS - - MIT - - MIT-0 - - MIT-advertising - - MIT-CMU - - MIT-enna - - MIT-feh - - MIT-Modern-Variant - - MIT-open-group - - MITNFA - - Motosoto - - mpi-permissive - - mpich2 - - MPL-1.0 - - MPL-1.1 - - MPL-2.0 - - MPL-2.0-no-copyleft-exception - - mplus - - MS-LPL - - MS-PL - - MS-RL - - MTLL - - MulanPSL-1.0 - - MulanPSL-2.0 - - Multics - - Mup - - NAIST-2003 - - NASA-1.3 - - Naumen - - NBPL-1.0 - - NCGL-UK-2.0 - - NCSA - - Net-SNMP - - NetCDF - - Newsletr - - NGPL - - NICTA-1.0 - - NIST-PD - - NIST-PD-fallback - - NLOD-1.0 - - NLOD-2.0 - - NLPL - - Nokia - - NOSL - - Noweb - - NPL-1.0 - - NPL-1.1 - - NPOSL-3.0 - - NRL - - NTP - - NTP-0 - - Nunit - - O-UDA-1.0 - - OCCT-PL - - OCLC-2.0 - - ODbL-1.0 - - ODC-By-1.0 - - OFL-1.0 - - OFL-1.0-no-RFN - - OFL-1.0-RFN - - OFL-1.1 - - OFL-1.1-no-RFN - - OFL-1.1-RFN - - OGC-1.0 - - OGDL-Taiwan-1.0 - - OGL-Canada-2.0 - - OGL-UK-1.0 - - OGL-UK-2.0 - - OGL-UK-3.0 - - OGTSL - - OLDAP-1.1 - - OLDAP-1.2 - - OLDAP-1.3 - - OLDAP-1.4 - - OLDAP-2.0 - - OLDAP-2.0.1 - - OLDAP-2.1 - - OLDAP-2.2 - - OLDAP-2.2.1 - - OLDAP-2.2.2 - - OLDAP-2.3 - - OLDAP-2.4 - - OLDAP-2.5 - - OLDAP-2.6 - - OLDAP-2.7 - - OLDAP-2.8 - - OML - - OpenSSL - - OPL-1.0 - - OPUBL-1.0 - - OSET-PL-2.1 - - OSL-1.0 - - OSL-1.1 - - OSL-2.0 - - OSL-2.1 - - OSL-3.0 - - Parity-6.0.0 - - Parity-7.0.0 - - PDDL-1.0 - - PHP-3.0 - - PHP-3.01 - - Plexus - - PolyForm-Noncommercial-1.0.0 - - PolyForm-Small-Business-1.0.0 - - PostgreSQL - - PSF-2.0 - - psfrag - - psutils - - Python-2.0 - - Python-2.0.1 - - Qhull - - QPL-1.0 - - Rdisc - - RHeCos-1.1 - - RPL-1.1 - - RPL-1.5 - - RPSL-1.0 - - RSA-MD - - RSCPL - - Ruby - - SAX-PD - - Saxpath - - SCEA - - SchemeReport - - Sendmail - - Sendmail-8.23 - - SGI-B-1.0 - - SGI-B-1.1 - - SGI-B-2.0 - - SHL-0.5 - - SHL-0.51 - - SimPL-2.0 - - SISSL - - SISSL-1.2 - - Sleepycat - - SMLNJ - - SMPPL - - SNIA - - Spencer-86 - - Spencer-94 - - Spencer-99 - - SPL-1.0 - - SSH-OpenSSH - - SSH-short - - SSPL-1.0 - - StandardML-NJ - - SugarCRM-1.1.3 - - SWL - - Symlinks - - TAPR-OHL-1.0 - - TCL - - TCP-wrappers - - TMate - - TORQUE-1.1 - - TOSL - - TU-Berlin-1.0 - - TU-Berlin-2.0 - - UCL-1.0 - - Unicode-DFS-2015 - - Unicode-DFS-2016 - - Unicode-TOU - - Unlicense - - UPL-1.0 - - Vim - - VOSTROM - - VSL-1.0 - - W3C - - W3C-19980720 - - W3C-20150513 - - Watcom-1.0 - - Wsuipa - - WTFPL - - wxWindows - - X11 - - X11-distribute-modifications-variant - - Xerox - - XFree86-1.1 - - xinetd - - Xnet - - xpp - - XSkat - - YPL-1.0 - - YPL-1.1 - - Zed - - Zend-2.0 - - Zimbra-1.3 - - Zimbra-1.4 - - Zlib - - zlib-acknowledgement - - ZPL-1.1 - - ZPL-2.0 - - ZPL-2.1 - IssuePackageScorecard: - allOf: - - $ref: '#/components/schemas/PackageIssue' - - type: object - properties: - date: - type: string - x-order: 0 - repo: - x-order: 1 - type: object - properties: - name: - type: string - x-order: 0 - description: respository that was analyzed - commit: - type: string - x-order: 1 - pattern: '^[0-9a-fA-F]{40}$' - description: SHA1 value of the analyzed commit expressed as hexadecimal - scorecard: - type: object - x-order: 2 - properties: - version: - type: string - x-order: 0 - description: Scorecard version used for this analysis - commit: - type: string - x-order: 1 - pattern: '^[0-9a-fA-F]{40}$' - description: SHA1 value of the Scorecard commit used for analysis - score: - type: number - x-omitempty: false - x-order: 3 - description: Aggregate score of the repository - checks: - type: array - x-order: 4 - items: - type: object - properties: - details: - type: array - x-order: 0 - items: - type: string - score: - type: integer - x-omitempty: false - x-order: 1 - reason: - type: string - x-order: 2 - name: - type: string - x-order: 3 - documentation: - type: object - x-order: 4 - properties: - url: - type: string - x-order: 0 - short: - type: string - x-order: 1 - metadata: - type: string - x-nullable: true - x-omitempty: false - x-order: 5 diff --git a/auth.go b/auth.go index b8a9f91..7565882 100644 --- a/auth.go +++ b/auth.go @@ -30,7 +30,7 @@ func newAuthCommand() *cobra.Command { } cmd.PersistentFlags().StringVarP(&authControlPlaneApiBaseUrl, "control-plane", "", - auth.DefaultControlPlaneApiUrl(), "Base URL of Control Plane API") + auth.DefaultControlTowerUrl(), "Base URL of Control Plane API") cmd.AddCommand(configureAuthCommand()) cmd.AddCommand(verifyAuthCommand()) diff --git a/go.mod b/go.mod index 5992ecb..90870a7 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,8 @@ module github.com/safedep/vet go 1.22.1 require ( + buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240926081214-ab2d7dfd2ee4.1 + buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240926081214-ab2d7dfd2ee4.2 github.com/AlecAivazis/survey/v2 v2.3.7 github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/anchore/syft v1.11.1 @@ -21,13 +23,14 @@ require ( github.com/kubescape/go-git-url v0.0.30 github.com/owenrumney/go-sarif/v2 v2.3.3 github.com/package-url/packageurl-go v0.1.3 - github.com/safedep/dry v0.0.0-20240808054916-b31bac30d0ef + github.com/safedep/dry v0.0.0-20240927023913-bb455ab56626 github.com/sirupsen/logrus v1.9.3 github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82 github.com/spdx/tools-golang v0.5.5 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 golang.org/x/oauth2 v0.23.0 + google.golang.org/grpc v1.66.0 google.golang.org/protobuf v1.34.2 gopkg.in/yaml.v2 v2.4.0 ) @@ -35,6 +38,7 @@ require ( replace github.com/owenrumney/go-sarif/v2 v2.3.1 => github.com/safedep/go-sarif/v2 v2.3.1 require ( + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2 // indirect github.com/BurntSushi/toml v1.4.0 // indirect github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect github.com/CloudyKit/jet/v6 v6.2.0 // indirect @@ -88,6 +92,8 @@ require ( github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-gonic/gin v1.10.0 // indirect github.com/github/go-spdx/v2 v2.3.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.22.0 // indirect @@ -105,6 +111,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/gookit/color v1.5.4 // indirect github.com/gorilla/css v1.0.1 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -193,6 +200,10 @@ require ( github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yosssi/ace v0.0.5 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.10.0 // indirect @@ -206,7 +217,6 @@ require ( golang.org/x/time v0.6.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 3b54de6..9406788 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,9 @@ +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2 h1:cFrEG/pJch6t62+jqndcPXeTNkYcztS4tBRgNkR+drw= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2/go.mod h1:ylS4c28ACSI59oJrOdW4pHS4n0Hw4TgSPHn8rpHl4Yw= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240926081214-ab2d7dfd2ee4.1 h1:3EzCYr2p0LEZZypVNa9858aMzDb1IaaIx6Yc4aFy9Pc= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240926081214-ab2d7dfd2ee4.1/go.mod h1:/a/eMLFwkuQ6l6FgqutzzADjVmzqOd+tB4e96/I8lWg= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240926081214-ab2d7dfd2ee4.2 h1:yxZyCiOpBy5QWnoEiqcMBL/uSrTk8bfm52wpORxReeU= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240926081214-ab2d7dfd2ee4.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -71,9 +77,6 @@ github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -100,22 +103,14 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/anchore/clio v0.0.0-20240522144804-d81e109008aa h1:pwlAn4O9SBUnlgfa69YcqIynbUyobLVFYu8HxSoCffA= -github.com/anchore/clio v0.0.0-20240522144804-d81e109008aa/go.mod h1:nD3H5uIvjxlfmakOBgtyFQbk5Zjp3l538kxfpHPslzI= github.com/anchore/clio v0.0.0-20240806233806-4c50c054c508 h1:dE7xKzC2eqd7QVt95jJaIbx6Kax/0GF8R1ppsXkfpCM= github.com/anchore/clio v0.0.0-20240806233806-4c50c054c508/go.mod h1:5q0B4t18buA/F3B5cd3+CQsyuyXd+4xCirEW7t5mNTk= -github.com/anchore/fangs v0.0.0-20240508143433-f016b099950f h1:NOhzafCyNYFi88qxkBFjMzQo4dRa1vDhBzx+0Uovx8Q= -github.com/anchore/fangs v0.0.0-20240508143433-f016b099950f/go.mod h1:sVpRS2yNCw6tLVpvA1QSDVWTJVpCuAm8JNZgn4Sjz/k= github.com/anchore/fangs v0.0.0-20240904151251-ac0148f53e5d h1:gdAg7ItS+SaNi+VZBHzVZtfLgqCXQi1uM6wGS/Q9s48= github.com/anchore/fangs v0.0.0-20240904151251-ac0148f53e5d/go.mod h1:Xh4ObY3fmoMzOEVXwDtS1uK44JC7+nRD0n29/1KYFYg= github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 h1:GjNGuwK5jWjJMyVppBjYS54eOiiSNv4Ba869k4wh72Q= github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537/go.mod h1:1aiktV46ATCkuVg0O573ZrH56BUawTECPETbZyBcqT8= -github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVClGVgG7sfM5mwoZlZ2zYpIzN2OhjWkw= -github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a/go.mod h1:ubLFmlsv8/DFUQrZwY5syT5/8Er3ugSr4rDFwHsE3hg= github.com/anchore/go-logger v0.0.0-20240217160628-ee28a485904f h1:qRQCz19ioRN2FtAct4j6Lb3Nl0VolFiuHtYMezGYBn0= github.com/anchore/go-logger v0.0.0-20240217160628-ee28a485904f/go.mod h1:ErB21zunlmQOE/aFPkt4Tv2Q00ttFxPZ2l87gSXxSec= -github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb h1:iDMnx6LIjtjZ46C0akqveX83WFzhpTD3eqOthawb5vU= -github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb/go.mod h1:DmTY2Mfcv38hsHbG78xMiTDdxFtkHpgYNVDPsF2TgHk= github.com/anchore/go-macholibre v0.0.0-20240116161251-5df1434a0b50 h1:HqAfjHHdD6P+U6iVcJl1cGYOh5YNUIffZ12fZfwMWpw= github.com/anchore/go-macholibre v0.0.0-20240116161251-5df1434a0b50/go.mod h1:xz7uczAHBrEQ3+kIb4bnsp74JqcKpBid+gznZil1X0Q= github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= @@ -125,8 +120,6 @@ github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0v github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA= github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.3-0.20240725180315-50ce3be7aa1f h1:xuBvotcht1Ns8IdaC4UuYV1U8MFln9c5ELeo5bzDEO8= -github.com/anchore/stereoscope v0.0.3-0.20240725180315-50ce3be7aa1f/go.mod h1:DcQdMes8SwpFli3rDH0v+Vd9qU9Jariq7JSHNJV5X/A= github.com/anchore/stereoscope v0.0.3 h1:JRPHySy8S6P+Ff3IDiQ29ap1i8/laUQxDk9K1eFh/2U= github.com/anchore/stereoscope v0.0.3/go.mod h1:5DJheGPjVRsSqegTB24Zi6SCHnYQnA519yeIG+RG+I4= github.com/anchore/syft v1.11.1 h1:uJVmZ1WuhMw2cutCsBj0aUgUZxaNlbBNimZEISFttWY= @@ -150,6 +143,7 @@ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuP github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/becheran/wildmatch-go v1.0.0 h1:mE3dGGkTmpKtT4Z+88t8RStG40yN9T+kFEGj2PZFSzA= github.com/becheran/wildmatch-go v1.0.0/go.mod h1:gbMvj0NtVdJ15Mg/mH9uxk2R1QCistMyU7d9KFzroX4= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -163,8 +157,6 @@ github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx2 github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/bytedance/sonic v1.12.1 h1:jWl5Qz1fy7X1ioY74WqO0KjAMtAGQs4sYnjiEBiyX24= -github.com/bytedance/sonic v1.12.1/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic v1.12.2 h1:oaMFuRTpMHYLpCntGca65YWt5ny+wAceDERTkT2L9lg= github.com/bytedance/sonic v1.12.2/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= @@ -178,7 +170,6 @@ github.com/cayleygraph/quad v1.3.0 h1:xg7HOLWWPgvZ4CcvzEpfCwq42L8mzYUR+8V0jtYoBz github.com/cayleygraph/quad v1.3.0/go.mod h1:NadtM7uMm78FskmX++XiOOrNvgkq0E1KvvhQdMseMz4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -203,8 +194,6 @@ github.com/cli/oauth v1.0.1/go.mod h1:qd/FX8ZBD6n1sVNQO3aIdRxeu5LGw9WhKnYhIIoC2A github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= -github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE= -github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY= github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= @@ -225,8 +214,6 @@ github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnTh github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/containerd v1.7.19 h1:/xQ4XRJ0tamDkdzrrBAUy/LE5nCcxFKdBm4EcPrSMEE= -github.com/containerd/containerd v1.7.19/go.mod h1:h4FtNYUUMB4Phr6v+xG89RYKj9XccvbNSCKjdufCrkc= github.com/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA= github.com/containerd/containerd v1.7.21/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= @@ -269,28 +256,20 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= -github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v27.2.0+incompatible h1:yHD1QEB1/0vr5eBNpu8tncu8gWxg8EydFPOSKHzXSMM= github.com/docker/cli v27.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v27.1.2+incompatible h1:AhGzR1xaQIy53qCkxARaFluI00WPGtXn0AJuoQsVYTY= github.com/docker/docker v27.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= -github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dop251/goja v0.0.0-20240806095544-3491d4a58fbe h1:jwFJkgsdelB87ohlXaAGSd05Cb5ALDFa9iW9IGRHcRM= -github.com/dop251/goja v0.0.0-20240806095544-3491d4a58fbe/go.mod h1:DF+w/nLMIkvRpyhd/0K+Okbh3fVZBtXLwRtS/ccAa5w= github.com/dop251/goja v0.0.0-20240828124009-016eb7256539 h1:YIxvsQAoCLGScK2c9ag+4sFCgiQFpMzywJG6dQZFu9k= github.com/dop251/goja v0.0.0-20240828124009-016eb7256539/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= @@ -305,8 +284,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= -github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= -github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155 h1:IgJPqnrlY2Mr4pYB6oaMKvFvwJ9H+X6CCY5x1vCTcpc= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= @@ -323,7 +302,6 @@ github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY= github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= @@ -345,13 +323,22 @@ github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/github/go-spdx/v2 v2.3.1 h1:ffGuHTbHuHzWPt53n8f9o8clGutuLPObo3zB4JAjxU8= github.com/github/go-spdx/v2 v2.3.1/go.mod h1:2ZxKsOhvBp+OYBDlsGnUMcchLeo2mrpEBn2L1C+U3IQ= +github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvpAv8= +github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= +github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= +github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= +github.com/gkampitakis/go-snaps v0.5.7 h1:uVGjHR4t4pPHU944udMx7VKHpwepZXmvDMF+yDmI0rg= +github.com/gkampitakis/go-snaps v0.5.7/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -464,8 +451,6 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/osv-scanner v1.8.3 h1:TVPk2aWhPK+bjp9ZPdGRphG/pwRq4nlyBqHsfQV3keQ= -github.com/google/osv-scanner v1.8.3/go.mod h1:O6tZsJMb/QYXzLjnxHBNLutjsdm8tsrmljiq1WxW8u4= github.com/google/osv-scanner v1.8.4 h1:CScR1b8GqvgbUwG5+bvOlyeE8dtl4zNmh3IDlJE2ZeY= github.com/google/osv-scanner v1.8.4/go.mod h1:ImQyo6WCoZ10iI20zD+iqt0g8cS5gJegqN0ngT1x53M= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -484,8 +469,6 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/pprof v0.0.0-20240903155634-a8630aee4ab9 h1:q5g0N9eal4bmJwXHC5z0QCKs8qhS35hFfq0BAYsIwZI= github.com/google/pprof v0.0.0-20240903155634-a8630aee4ab9/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= @@ -506,6 +489,8 @@ github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= @@ -603,7 +588,6 @@ github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -638,6 +622,8 @@ github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqA github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= +github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -691,9 +677,10 @@ github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5 github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= -github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= -github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -705,7 +692,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= @@ -719,8 +705,8 @@ github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bl github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= -github.com/owenrumney/go-sarif v1.1.1 h1:QNObu6YX1igyFKhdzd7vgzmw7XsWN3/6NMGuDzBgXmE= github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U= github.com/owenrumney/go-sarif/v2 v2.3.3 h1:ubWDJcF5i3L/EIOER+ZyQ03IfplbSU1BLOE26uKQIIU= github.com/owenrumney/go-sarif/v2 v2.3.3/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w= @@ -736,13 +722,9 @@ github.com/pborman/indent v1.2.1/go.mod h1:FitS+t35kIYtB5xWTZAPhnmrxcciEEOdbyrrp github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrec/lz4/v4 v4.1.19 h1:tYLzDnjDXh9qIxSTKHwXwOYmm9d887Y7Y1ZkyXYHAN4= -github.com/pierrec/lz4/v4 v4.1.19/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/piprate/json-gold v0.5.0 h1:RmGh1PYboCFcchVFuh2pbSWAZy4XJaqTMU4KQYsApbM= @@ -754,6 +736,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -764,8 +748,6 @@ github.com/pquerna/cachecontrol v0.2.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -776,8 +758,6 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -799,11 +779,11 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/safedep/dry v0.0.0-20240808054916-b31bac30d0ef h1:liYqq19DtflpN4gX2aaGUN0XJJYC/xnhx703GR+CJYU= -github.com/safedep/dry v0.0.0-20240808054916-b31bac30d0ef/go.mod h1:OHfFlBHlJsIJyK3vsc40yaInGUxrzPhwYu8hM1h+kxs= +github.com/safedep/dry v0.0.0-20240927022242-9d60282446c5 h1:QBaQizpZq2laao6/xO6vians/3TEfrxY6DcRJswlvm0= +github.com/safedep/dry v0.0.0-20240927022242-9d60282446c5/go.mod h1:OHfFlBHlJsIJyK3vsc40yaInGUxrzPhwYu8hM1h+kxs= +github.com/safedep/dry v0.0.0-20240927023913-bb455ab56626 h1:0WadRINp2CAx5AvZkix9uFsibU9PXTtmoass7H+Z+9w= +github.com/safedep/dry v0.0.0-20240927023913-bb455ab56626/go.mod h1:OHfFlBHlJsIJyK3vsc40yaInGUxrzPhwYu8hM1h+kxs= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= -github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk= github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -826,8 +806,6 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smacker/go-tree-sitter v0.0.0-20240625050157-a31a98a7c0f6 h1:mtD4ESyObQZnRVxHFcaYp2d7jMBDa4WJRXSB1Vszj+A= -github.com/smacker/go-tree-sitter v0.0.0-20240625050157-a31a98a7c0f6/go.mod h1:q99oHDsbP0xRwmn7Vmob8gbSMNyvJ83OauXPSuHQuKE= github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82 h1:6C8qej6f1bStuePVkLSFxoU22XBS165D3klxlzRg8F4= github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82/go.mod h1:xe4pgH49k4SsmkQq5OT8abwhWmnzkhpgnXeekbx2efw= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= @@ -845,8 +823,6 @@ github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= -github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= @@ -875,7 +851,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -899,6 +874,14 @@ github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uR github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw= github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= +github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94= +github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -966,6 +949,8 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= @@ -976,16 +961,16 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/arch v0.9.0 h1:ub9TgUInamJ8mrZIGlBG6/4TqWeMszd4N8lNorbrr6k= -golang.org/x/arch v0.9.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8= golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1001,8 +986,6 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1015,8 +998,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= -golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk= golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -1048,8 +1029,6 @@ golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1099,8 +1078,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1120,8 +1097,6 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1203,6 +1178,7 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1214,8 +1190,6 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1223,8 +1197,6 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1239,8 +1211,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1265,6 +1235,7 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1370,6 +1341,7 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -1414,12 +1386,8 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto/googleapis/api v0.0.0-20240812133136-8ffd90a71988 h1:+/tmTy5zAieooKIXfzDm9KiA3Bv6JBwriRN9LY+yayk= -google.golang.org/genproto/googleapis/api v0.0.0-20240812133136-8ffd90a71988/go.mod h1:4+X6GvPs+25wZKbQq9qyAXrwIRExv7w0Ea6MgZLZiDM= google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 h1:V71AcdLZr2p8dC9dbOIMCpqi4EmRl8wUwnJzXXLmbmc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1449,8 +1417,6 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1504,8 +1470,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3 h1:b2FmK8YH+QEwq/Sy2uAEhmqL5nPfGYbJOcaqjeYYZoA= k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= diff --git a/internal/auth/auth.go b/internal/auth/auth.go index cba8bbe..dc3272a 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -15,10 +15,12 @@ const ( apiKeyAlternateEnvKey = "VET_API_KEY" communityModeEnvKey = "VET_COMMUNITY_MODE" - defaultApiUrl = "https://api.safedep.io/insights/v1" - defaultCommunityApiUrl = "https://api.safedep.io/insights-community/v1" - defaultControlPlaneApiUrl = "https://api.safedep.io/control-plane/v1" - defaultSyncApiUrl = "https://api.safedep.io/sync/v1" + defaultApiUrl = "https://api.safedep.io/insights/v1" + defaultCommunityApiUrl = "https://api.safedep.io/insights-community/v1" + defaultSyncApiUrl = "https://api.safedep.io/sync/v1" + + // gRPC service base URL. + defaultControlPlaneApiUrl = "https://api.safedep.io" homeRelativeConfigPath = ".safedep/vet-auth.yml" ) @@ -51,14 +53,6 @@ func DefaultCommunityApiUrl() string { return defaultCommunityApiUrl } -func DefaultControlPlaneApiUrl() string { - if (globalConfig != nil) && (globalConfig.ControlPlaneApiUrl != "") { - return globalConfig.ControlPlaneApiUrl - } - - return defaultControlPlaneApiUrl -} - func DefaultSyncApiUrl() string { if (globalConfig != nil) && (globalConfig.SyncApiUrl != "") { return globalConfig.SyncApiUrl @@ -67,6 +61,14 @@ func DefaultSyncApiUrl() string { return defaultSyncApiUrl } +func DefaultControlTowerUrl() string { + if (globalConfig != nil) && (globalConfig.ControlPlaneApiUrl != "") { + return globalConfig.ControlPlaneApiUrl + } + + return defaultControlPlaneApiUrl +} + func ApiUrl() string { if url, ok := os.LookupEnv(apiUrlEnvKey); ok { return url diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index 4f39550..3defa1e 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -4,19 +4,20 @@ import ( "context" "errors" "fmt" - "math" "net/http" + "net/url" "sync" - api_errors "github.com/safedep/dry/errors" + "buf.build/gen/go/safedep/api/grpc/go/safedep/services/controltower/v1/controltowerv1grpc" + controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/controltower/v1" + drygrpc "github.com/safedep/dry/adapters/grpc" "github.com/safedep/dry/utils" - "github.com/safedep/vet/gen/syncv1" - "github.com/safedep/vet/internal/auth" "github.com/safedep/vet/pkg/analyzer" "github.com/safedep/vet/pkg/common/logger" "github.com/safedep/vet/pkg/models" "github.com/safedep/vet/pkg/policy" "github.com/safedep/vet/pkg/readers" + "google.golang.org/grpc" ) const ( @@ -26,84 +27,93 @@ const ( ) type SyncReporterConfig struct { + // ControlTower API Base URL + ControlTowerBaseUrl string + ControlTowerToken string + // Required - ProjectName string - StreamName string - TriggerEvent string + ProjectName string + ProjectVersion string + TriggerEvent string // Optional or auto-discovered from environment - ProjectSource string - GitRef string - GitRefName string - GitRefType string - GitSha string + GitRef string + GitRefName string + GitRefType string + GitSha string // Performance WorkerCount int - // Internal config - toolName string - toolVersion string - toolType string -} - -type syncIssueWrapper struct { - retries int - issue any + // Tool details + ToolName string + ToolVersion string } type syncReporter struct { - client *syncv1.ClientWithResponses - config *SyncReporterConfig - issueChannel chan *syncIssueWrapper - done chan bool - wg sync.WaitGroup - jobId string + config *SyncReporterConfig + workQueue chan *models.Package + done chan bool + wg sync.WaitGroup + client *grpc.ClientConn + toolServiceClient controltowerv1grpc.ToolServiceClient + sessionId string } func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { - apiKeyApplier := func(ctx context.Context, req *http.Request) error { - req.Header.Set("Authorization", auth.ApiKey()) - return nil - } - - // TODO: Use hysterix as the API client with retries, backoff - // connection pooling etc. - - client, err := syncv1.NewClientWithResponses(auth.DefaultSyncApiUrl(), - syncv1.WithRequestEditorFn(apiKeyApplier)) + parsedUrl, err := url.Parse(config.ControlTowerBaseUrl) if err != nil { - return nil, fmt.Errorf("failed to initialize client for sync reporter: %w", err) + return nil, fmt.Errorf("failed to parse ControlTower base URL: %w", err) } - config.TriggerEvent = string(syncv1.CreateJobRequestTriggerEventManual) - config.ProjectSource = string(syncv1.CreateJobRequestProjectSourceOther) - config.toolType = string(syncv1.CreateJobRequestToolTypeOssVet) - config.toolName = syncReporterToolName - config.toolVersion = "FIXME" + host, port := parsedUrl.Hostname(), parsedUrl.Port() + if port == "" { + port = "443" + } - // TODO: Use an interface to auto-discover environmental details - // if not provided and update config + logger.Debugf("ControlTower host: %s, port: %s", host, port) - err = validateSyncReporterConfig(&config) + headers := http.Header{} + headers.Set("x-tenant-id", "default-team.safedep-io.safedep.io") + headers.Set("x-mock-user", "abhisek@safedep.io") + + client, err := drygrpc.GrpcClient("vet-sync", host, port, + config.ControlTowerToken, headers, []grpc.DialOption{}) if err != nil { - return nil, fmt.Errorf("failed to validate sync reporter config : %w", err) + return nil, fmt.Errorf("failed to create gRPC client: %w", err) } - jobId, err := createJobForSyncReportSession(client, &config) + trigger := controltowerv1.ToolTrigger_TOOL_TRIGGER_MANUAL + source := controltowerv1.ProjectSource_PROJECT_SOURCE_OTHER + + logger.Debugf("Report Sync: Creating tool session for project: %s, version: %s", + config.ProjectName, config.ProjectVersion) + + toolServiceClient := controltowerv1grpc.NewToolServiceClient(client) + toolSessionRes, err := toolServiceClient.CreateToolSession(context.Background(), + &controltowerv1.CreateToolSessionRequest{ + ToolName: config.ToolName, + ToolVersion: config.ToolVersion, + ProjectName: config.ProjectName, + ProjectVersion: &config.ProjectVersion, + ProjectSource: &source, + Trigger: &trigger, + }) if err != nil { - return nil, fmt.Errorf("failed to create job for sync reporter: %w", err) + return nil, fmt.Errorf("failed to create tool session: %w", err) } + logger.Debugf("Report Sync: Tool data upload session ID: %s", + toolSessionRes.GetToolSession().GetToolSessionId()) + done := make(chan bool) - issuesChan := make(chan *syncIssueWrapper, 100000) - self := &syncReporter{ - config: &config, - client: client, - issueChannel: issuesChan, - jobId: jobId, - done: done, + config: &config, + done: done, + workQueue: make(chan *models.Package, 1000), + client: client, + toolServiceClient: toolServiceClient, + sessionId: toolSessionRes.GetToolSession().GetToolSessionId(), } self.startWorkers() @@ -117,13 +127,7 @@ func (s *syncReporter) Name() string { func (s *syncReporter) AddManifest(manifest *models.PackageManifest) { // We are ignoring the error here because we are asynchronously handling the sync of Manifest _ = readers.NewManifestModelReader(manifest).EnumPackages(func(pkg *models.Package) error { - - s.queuePackageDependencyIssue(manifest, pkg) - s.queuePackageMetadataIssue(manifest, pkg) - s.queuePackageLicenseIssue(manifest, pkg) - s.queuePackageVulnerabilityIssue(manifest, pkg) - s.queuePackageScorecardIssue(manifest, pkg) - + s.queuePackage(pkg) return nil }) } @@ -141,9 +145,9 @@ func (s *syncReporter) Finish() error { return nil } -func (s *syncReporter) queueIssueForSync(issue *syncIssueWrapper) { +func (s *syncReporter) queuePackage(pkg *models.Package) { s.wg.Add(1) - s.issueChannel <- issue + s.workQueue <- pkg } func (s *syncReporter) startWorkers() { @@ -160,10 +164,10 @@ func (s *syncReporter) startWorkers() { func (s *syncReporter) syncReportWorker() { for { select { - case issue := <-s.issueChannel: - err := s.syncReportIssue(issue) + case pkg := <-s.workQueue: + err := s.syncPackage(pkg) if err != nil { - logger.Errorf("failed to sync issue: %v", err) + logger.Errorf("failed to sync package: %v", err) } case <-s.done: return @@ -171,230 +175,17 @@ func (s *syncReporter) syncReportWorker() { } } -func (s *syncReporter) syncReportIssue(iw *syncIssueWrapper) error { +func (s *syncReporter) syncPackage(pkg *models.Package) error { defer s.wg.Done() - - res, err := s.client.CreateJobIssueWithResponse(context.Background(), s.jobId, iw.issue) - if err != nil { - return err - } - - defer res.HTTPResponse.Body.Close() - - if res.HTTPResponse.StatusCode != http.StatusCreated { - apiErr, _ := api_errors.UnmarshalApiError(res.Body) - if apiErr.Retriable() && (iw.retries < syncReporterMaxRetries) { - iw.retries++ - s.queueIssueForSync(iw) - return nil - } - - return fmt.Errorf("invalid response code %d from Issue API : %w", - res.HTTPResponse.StatusCode, err) - } - - response := utils.SafelyGetValue(res.JSON201) - logger.Debugf("Synced issued with ID: %s", response.Id) - return nil } -func (s *syncReporter) buildPackageIssue(issueType syncv1.IssueIssueType, - manifest *models.PackageManifest, pkg *models.Package) syncv1.PackageIssue { - ecosystem := syncv1.PackageIssueManifestEcosystem(manifest.Ecosystem) - return syncv1.PackageIssue{ - Issue: syncv1.Issue{ - IssueType: issueType, - }, - ManifestEcosystem: &ecosystem, - ManifestPath: &manifest.Path, - PackageName: &pkg.Name, - PackageVersion: &pkg.Version, - } -} - -func (s *syncReporter) queuePackageDependencyIssue(manifest *models.PackageManifest, pkg *models.Package) { - issue := syncv1.IssuePackageDependency{ - PackageIssue: s.buildPackageIssue(syncv1.IssueIssueTypePackageDependency, - manifest, pkg), - } - - if pkg.Parent != nil { - issue.ParentPackageName = &pkg.Parent.Name - issue.ParentPackageVersion = &pkg.Parent.Version - } - - iw := syncIssueWrapper{issue: issue} - s.queueIssueForSync(&iw) -} - -func (s *syncReporter) queuePackageMetadataIssue(manifest *models.PackageManifest, pkg *models.Package) { - insights := utils.SafelyGetValue(pkg.Insights) - projects := utils.SafelyGetValue(insights.Projects) - - for _, project := range projects { - issue := syncv1.IssuePackageSource{ - PackageIssue: s.buildPackageIssue(syncv1.IssueIssueTypePackageSourceInfo, - manifest, pkg), - } - - sourceType := utils.SafelyGetValue(project.Type) - issueSourceType := syncv1.IssuePackageSourceSourceTypeOther - - switch sourceType { - case "GITHUB": - issueSourceType = syncv1.IssuePackageSourceSourceTypeGithub - case "BITBUCKET": - issueSourceType = syncv1.IssuePackageSourceSourceTypeBitbucket - case "GITLAB": - issueSourceType = syncv1.IssuePackageSourceSourceTypeGitlab - } - - issue.SourceType = &issueSourceType - issue.SourceUrl = project.Link - issue.SourceDisplayName = project.DisplayName - issue.SourceForks = project.Forks - issue.SourceStars = project.Stars - - s.queueIssueForSync(&syncIssueWrapper{issue: issue}) - } -} - -func (s *syncReporter) queuePackageLicenseIssue(manifest *models.PackageManifest, pkg *models.Package) { - insights := utils.SafelyGetValue(pkg.Insights) - licenses := utils.SafelyGetValue(insights.Licenses) - - for _, license := range licenses { - licenseId := syncv1.IssuePackageLicenseLicenseId(license) - issue := syncv1.IssuePackageLicense{ - PackageIssue: s.buildPackageIssue(syncv1.IssueIssueTypePackageLicense, - manifest, pkg), - LicenseId: &licenseId, - } - - s.queueIssueForSync(&syncIssueWrapper{issue: issue}) - } -} - -func (s *syncReporter) queuePackageVulnerabilityIssue(manifest *models.PackageManifest, pkg *models.Package) { - insights := utils.SafelyGetValue(pkg.Insights) - vulnerabilities := utils.SafelyGetValue(insights.Vulnerabilities) - - for _, vuln := range vulnerabilities { - issue := syncv1.IssuePackageVulnerability{ - PackageIssue: s.buildPackageIssue(syncv1.IssueIssueTypePackageVulnerability, - manifest, pkg), - } - - severities := []struct { - Risk *syncv1.IssuePackageCommonVulnerabilitySeveritiesRisk `json:"risk,omitempty"` - Score *string `json:"score,omitempty"` - Type *syncv1.IssuePackageCommonVulnerabilitySeveritiesType `json:"type,omitempty"` - }{} - - issue.Vulnerability = &syncv1.IssuePackageCommonVulnerability{ - Id: vuln.Id, - Summary: vuln.Summary, - Aliases: vuln.Aliases, - Related: vuln.Related, - } - - insightsVulnSeverities := utils.SafelyGetValue(vuln.Severities) - for _, severity := range insightsVulnSeverities { - sRisk := syncv1.IssuePackageCommonVulnerabilitySeveritiesRisk(utils.SafelyGetValue(severity.Risk)) - sType := syncv1.IssuePackageCommonVulnerabilitySeveritiesType(utils.SafelyGetValue(severity.Type)) - - severities = append(severities, struct { - Risk *syncv1.IssuePackageCommonVulnerabilitySeveritiesRisk `json:"risk,omitempty"` - Score *string `json:"score,omitempty"` - Type *syncv1.IssuePackageCommonVulnerabilitySeveritiesType `json:"type,omitempty"` - }{ - Score: severity.Score, - Risk: &sRisk, - Type: &sType, - }) - } - - issue.Vulnerability.Severities = &severities - s.queueIssueForSync(&syncIssueWrapper{issue: issue}) - } -} - -func (s *syncReporter) queuePackageScorecardIssue(manifest *models.PackageManifest, pkg *models.Package) { - insights := utils.SafelyGetValue(pkg.Insights) - - // Basic sanity test to fail fast if Scorecard is unavailable - if (insights.Scorecard == nil) || (insights.Scorecard.Content == nil) { - return - } - - scorecard := utils.SafelyGetValue(insights.Scorecard) - scorecardContent := utils.SafelyGetValue(scorecard.Content) - scorecardRepo := utils.SafelyGetValue(scorecardContent.Repository) - scorecardChecks := utils.SafelyGetValue(scorecardContent.Checks) - - date := utils.SafelyGetValue(scorecardContent.Date).Format("2006-01-02") - repo := struct { - Commit *string `json:"commit,omitempty"` - Name *string `json:"name,omitempty"` - }{ - Commit: scorecardRepo.Commit, - Name: scorecardRepo.Name, - } - - checks := []struct { - Details *[]string `json:"details,omitempty"` - Documentation *struct { - Short *string `json:"short,omitempty"` - Url *string `json:"url,omitempty"` - } `json:"documentation,omitempty"` - Name *string `json:"name,omitempty"` - Reason *string `json:"reason,omitempty"` - Score *int `json:"score"` - }{} - - for _, check := range scorecardChecks { - // We have to do this stupid type conversion because Scorecard check score seems - // be to int / float32 in different specs. We are good with downsizing width because - // scorecard score is max 10 - checkScore := utils.SafelyGetValue(check.Score) - checkScoreInt := int(math.Round(float64(checkScore))) - - checks = append(checks, struct { - Details *[]string `json:"details,omitempty"` - Documentation *struct { - Short *string `json:"short,omitempty"` - Url *string `json:"url,omitempty"` - } `json:"documentation,omitempty"` - Name *string `json:"name,omitempty"` - Reason *string `json:"reason,omitempty"` - Score *int `json:"score"` - }{ - Details: check.Details, - Name: (*string)(check.Name), - Reason: check.Reason, - Score: &checkScoreInt, - }) - } - - issue := &syncv1.IssuePackageScorecard{ - PackageIssue: s.buildPackageIssue(syncv1.IssueIssueTypePackageOpenssfScorecard, - manifest, pkg), - Date: &date, - Score: scorecardContent.Score, - Repo: &repo, - Checks: &checks, - } - - s.queueIssueForSync(&syncIssueWrapper{issue: issue}) -} - func validateSyncReporterConfig(config *SyncReporterConfig) error { if utils.IsEmptyString(config.ProjectName) { return errors.New("project name not in config") } - if utils.IsEmptyString(config.StreamName) { + if utils.IsEmptyString(config.ProjectVersion) { return errors.New("stream name not in config") } @@ -404,37 +195,3 @@ func validateSyncReporterConfig(config *SyncReporterConfig) error { return nil } - -func createJobForSyncReportSession(client *syncv1.ClientWithResponses, - config *SyncReporterConfig) (string, error) { - - jobConfig := syncv1.CreateSyncJobJSONRequestBody{ - ProjectName: config.ProjectName, - ProjectSource: syncv1.CreateJobRequestProjectSource(config.ProjectSource), - StreamName: config.StreamName, - TriggerEvent: syncv1.CreateJobRequestTriggerEvent(config.TriggerEvent), - ToolType: syncv1.CreateJobRequestToolType(config.toolType), - ToolName: config.toolName, - ToolVersion: config.toolVersion, - GitRefType: (*syncv1.CreateJobRequestGitRefType)(&config.GitRefType), - GitRef: &config.GitRef, - GitRefName: &config.GitRefName, - GitSha: &config.GitSha, - } - - job, err := client.CreateSyncJobWithResponse(context.Background(), jobConfig) - if err != nil { - return "", err - } - - defer job.HTTPResponse.Body.Close() - - if job.HTTPResponse.StatusCode != http.StatusCreated { - err, _ = api_errors.UnmarshalApiError(job.Body) - return "", fmt.Errorf("invalid response code %d from Job API : %w", - job.HTTPResponse.StatusCode, err) - } - - res := utils.SafelyGetValue(job.JSON201) - return utils.SafelyGetValue(res.Id), nil -} diff --git a/scan.go b/scan.go index 41d935c..a196d6e 100644 --- a/scan.go +++ b/scan.go @@ -176,7 +176,7 @@ func listParsersCommand() *cobra.Command { func startScan() { if !disableAuthVerifyBeforeScan { err := auth.Verify(&auth.VerifyConfig{ - ControlPlaneApiUrl: auth.DefaultControlPlaneApiUrl(), + ControlPlaneApiUrl: auth.DefaultControlTowerUrl(), }) // We will fallback to community mode by default to provide @@ -394,8 +394,12 @@ func internalStartScan() error { if syncReport { rp, err := reporter.NewSyncReporter(reporter.SyncReporterConfig{ - ProjectName: syncReportProject, - StreamName: syncReportStream, + ToolName: "vet", + ToolVersion: version, + ProjectName: syncReportProject, + ProjectVersion: syncReportStream, + ControlTowerBaseUrl: auth.DefaultControlTowerUrl(), + ControlTowerToken: auth.ApiKey(), }) if err != nil { return err From 70511831cefe1953b6957d233da36fc9176fb7b9 Mon Sep 17 00:00:00 2001 From: abhisek Date: Fri, 27 Sep 2024 13:40:32 +0530 Subject: [PATCH 02/28] feat: Update report sync using grpc --- go.mod | 4 +- go.sum | 10 ++--- pkg/models/models.go | 16 ++++++++ pkg/reporter/sync.go | 89 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 97 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index 90870a7..ce922a1 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/safedep/vet go 1.22.1 require ( - buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240926081214-ab2d7dfd2ee4.1 - buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240926081214-ab2d7dfd2ee4.2 + buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240927074119-125b1e169aaf.1 + buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240927074119-125b1e169aaf.2 github.com/AlecAivazis/survey/v2 v2.3.7 github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/anchore/syft v1.11.1 diff --git a/go.sum b/go.sum index 9406788..5fc8883 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2 h1:cFrEG/pJch6t62+jqndcPXeTNkYcztS4tBRgNkR+drw= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2/go.mod h1:ylS4c28ACSI59oJrOdW4pHS4n0Hw4TgSPHn8rpHl4Yw= -buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240926081214-ab2d7dfd2ee4.1 h1:3EzCYr2p0LEZZypVNa9858aMzDb1IaaIx6Yc4aFy9Pc= -buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240926081214-ab2d7dfd2ee4.1/go.mod h1:/a/eMLFwkuQ6l6FgqutzzADjVmzqOd+tB4e96/I8lWg= -buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240926081214-ab2d7dfd2ee4.2 h1:yxZyCiOpBy5QWnoEiqcMBL/uSrTk8bfm52wpORxReeU= -buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240926081214-ab2d7dfd2ee4.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240927074119-125b1e169aaf.1 h1:2ELSEnzC34KBVKPsmdzbFSUdZoCa56K/xb6bQ/QKfd4= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240927074119-125b1e169aaf.1/go.mod h1:N2s2AvQRTd39jzo6zQL1b7aohwR6HF8J6pyXbBzbkak= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240927074119-125b1e169aaf.2 h1:UZdrFL+T3SUjJy8rX8N3HD4gb18Wp1gcPmIHKbEG3cA= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240927074119-125b1e169aaf.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -779,8 +779,6 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/safedep/dry v0.0.0-20240927022242-9d60282446c5 h1:QBaQizpZq2laao6/xO6vians/3TEfrxY6DcRJswlvm0= -github.com/safedep/dry v0.0.0-20240927022242-9d60282446c5/go.mod h1:OHfFlBHlJsIJyK3vsc40yaInGUxrzPhwYu8hM1h+kxs= github.com/safedep/dry v0.0.0-20240927023913-bb455ab56626 h1:0WadRINp2CAx5AvZkix9uFsibU9PXTtmoass7H+Z+9w= github.com/safedep/dry v0.0.0-20240927023913-bb455ab56626/go.mod h1:OHfFlBHlJsIJyK3vsc40yaInGUxrzPhwYu8hM1h+kxs= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= diff --git a/pkg/models/models.go b/pkg/models/models.go index 5ab8782..cc79729 100644 --- a/pkg/models/models.go +++ b/pkg/models/models.go @@ -7,6 +7,7 @@ import ( "strings" "sync" + packagev1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/package/v1" "github.com/google/osv-scanner/pkg/lockfile" "github.com/safedep/vet/gen/insightapi" @@ -111,6 +112,21 @@ func (pm *PackageManifest) GetPackagesCount() int { return len(pm.GetPackages()) } +func (pm *PackageManifest) GetControlTowerSpecEcosystem() packagev1.Ecosystem { + switch pm.Ecosystem { + case EcosystemCargo: + return packagev1.Ecosystem_ECOSYSTEM_CARGO + case EcosystemGo: + return packagev1.Ecosystem_ECOSYSTEM_GO + case EcosystemMaven: + return packagev1.Ecosystem_ECOSYSTEM_MAVEN + case EcosystemNpm: + return packagev1.Ecosystem_ECOSYSTEM_NPM + default: + return packagev1.Ecosystem_ECOSYSTEM_UNSPECIFIED + } +} + func (pm *PackageManifest) GetSpecEcosystem() modelspec.Ecosystem { switch pm.Ecosystem { case EcosystemCargo: diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index 3defa1e..d9cb8ca 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -2,16 +2,16 @@ package reporter import ( "context" - "errors" "fmt" "net/http" "net/url" + "os" "sync" "buf.build/gen/go/safedep/api/grpc/go/safedep/services/controltower/v1/controltowerv1grpc" + packagev1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/package/v1" controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/controltower/v1" drygrpc "github.com/safedep/dry/adapters/grpc" - "github.com/safedep/dry/utils" "github.com/safedep/vet/pkg/analyzer" "github.com/safedep/vet/pkg/common/logger" "github.com/safedep/vet/pkg/models" @@ -73,9 +73,12 @@ func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { logger.Debugf("ControlTower host: %s, port: %s", host, port) + vetTenantId := os.Getenv("VET_CONTROL_TOWER_TENANT_ID") + vetTenantMockUser := os.Getenv("VET_CONTROL_TOWER_MOCK_USER") // Used in dev + headers := http.Header{} - headers.Set("x-tenant-id", "default-team.safedep-io.safedep.io") - headers.Set("x-mock-user", "abhisek@safedep.io") + headers.Set("x-tenant-id", vetTenantId) + headers.Set("x-mock-user", vetTenantMockUser) client, err := drygrpc.GrpcClient("vet-sync", host, port, config.ControlTowerToken, headers, []grpc.DialOption{}) @@ -142,7 +145,18 @@ func (s *syncReporter) Finish() error { s.wg.Wait() close(s.done) - return nil + logger.Debugf("Report Sync: Completing tool session: %s", s.sessionId) + + _, err := s.toolServiceClient.CompleteToolSession(context.Background(), + &controltowerv1.CompleteToolSessionRequest{ + ToolSession: &controltowerv1.ToolSession{ + ToolSessionId: s.sessionId, + }, + + Status: controltowerv1.CompleteToolSessionRequest_STATUS_SUCCESS, + }) + + return err } func (s *syncReporter) queuePackage(pkg *models.Package) { @@ -177,20 +191,67 @@ func (s *syncReporter) syncReportWorker() { func (s *syncReporter) syncPackage(pkg *models.Package) error { defer s.wg.Done() - return nil -} -func validateSyncReporterConfig(config *SyncReporterConfig) error { - if utils.IsEmptyString(config.ProjectName) { - return errors.New("project name not in config") + req := controltowerv1.PublishPackageInsightRequest{ + ToolSession: &controltowerv1.ToolSession{ + ToolSessionId: s.sessionId, + }, + + Manifest: &packagev1.PackageManifest{ + Ecosystem: pkg.Manifest.GetControlTowerSpecEcosystem(), + Name: pkg.Manifest.GetDisplayPath(), + }, + + PackageVersion: &packagev1.PackageVersion{ + Package: &packagev1.Package{ + Ecosystem: pkg.Manifest.GetControlTowerSpecEcosystem(), + Name: pkg.Name, + }, + + Version: pkg.Version, + }, + + PackageVersionInsight: &packagev1.PackageVersionInsight{ + Dependencies: []*packagev1.PackageVersion{}, + }, } - if utils.IsEmptyString(config.ProjectVersion) { - return errors.New("stream name not in config") + // We should move this to models + graph := pkg.GetDependencyGraph() + if graph != nil { + nodes := graph.GetNodes() + for _, node := range nodes { + if node.Root { + continue + } + + thisPkg := node.Data + if thisPkg == nil { + continue + } + + if thisPkg.GetName() != pkg.GetName() && + thisPkg.GetVersion() != pkg.GetVersion() && + thisPkg.GetSpecEcosystem() != pkg.GetSpecEcosystem() { + continue + } + + for _, child := range node.Children { + req.PackageVersionInsight.Dependencies = append(req.PackageVersionInsight.Dependencies, &packagev1.PackageVersion{ + Package: &packagev1.Package{ + Ecosystem: child.Manifest.GetControlTowerSpecEcosystem(), + Name: child.GetName(), + }, + + Version: child.GetVersion(), + }) + } + } } - if utils.IsEmptyString(config.TriggerEvent) { - return errors.New("trigger event not in config") + _, err := s.toolServiceClient.PublishPackageInsight(context.Background(), &req) + if err != nil { + return fmt.Errorf("failed to publish package insight: %w", err) } return nil From 95c87b4f7be2c838d67703b30dd56f82829b0fa8 Mon Sep 17 00:00:00 2001 From: abhisek Date: Sat, 28 Sep 2024 15:59:02 +0530 Subject: [PATCH 03/28] refactor: Move get dependencies enumerator to models --- go.mod | 4 ++-- go.sum | 4 ++++ pkg/models/models.go | 31 +++++++++++++++++++++++++++++ pkg/reporter/sync.go | 46 +++++++++++++++----------------------------- 4 files changed, 52 insertions(+), 33 deletions(-) diff --git a/go.mod b/go.mod index ce922a1..33b1b1e 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/safedep/vet go 1.22.1 require ( - buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240927074119-125b1e169aaf.1 - buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240927074119-125b1e169aaf.2 + buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240928092914-054512bde05f.1 + buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240928092914-054512bde05f.2 github.com/AlecAivazis/survey/v2 v2.3.7 github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/anchore/syft v1.11.1 diff --git a/go.sum b/go.sum index 5fc8883..f863f3b 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,12 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-2024050820065 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2/go.mod h1:ylS4c28ACSI59oJrOdW4pHS4n0Hw4TgSPHn8rpHl4Yw= buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240927074119-125b1e169aaf.1 h1:2ELSEnzC34KBVKPsmdzbFSUdZoCa56K/xb6bQ/QKfd4= buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240927074119-125b1e169aaf.1/go.mod h1:N2s2AvQRTd39jzo6zQL1b7aohwR6HF8J6pyXbBzbkak= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240928092914-054512bde05f.1 h1:D25CwoCuLxqjaHYtlWmRaGXrXWeqPW3+eGWozHKRbFw= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240928092914-054512bde05f.1/go.mod h1:tkD4uIlOlf/6Zt/zeRoWyfmwuV3sJdGvFolWB41YVPs= buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240927074119-125b1e169aaf.2 h1:UZdrFL+T3SUjJy8rX8N3HD4gb18Wp1gcPmIHKbEG3cA= buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240927074119-125b1e169aaf.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240928092914-054512bde05f.2 h1:A9H0rP48/ZhngHW/8zJj+l1zRJYakvgEMw2KuwQCBkA= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240928092914-054512bde05f.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= diff --git a/pkg/models/models.go b/pkg/models/models.go index cc79729..4e8c1bf 100644 --- a/pkg/models/models.go +++ b/pkg/models/models.go @@ -232,6 +232,37 @@ func (p *Package) DependencyPath() []*Package { return dg.PathToRoot(p) } +func (p *Package) GetDependencies() ([]*Package, error) { + graph := p.GetDependencyGraph() + if graph == nil { + return nil, fmt.Errorf("dependency graph not available") + } + + dependencies := []*Package{} + + nodes := graph.GetNodes() + for _, node := range nodes { + if node.Root { + continue + } + + if node.Data == nil { + continue + } + + if p.GetName() != node.Data.GetName() && + p.GetVersion() != node.Data.GetVersion() && + p.GetSpecEcosystem() != node.Data.GetSpecEcosystem() { + continue + } + + dependencies = append(dependencies, node.Children...) + break + } + + return dependencies, nil +} + func NewPackageDetail(ecosystem, name, version string) lockfile.PackageDetails { return lockfile.PackageDetails{ Ecosystem: lockfile.Ecosystem(ecosystem), diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index d9cb8ca..b148ff5 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -87,7 +87,7 @@ func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { } trigger := controltowerv1.ToolTrigger_TOOL_TRIGGER_MANUAL - source := controltowerv1.ProjectSource_PROJECT_SOURCE_OTHER + source := packagev1.ProjectSourceType_PROJECT_SOURCE_TYPE_UNSPECIFIED logger.Debugf("Report Sync: Creating tool session for project: %s, version: %s", config.ProjectName, config.ProjectVersion) @@ -216,40 +216,24 @@ func (s *syncReporter) syncPackage(pkg *models.Package) error { }, } - // We should move this to models - graph := pkg.GetDependencyGraph() - if graph != nil { - nodes := graph.GetNodes() - for _, node := range nodes { - if node.Root { - continue - } + dependencies, err := pkg.GetDependencies() + if err != nil { + logger.Warnf("failed to get dependencies for package: %s/%s/%s: %s", + pkg.Manifest.Ecosystem, pkg.GetName(), pkg.GetVersion(), err.Error()) + } else { + for _, child := range dependencies { + req.PackageVersionInsight.Dependencies = append(req.PackageVersionInsight.Dependencies, &packagev1.PackageVersion{ + Package: &packagev1.Package{ + Ecosystem: child.Manifest.GetControlTowerSpecEcosystem(), + Name: child.GetName(), + }, - thisPkg := node.Data - if thisPkg == nil { - continue - } - - if thisPkg.GetName() != pkg.GetName() && - thisPkg.GetVersion() != pkg.GetVersion() && - thisPkg.GetSpecEcosystem() != pkg.GetSpecEcosystem() { - continue - } - - for _, child := range node.Children { - req.PackageVersionInsight.Dependencies = append(req.PackageVersionInsight.Dependencies, &packagev1.PackageVersion{ - Package: &packagev1.Package{ - Ecosystem: child.Manifest.GetControlTowerSpecEcosystem(), - Name: child.GetName(), - }, - - Version: child.GetVersion(), - }) - } + Version: child.GetVersion(), + }) } } - _, err := s.toolServiceClient.PublishPackageInsight(context.Background(), &req) + _, err = s.toolServiceClient.PublishPackageInsight(context.Background(), &req) if err != nil { return fmt.Errorf("failed to publish package insight: %w", err) } From 5c1052c6c6643b60ffd7f42123c8dc2de4b2bb32 Mon Sep 17 00:00:00 2001 From: abhisek Date: Mon, 30 Sep 2024 10:30:04 +0530 Subject: [PATCH 04/28] feat: Update cloud sync reporter to include namespace --- pkg/reporter/ci/ci.go | 42 +++++++++++++++++++++++ pkg/reporter/sync.go | 80 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 pkg/reporter/ci/ci.go diff --git a/pkg/reporter/ci/ci.go b/pkg/reporter/ci/ci.go new file mode 100644 index 0000000..8b06874 --- /dev/null +++ b/pkg/reporter/ci/ci.go @@ -0,0 +1,42 @@ +package ci + +import "net/url" + +type gitRefType string + +const ( + Branch = gitRefType("branch") + Tag = gitRefType("tag") + PullRequest = gitRefType("pull_request") +) + +// Introspector defines a contract for implementing +// runtime information collector from various CI environments. +// This is modeled based on the default environments in GHA. But +// we will keep this minimal and add extended interfaces for +// additional CI specific information. +// https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables +type Introspector interface { + // Returns the URL of the repository for which the CI job is running + GetRepositoryURL() (url.URL, error) + + // Returns the repository name for which the CI job is running + GetRepositoryName() (string, error) + + // Returns the event that triggered the CI job + GetEvent() (gitRefType, error) + + // Returns the GitRef for which the CI job is running + // This is fulled formed e.g. refs/heads/master + GetGitRef() (string, error) + + // Get the ref name for which the CI job is running + // This is the short form of the GitRef e.g. master + GetRefName() (string, error) + + // Get the git ref type for which the CI job is running + GetRefType() (string, error) + + // GitSHA returns the commit SHA for which the CI job is running + GetGitSHA() (string, error) +} diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index b148ff5..694b5ef 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -6,12 +6,15 @@ import ( "net/http" "net/url" "os" + "strings" "sync" "buf.build/gen/go/safedep/api/grpc/go/safedep/services/controltower/v1/controltowerv1grpc" packagev1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/package/v1" + vulnerabilityv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/vulnerability/v1" controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/controltower/v1" drygrpc "github.com/safedep/dry/adapters/grpc" + "github.com/safedep/dry/utils" "github.com/safedep/vet/pkg/analyzer" "github.com/safedep/vet/pkg/common/logger" "github.com/safedep/vet/pkg/models" @@ -192,6 +195,7 @@ func (s *syncReporter) syncReportWorker() { func (s *syncReporter) syncPackage(pkg *models.Package) error { defer s.wg.Done() + // Build the base package manifest and package req := controltowerv1.PublishPackageInsightRequest{ ToolSession: &controltowerv1.ToolSession{ ToolSessionId: s.sessionId, @@ -199,6 +203,7 @@ func (s *syncReporter) syncPackage(pkg *models.Package) error { Manifest: &packagev1.PackageManifest{ Ecosystem: pkg.Manifest.GetControlTowerSpecEcosystem(), + Namespace: &pkg.Manifest.Path, Name: pkg.Manifest.GetDisplayPath(), }, @@ -212,10 +217,16 @@ func (s *syncReporter) syncPackage(pkg *models.Package) error { }, PackageVersionInsight: &packagev1.PackageVersionInsight{ - Dependencies: []*packagev1.PackageVersion{}, + Dependencies: []*packagev1.PackageVersion{}, + Vulnerabilities: []*vulnerabilityv1.Vulnerability{}, + ProjectInsights: []*packagev1.ProjectInsight{}, + Licenses: &packagev1.LicenseMetaList{ + Licenses: []*packagev1.LicenseMeta{}, + }, }, } + // Add package dependencies dependencies, err := pkg.GetDependencies() if err != nil { logger.Warnf("failed to get dependencies for package: %s/%s/%s: %s", @@ -233,6 +244,73 @@ func (s *syncReporter) syncPackage(pkg *models.Package) error { } } + // Get the insights + insights := utils.SafelyGetValue(pkg.Insights) + + // Add vulnerabilities. We will publish only the minimum required information. + // The backend should have its own VDB to enrich the data. + vulnerabilities := utils.SafelyGetValue(insights.Vulnerabilities) + for _, v := range vulnerabilities { + vId := utils.SafelyGetValue(v.Id) + vulnerability := vulnerabilityv1.Vulnerability{ + Id: &vulnerabilityv1.VulnerabilityIdentifier{ + Value: vId, + }, + Summary: utils.SafelyGetValue(v.Summary), + } + + if strings.HasPrefix(vId, "CVE-") { + vulnerability.Id.Type = vulnerabilityv1.VulnerabilityIdentifierType_VULNERABILITY_IDENTIFIER_TYPE_CVE + } else if strings.HasPrefix(vId, "OSV-") { + vulnerability.Id.Type = vulnerabilityv1.VulnerabilityIdentifierType_VULNERABILITY_IDENTIFIER_TYPE_OSV + } + + req.PackageVersionInsight.Vulnerabilities = append(req.PackageVersionInsight.Vulnerabilities, &vulnerability) + } + + // Add project information + project := utils.SafelyGetValue(insights.Projects) + for _, p := range project { + stars := int64(utils.SafelyGetValue(p.Stars)) + forks := int64(utils.SafelyGetValue(p.Forks)) + issues := int64(utils.SafelyGetValue(p.Issues)) + + vt := packagev1.ProjectSourceType_PROJECT_SOURCE_TYPE_UNSPECIFIED + switch utils.SafelyGetValue(p.Type) { + case "GITHUB": + vt = packagev1.ProjectSourceType_PROJECT_SOURCE_TYPE_GITHUB + case "GITLAB": + vt = packagev1.ProjectSourceType_PROJECT_SOURCE_TYPE_GITLAB + } + + req.PackageVersionInsight.ProjectInsights = append(req.PackageVersionInsight.ProjectInsights, &packagev1.ProjectInsight{ + Project: &packagev1.Project{ + Type: vt, + Name: utils.SafelyGetValue(p.Name), + Url: utils.SafelyGetValue(p.Link), + }, + + Stars: &stars, + Forks: &forks, + Issues: &packagev1.ProjectInsight_IssueStat{ + Total: issues, + }, + }) + } + + licenses := utils.SafelyGetValue(insights.Licenses) + for _, license := range licenses { + req.PackageVersionInsight.Licenses.Licenses = append(req.PackageVersionInsight.Licenses.Licenses, &packagev1.LicenseMeta{ + LicenseId: string(license), + Name: string(license), + }) + } + + // OpenSSF + // We can't use vet's collected scorecard because its data model is wrong. There is + // not a single scorecard per package. Rather there is a scorecard per project. Since + // a package may be related to multiple projects, we will have multiple related scorecards. + _, err = s.toolServiceClient.PublishPackageInsight(context.Background(), &req) if err != nil { return fmt.Errorf("failed to publish package insight: %w", err) From 7a5d637a50541b07a36bb87cbe0396e667dcff51 Mon Sep 17 00:00:00 2001 From: abhisek Date: Mon, 30 Sep 2024 12:48:44 +0530 Subject: [PATCH 05/28] refactor: Enable tool service session pooling in cloud sync reporter --- pkg/reporter/sync.go | 162 ++++++++++++++++++++++++++++++++----------- scan.go | 2 +- 2 files changed, 122 insertions(+), 42 deletions(-) diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index 694b5ef..eabe189 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -34,6 +34,10 @@ type SyncReporterConfig struct { ControlTowerBaseUrl string ControlTowerToken string + // Enable multi-project syncing + // In this case, a new project is created per package manifest + EnableMultiProjectSync bool + // Required ProjectName string ProjectVersion string @@ -53,14 +57,72 @@ type SyncReporterConfig struct { ToolVersion string } -type syncReporter struct { - config *SyncReporterConfig - workQueue chan *models.Package - done chan bool - wg sync.WaitGroup - client *grpc.ClientConn - toolServiceClient controltowerv1grpc.ToolServiceClient +type syncSession struct { sessionId string + toolServiceClient controltowerv1grpc.ToolServiceClient +} + +type syncSessionPool struct { + mu sync.RWMutex + syncSessions map[string]syncSession +} + +// Only use this session +func (s *syncSessionPool) addPrimarySession(sessionId string, client controltowerv1grpc.ToolServiceClient) { + s.mu.Lock() + defer s.mu.Unlock() + + s.syncSessions["*"] = syncSession{ + sessionId: sessionId, + toolServiceClient: client, + } +} + +func (s *syncSessionPool) addKeyedSession(key, sessionId string, client controltowerv1grpc.ToolServiceClient) { + s.mu.Lock() + defer s.mu.Unlock() + + s.syncSessions[key] = syncSession{ + sessionId: sessionId, + toolServiceClient: client, + } +} + +func (s *syncSessionPool) getSession(key string) (*syncSession, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + if s, ok := s.syncSessions["*"]; ok { + return &s, nil + } + + if s, ok := s.syncSessions[key]; ok { + return &s, nil + } + + return nil, fmt.Errorf("session not found for key: %s", key) +} + +func (s *syncSessionPool) forEach(f func(key string, session *syncSession) error) error { + s.mu.RLock() + defer s.mu.RUnlock() + + for key, session := range s.syncSessions { + err := f(key, &session) + if err != nil { + return err + } + } + + return nil +} + +type syncReporter struct { + config *SyncReporterConfig + workQueue chan *models.Package + done chan bool + wg sync.WaitGroup + sessions *syncSessionPool } func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { @@ -89,37 +151,47 @@ func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { return nil, fmt.Errorf("failed to create gRPC client: %w", err) } + // TODO: Auto-discover config using CI environment variables + // if enabled by the user + + syncSessionPool := syncSessionPool{ + syncSessions: make(map[string]syncSession), + } + trigger := controltowerv1.ToolTrigger_TOOL_TRIGGER_MANUAL source := packagev1.ProjectSourceType_PROJECT_SOURCE_TYPE_UNSPECIFIED - logger.Debugf("Report Sync: Creating tool session for project: %s, version: %s", - config.ProjectName, config.ProjectVersion) + if !config.EnableMultiProjectSync { + logger.Debugf("Report Sync: Creating tool session for project: %s, version: %s", + config.ProjectName, config.ProjectVersion) - toolServiceClient := controltowerv1grpc.NewToolServiceClient(client) - toolSessionRes, err := toolServiceClient.CreateToolSession(context.Background(), - &controltowerv1.CreateToolSessionRequest{ - ToolName: config.ToolName, - ToolVersion: config.ToolVersion, - ProjectName: config.ProjectName, - ProjectVersion: &config.ProjectVersion, - ProjectSource: &source, - Trigger: &trigger, - }) - if err != nil { - return nil, fmt.Errorf("failed to create tool session: %w", err) + toolServiceClient := controltowerv1grpc.NewToolServiceClient(client) + toolSessionRes, err := toolServiceClient.CreateToolSession(context.Background(), + &controltowerv1.CreateToolSessionRequest{ + ToolName: config.ToolName, + ToolVersion: config.ToolVersion, + ProjectName: config.ProjectName, + ProjectVersion: &config.ProjectVersion, + ProjectSource: &source, + Trigger: &trigger, + }) + if err != nil { + return nil, fmt.Errorf("failed to create tool session: %w", err) + } + + logger.Debugf("Report Sync: Tool data upload session ID: %s", + toolSessionRes.GetToolSession().GetToolSessionId()) + + syncSessionPool.addPrimarySession(toolSessionRes.GetToolSession().GetToolSessionId(), + toolServiceClient) } - logger.Debugf("Report Sync: Tool data upload session ID: %s", - toolSessionRes.GetToolSession().GetToolSessionId()) - done := make(chan bool) self := &syncReporter{ - config: &config, - done: done, - workQueue: make(chan *models.Package, 1000), - client: client, - toolServiceClient: toolServiceClient, - sessionId: toolSessionRes.GetToolSession().GetToolSessionId(), + config: &config, + done: done, + workQueue: make(chan *models.Package, 1000), + sessions: &syncSessionPool, } self.startWorkers() @@ -148,18 +220,20 @@ func (s *syncReporter) Finish() error { s.wg.Wait() close(s.done) - logger.Debugf("Report Sync: Completing tool session: %s", s.sessionId) + return s.sessions.forEach(func(_ string, session *syncSession) error { + logger.Debugf("Report Sync: Completing tool session: %s", session.sessionId) - _, err := s.toolServiceClient.CompleteToolSession(context.Background(), - &controltowerv1.CompleteToolSessionRequest{ - ToolSession: &controltowerv1.ToolSession{ - ToolSessionId: s.sessionId, - }, + _, err := session.toolServiceClient.CompleteToolSession(context.Background(), + &controltowerv1.CompleteToolSessionRequest{ + ToolSession: &controltowerv1.ToolSession{ + ToolSessionId: session.sessionId, + }, - Status: controltowerv1.CompleteToolSessionRequest_STATUS_SUCCESS, - }) + Status: controltowerv1.CompleteToolSessionRequest_STATUS_SUCCESS, + }) - return err + return err + }) } func (s *syncReporter) queuePackage(pkg *models.Package) { @@ -195,10 +269,16 @@ func (s *syncReporter) syncReportWorker() { func (s *syncReporter) syncPackage(pkg *models.Package) error { defer s.wg.Done() + session, err := s.sessions.getSession(pkg.Manifest.Path) + if err != nil { + return fmt.Errorf("failed to get session for package: %s/%s/%s: %w", + pkg.Manifest.Ecosystem, pkg.GetName(), pkg.GetVersion(), err) + } + // Build the base package manifest and package req := controltowerv1.PublishPackageInsightRequest{ ToolSession: &controltowerv1.ToolSession{ - ToolSessionId: s.sessionId, + ToolSessionId: session.sessionId, }, Manifest: &packagev1.PackageManifest{ @@ -311,7 +391,7 @@ func (s *syncReporter) syncPackage(pkg *models.Package) error { // not a single scorecard per package. Rather there is a scorecard per project. Since // a package may be related to multiple projects, we will have multiple related scorecards. - _, err = s.toolServiceClient.PublishPackageInsight(context.Background(), &req) + _, err = session.toolServiceClient.PublishPackageInsight(context.Background(), &req) if err != nil { return fmt.Errorf("failed to publish package insight: %w", err) } diff --git a/scan.go b/scan.go index a196d6e..50f05ad 100644 --- a/scan.go +++ b/scan.go @@ -140,7 +140,7 @@ func newScanCommand() *cobra.Command { "Enable syncing report data to cloud") cmd.Flags().StringVarP(&syncReportProject, "report-sync-project", "", "", "Project name to use in cloud") - cmd.Flags().StringVarP(&syncReportStream, "report-sync-stream", "", "", + cmd.Flags().StringVarP(&syncReportStream, "report-sync-project-version", "", "", "Project stream name (e.g. branch) to use in cloud") cmd.Flags().StringArrayVarP(&trustedRegistryUrls, "trusted-registry", "", []string{}, "Trusted registry URLs to use for package manifest verification") From fca2b8e3ab25aba28a516325236d0c023de9b32a Mon Sep 17 00:00:00 2001 From: abhisek Date: Mon, 30 Sep 2024 13:59:12 +0530 Subject: [PATCH 06/28] feat: Cloud report sync support multi-project sync --- pkg/readers/github_reader.go | 2 +- pkg/reporter/sync.go | 47 +++++++++++++++++++++++++++++++++++- scan.go | 16 +++++++----- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/pkg/readers/github_reader.go b/pkg/readers/github_reader.go index d27631e..21c7b37 100644 --- a/pkg/readers/github_reader.go +++ b/pkg/readers/github_reader.go @@ -129,7 +129,7 @@ func (p *githubReader) processTopLevelLockfiles(ctx context.Context, client *git return err } - pm.SetDisplayPath(entry.GetURL()) + pm.SetDisplayPath(gitUrl.GetHttpCloneURL()) err = handler(pm, NewManifestModelReader(pm)) if err != nil { return err diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index eabe189..0491e8e 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -78,6 +78,14 @@ func (s *syncSessionPool) addPrimarySession(sessionId string, client controltowe } } +func (s *syncSessionPool) hasKeyedSession(key string) bool { + s.mu.RLock() + defer s.mu.RUnlock() + + _, ok := s.syncSessions[key] + return ok +} + func (s *syncSessionPool) addKeyedSession(key, sessionId string, client controltowerv1grpc.ToolServiceClient) { s.mu.Lock() defer s.mu.Unlock() @@ -122,6 +130,7 @@ type syncReporter struct { workQueue chan *models.Package done chan bool wg sync.WaitGroup + client *grpc.ClientConn sessions *syncSessionPool } @@ -191,6 +200,7 @@ func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { config: &config, done: done, workQueue: make(chan *models.Package, 1000), + client: client, sessions: &syncSessionPool, } @@ -203,6 +213,40 @@ func (s *syncReporter) Name() string { } func (s *syncReporter) AddManifest(manifest *models.PackageManifest) { + manifestSessionKey := manifest.Path + if s.config.EnableMultiProjectSync && !s.sessions.hasKeyedSession(manifestSessionKey) { + projectName := manifest.GetDisplayPath() + projectVersion := "main" + + source := packagev1.ProjectSourceType_PROJECT_SOURCE_TYPE_UNSPECIFIED + trigger := controltowerv1.ToolTrigger_TOOL_TRIGGER_MANUAL + + logger.Debugf("Report Sync: Creating tool session for project: %s, version: %s", + projectName, projectVersion) + + toolServiceClient := controltowerv1grpc.NewToolServiceClient(s.client) + toolSessionRes, err := toolServiceClient.CreateToolSession(context.Background(), + &controltowerv1.CreateToolSessionRequest{ + ToolName: s.config.ToolName, + ToolVersion: s.config.ToolVersion, + ProjectName: projectName, + ProjectVersion: &projectVersion, + ProjectSource: &source, + Trigger: &trigger, + }) + if err != nil { + logger.Errorf("failed to create tool session for project: %s/%s: %v", + projectName, projectVersion, err) + } + + logger.Debugf("Report Sync: Tool data upload session ID: %s", + toolSessionRes.GetToolSession().GetToolSessionId()) + + s.sessions.addKeyedSession(manifestSessionKey, + toolSessionRes.GetToolSession().GetToolSessionId(), toolServiceClient) + + } + // We are ignoring the error here because we are asynchronously handling the sync of Manifest _ = readers.NewManifestModelReader(manifest).EnumPackages(func(pkg *models.Package) error { s.queuePackage(pkg) @@ -269,7 +313,8 @@ func (s *syncReporter) syncReportWorker() { func (s *syncReporter) syncPackage(pkg *models.Package) error { defer s.wg.Done() - session, err := s.sessions.getSession(pkg.Manifest.Path) + manifestSessionKey := pkg.Manifest.Path + session, err := s.sessions.getSession(manifestSessionKey) if err != nil { return fmt.Errorf("failed to get session for package: %s/%s/%s: %w", pkg.Manifest.Ecosystem, pkg.GetName(), pkg.GetVersion(), err) diff --git a/scan.go b/scan.go index 50f05ad..a7785e5 100644 --- a/scan.go +++ b/scan.go @@ -51,6 +51,7 @@ var ( disableAuthVerifyBeforeScan bool syncReport bool syncReportProject string + syncEnableMultiProject bool graphReportDirectory string syncReportStream string listExperimentalParsers bool @@ -140,6 +141,8 @@ func newScanCommand() *cobra.Command { "Enable syncing report data to cloud") cmd.Flags().StringVarP(&syncReportProject, "report-sync-project", "", "", "Project name to use in cloud") + cmd.Flags().BoolVarP(&syncEnableMultiProject, "report-sync-multi-project", "", false, + "Lazily create cloud sessions for multiple projects (per manifest)") cmd.Flags().StringVarP(&syncReportStream, "report-sync-project-version", "", "", "Project stream name (e.g. branch) to use in cloud") cmd.Flags().StringArrayVarP(&trustedRegistryUrls, "trusted-registry", "", []string{}, @@ -394,12 +397,13 @@ func internalStartScan() error { if syncReport { rp, err := reporter.NewSyncReporter(reporter.SyncReporterConfig{ - ToolName: "vet", - ToolVersion: version, - ProjectName: syncReportProject, - ProjectVersion: syncReportStream, - ControlTowerBaseUrl: auth.DefaultControlTowerUrl(), - ControlTowerToken: auth.ApiKey(), + ToolName: "vet", + ToolVersion: version, + ProjectName: syncReportProject, + ProjectVersion: syncReportStream, + ControlTowerBaseUrl: auth.DefaultControlTowerUrl(), + ControlTowerToken: auth.ApiKey(), + EnableMultiProjectSync: syncEnableMultiProject, }) if err != nil { return err From a9b424dc51d4345c8b98d4b725817216c9ff43ae Mon Sep 17 00:00:00 2001 From: abhisek Date: Tue, 1 Oct 2024 09:09:14 +0530 Subject: [PATCH 07/28] refactor: Cloud report sync to enable syncing violation events --- pkg/reporter/sync.go | 45 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index 0491e8e..5421e7d 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -125,9 +125,14 @@ func (s *syncSessionPool) forEach(f func(key string, session *syncSession) error return nil } +type workItem struct { + pkg *models.Package + event *analyzer.AnalyzerEvent +} + type syncReporter struct { config *SyncReporterConfig - workQueue chan *models.Package + workQueue chan *workItem done chan bool wg sync.WaitGroup client *grpc.ClientConn @@ -199,7 +204,7 @@ func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { self := &syncReporter{ config: &config, done: done, - workQueue: make(chan *models.Package, 1000), + workQueue: make(chan *workItem, 1000), client: client, sessions: &syncSessionPool, } @@ -255,6 +260,7 @@ func (s *syncReporter) AddManifest(manifest *models.PackageManifest) { } func (s *syncReporter) AddAnalyzerEvent(event *analyzer.AnalyzerEvent) { + s.queueEvent(event) } func (s *syncReporter) AddPolicyEvent(event *policy.PolicyEvent) { @@ -280,9 +286,14 @@ func (s *syncReporter) Finish() error { }) } +func (s *syncReporter) queueEvent(event *analyzer.AnalyzerEvent) { + s.wg.Add(1) + s.workQueue <- &workItem{event: event} +} + func (s *syncReporter) queuePackage(pkg *models.Package) { s.wg.Add(1) - s.workQueue <- pkg + s.workQueue <- &workItem{pkg: pkg} } func (s *syncReporter) startWorkers() { @@ -299,10 +310,17 @@ func (s *syncReporter) startWorkers() { func (s *syncReporter) syncReportWorker() { for { select { - case pkg := <-s.workQueue: - err := s.syncPackage(pkg) - if err != nil { - logger.Errorf("failed to sync package: %v", err) + case item := <-s.workQueue: + if item.event != nil { + err := s.syncEvent(item.event) + if err != nil { + logger.Errorf("failed to sync event: %v", err) + } + } else if item.pkg != nil { + err := s.syncPackage(item.pkg) + if err != nil { + logger.Errorf("failed to sync package: %v", err) + } } case <-s.done: return @@ -310,6 +328,19 @@ func (s *syncReporter) syncReportWorker() { } } +func (s *syncReporter) syncEvent(event *analyzer.AnalyzerEvent) error { + defer s.wg.Done() + + pkg := event.Package + filter := event.Filter + + if pkg == nil || filter == nil || pkg.Manifest == nil { + return fmt.Errorf("failed to sync event: invalid event data") + } + + return nil +} + func (s *syncReporter) syncPackage(pkg *models.Package) error { defer s.wg.Done() From fce0410ae35d7f3d1eb092394ad728cc92e9b3af Mon Sep 17 00:00:00 2001 From: abhisek Date: Tue, 1 Oct 2024 12:00:17 +0530 Subject: [PATCH 08/28] feat: Add support for publishing policy violation --- go.mod | 4 +-- go.sum | 12 +++------ pkg/reporter/sync.go | 64 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 33b1b1e..829e577 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/safedep/vet go 1.22.1 require ( - buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240928092914-054512bde05f.1 - buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240928092914-054512bde05f.2 + buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241001040428-5024b95e2438.1 + buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241001040428-5024b95e2438.2 github.com/AlecAivazis/survey/v2 v2.3.7 github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/anchore/syft v1.11.1 diff --git a/go.sum b/go.sum index f863f3b..7ddc458 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,9 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2 h1:cFrEG/pJch6t62+jqndcPXeTNkYcztS4tBRgNkR+drw= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2/go.mod h1:ylS4c28ACSI59oJrOdW4pHS4n0Hw4TgSPHn8rpHl4Yw= -buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240927074119-125b1e169aaf.1 h1:2ELSEnzC34KBVKPsmdzbFSUdZoCa56K/xb6bQ/QKfd4= -buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240927074119-125b1e169aaf.1/go.mod h1:N2s2AvQRTd39jzo6zQL1b7aohwR6HF8J6pyXbBzbkak= -buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240928092914-054512bde05f.1 h1:D25CwoCuLxqjaHYtlWmRaGXrXWeqPW3+eGWozHKRbFw= -buf.build/gen/go/safedep/api/grpc/go v1.5.1-20240928092914-054512bde05f.1/go.mod h1:tkD4uIlOlf/6Zt/zeRoWyfmwuV3sJdGvFolWB41YVPs= -buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240927074119-125b1e169aaf.2 h1:UZdrFL+T3SUjJy8rX8N3HD4gb18Wp1gcPmIHKbEG3cA= -buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240927074119-125b1e169aaf.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= -buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240928092914-054512bde05f.2 h1:A9H0rP48/ZhngHW/8zJj+l1zRJYakvgEMw2KuwQCBkA= -buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20240928092914-054512bde05f.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241001040428-5024b95e2438.1 h1:nQMeHCwT5hnmDgzX1oYuaPIz+hV442uWwdsP0TJ4qYc= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241001040428-5024b95e2438.1/go.mod h1:+aEd+E2o+EacpWkrNgH6Zb1oZRfG+jefNMovX918l9E= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241001040428-5024b95e2438.2 h1:XO8i9KutEuRIkoPB6wYtIXI3RIWQEmol5CE8Y/WTjaI= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241001040428-5024b95e2438.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index 5421e7d..53c9c09 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -11,10 +11,12 @@ import ( "buf.build/gen/go/safedep/api/grpc/go/safedep/services/controltower/v1/controltowerv1grpc" packagev1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/package/v1" + policyv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/policy/v1" vulnerabilityv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/vulnerability/v1" controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/controltower/v1" drygrpc "github.com/safedep/dry/adapters/grpc" "github.com/safedep/dry/utils" + "github.com/safedep/vet/gen/checks" "github.com/safedep/vet/pkg/analyzer" "github.com/safedep/vet/pkg/common/logger" "github.com/safedep/vet/pkg/models" @@ -338,6 +340,68 @@ func (s *syncReporter) syncEvent(event *analyzer.AnalyzerEvent) error { return fmt.Errorf("failed to sync event: invalid event data") } + manifestSessionKey := pkg.Manifest.Path + session, err := s.sessions.getSession(manifestSessionKey) + if err != nil { + return fmt.Errorf("failed to get session for package: %s/%s/%s: %w", + pkg.Manifest.Ecosystem, pkg.GetName(), pkg.GetVersion(), err) + } + + checkType := policyv1.RuleCheck_RULE_CHECK_UNSPECIFIED + switch filter.GetCheckType() { + case checks.CheckType_CheckTypeVulnerability: + checkType = policyv1.RuleCheck_RULE_CHECK_VULNERABILITY + case checks.CheckType_CheckTypeLicense: + checkType = policyv1.RuleCheck_RULE_CHECK_LICENSE + case checks.CheckType_CheckTypeMalware: + checkType = policyv1.RuleCheck_RULE_CHECK_MALWARE + case checks.CheckType_CheckTypeMaintenance: + checkType = policyv1.RuleCheck_RULE_CHECK_MAINTENANCE + case checks.CheckType_CheckTypePopularity: + checkType = policyv1.RuleCheck_RULE_CHECK_POPULARITY + case checks.CheckType_CheckTypeSecurityScorecard: + checkType = policyv1.RuleCheck_RULE_CHECK_PROJECT_SCORECARD + default: + logger.Warnf("unsupported check type: %s", filter.GetCheckType()) + } + + req := controltowerv1.PublishPolicyViolationRequest{ + ToolSession: &controltowerv1.ToolSession{ + ToolSessionId: session.sessionId, + }, + + Manifest: &packagev1.PackageManifest{ + Ecosystem: pkg.Manifest.GetControlTowerSpecEcosystem(), + Namespace: &pkg.Manifest.Path, + Name: pkg.Manifest.GetDisplayPath(), + }, + + PackageVersion: &packagev1.PackageVersion{ + Package: &packagev1.Package{ + Ecosystem: pkg.Manifest.GetControlTowerSpecEcosystem(), + Name: pkg.Name, + }, + + Version: pkg.Version, + }, + + Violation: &policyv1.Violation{ + Rule: &policyv1.Rule{ + Name: filter.GetName(), + Description: filter.GetSummary(), + Value: filter.GetValue(), + Check: checkType, + }, + + Evidences: []*policyv1.ViolationEvidence{}, + }, + } + + _, err = session.toolServiceClient.PublishPolicyViolation(context.Background(), &req) + if err != nil { + return fmt.Errorf("failed to publish policy violation: %w", err) + } + return nil } From 476cd4d29d52675679258b1dd445135f79fd9dfa Mon Sep 17 00:00:00 2001 From: abhisek Date: Wed, 2 Oct 2024 21:57:57 +0530 Subject: [PATCH 09/28] refactor: gRPC connection setup into auth package --- auth.go | 2 +- cmd/cloud/main.go | 13 +++++++++++++ internal/auth/grpc.go | 45 +++++++++++++++++++++++++++++++++++++++++++ main.go | 2 ++ pkg/reporter/sync.go | 38 ++++++------------------------------ scan.go | 8 ++++++-- 6 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 cmd/cloud/main.go create mode 100644 internal/auth/grpc.go diff --git a/auth.go b/auth.go index 7565882..fb26b5f 100644 --- a/auth.go +++ b/auth.go @@ -23,7 +23,7 @@ var ( func newAuthCommand() *cobra.Command { cmd := &cobra.Command{ Use: "auth", - Short: "Configure and verify Insights API authentication", + Short: "[Deprecated] Use cloud command", RunE: func(cmd *cobra.Command, args []string) error { return errors.New("a valid sub-command is required") }, diff --git a/cmd/cloud/main.go b/cmd/cloud/main.go new file mode 100644 index 0000000..dfa33a7 --- /dev/null +++ b/cmd/cloud/main.go @@ -0,0 +1,13 @@ +package cloud + +import "github.com/spf13/cobra" + +func NewCloudCommand() *cobra.Command { + return &cobra.Command{ + Use: "cloud", + Short: "Manage and query cloud resources (control plane)", + RunE: func(cmd *cobra.Command, args []string) error { + return cmd.Help() + }, + } +} diff --git a/internal/auth/grpc.go b/internal/auth/grpc.go new file mode 100644 index 0000000..b7dfd2c --- /dev/null +++ b/internal/auth/grpc.go @@ -0,0 +1,45 @@ +package auth + +import ( + "fmt" + "net/http" + "net/url" + "os" + + "github.com/safedep/vet/pkg/common/logger" + "google.golang.org/grpc" + + drygrpc "github.com/safedep/dry/adapters/grpc" +) + +// Create a gRPC client connection for the control plane +// based on available configuration +func ControlPlaneClientConnection(name string) (*grpc.ClientConn, error) { + parsedUrl, err := url.Parse(DefaultControlTowerUrl()) + if err != nil { + return nil, err + } + + host, port := parsedUrl.Hostname(), parsedUrl.Port() + if port == "" { + port = "443" + } + + logger.Debugf("ControlTower host: %s, port: %s", host, port) + + // For local development, we use the mock user. + vetTenantId := os.Getenv("VET_CONTROL_TOWER_TENANT_ID") + vetTenantMockUser := os.Getenv("VET_CONTROL_TOWER_MOCK_USER") + + headers := http.Header{} + headers.Set("x-tenant-id", vetTenantId) + headers.Set("x-mock-user", vetTenantMockUser) + + client, err := drygrpc.GrpcClient(name, host, port, + ApiKey(), headers, []grpc.DialOption{}) + if err != nil { + return nil, fmt.Errorf("failed to create gRPC client: %w", err) + } + + return client, nil +} diff --git a/main.go b/main.go index 3bdf251..4d2f4e9 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "strconv" "github.com/safedep/dry/utils" + "github.com/safedep/vet/cmd/cloud" "github.com/safedep/vet/internal/ui" "github.com/safedep/vet/pkg/common/logger" "github.com/safedep/vet/pkg/exceptions" @@ -64,6 +65,7 @@ func main() { cmd.AddCommand(newCodeCommand()) cmd.AddCommand(newVersionCommand()) cmd.AddCommand(newConnectCommand()) + cmd.AddCommand(cloud.NewCloudCommand()) cobra.OnInitialize(func() { printBanner() diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index 53c9c09..e77fda5 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -3,9 +3,6 @@ package reporter import ( "context" "fmt" - "net/http" - "net/url" - "os" "strings" "sync" @@ -14,7 +11,6 @@ import ( policyv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/policy/v1" vulnerabilityv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/vulnerability/v1" controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/controltower/v1" - drygrpc "github.com/safedep/dry/adapters/grpc" "github.com/safedep/dry/utils" "github.com/safedep/vet/gen/checks" "github.com/safedep/vet/pkg/analyzer" @@ -32,9 +28,8 @@ const ( ) type SyncReporterConfig struct { - // ControlTower API Base URL - ControlTowerBaseUrl string - ControlTowerToken string + // gRPC connection for ControlTower + ClientConnection *grpc.ClientConn // Enable multi-project syncing // In this case, a new project is created per package manifest @@ -142,29 +137,8 @@ type syncReporter struct { } func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { - parsedUrl, err := url.Parse(config.ControlTowerBaseUrl) - if err != nil { - return nil, fmt.Errorf("failed to parse ControlTower base URL: %w", err) - } - - host, port := parsedUrl.Hostname(), parsedUrl.Port() - if port == "" { - port = "443" - } - - logger.Debugf("ControlTower host: %s, port: %s", host, port) - - vetTenantId := os.Getenv("VET_CONTROL_TOWER_TENANT_ID") - vetTenantMockUser := os.Getenv("VET_CONTROL_TOWER_MOCK_USER") // Used in dev - - headers := http.Header{} - headers.Set("x-tenant-id", vetTenantId) - headers.Set("x-mock-user", vetTenantMockUser) - - client, err := drygrpc.GrpcClient("vet-sync", host, port, - config.ControlTowerToken, headers, []grpc.DialOption{}) - if err != nil { - return nil, fmt.Errorf("failed to create gRPC client: %w", err) + if config.ClientConnection == nil { + return nil, fmt.Errorf("missing gRPC client connection") } // TODO: Auto-discover config using CI environment variables @@ -181,7 +155,7 @@ func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { logger.Debugf("Report Sync: Creating tool session for project: %s, version: %s", config.ProjectName, config.ProjectVersion) - toolServiceClient := controltowerv1grpc.NewToolServiceClient(client) + toolServiceClient := controltowerv1grpc.NewToolServiceClient(config.ClientConnection) toolSessionRes, err := toolServiceClient.CreateToolSession(context.Background(), &controltowerv1.CreateToolSessionRequest{ ToolName: config.ToolName, @@ -207,7 +181,7 @@ func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { config: &config, done: done, workQueue: make(chan *workItem, 1000), - client: client, + client: config.ClientConnection, sessions: &syncSessionPool, } diff --git a/scan.go b/scan.go index a7785e5..b51b39f 100644 --- a/scan.go +++ b/scan.go @@ -396,14 +396,18 @@ func internalStartScan() error { } if syncReport { + clientConn, err := auth.ControlPlaneClientConnection("vet-sync") + if err != nil { + return err + } + rp, err := reporter.NewSyncReporter(reporter.SyncReporterConfig{ ToolName: "vet", ToolVersion: version, ProjectName: syncReportProject, ProjectVersion: syncReportStream, - ControlTowerBaseUrl: auth.DefaultControlTowerUrl(), - ControlTowerToken: auth.ApiKey(), EnableMultiProjectSync: syncEnableMultiProject, + ClientConnection: clientConn, }) if err != nil { return err From debe15e572a3c59216a0dc268ca00645a2b74303 Mon Sep 17 00:00:00 2001 From: abhisek Date: Wed, 2 Oct 2024 23:41:26 +0530 Subject: [PATCH 10/28] feat: Add cloud query command --- cmd/cloud/main.go | 6 +- cmd/cloud/query.go | 113 +++++++++++++++++++++++++++++++ go.mod | 4 +- go.sum | 8 +-- pkg/cloud/cloud.go | 3 + pkg/cloud/query/query_service.go | 42 ++++++++++++ pkg/cloud/query/response.go | 48 +++++++++++++ 7 files changed, 217 insertions(+), 7 deletions(-) create mode 100644 cmd/cloud/query.go create mode 100644 pkg/cloud/cloud.go create mode 100644 pkg/cloud/query/query_service.go create mode 100644 pkg/cloud/query/response.go diff --git a/cmd/cloud/main.go b/cmd/cloud/main.go index dfa33a7..f7602c4 100644 --- a/cmd/cloud/main.go +++ b/cmd/cloud/main.go @@ -3,11 +3,15 @@ package cloud import "github.com/spf13/cobra" func NewCloudCommand() *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "cloud", Short: "Manage and query cloud resources (control plane)", RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }, } + + cmd.AddCommand(newQueryCommand()) + + return cmd } diff --git a/cmd/cloud/query.go b/cmd/cloud/query.go new file mode 100644 index 0000000..9014bb3 --- /dev/null +++ b/cmd/cloud/query.go @@ -0,0 +1,113 @@ +package cloud + +import ( + "errors" + "os" + "sort" + + "github.com/jedib0t/go-pretty/v6/table" + "github.com/safedep/vet/internal/auth" + "github.com/safedep/vet/pkg/cloud/query" + "github.com/safedep/vet/pkg/common/logger" + "github.com/spf13/cobra" +) + +var ( + querySql string +) + +func newQueryCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "query", + Short: "Query cloud resources", + RunE: func(cmd *cobra.Command, args []string) error { + return cmd.Help() + }, + } + + cmd.AddCommand(newQueryExecuteCommand()) + + return cmd +} + +func newQueryExecuteCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "execute", + Short: "Execute a query", + RunE: func(cmd *cobra.Command, args []string) error { + err := executeQuery() + if err != nil { + logger.Errorf("Failed to execute query: %v", err) + } + + return nil + }, + } + + cmd.Flags().StringVarP(&querySql, "sql", "s", "", "SQL query to execute") + + return cmd +} + +func executeQuery() error { + if querySql == "" { + return errors.New("SQL string is required") + } + + client, err := auth.ControlPlaneClientConnection("vet-cloud-query") + if err != nil { + return err + } + + queryService, err := query.NewQueryService(client) + if err != nil { + return err + } + + response, err := queryService.ExecuteSql(querySql) + if err != nil { + return err + } + + return renderQueryResponseAsTable(response) +} + +func renderQueryResponseAsTable(response *query.QueryResponse) error { + tbl := table.NewWriter() + tbl.SetOutputMirror(os.Stdout) + tbl.SetStyle(table.StyleLight) + + if response.Count() == 0 { + logger.Infof("No results found") + return nil + } + + // Header + headers := []string{} + response.GetRow(0).ForEachField(func(key string, _ interface{}) { + headers = append(headers, key) + }) + + sort.Strings(headers) + + headerRow := []interface{}{} + for _, header := range headers { + headerRow = append(headerRow, header) + } + + tbl.AppendHeader(headerRow) + + // Ensure we have a consistent order of columns + response.ForEachRow(func(row *query.QueryRow) { + rowValues := []interface{}{} + for _, header := range headers { + rowValues = append(rowValues, row.GetField(header)) + } + + tbl.AppendRow(rowValues) + tbl.AppendSeparator() + }) + + tbl.Render() + return nil +} diff --git a/go.mod b/go.mod index 829e577..394e3ba 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/safedep/vet go 1.22.1 require ( - buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241001040428-5024b95e2438.1 - buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241001040428-5024b95e2438.2 + buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241002100539-9b93cced4b10.1 + buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241002100539-9b93cced4b10.2 github.com/AlecAivazis/survey/v2 v2.3.7 github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/anchore/syft v1.11.1 diff --git a/go.sum b/go.sum index 7ddc458..c84c676 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2 h1:cFrEG/pJch6t62+jqndcPXeTNkYcztS4tBRgNkR+drw= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2/go.mod h1:ylS4c28ACSI59oJrOdW4pHS4n0Hw4TgSPHn8rpHl4Yw= -buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241001040428-5024b95e2438.1 h1:nQMeHCwT5hnmDgzX1oYuaPIz+hV442uWwdsP0TJ4qYc= -buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241001040428-5024b95e2438.1/go.mod h1:+aEd+E2o+EacpWkrNgH6Zb1oZRfG+jefNMovX918l9E= -buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241001040428-5024b95e2438.2 h1:XO8i9KutEuRIkoPB6wYtIXI3RIWQEmol5CE8Y/WTjaI= -buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241001040428-5024b95e2438.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241002100539-9b93cced4b10.1 h1:U+pGWWpAHlz2+12wVzLC4yUc/oZV9cswW5jr1vrRYqY= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241002100539-9b93cced4b10.1/go.mod h1:mL26RCu1W/JVQ4HXTJMMv24cfKfxD1K00BeOKknuDMk= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241002100539-9b93cced4b10.2 h1:7CMpO8cC93Oe75a5row5mHHe+zSSMszvF2uvDEQpRxc= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241002100539-9b93cced4b10.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= diff --git a/pkg/cloud/cloud.go b/pkg/cloud/cloud.go new file mode 100644 index 0000000..3c412de --- /dev/null +++ b/pkg/cloud/cloud.go @@ -0,0 +1,3 @@ +// Package cloud contains the services for interacting with SafeDep +// Cloud. It uses SafeDep gRPC API for communication. +package cloud diff --git a/pkg/cloud/query/query_service.go b/pkg/cloud/query/query_service.go new file mode 100644 index 0000000..82d0cf3 --- /dev/null +++ b/pkg/cloud/query/query_service.go @@ -0,0 +1,42 @@ +package query + +import ( + "context" + + "buf.build/gen/go/safedep/api/grpc/go/safedep/services/controltower/v1/controltowerv1grpc" + controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/controltower/v1" + "google.golang.org/grpc" +) + +type queryService struct { + client *grpc.ClientConn +} + +func NewQueryService(client *grpc.ClientConn) (*queryService, error) { + return &queryService{client: client}, nil +} + +func (q *queryService) ExecuteSql(sql string) (*QueryResponse, error) { + queryServiceClient := controltowerv1grpc.NewQueryServiceClient(q.client) + + res, err := queryServiceClient.QueryBySql(context.Background(), &controltowerv1.QueryBySqlRequest{ + Query: sql, + PageSize: 100, + }) + + if err != nil { + return nil, err + } + + var response QueryResponse + for _, row := range res.Rows { + rowMap := make(map[string]interface{}) + for key, val := range row.Fields { + rowMap[key] = val.GetStringValue() + } + + response = append(response, rowMap) + } + + return &response, nil +} diff --git a/pkg/cloud/query/response.go b/pkg/cloud/query/response.go new file mode 100644 index 0000000..d0c606b --- /dev/null +++ b/pkg/cloud/query/response.go @@ -0,0 +1,48 @@ +package query + +type QueryRow map[string]interface{} +type QueryResponse []QueryRow + +func (q *QueryResponse) Count() int { + if q == nil { + return 0 + } + + return len(*q) +} + +func (q *QueryResponse) GetRow(index int) *QueryRow { + if q.Count() <= index { + return nil + } + + return &(*q)[index] +} + +func (q *QueryResponse) ForEachRow(fn func(*QueryRow)) { + if q == nil { + return + } + + for _, row := range *q { + fn(&row) + } +} + +func (q *QueryRow) ForEachField(fn func(string, interface{})) { + if q == nil { + return + } + + for key, val := range *q { + fn(key, val) + } +} + +func (q *QueryRow) GetField(key string) interface{} { + if q == nil { + return nil + } + + return (*q)[key] +} From c0e915cfaa16050359211e5bb0aa8217a1bb321d Mon Sep 17 00:00:00 2001 From: abhisek Date: Sat, 5 Oct 2024 08:56:24 +0530 Subject: [PATCH 11/28] Remove auth trial command for cloud commands --- auth.go | 32 -------------------------------- internal/auth/verify.go | 4 ++++ pkg/reporter/sync.go | 2 ++ 3 files changed, 6 insertions(+), 32 deletions(-) diff --git a/auth.go b/auth.go index fb26b5f..b871196 100644 --- a/auth.go +++ b/auth.go @@ -2,7 +2,6 @@ package main import ( "errors" - "fmt" "os" "github.com/AlecAivazis/survey/v2" @@ -16,7 +15,6 @@ import ( var ( authInsightApiBaseUrl string authControlPlaneApiBaseUrl string - authTrialEmail string authCommunity bool ) @@ -34,7 +32,6 @@ func newAuthCommand() *cobra.Command { cmd.AddCommand(configureAuthCommand()) cmd.AddCommand(verifyAuthCommand()) - cmd.AddCommand(trialsRegisterCommand()) return cmd } @@ -101,32 +98,3 @@ func verifyAuthCommand() *cobra.Command { return cmd } - -func trialsRegisterCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "trial", - RunE: func(cmd *cobra.Command, args []string) error { - client := auth.NewTrialRegistrationClient(auth.TrialConfig{ - Email: authTrialEmail, - ControlPlaneApiUrl: authControlPlaneApiBaseUrl, - }) - - res, err := client.Execute() - if err != nil { - fmt.Printf("Error: %v\n", err) - os.Exit(1) - } - - fmt.Printf("Trial registration successful with Id:%s\n", res.Id) - fmt.Printf("Check your email (%s) for API key and usage instructions\n", authTrialEmail) - fmt.Printf("The trial API key will expire on %s\n", res.ExpiresAt.String()) - - return nil - }, - } - - cmd.Flags().StringVarP(&authTrialEmail, "email", "", "", - "Email address to use for sending trial API key") - - return cmd -} diff --git a/internal/auth/verify.go b/internal/auth/verify.go index e4a1b2b..9dfcc7b 100644 --- a/internal/auth/verify.go +++ b/internal/auth/verify.go @@ -23,6 +23,10 @@ func Verify(config *VerifyConfig) error { return nil } + if ApiKey() == "" { + return fmt.Errorf("API key is not set") + } + logger.Infof("Verifying auth token using Control Plane: %s", config.ControlPlaneApiUrl) client, err := cpv1.NewClientWithResponses(config.ControlPlaneApiUrl) diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index e77fda5..285cf77 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -155,6 +155,7 @@ func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { logger.Debugf("Report Sync: Creating tool session for project: %s, version: %s", config.ProjectName, config.ProjectVersion) + // Refactor this into a common session creator function toolServiceClient := controltowerv1grpc.NewToolServiceClient(config.ClientConnection) toolSessionRes, err := toolServiceClient.CreateToolSession(context.Background(), &controltowerv1.CreateToolSessionRequest{ @@ -205,6 +206,7 @@ func (s *syncReporter) AddManifest(manifest *models.PackageManifest) { logger.Debugf("Report Sync: Creating tool session for project: %s, version: %s", projectName, projectVersion) + // Refactor this into a common session creator function toolServiceClient := controltowerv1grpc.NewToolServiceClient(s.client) toolSessionRes, err := toolServiceClient.CreateToolSession(context.Background(), &controltowerv1.CreateToolSessionRequest{ From d016c63174c986d62b4c671542f0fc6274055e88 Mon Sep 17 00:00:00 2001 From: abhisek Date: Mon, 7 Oct 2024 23:04:18 +0530 Subject: [PATCH 12/28] refactor: grpc client to separate cloud and sync API --- auth.go | 33 +++++++++++++++++++++++++++++++-- internal/auth/auth.go | 19 ++++++++++++++----- internal/auth/grpc.go | 25 ++++++++++++++++++++----- scan.go | 4 ++-- 4 files changed, 67 insertions(+), 14 deletions(-) diff --git a/auth.go b/auth.go index b871196..5641267 100644 --- a/auth.go +++ b/auth.go @@ -2,6 +2,7 @@ package main import ( "errors" + "fmt" "os" "github.com/AlecAivazis/survey/v2" @@ -15,20 +16,24 @@ import ( var ( authInsightApiBaseUrl string authControlPlaneApiBaseUrl string + authSyncApiBaseUrl string authCommunity bool + authTenantDomain string ) func newAuthCommand() *cobra.Command { cmd := &cobra.Command{ Use: "auth", - Short: "[Deprecated] Use cloud command", + Short: "Configure vet authentication", RunE: func(cmd *cobra.Command, args []string) error { return errors.New("a valid sub-command is required") }, } cmd.PersistentFlags().StringVarP(&authControlPlaneApiBaseUrl, "control-plane", "", - auth.DefaultControlTowerUrl(), "Base URL of Control Plane API") + auth.ControlTowerUrl(), "Base URL of Control Plane API") + cmd.PersistentFlags().StringVarP(&authSyncApiBaseUrl, "sync", "", auth.SyncApiUrl(), + "Base URL of Sync API") cmd.AddCommand(configureAuthCommand()) cmd.AddCommand(verifyAuthCommand()) @@ -55,11 +60,31 @@ func configureAuthCommand() *cobra.Command { logger.Fatalf("Failed to setup auth: %v", err) } + if auth.TenantDomain() != "" && auth.TenantDomain() != authTenantDomain { + ui.PrintWarning(fmt.Sprintf("Tenant domain mismatch. Existing: %s, New: %s, continue? ", + auth.TenantDomain(), authTenantDomain)) + + var confirm bool + err = survey.AskOne(&survey.Confirm{ + Message: "Do you want to continue?", + }, &confirm) + + if err != nil { + logger.Fatalf("Failed to setup auth: %v", err) + } + + if !confirm { + return nil + } + } + err = auth.Configure(auth.Config{ ApiUrl: authInsightApiBaseUrl, ApiKey: string(key), ControlPlaneApiUrl: authControlPlaneApiBaseUrl, + SyncApiUrl: authSyncApiBaseUrl, Community: authCommunity, + TenantDomain: authTenantDomain, }) if err != nil { @@ -71,11 +96,15 @@ func configureAuthCommand() *cobra.Command { }, } + cmd.Flags().StringVarP(&authTenantDomain, "tenant-domain", "", "", + "Tenant domain for SafeDep Cloud") cmd.Flags().StringVarP(&authInsightApiBaseUrl, "api", "", auth.DefaultApiUrl(), "Base URL of Insights API") cmd.Flags().BoolVarP(&authCommunity, "community", "", false, "Use community API endpoint for Insights") + _ = cmd.MarkFlagRequired("tenant-domain") + return cmd } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index dc3272a..bfb3caa 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -17,10 +17,10 @@ const ( defaultApiUrl = "https://api.safedep.io/insights/v1" defaultCommunityApiUrl = "https://api.safedep.io/insights-community/v1" - defaultSyncApiUrl = "https://api.safedep.io/sync/v1" // gRPC service base URL. - defaultControlPlaneApiUrl = "https://api.safedep.io" + defaultSyncApiUrl = "https://api.safedep.io" + defaultControlPlaneApiUrl = "https://cloud.safedep.io" homeRelativeConfigPath = ".safedep/vet-auth.yml" ) @@ -29,8 +29,9 @@ type Config struct { ApiUrl string `yaml:"api_url"` ApiKey string `yaml:"api_key"` Community bool `yaml:"community"` - ControlPlaneApiUrl string `yaml:"cp_api_url"` + ControlPlaneApiUrl string `yaml:"control_api_url"` SyncApiUrl string `yaml:"sync_api_url"` + TenantDomain string `yaml:"tenant_domain"` } // Global config to be used during runtime @@ -53,7 +54,7 @@ func DefaultCommunityApiUrl() string { return defaultCommunityApiUrl } -func DefaultSyncApiUrl() string { +func SyncApiUrl() string { if (globalConfig != nil) && (globalConfig.SyncApiUrl != "") { return globalConfig.SyncApiUrl } @@ -61,7 +62,7 @@ func DefaultSyncApiUrl() string { return defaultSyncApiUrl } -func DefaultControlTowerUrl() string { +func ControlTowerUrl() string { if (globalConfig != nil) && (globalConfig.ControlPlaneApiUrl != "") { return globalConfig.ControlPlaneApiUrl } @@ -69,6 +70,14 @@ func DefaultControlTowerUrl() string { return defaultControlPlaneApiUrl } +func TenantDomain() string { + if globalConfig != nil { + return globalConfig.TenantDomain + } + + return "" +} + func ApiUrl() string { if url, ok := os.LookupEnv(apiUrlEnvKey); ok { return url diff --git a/internal/auth/grpc.go b/internal/auth/grpc.go index b7dfd2c..f4b640f 100644 --- a/internal/auth/grpc.go +++ b/internal/auth/grpc.go @@ -15,7 +15,15 @@ import ( // Create a gRPC client connection for the control plane // based on available configuration func ControlPlaneClientConnection(name string) (*grpc.ClientConn, error) { - parsedUrl, err := url.Parse(DefaultControlTowerUrl()) + return cloudClientConnection(name, ControlTowerUrl()) +} + +func SyncClientConnection(name string) (*grpc.ClientConn, error) { + return cloudClientConnection(name, SyncApiUrl()) +} + +func cloudClientConnection(name, loc string) (*grpc.ClientConn, error) { + parsedUrl, err := url.Parse(loc) if err != nil { return nil, err } @@ -27,13 +35,20 @@ func ControlPlaneClientConnection(name string) (*grpc.ClientConn, error) { logger.Debugf("ControlTower host: %s, port: %s", host, port) - // For local development, we use the mock user. - vetTenantId := os.Getenv("VET_CONTROL_TOWER_TENANT_ID") - vetTenantMockUser := os.Getenv("VET_CONTROL_TOWER_MOCK_USER") + vetTenantId := TenantDomain() + tenantIdOverride := os.Getenv("VET_CONTROL_TOWER_TENANT_ID") + + if tenantIdOverride != "" { + vetTenantId = tenantIdOverride + } headers := http.Header{} headers.Set("x-tenant-id", vetTenantId) - headers.Set("x-mock-user", vetTenantMockUser) + + vetTenantMockUser := os.Getenv("VET_CONTROL_TOWER_MOCK_USER") + if vetTenantMockUser != "" { + headers.Set("x-mock-user", vetTenantMockUser) + } client, err := drygrpc.GrpcClient(name, host, port, ApiKey(), headers, []grpc.DialOption{}) diff --git a/scan.go b/scan.go index b51b39f..945d1ee 100644 --- a/scan.go +++ b/scan.go @@ -179,7 +179,7 @@ func listParsersCommand() *cobra.Command { func startScan() { if !disableAuthVerifyBeforeScan { err := auth.Verify(&auth.VerifyConfig{ - ControlPlaneApiUrl: auth.DefaultControlTowerUrl(), + ControlPlaneApiUrl: auth.ControlTowerUrl(), }) // We will fallback to community mode by default to provide @@ -396,7 +396,7 @@ func internalStartScan() error { } if syncReport { - clientConn, err := auth.ControlPlaneClientConnection("vet-sync") + clientConn, err := auth.SyncClientConnection("vet-sync") if err != nil { return err } From 30ac9c043ee428235bd1aa68b1d32bd4ee0fc571 Mon Sep 17 00:00:00 2001 From: abhisek Date: Tue, 8 Oct 2024 14:03:17 +0530 Subject: [PATCH 13/28] feat: Add support for cloud login --- cmd/cloud/login.go | 56 ++++++++++++++++++++++++++++++++++++ cmd/cloud/main.go | 1 + go.mod | 3 ++ go.sum | 4 +-- internal/auth/auth.go | 66 +++++++++++++++++++++++++++++++++++++++++++ internal/auth/grpc.go | 8 +++--- 6 files changed, 132 insertions(+), 6 deletions(-) create mode 100644 cmd/cloud/login.go diff --git a/cmd/cloud/login.go b/cmd/cloud/login.go new file mode 100644 index 0000000..f2bff03 --- /dev/null +++ b/cmd/cloud/login.go @@ -0,0 +1,56 @@ +package cloud + +import ( + "context" + "fmt" + "net/http" + + "github.com/cli/oauth/device" + "github.com/safedep/vet/internal/auth" + "github.com/safedep/vet/internal/ui" + "github.com/safedep/vet/pkg/common/logger" + "github.com/spf13/cobra" +) + +func newCloudLoginCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "login", + Short: "Login to the SafeDep cloud for management", + RunE: func(cmd *cobra.Command, args []string) error { + err := executeDeviceAuthFlow() + if err != nil { + logger.Errorf("Failed to login to the SafeDep cloud: %v", err) + } + + return nil + }, + } + + return cmd +} + +func executeDeviceAuthFlow() error { + code, err := device.RequestCode(http.DefaultClient, + auth.CloudIdentityServiceDeviceCodeUrl(), + auth.CloudIdentityServiceClientId(), + []string{"offline_access", "openid", "profile", "email"}, + device.WithAudience(auth.CloudIdentityServiceAudience())) + if err != nil { + return fmt.Errorf("failed to request device code: %w", err) + } + + ui.PrintSuccess("Please visit %s and enter the code %s to authenticate", + code.VerificationURIComplete, code.UserCode) + + token, err := device.Wait(context.TODO(), + http.DefaultClient, auth.CloudIdentityServiceTokenUrl(), + device.WaitOptions{ + ClientID: auth.CloudIdentityServiceClientId(), + DeviceCode: code, + }) + if err != nil { + return fmt.Errorf("failed to authenticate: %w", err) + } + + return auth.PersistCloudTokens(token.Token, token.RefreshToken) +} diff --git a/cmd/cloud/main.go b/cmd/cloud/main.go index f7602c4..ff07b10 100644 --- a/cmd/cloud/main.go +++ b/cmd/cloud/main.go @@ -11,6 +11,7 @@ func NewCloudCommand() *cobra.Command { }, } + cmd.AddCommand(newCloudLoginCommand()) cmd.AddCommand(newQueryCommand()) return cmd diff --git a/go.mod b/go.mod index 394e3ba..0582503 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,9 @@ require ( replace github.com/owenrumney/go-sarif/v2 v2.3.1 => github.com/safedep/go-sarif/v2 v2.3.1 +// https://github.com/cli/oauth/pull/68 +replace github.com/cli/oauth v1.0.1 => github.com/abhisek/oauth v1.0.1-audience + require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2 // indirect github.com/BurntSushi/toml v1.4.0 // indirect diff --git a/go.sum b/go.sum index c84c676..4ca58a9 100644 --- a/go.sum +++ b/go.sum @@ -91,6 +91,8 @@ github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azu github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/Shopify/goreferrer v0.0.0-20240724165105-aceaa0259138 h1:gjbp60h8IZQbN/TpDaYJedWbbD1h1aDPEwWnYWaDaUY= github.com/Shopify/goreferrer v0.0.0-20240724165105-aceaa0259138/go.mod h1:NYezi6wtnJtBm5btoprXc5SvAdqH0XTXWnUup0MptAI= +github.com/abhisek/oauth v1.0.1-audience h1:nFfFPI3sRc1ofYIqt12WPFmSYSHsBBo4boLVmASiQgw= +github.com/abhisek/oauth v1.0.1-audience/go.mod h1:qd/FX8ZBD6n1sVNQO3aIdRxeu5LGw9WhKnYhIIoC2A4= github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE= github.com/acobaugh/osrelease v0.1.0/go.mod h1:4bFEs0MtgHNHBrmHCt67gNisnabCRAlzdVasCEGHTWY= github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY= @@ -189,8 +191,6 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38 github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/cli/browser v1.0.0/go.mod h1:IEWkHYbLjkhtjwwWlwTHW2lGxeS5gezEQBMLTwDHf5Q= -github.com/cli/oauth v1.0.1 h1:pXnTFl/qUegXHK531Dv0LNjW4mLx626eS42gnzfXJPA= -github.com/cli/oauth v1.0.1/go.mod h1:qd/FX8ZBD6n1sVNQO3aIdRxeu5LGw9WhKnYhIIoC2A4= github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= diff --git a/internal/auth/auth.go b/internal/auth/auth.go index bfb3caa..5c450f6 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -23,6 +23,13 @@ const ( defaultControlPlaneApiUrl = "https://cloud.safedep.io" homeRelativeConfigPath = ".safedep/vet-auth.yml" + + // https://dev-dkwn3e2k4k1fornc.us.auth0.com/.well-known/openid-configuration + cloudIdentityServiceClientId = "VzkDpYHdGOHJ51w2iym0AEx68cdecM83" + cloudIdentityServiceAudience = "https://cloud.safedep.io" + cloudIdentityServiceBaseUrl = "https://dev-dkwn3e2k4k1fornc.us.auth0.com" + cloudIdentityServiceDeviceCodeUrl = "https://dev-dkwn3e2k4k1fornc.us.auth0.com/oauth/device/code" + cloudIdentityServiceTokenUrl = "https://dev-dkwn3e2k4k1fornc.us.auth0.com/oauth/token" ) type Config struct { @@ -32,6 +39,8 @@ type Config struct { ControlPlaneApiUrl string `yaml:"control_api_url"` SyncApiUrl string `yaml:"sync_api_url"` TenantDomain string `yaml:"tenant_domain"` + CloudAccessToken string `yaml:"cloud_access_token"` + CloudRefreshToken string `yaml:"cloud_refresh_token"` } // Global config to be used during runtime @@ -41,11 +50,32 @@ func init() { loadConfiguration() } +func DefaultConfig() Config { + return Config{ + ApiUrl: defaultApiUrl, + Community: false, + ControlPlaneApiUrl: defaultControlPlaneApiUrl, + SyncApiUrl: defaultSyncApiUrl, + } +} + func Configure(m Config) error { globalConfig = &m return persistConfiguration() } +func PersistCloudTokens(accessToken, refreshToken string) error { + if globalConfig == nil { + c := DefaultConfig() + globalConfig = &c + } + + globalConfig.CloudAccessToken = accessToken + globalConfig.CloudRefreshToken = refreshToken + + return persistConfiguration() +} + func DefaultApiUrl() string { return defaultApiUrl } @@ -54,6 +84,42 @@ func DefaultCommunityApiUrl() string { return defaultCommunityApiUrl } +func CloudIdentityServiceClientId() string { + return cloudIdentityServiceClientId +} + +func CloudIdentityServiceBaseUrl() string { + return cloudIdentityServiceBaseUrl +} + +func CloudIdentityServiceDeviceCodeUrl() string { + return cloudIdentityServiceDeviceCodeUrl +} + +func CloudIdentityServiceAudience() string { + return cloudIdentityServiceAudience +} + +func CloudIdentityServiceTokenUrl() string { + return cloudIdentityServiceTokenUrl +} + +func CloudAccessToken() string { + if globalConfig != nil { + return globalConfig.CloudAccessToken + } + + return "" +} + +func CloudRefreshToken() string { + if globalConfig != nil { + return globalConfig.CloudRefreshToken + } + + return "" +} + func SyncApiUrl() string { if (globalConfig != nil) && (globalConfig.SyncApiUrl != "") { return globalConfig.SyncApiUrl diff --git a/internal/auth/grpc.go b/internal/auth/grpc.go index f4b640f..d970286 100644 --- a/internal/auth/grpc.go +++ b/internal/auth/grpc.go @@ -15,14 +15,14 @@ import ( // Create a gRPC client connection for the control plane // based on available configuration func ControlPlaneClientConnection(name string) (*grpc.ClientConn, error) { - return cloudClientConnection(name, ControlTowerUrl()) + return cloudClientConnection(name, ControlTowerUrl(), CloudAccessToken()) } func SyncClientConnection(name string) (*grpc.ClientConn, error) { - return cloudClientConnection(name, SyncApiUrl()) + return cloudClientConnection(name, SyncApiUrl(), ApiKey()) } -func cloudClientConnection(name, loc string) (*grpc.ClientConn, error) { +func cloudClientConnection(name, loc, tok string) (*grpc.ClientConn, error) { parsedUrl, err := url.Parse(loc) if err != nil { return nil, err @@ -51,7 +51,7 @@ func cloudClientConnection(name, loc string) (*grpc.ClientConn, error) { } client, err := drygrpc.GrpcClient(name, host, port, - ApiKey(), headers, []grpc.DialOption{}) + tok, headers, []grpc.DialOption{}) if err != nil { return nil, fmt.Errorf("failed to create gRPC client: %w", err) } From a613190e64b220e9ab349c43b17d79d2f9171d15 Mon Sep 17 00:00:00 2001 From: abhisek Date: Wed, 9 Oct 2024 15:58:47 +0530 Subject: [PATCH 14/28] feat: Add cloud ping command --- cmd/cloud/main.go | 1 + cmd/cloud/ping.go | 49 +++++++++++++++++++++++++++++++++++++++++++ internal/auth/auth.go | 21 +++++++++++-------- main.go | 15 ++++--------- pkg/cloud/ping.go | 42 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 cmd/cloud/ping.go create mode 100644 pkg/cloud/ping.go diff --git a/cmd/cloud/main.go b/cmd/cloud/main.go index ff07b10..2e0a43a 100644 --- a/cmd/cloud/main.go +++ b/cmd/cloud/main.go @@ -13,6 +13,7 @@ func NewCloudCommand() *cobra.Command { cmd.AddCommand(newCloudLoginCommand()) cmd.AddCommand(newQueryCommand()) + cmd.AddCommand(newPingCommand()) return cmd } diff --git a/cmd/cloud/ping.go b/cmd/cloud/ping.go new file mode 100644 index 0000000..92452c8 --- /dev/null +++ b/cmd/cloud/ping.go @@ -0,0 +1,49 @@ +package cloud + +import ( + "time" + + "github.com/safedep/vet/internal/auth" + "github.com/safedep/vet/internal/ui" + "github.com/safedep/vet/pkg/cloud" + "github.com/safedep/vet/pkg/common/logger" + "github.com/spf13/cobra" +) + +func newPingCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "ping", + Short: "Ping the control plane to check authentication and connectivity", + RunE: func(cmd *cobra.Command, args []string) error { + err := pingControlPlane() + if err != nil { + logger.Errorf("Failed to ping control plane: %v", err) + } + + return nil + }, + } + + return cmd +} + +func pingControlPlane() error { + conn, err := auth.ControlPlaneClientConnection("vet-cloud-ping") + if err != nil { + return err + } + + pingService, err := cloud.NewPingService(conn) + if err != nil { + return err + } + + pr, err := pingService.Ping() + if err != nil { + return err + } + + ui.PrintSuccess("Ping successful. Started at %s, finished at %s", + pr.StartedAt.Format(time.RFC3339), pr.FinishedAt.Format(time.RFC3339)) + return nil +} diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 5c450f6..c37b325 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -5,6 +5,7 @@ import ( "os" "path/filepath" "strconv" + "time" "gopkg.in/yaml.v2" ) @@ -25,7 +26,7 @@ const ( homeRelativeConfigPath = ".safedep/vet-auth.yml" // https://dev-dkwn3e2k4k1fornc.us.auth0.com/.well-known/openid-configuration - cloudIdentityServiceClientId = "VzkDpYHdGOHJ51w2iym0AEx68cdecM83" + cloudIdentityServiceClientId = "xidzYke2rDMJmNyXId2dLpNs4DLm4yZX" // gitleaks:allow cloudIdentityServiceAudience = "https://cloud.safedep.io" cloudIdentityServiceBaseUrl = "https://dev-dkwn3e2k4k1fornc.us.auth0.com" cloudIdentityServiceDeviceCodeUrl = "https://dev-dkwn3e2k4k1fornc.us.auth0.com/oauth/device/code" @@ -33,14 +34,15 @@ const ( ) type Config struct { - ApiUrl string `yaml:"api_url"` - ApiKey string `yaml:"api_key"` - Community bool `yaml:"community"` - ControlPlaneApiUrl string `yaml:"control_api_url"` - SyncApiUrl string `yaml:"sync_api_url"` - TenantDomain string `yaml:"tenant_domain"` - CloudAccessToken string `yaml:"cloud_access_token"` - CloudRefreshToken string `yaml:"cloud_refresh_token"` + ApiUrl string `yaml:"api_url"` + ApiKey string `yaml:"api_key"` + Community bool `yaml:"community"` + ControlPlaneApiUrl string `yaml:"control_api_url"` + SyncApiUrl string `yaml:"sync_api_url"` + TenantDomain string `yaml:"tenant_domain"` + CloudAccessToken string `yaml:"cloud_access_token"` + CloudRefreshToken string `yaml:"cloud_refresh_token"` + CloudAccessTokenUpdatedAt time.Time `yaml:"cloud_access_token_updated_at"` } // Global config to be used during runtime @@ -72,6 +74,7 @@ func PersistCloudTokens(accessToken, refreshToken string) error { globalConfig.CloudAccessToken = accessToken globalConfig.CloudRefreshToken = refreshToken + globalConfig.CloudAccessTokenUpdatedAt = time.Now() return persistConfiguration() } diff --git a/main.go b/main.go index 4d2f4e9..62b77cf 100644 --- a/main.go +++ b/main.go @@ -24,17 +24,10 @@ var ( ) var banner string = ` - .----------------. .----------------. .----------------. -| .--------------. || .--------------. || .--------------. | -| | ____ ____ | || | _________ | || | _________ | | -| ||_ _| |_ _| | || | |_ ___ | | || | | _ _ | | | -| | \ \ / / | || | | |_ \_| | || | |_/ | | \_| | | -| | \ \ / / | || | | _| _ | || | | | | | -| | \ ' / | || | _| |___/ | | || | _| |_ | | -| | \_/ | || | |_________| | || | |_____| | | -| | | || | | || | | | -| '--------------' || '--------------' || '--------------' | - '----------------' '----------------' '----------------' +Yb dP 888888 888888 + Yb dP 88__ 88 + YbdP 88"" 88 + YP 888888 88 ` diff --git a/pkg/cloud/ping.go b/pkg/cloud/ping.go new file mode 100644 index 0000000..9ac8cc3 --- /dev/null +++ b/pkg/cloud/ping.go @@ -0,0 +1,42 @@ +package cloud + +import ( + "context" + "time" + + "buf.build/gen/go/safedep/api/grpc/go/safedep/services/controltower/v1/controltowerv1grpc" + controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/controltower/v1" + "github.com/oklog/ulid/v2" + "google.golang.org/grpc" +) + +type pingService struct { + conn *grpc.ClientConn +} + +type PingResponse struct { + StartedAt time.Time + FinishedAt time.Time +} + +func NewPingService(conn *grpc.ClientConn) (*pingService, error) { + return &pingService{conn: conn}, nil +} + +func (p *pingService) Ping() (*PingResponse, error) { + pr := PingResponse{ + StartedAt: time.Now(), + } + + pingService := controltowerv1grpc.NewPingServiceClient(p.conn) + _, err := pingService.Ping(context.Background(), &controltowerv1.PingRequest{ + Id: ulid.MustNew(ulid.Now(), nil).String(), + }) + + if err != nil { + return nil, err + } + + pr.FinishedAt = time.Now() + return &pr, nil +} From eeaf4e1e297ff8458017ca8b2f37f97680df417a Mon Sep 17 00:00:00 2001 From: abhisek Date: Wed, 9 Oct 2024 16:27:39 +0530 Subject: [PATCH 15/28] feat: Add cloud whoami command --- cmd/cloud/main.go | 1 + cmd/cloud/query.go | 2 +- cmd/cloud/whoami.go | 54 +++++++++++++++++++++++++++++++++++++++++++++ go.mod | 10 ++++----- go.sum | 16 +++++++------- pkg/cloud/user.go | 27 +++++++++++++++++++++++ 6 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 cmd/cloud/whoami.go create mode 100644 pkg/cloud/user.go diff --git a/cmd/cloud/main.go b/cmd/cloud/main.go index 2e0a43a..e67eea2 100644 --- a/cmd/cloud/main.go +++ b/cmd/cloud/main.go @@ -14,6 +14,7 @@ func NewCloudCommand() *cobra.Command { cmd.AddCommand(newCloudLoginCommand()) cmd.AddCommand(newQueryCommand()) cmd.AddCommand(newPingCommand()) + cmd.AddCommand(newWhoamiCommand()) return cmd } diff --git a/cmd/cloud/query.go b/cmd/cloud/query.go index 9014bb3..f5fac05 100644 --- a/cmd/cloud/query.go +++ b/cmd/cloud/query.go @@ -19,7 +19,7 @@ var ( func newQueryCommand() *cobra.Command { cmd := &cobra.Command{ Use: "query", - Short: "Query cloud resources", + Short: "Query risks by executing SQL queries", RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }, diff --git a/cmd/cloud/whoami.go b/cmd/cloud/whoami.go new file mode 100644 index 0000000..702f6dc --- /dev/null +++ b/cmd/cloud/whoami.go @@ -0,0 +1,54 @@ +package cloud + +import ( + "github.com/safedep/vet/internal/auth" + "github.com/safedep/vet/internal/ui" + "github.com/safedep/vet/pkg/cloud" + "github.com/safedep/vet/pkg/common/logger" + "github.com/spf13/cobra" +) + +func newWhoamiCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "whoami", + Short: "Print information about the current user", + RunE: func(cmd *cobra.Command, args []string) error { + err := executeWhoami() + if err != nil { + logger.Errorf("Failed to execute whoami: %v", err) + } + + return nil + }, + } + + return cmd +} + +func executeWhoami() error { + conn, err := auth.ControlPlaneClientConnection("vet-cloud-whoami") + if err != nil { + return err + } + + userService, err := cloud.NewUserService(conn) + if err != nil { + return err + } + + res, err := userService.CurrentUserInfo() + if err != nil { + return err + } + + ui.PrintSuccess("Authenticated as: %s <%s>", res.GetUser().GetName(), + res.GetUser().GetEmail()) + + ui.PrintSuccess("Has access to the following tenants:") + for _, access := range res.GetAccess() { + ui.PrintSuccess(" - %s [%d]", access.GetTenant().GetDomain(), + access.GetLevel()) + } + + return nil +} diff --git a/go.mod b/go.mod index 0582503..8afee65 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/safedep/vet go 1.22.1 require ( - buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241002100539-9b93cced4b10.1 - buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241002100539-9b93cced4b10.2 + buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241009065537-4ffd9786549f.1 + buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241009065537-4ffd9786549f.1 github.com/AlecAivazis/survey/v2 v2.3.7 github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/anchore/syft v1.11.1 @@ -21,6 +21,7 @@ require ( github.com/google/osv-scanner v1.8.4 github.com/jedib0t/go-pretty/v6 v6.5.9 github.com/kubescape/go-git-url v0.0.30 + github.com/oklog/ulid/v2 v2.1.0 github.com/owenrumney/go-sarif/v2 v2.3.3 github.com/package-url/packageurl-go v0.1.3 github.com/safedep/dry v0.0.0-20240927023913-bb455ab56626 @@ -31,7 +32,7 @@ require ( github.com/stretchr/testify v1.9.0 golang.org/x/oauth2 v0.23.0 google.golang.org/grpc v1.66.0 - google.golang.org/protobuf v1.34.2 + google.golang.org/protobuf v1.35.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -41,7 +42,7 @@ replace github.com/owenrumney/go-sarif/v2 v2.3.1 => github.com/safedep/go-sarif/ replace github.com/cli/oauth v1.0.1 => github.com/abhisek/oauth v1.0.1-audience require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2 // indirect + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.1-20240508200655-46a4cf4ba109.1 // indirect github.com/BurntSushi/toml v1.4.0 // indirect github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect github.com/CloudyKit/jet/v6 v6.2.0 // indirect @@ -155,7 +156,6 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nwaples/rardecode v1.1.3 // indirect - github.com/oklog/ulid/v2 v2.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pborman/indent v1.2.1 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect diff --git a/go.sum b/go.sum index 4ca58a9..afe04c0 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2 h1:cFrEG/pJch6t62+jqndcPXeTNkYcztS4tBRgNkR+drw= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2/go.mod h1:ylS4c28ACSI59oJrOdW4pHS4n0Hw4TgSPHn8rpHl4Yw= -buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241002100539-9b93cced4b10.1 h1:U+pGWWpAHlz2+12wVzLC4yUc/oZV9cswW5jr1vrRYqY= -buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241002100539-9b93cced4b10.1/go.mod h1:mL26RCu1W/JVQ4HXTJMMv24cfKfxD1K00BeOKknuDMk= -buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241002100539-9b93cced4b10.2 h1:7CMpO8cC93Oe75a5row5mHHe+zSSMszvF2uvDEQpRxc= -buf.build/gen/go/safedep/api/protocolbuffers/go v1.34.2-20241002100539-9b93cced4b10.2/go.mod h1:s12A8dY1Tq74LKOkUHLOOLXPJOaAhdVDAakFTSlB/cM= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.1-20240508200655-46a4cf4ba109.1 h1:PvjTFY+MqrYYulH74R8ddQodrEP1sThjkba8kcqO2dM= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.1-20240508200655-46a4cf4ba109.1/go.mod h1:Duw/9JoXkXIydyASnLYIiufkzySThoqavOsF+IihqvM= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241009065537-4ffd9786549f.1 h1:7+y3t/2/6sEf63xCX9ErNdsuFzB0Q18PIT14aAxz5wo= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241009065537-4ffd9786549f.1/go.mod h1:Io32CuF5oJZDSkWJVgKvfOBTqSHnC7mqh9dpqq/PSNA= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241009065537-4ffd9786549f.1 h1:F4fk9nhlB2ZU8odF5S/w/nS8r0htIbu6eKDKDBP+kzQ= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241009065537-4ffd9786549f.1/go.mod h1:WCxZaBpYxgWnSpauuzVhzbJawAp6uPXJPN5tbDpceQ0= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -1431,8 +1431,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/cloud/user.go b/pkg/cloud/user.go new file mode 100644 index 0000000..baba56c --- /dev/null +++ b/pkg/cloud/user.go @@ -0,0 +1,27 @@ +package cloud + +import ( + "context" + + "buf.build/gen/go/safedep/api/grpc/go/safedep/services/controltower/v1/controltowerv1grpc" + controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/controltower/v1" + "google.golang.org/grpc" +) + +type userService struct { + conn *grpc.ClientConn +} + +func NewUserService(conn *grpc.ClientConn) (*userService, error) { + return &userService{conn: conn}, nil +} + +func (s *userService) CurrentUserInfo() (*controltowerv1.GetUserInfoResponse, error) { + userService := controltowerv1grpc.NewUserServiceClient(s.conn) + res, err := userService.GetUserInfo(context.Background(), &controltowerv1.GetUserInfoRequest{}) + if err != nil { + return nil, err + } + + return res, nil +} From 7686e85e5237cadd643de4f20a2bd85cc277cc1f Mon Sep 17 00:00:00 2001 From: abhisek Date: Wed, 9 Oct 2024 16:42:05 +0530 Subject: [PATCH 16/28] feat: Add cloud register command --- cmd/cloud/main.go | 1 + cmd/cloud/register.go | 70 +++++++++++++++++++++++++++++++++++++++++ pkg/cloud/onboarding.go | 46 +++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 cmd/cloud/register.go create mode 100644 pkg/cloud/onboarding.go diff --git a/cmd/cloud/main.go b/cmd/cloud/main.go index e67eea2..9172885 100644 --- a/cmd/cloud/main.go +++ b/cmd/cloud/main.go @@ -12,6 +12,7 @@ func NewCloudCommand() *cobra.Command { } cmd.AddCommand(newCloudLoginCommand()) + cmd.AddCommand(newRegisterCommand()) cmd.AddCommand(newQueryCommand()) cmd.AddCommand(newPingCommand()) cmd.AddCommand(newWhoamiCommand()) diff --git a/cmd/cloud/register.go b/cmd/cloud/register.go new file mode 100644 index 0000000..3ed3dc4 --- /dev/null +++ b/cmd/cloud/register.go @@ -0,0 +1,70 @@ +package cloud + +import ( + "github.com/safedep/vet/internal/auth" + "github.com/safedep/vet/internal/ui" + "github.com/safedep/vet/pkg/cloud" + "github.com/safedep/vet/pkg/common/logger" + "github.com/spf13/cobra" +) + +var ( + registerEmail string + registerName string + registerOrgName string + registerOrgDomain string +) + +func newRegisterCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "register", + Short: "Register a new user and tenant", + RunE: func(cmd *cobra.Command, args []string) error { + err := registerUserTenant() + if err != nil { + logger.Errorf("Failed to register user: %v", err) + } + + return nil + }, + } + + cmd.Flags().StringVar(®isterEmail, "email", "cloud@safedep.io", "Email of the user (not required for SafeDep cloud)") + cmd.Flags().StringVar(®isterName, "name", "", "Name of the user") + cmd.Flags().StringVar(®isterOrgName, "org-name", "", "Name of the organization") + cmd.Flags().StringVar(®isterOrgDomain, "org-domain", "", "Domain of the organization") + + _ = cmd.MarkFlagRequired("name") + _ = cmd.MarkFlagRequired("org-name") + _ = cmd.MarkFlagRequired("org-domain") + + return cmd +} + +func registerUserTenant() error { + conn, err := auth.ControlPlaneClientConnection("vet-cloud-register") + if err != nil { + return err + } + + onboardingService, err := cloud.NewOnboardingService(conn) + if err != nil { + return err + } + + res, err := onboardingService.Register(&cloud.RegisterRequest{ + Name: registerName, + Email: registerEmail, + OrgName: registerOrgName, + OrgDomain: registerOrgDomain, + }) + + if err != nil { + return err + } + + ui.PrintSuccess("Registered user and tenant.") + ui.PrintSuccess("Tenant domain: %s", res.TenantDomain) + + return nil +} diff --git a/pkg/cloud/onboarding.go b/pkg/cloud/onboarding.go new file mode 100644 index 0000000..055db45 --- /dev/null +++ b/pkg/cloud/onboarding.go @@ -0,0 +1,46 @@ +package cloud + +import ( + "context" + + "buf.build/gen/go/safedep/api/grpc/go/safedep/services/controltower/v1/controltowerv1grpc" + controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/controltower/v1" + "google.golang.org/grpc" +) + +type onboardingService struct { + conn *grpc.ClientConn +} + +type RegisterRequest struct { + Email string + Name string + OrgName string + OrgDomain string +} + +type RegisterResponse struct { + TenantDomain string +} + +func NewOnboardingService(conn *grpc.ClientConn) (*onboardingService, error) { + return &onboardingService{conn}, nil +} + +func (s *onboardingService) Register(req *RegisterRequest) (*RegisterResponse, error) { + onbService := controltowerv1grpc.NewOnboardingServiceClient(s.conn) + res, err := onbService.OnboardUser(context.Background(), &controltowerv1.OnboardUserRequest{ + Email: req.Email, + Name: req.Name, + OrganizationName: req.OrgName, + OrganizationDomain: req.OrgDomain, + }) + + if err != nil { + return nil, err + } + + return &RegisterResponse{ + TenantDomain: res.GetTenant().GetDomain(), + }, nil +} From 7cb7e7fc955ad1cb350ff3d5747a912947bd91ab Mon Sep 17 00:00:00 2001 From: abhisek Date: Wed, 9 Oct 2024 17:06:01 +0530 Subject: [PATCH 17/28] fix: Persist tenant domain post onboarding and login --- cmd/cloud/login.go | 11 +++++++++-- cmd/cloud/register.go | 7 +++++++ internal/auth/auth.go | 19 ++++++++++++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/cmd/cloud/login.go b/cmd/cloud/login.go index f2bff03..39bd6ff 100644 --- a/cmd/cloud/login.go +++ b/cmd/cloud/login.go @@ -12,10 +12,14 @@ import ( "github.com/spf13/cobra" ) +var ( + loginTenantDomain string +) + func newCloudLoginCommand() *cobra.Command { cmd := &cobra.Command{ Use: "login", - Short: "Login to the SafeDep cloud for management", + Short: "Login to SafeDep cloud for management tasks", RunE: func(cmd *cobra.Command, args []string) error { err := executeDeviceAuthFlow() if err != nil { @@ -26,6 +30,9 @@ func newCloudLoginCommand() *cobra.Command { }, } + cmd.Flags().StringVar(&loginTenantDomain, "tenant", "", + "Domain of the tenant to login to for existing users") + return cmd } @@ -52,5 +59,5 @@ func executeDeviceAuthFlow() error { return fmt.Errorf("failed to authenticate: %w", err) } - return auth.PersistCloudTokens(token.Token, token.RefreshToken) + return auth.PersistCloudTokens(token.Token, token.RefreshToken, loginTenantDomain) } diff --git a/cmd/cloud/register.go b/cmd/cloud/register.go index 3ed3dc4..edcaaf2 100644 --- a/cmd/cloud/register.go +++ b/cmd/cloud/register.go @@ -1,6 +1,8 @@ package cloud import ( + "fmt" + "github.com/safedep/vet/internal/auth" "github.com/safedep/vet/internal/ui" "github.com/safedep/vet/pkg/cloud" @@ -66,5 +68,10 @@ func registerUserTenant() error { ui.PrintSuccess("Registered user and tenant.") ui.PrintSuccess("Tenant domain: %s", res.TenantDomain) + err = auth.PersistTenantDomain(res.TenantDomain) + if err != nil { + return fmt.Errorf("failed to persist tenant domain: %w", err) + } + return nil } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index c37b325..2600abe 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -66,12 +66,19 @@ func Configure(m Config) error { return persistConfiguration() } -func PersistCloudTokens(accessToken, refreshToken string) error { +func PersistCloudTokens(accessToken, refreshToken, domain string) error { if globalConfig == nil { c := DefaultConfig() globalConfig = &c } + // We are explicitly check for empty string for domain + // because we do not want to overwrite the domain if it is + // not provided. + if domain != "" { + globalConfig.TenantDomain = domain + } + globalConfig.CloudAccessToken = accessToken globalConfig.CloudRefreshToken = refreshToken globalConfig.CloudAccessTokenUpdatedAt = time.Now() @@ -79,6 +86,16 @@ func PersistCloudTokens(accessToken, refreshToken string) error { return persistConfiguration() } +func PersistTenantDomain(domain string) error { + if globalConfig == nil { + c := DefaultConfig() + globalConfig = &c + } + + globalConfig.TenantDomain = domain + return persistConfiguration() +} + func DefaultApiUrl() string { return defaultApiUrl } From d8d94b7c1a9ac21f9dc885f43800a10d9fe2985d Mon Sep 17 00:00:00 2001 From: abhisek Date: Wed, 9 Oct 2024 19:54:25 +0530 Subject: [PATCH 18/28] refactor: Remove deprecated API generated code --- Makefile | 6 +- gen/cpv1trials/trials.client.go | 297 ------ gen/cpv1trials/trials.types.go | 159 ---- gen/syncv1/sync.client.go | 639 ------------- gen/syncv1/sync.types.go | 1510 ------------------------------- internal/auth/trial.go | 77 -- 6 files changed, 3 insertions(+), 2685 deletions(-) delete mode 100644 gen/cpv1trials/trials.client.go delete mode 100644 gen/cpv1trials/trials.types.go delete mode 100644 gen/syncv1/sync.client.go delete mode 100644 gen/syncv1/sync.types.go delete mode 100644 internal/auth/trial.go diff --git a/Makefile b/Makefile index a8fca75..bb38417 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ SHELL := /bin/bash GITCOMMIT := $(shell git rev-parse HEAD) VERSION := "$(shell git describe --tags --abbrev=0)-$(shell git rev-parse --short HEAD)" -all: clean setup vet +all: quick-vet linter-install: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.0 @@ -70,10 +70,10 @@ setup: GO_CFLAGS=-X main.commit=$(GITCOMMIT) -X main.version=$(VERSION) GO_LDFLAGS=-ldflags "-w $(GO_CFLAGS)" -vet: oapi-codegen protoc-codegen +quick-vet: go build ${GO_LDFLAGS} -quick-vet: +vet: oapi-codegen protoc-codegen go build ${GO_LDFLAGS} .PHONY: test diff --git a/gen/cpv1trials/trials.client.go b/gen/cpv1trials/trials.client.go deleted file mode 100644 index 71357ee..0000000 --- a/gen/cpv1trials/trials.client.go +++ /dev/null @@ -1,297 +0,0 @@ -// Package cpv1trials provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT. -package cpv1trials - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "strings" -) - -// RequestEditorFn is the function signature for the RequestEditor callback function -type RequestEditorFn func(ctx context.Context, req *http.Request) error - -// Doer performs HTTP requests. -// -// The standard http.Client implements this interface. -type HttpRequestDoer interface { - Do(req *http.Request) (*http.Response, error) -} - -// Client which conforms to the OpenAPI3 specification for this service. -type Client struct { - // The endpoint of the server conforming to this interface, with scheme, - // https://api.deepmap.com for example. This can contain a path relative - // to the server, such as https://api.deepmap.com/dev-test, and all the - // paths in the swagger spec will be appended to the server. - Server string - - // Doer for performing requests, typically a *http.Client with any - // customized settings, such as certificate chains. - Client HttpRequestDoer - - // A list of callbacks for modifying requests which are generated before sending over - // the network. - RequestEditors []RequestEditorFn -} - -// ClientOption allows setting custom parameters during construction -type ClientOption func(*Client) error - -// Creates a new Client, with reasonable defaults -func NewClient(server string, opts ...ClientOption) (*Client, error) { - // create a client with sane default values - client := Client{ - Server: server, - } - // mutate client and add all optional params - for _, o := range opts { - if err := o(&client); err != nil { - return nil, err - } - } - // ensure the server URL always has a trailing slash - if !strings.HasSuffix(client.Server, "/") { - client.Server += "/" - } - // create httpClient, if not already present - if client.Client == nil { - client.Client = &http.Client{} - } - return &client, nil -} - -// WithHTTPClient allows overriding the default Doer, which is -// automatically created using http.Client. This is useful for tests. -func WithHTTPClient(doer HttpRequestDoer) ClientOption { - return func(c *Client) error { - c.Client = doer - return nil - } -} - -// WithRequestEditorFn allows setting up a callback function, which will be -// called right before sending the request. This can be used to mutate the request. -func WithRequestEditorFn(fn RequestEditorFn) ClientOption { - return func(c *Client) error { - c.RequestEditors = append(c.RequestEditors, fn) - return nil - } -} - -// The interface specification for the client above. -type ClientInterface interface { - // RegisterTrialUser request with any body - RegisterTrialUserWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - RegisterTrialUser(ctx context.Context, body RegisterTrialUserJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) -} - -func (c *Client) RegisterTrialUserWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewRegisterTrialUserRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) RegisterTrialUser(ctx context.Context, body RegisterTrialUserJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewRegisterTrialUserRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -// NewRegisterTrialUserRequest calls the generic RegisterTrialUser builder with application/json body -func NewRegisterTrialUserRequest(server string, body RegisterTrialUserJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewRegisterTrialUserRequestWithBody(server, "application/json", bodyReader) -} - -// NewRegisterTrialUserRequestWithBody generates requests for RegisterTrialUser with any type of body -func NewRegisterTrialUserRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/trials") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { - for _, r := range c.RequestEditors { - if err := r(ctx, req); err != nil { - return err - } - } - for _, r := range additionalEditors { - if err := r(ctx, req); err != nil { - return err - } - } - return nil -} - -// ClientWithResponses builds on ClientInterface to offer response payloads -type ClientWithResponses struct { - ClientInterface -} - -// NewClientWithResponses creates a new ClientWithResponses, which wraps -// Client with return type handling -func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { - client, err := NewClient(server, opts...) - if err != nil { - return nil, err - } - return &ClientWithResponses{client}, nil -} - -// WithBaseURL overrides the baseURL. -func WithBaseURL(baseURL string) ClientOption { - return func(c *Client) error { - newBaseURL, err := url.Parse(baseURL) - if err != nil { - return err - } - c.Server = newBaseURL.String() - return nil - } -} - -// ClientWithResponsesInterface is the interface specification for the client with responses above. -type ClientWithResponsesInterface interface { - // RegisterTrialUser request with any body - RegisterTrialUserWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RegisterTrialUserResponse, error) - - RegisterTrialUserWithResponse(ctx context.Context, body RegisterTrialUserJSONRequestBody, reqEditors ...RequestEditorFn) (*RegisterTrialUserResponse, error) -} - -type RegisterTrialUserResponse struct { - Body []byte - HTTPResponse *http.Response - JSON201 *TrialResponse - JSON403 *ApiError - JSON429 *ApiError - JSON500 *ApiError -} - -// Status returns HTTPResponse.Status -func (r RegisterTrialUserResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r RegisterTrialUserResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// RegisterTrialUserWithBodyWithResponse request with arbitrary body returning *RegisterTrialUserResponse -func (c *ClientWithResponses) RegisterTrialUserWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RegisterTrialUserResponse, error) { - rsp, err := c.RegisterTrialUserWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseRegisterTrialUserResponse(rsp) -} - -func (c *ClientWithResponses) RegisterTrialUserWithResponse(ctx context.Context, body RegisterTrialUserJSONRequestBody, reqEditors ...RequestEditorFn) (*RegisterTrialUserResponse, error) { - rsp, err := c.RegisterTrialUser(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseRegisterTrialUserResponse(rsp) -} - -// ParseRegisterTrialUserResponse parses an HTTP response from a RegisterTrialUserWithResponse call -func ParseRegisterTrialUserResponse(rsp *http.Response) (*RegisterTrialUserResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &RegisterTrialUserResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: - var dest TrialResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON201 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON403 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON429 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} diff --git a/gen/cpv1trials/trials.types.go b/gen/cpv1trials/trials.types.go deleted file mode 100644 index f98dab8..0000000 --- a/gen/cpv1trials/trials.types.go +++ /dev/null @@ -1,159 +0,0 @@ -// Package cpv1trials provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT. -package cpv1trials - -import ( - "encoding/json" - "fmt" - "time" - - openapi_types "github.com/deepmap/oapi-codegen/pkg/types" -) - -// Defines values for ApiErrorCode. -const ( - ApiErrorCodeApiGuardError ApiErrorCode = "api_guard_error" - - ApiErrorCodeApiGuardInvalidCredentials ApiErrorCode = "api_guard_invalid_credentials" - - ApiErrorCodeApiGuardRateLimitExceeded ApiErrorCode = "api_guard_rate_limit_exceeded" - - ApiErrorCodeApiGuardUnauthorized ApiErrorCode = "api_guard_unauthorized" - - ApiErrorCodeAppFeatureNotEnabled ApiErrorCode = "app_feature_not_enabled" - - ApiErrorCodeAppGenericError ApiErrorCode = "app_generic_error" - - ApiErrorCodeAppInsufficientParameters ApiErrorCode = "app_insufficient_parameters" - - ApiErrorCodeAppPackageVersionNotFound ApiErrorCode = "app_package_version_not_found" - - ApiErrorCodeAppSecurityError ApiErrorCode = "app_security_error" -) - -// Defines values for ApiErrorType. -const ( - ApiErrorTypeInternalError ApiErrorType = "internal_error" - - ApiErrorTypeInvalidRequest ApiErrorType = "invalid_request" - - ApiErrorTypeOperationFailed ApiErrorType = "operation_failed" -) - -// ApiError defines model for ApiError. -type ApiError struct { - // An error code identifying the error - Code *ApiErrorCode `json:"code,omitempty"` - - // A descriptive message about the error meant for developer consumption - Message *string `json:"message,omitempty"` - - // Optional error specific attributes - Params *ApiError_Params `json:"params,omitempty"` - - // An optional service or domain specific error group - Type *ApiErrorType `json:"type,omitempty"` -} - -// An error code identifying the error -type ApiErrorCode string - -// Optional error specific attributes -type ApiError_Params struct { - AdditionalProperties map[string]struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` - } `json:"-"` -} - -// An optional service or domain specific error group -type ApiErrorType string - -// TrialRequest defines model for TrialRequest. -type TrialRequest struct { - Email openapi_types.Email `json:"email"` -} - -// TrialResponse defines model for TrialResponse. -type TrialResponse struct { - // The expiry time of the API key - ExpiresAt *time.Time `json:"expires_at,omitempty"` - - // The ID of the trial registration request created in the system - Id *string `json:"id,omitempty"` -} - -// RegisterTrialUserJSONBody defines parameters for RegisterTrialUser. -type RegisterTrialUserJSONBody TrialRequest - -// RegisterTrialUserJSONRequestBody defines body for RegisterTrialUser for application/json ContentType. -type RegisterTrialUserJSONRequestBody RegisterTrialUserJSONBody - -// Getter for additional properties for ApiError_Params. Returns the specified -// element and whether it was found -func (a ApiError_Params) Get(fieldName string) (value struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` -}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for ApiError_Params -func (a *ApiError_Params) Set(fieldName string, value struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` -}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` - }) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for ApiError_Params to handle AdditionalProperties -func (a *ApiError_Params) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` - }) - for fieldName, fieldBuf := range object { - var fieldVal struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` - } - err := json.Unmarshal(fieldBuf, &fieldVal) - if err != nil { - return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) - } - a.AdditionalProperties[fieldName] = fieldVal - } - } - return nil -} - -// Override default JSON handling for ApiError_Params to handle AdditionalProperties -func (a ApiError_Params) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - for fieldName, field := range a.AdditionalProperties { - object[fieldName], err = json.Marshal(field) - if err != nil { - return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) - } - } - return json.Marshal(object) -} diff --git a/gen/syncv1/sync.client.go b/gen/syncv1/sync.client.go deleted file mode 100644 index 9f23749..0000000 --- a/gen/syncv1/sync.client.go +++ /dev/null @@ -1,639 +0,0 @@ -// Package syncv1 provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT. -package syncv1 - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "strings" - - "github.com/deepmap/oapi-codegen/pkg/runtime" -) - -// RequestEditorFn is the function signature for the RequestEditor callback function -type RequestEditorFn func(ctx context.Context, req *http.Request) error - -// Doer performs HTTP requests. -// -// The standard http.Client implements this interface. -type HttpRequestDoer interface { - Do(req *http.Request) (*http.Response, error) -} - -// Client which conforms to the OpenAPI3 specification for this service. -type Client struct { - // The endpoint of the server conforming to this interface, with scheme, - // https://api.deepmap.com for example. This can contain a path relative - // to the server, such as https://api.deepmap.com/dev-test, and all the - // paths in the swagger spec will be appended to the server. - Server string - - // Doer for performing requests, typically a *http.Client with any - // customized settings, such as certificate chains. - Client HttpRequestDoer - - // A list of callbacks for modifying requests which are generated before sending over - // the network. - RequestEditors []RequestEditorFn -} - -// ClientOption allows setting custom parameters during construction -type ClientOption func(*Client) error - -// Creates a new Client, with reasonable defaults -func NewClient(server string, opts ...ClientOption) (*Client, error) { - // create a client with sane default values - client := Client{ - Server: server, - } - // mutate client and add all optional params - for _, o := range opts { - if err := o(&client); err != nil { - return nil, err - } - } - // ensure the server URL always has a trailing slash - if !strings.HasSuffix(client.Server, "/") { - client.Server += "/" - } - // create httpClient, if not already present - if client.Client == nil { - client.Client = &http.Client{} - } - return &client, nil -} - -// WithHTTPClient allows overriding the default Doer, which is -// automatically created using http.Client. This is useful for tests. -func WithHTTPClient(doer HttpRequestDoer) ClientOption { - return func(c *Client) error { - c.Client = doer - return nil - } -} - -// WithRequestEditorFn allows setting up a callback function, which will be -// called right before sending the request. This can be used to mutate the request. -func WithRequestEditorFn(fn RequestEditorFn) ClientOption { - return func(c *Client) error { - c.RequestEditors = append(c.RequestEditors, fn) - return nil - } -} - -// The interface specification for the client above. -type ClientInterface interface { - // CreateSyncJob request with any body - CreateSyncJobWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - CreateSyncJob(ctx context.Context, body CreateSyncJobJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // UpdateSyncJob request with any body - UpdateSyncJobWithBody(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - UpdateSyncJob(ctx context.Context, jobId string, body UpdateSyncJobJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // CreateJobIssue request with any body - CreateJobIssueWithBody(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - CreateJobIssue(ctx context.Context, jobId string, body CreateJobIssueJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) -} - -func (c *Client) CreateSyncJobWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewCreateSyncJobRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) CreateSyncJob(ctx context.Context, body CreateSyncJobJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewCreateSyncJobRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) UpdateSyncJobWithBody(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateSyncJobRequestWithBody(c.Server, jobId, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) UpdateSyncJob(ctx context.Context, jobId string, body UpdateSyncJobJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateSyncJobRequest(c.Server, jobId, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) CreateJobIssueWithBody(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewCreateJobIssueRequestWithBody(c.Server, jobId, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) CreateJobIssue(ctx context.Context, jobId string, body CreateJobIssueJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewCreateJobIssueRequest(c.Server, jobId, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -// NewCreateSyncJobRequest calls the generic CreateSyncJob builder with application/json body -func NewCreateSyncJobRequest(server string, body CreateSyncJobJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewCreateSyncJobRequestWithBody(server, "application/json", bodyReader) -} - -// NewCreateSyncJobRequestWithBody generates requests for CreateSyncJob with any type of body -func NewCreateSyncJobRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/jobs") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewUpdateSyncJobRequest calls the generic UpdateSyncJob builder with application/json body -func NewUpdateSyncJobRequest(server string, jobId string, body UpdateSyncJobJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewUpdateSyncJobRequestWithBody(server, jobId, "application/json", bodyReader) -} - -// NewUpdateSyncJobRequestWithBody generates requests for UpdateSyncJob with any type of body -func NewUpdateSyncJobRequestWithBody(server string, jobId string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "job_id", runtime.ParamLocationPath, jobId) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/jobs/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("PUT", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewCreateJobIssueRequest calls the generic CreateJobIssue builder with application/json body -func NewCreateJobIssueRequest(server string, jobId string, body CreateJobIssueJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewCreateJobIssueRequestWithBody(server, jobId, "application/json", bodyReader) -} - -// NewCreateJobIssueRequestWithBody generates requests for CreateJobIssue with any type of body -func NewCreateJobIssueRequestWithBody(server string, jobId string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "job_id", runtime.ParamLocationPath, jobId) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/jobs/%s/issues", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { - for _, r := range c.RequestEditors { - if err := r(ctx, req); err != nil { - return err - } - } - for _, r := range additionalEditors { - if err := r(ctx, req); err != nil { - return err - } - } - return nil -} - -// ClientWithResponses builds on ClientInterface to offer response payloads -type ClientWithResponses struct { - ClientInterface -} - -// NewClientWithResponses creates a new ClientWithResponses, which wraps -// Client with return type handling -func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { - client, err := NewClient(server, opts...) - if err != nil { - return nil, err - } - return &ClientWithResponses{client}, nil -} - -// WithBaseURL overrides the baseURL. -func WithBaseURL(baseURL string) ClientOption { - return func(c *Client) error { - newBaseURL, err := url.Parse(baseURL) - if err != nil { - return err - } - c.Server = newBaseURL.String() - return nil - } -} - -// ClientWithResponsesInterface is the interface specification for the client with responses above. -type ClientWithResponsesInterface interface { - // CreateSyncJob request with any body - CreateSyncJobWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateSyncJobResponse, error) - - CreateSyncJobWithResponse(ctx context.Context, body CreateSyncJobJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateSyncJobResponse, error) - - // UpdateSyncJob request with any body - UpdateSyncJobWithBodyWithResponse(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateSyncJobResponse, error) - - UpdateSyncJobWithResponse(ctx context.Context, jobId string, body UpdateSyncJobJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateSyncJobResponse, error) - - // CreateJobIssue request with any body - CreateJobIssueWithBodyWithResponse(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateJobIssueResponse, error) - - CreateJobIssueWithResponse(ctx context.Context, jobId string, body CreateJobIssueJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateJobIssueResponse, error) -} - -type CreateSyncJobResponse struct { - Body []byte - HTTPResponse *http.Response - JSON201 *AnyJobResponse - JSON403 *ApiError - JSON429 *ApiError - JSON500 *ApiError -} - -// Status returns HTTPResponse.Status -func (r CreateSyncJobResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r CreateSyncJobResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type UpdateSyncJobResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AnyJobResponse - JSON403 *ApiError - JSON429 *ApiError - JSON500 *ApiError -} - -// Status returns HTTPResponse.Status -func (r UpdateSyncJobResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r UpdateSyncJobResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type CreateJobIssueResponse struct { - Body []byte - HTTPResponse *http.Response - JSON201 *CreateIssueResponse - JSON403 *ApiError - JSON429 *ApiError - JSON500 *ApiError -} - -// Status returns HTTPResponse.Status -func (r CreateJobIssueResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r CreateJobIssueResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// CreateSyncJobWithBodyWithResponse request with arbitrary body returning *CreateSyncJobResponse -func (c *ClientWithResponses) CreateSyncJobWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateSyncJobResponse, error) { - rsp, err := c.CreateSyncJobWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseCreateSyncJobResponse(rsp) -} - -func (c *ClientWithResponses) CreateSyncJobWithResponse(ctx context.Context, body CreateSyncJobJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateSyncJobResponse, error) { - rsp, err := c.CreateSyncJob(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseCreateSyncJobResponse(rsp) -} - -// UpdateSyncJobWithBodyWithResponse request with arbitrary body returning *UpdateSyncJobResponse -func (c *ClientWithResponses) UpdateSyncJobWithBodyWithResponse(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateSyncJobResponse, error) { - rsp, err := c.UpdateSyncJobWithBody(ctx, jobId, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseUpdateSyncJobResponse(rsp) -} - -func (c *ClientWithResponses) UpdateSyncJobWithResponse(ctx context.Context, jobId string, body UpdateSyncJobJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateSyncJobResponse, error) { - rsp, err := c.UpdateSyncJob(ctx, jobId, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseUpdateSyncJobResponse(rsp) -} - -// CreateJobIssueWithBodyWithResponse request with arbitrary body returning *CreateJobIssueResponse -func (c *ClientWithResponses) CreateJobIssueWithBodyWithResponse(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateJobIssueResponse, error) { - rsp, err := c.CreateJobIssueWithBody(ctx, jobId, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseCreateJobIssueResponse(rsp) -} - -func (c *ClientWithResponses) CreateJobIssueWithResponse(ctx context.Context, jobId string, body CreateJobIssueJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateJobIssueResponse, error) { - rsp, err := c.CreateJobIssue(ctx, jobId, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseCreateJobIssueResponse(rsp) -} - -// ParseCreateSyncJobResponse parses an HTTP response from a CreateSyncJobWithResponse call -func ParseCreateSyncJobResponse(rsp *http.Response) (*CreateSyncJobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &CreateSyncJobResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: - var dest AnyJobResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON201 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON403 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON429 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseUpdateSyncJobResponse parses an HTTP response from a UpdateSyncJobWithResponse call -func ParseUpdateSyncJobResponse(rsp *http.Response) (*UpdateSyncJobResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &UpdateSyncJobResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AnyJobResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON403 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON429 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseCreateJobIssueResponse parses an HTTP response from a CreateJobIssueWithResponse call -func ParseCreateJobIssueResponse(rsp *http.Response) (*CreateJobIssueResponse, error) { - bodyBytes, err := ioutil.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &CreateJobIssueResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: - var dest CreateIssueResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON201 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON403 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON429 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ApiError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} diff --git a/gen/syncv1/sync.types.go b/gen/syncv1/sync.types.go deleted file mode 100644 index b9997d9..0000000 --- a/gen/syncv1/sync.types.go +++ /dev/null @@ -1,1510 +0,0 @@ -// Package syncv1 provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT. -package syncv1 - -import ( - "encoding/json" - "fmt" -) - -// Defines values for ApiErrorCode. -const ( - ApiErrorCodeApiGuardError ApiErrorCode = "api_guard_error" - - ApiErrorCodeApiGuardInvalidCredentials ApiErrorCode = "api_guard_invalid_credentials" - - ApiErrorCodeApiGuardRateLimitExceeded ApiErrorCode = "api_guard_rate_limit_exceeded" - - ApiErrorCodeApiGuardUnauthorized ApiErrorCode = "api_guard_unauthorized" - - ApiErrorCodeAppFeatureNotEnabled ApiErrorCode = "app_feature_not_enabled" - - ApiErrorCodeAppGenericError ApiErrorCode = "app_generic_error" - - ApiErrorCodeAppInsufficientParameters ApiErrorCode = "app_insufficient_parameters" - - ApiErrorCodeAppPackageVersionNotFound ApiErrorCode = "app_package_version_not_found" - - ApiErrorCodeAppSecurityError ApiErrorCode = "app_security_error" -) - -// Defines values for ApiErrorType. -const ( - ApiErrorTypeInternalError ApiErrorType = "internal_error" - - ApiErrorTypeInvalidRequest ApiErrorType = "invalid_request" - - ApiErrorTypeOperationFailed ApiErrorType = "operation_failed" -) - -// Defines values for CreateJobRequestGitRefType. -const ( - CreateJobRequestGitRefTypeGitBranch CreateJobRequestGitRefType = "git_branch" - - CreateJobRequestGitRefTypeGitTag CreateJobRequestGitRefType = "git_tag" -) - -// Defines values for CreateJobRequestProjectSource. -const ( - CreateJobRequestProjectSourceBitbucket CreateJobRequestProjectSource = "bitbucket" - - CreateJobRequestProjectSourceGenericCi CreateJobRequestProjectSource = "generic_ci" - - CreateJobRequestProjectSourceGithub CreateJobRequestProjectSource = "github" - - CreateJobRequestProjectSourceGitlab CreateJobRequestProjectSource = "gitlab" - - CreateJobRequestProjectSourceOther CreateJobRequestProjectSource = "other" -) - -// Defines values for CreateJobRequestToolType. -const ( - CreateJobRequestToolTypeOssVet CreateJobRequestToolType = "oss_vet" -) - -// Defines values for CreateJobRequestTriggerEvent. -const ( - CreateJobRequestTriggerEventGitScmPullRequest CreateJobRequestTriggerEvent = "git_scm_pull_request" - - CreateJobRequestTriggerEventGitScmPush CreateJobRequestTriggerEvent = "git_scm_push" - - CreateJobRequestTriggerEventGitScmTagRelease CreateJobRequestTriggerEvent = "git_scm_tag_release" - - CreateJobRequestTriggerEventManual CreateJobRequestTriggerEvent = "manual" - - CreateJobRequestTriggerEventOther CreateJobRequestTriggerEvent = "other" - - CreateJobRequestTriggerEventScheduled CreateJobRequestTriggerEvent = "scheduled" -) - -// Defines values for IssueIssueType. -const ( - IssueIssueTypePackageDependency IssueIssueType = "package_dependency" - - IssueIssueTypePackageLicense IssueIssueType = "package_license" - - IssueIssueTypePackageOpenssfScorecard IssueIssueType = "package_openssf_scorecard" - - IssueIssueTypePackageSourceInfo IssueIssueType = "package_source_info" - - IssueIssueTypePackageVulnerability IssueIssueType = "package_vulnerability" -) - -// Defines values for IssuePackageCommonVulnerabilitySeveritiesRisk. -const ( - IssuePackageCommonVulnerabilitySeveritiesRiskCRITICAL IssuePackageCommonVulnerabilitySeveritiesRisk = "CRITICAL" - - IssuePackageCommonVulnerabilitySeveritiesRiskHIGH IssuePackageCommonVulnerabilitySeveritiesRisk = "HIGH" - - IssuePackageCommonVulnerabilitySeveritiesRiskLOW IssuePackageCommonVulnerabilitySeveritiesRisk = "LOW" - - IssuePackageCommonVulnerabilitySeveritiesRiskMEDIUM IssuePackageCommonVulnerabilitySeveritiesRisk = "MEDIUM" - - IssuePackageCommonVulnerabilitySeveritiesRiskUNKNOWN IssuePackageCommonVulnerabilitySeveritiesRisk = "UNKNOWN" -) - -// Defines values for IssuePackageCommonVulnerabilitySeveritiesType. -const ( - IssuePackageCommonVulnerabilitySeveritiesTypeCVSSV2 IssuePackageCommonVulnerabilitySeveritiesType = "CVSS_V2" - - IssuePackageCommonVulnerabilitySeveritiesTypeCVSSV3 IssuePackageCommonVulnerabilitySeveritiesType = "CVSS_V3" - - IssuePackageCommonVulnerabilitySeveritiesTypeUNSPECIFIED IssuePackageCommonVulnerabilitySeveritiesType = "UNSPECIFIED" -) - -// Defines values for IssuePackageLicenseLicenseId. -const ( - IssuePackageLicenseLicenseIdAAL IssuePackageLicenseLicenseId = "AAL" - - IssuePackageLicenseLicenseIdADSL IssuePackageLicenseLicenseId = "ADSL" - - IssuePackageLicenseLicenseIdAFL11 IssuePackageLicenseLicenseId = "AFL-1.1" - - IssuePackageLicenseLicenseIdAFL12 IssuePackageLicenseLicenseId = "AFL-1.2" - - IssuePackageLicenseLicenseIdAFL20 IssuePackageLicenseLicenseId = "AFL-2.0" - - IssuePackageLicenseLicenseIdAFL21 IssuePackageLicenseLicenseId = "AFL-2.1" - - IssuePackageLicenseLicenseIdAFL30 IssuePackageLicenseLicenseId = "AFL-3.0" - - IssuePackageLicenseLicenseIdAGPL10 IssuePackageLicenseLicenseId = "AGPL-1.0" - - IssuePackageLicenseLicenseIdAGPL10Only IssuePackageLicenseLicenseId = "AGPL-1.0-only" - - IssuePackageLicenseLicenseIdAGPL10OrLater IssuePackageLicenseLicenseId = "AGPL-1.0-or-later" - - IssuePackageLicenseLicenseIdAGPL30 IssuePackageLicenseLicenseId = "AGPL-3.0" - - IssuePackageLicenseLicenseIdAGPL30Only IssuePackageLicenseLicenseId = "AGPL-3.0-only" - - IssuePackageLicenseLicenseIdAGPL30OrLater IssuePackageLicenseLicenseId = "AGPL-3.0-or-later" - - IssuePackageLicenseLicenseIdAMDPLPA IssuePackageLicenseLicenseId = "AMDPLPA" - - IssuePackageLicenseLicenseIdAML IssuePackageLicenseLicenseId = "AML" - - IssuePackageLicenseLicenseIdAMPAS IssuePackageLicenseLicenseId = "AMPAS" - - IssuePackageLicenseLicenseIdANTLRPD IssuePackageLicenseLicenseId = "ANTLR-PD" - - IssuePackageLicenseLicenseIdANTLRPDFallback IssuePackageLicenseLicenseId = "ANTLR-PD-fallback" - - IssuePackageLicenseLicenseIdAPAFML IssuePackageLicenseLicenseId = "APAFML" - - IssuePackageLicenseLicenseIdAPL10 IssuePackageLicenseLicenseId = "APL-1.0" - - IssuePackageLicenseLicenseIdAPSL10 IssuePackageLicenseLicenseId = "APSL-1.0" - - IssuePackageLicenseLicenseIdAPSL11 IssuePackageLicenseLicenseId = "APSL-1.1" - - IssuePackageLicenseLicenseIdAPSL12 IssuePackageLicenseLicenseId = "APSL-1.2" - - IssuePackageLicenseLicenseIdAPSL20 IssuePackageLicenseLicenseId = "APSL-2.0" - - IssuePackageLicenseLicenseIdAbstyles IssuePackageLicenseLicenseId = "Abstyles" - - IssuePackageLicenseLicenseIdAdobe2006 IssuePackageLicenseLicenseId = "Adobe-2006" - - IssuePackageLicenseLicenseIdAdobeGlyph IssuePackageLicenseLicenseId = "Adobe-Glyph" - - IssuePackageLicenseLicenseIdAfmparse IssuePackageLicenseLicenseId = "Afmparse" - - IssuePackageLicenseLicenseIdAladdin IssuePackageLicenseLicenseId = "Aladdin" - - IssuePackageLicenseLicenseIdApache10 IssuePackageLicenseLicenseId = "Apache-1.0" - - IssuePackageLicenseLicenseIdApache11 IssuePackageLicenseLicenseId = "Apache-1.1" - - IssuePackageLicenseLicenseIdApache20 IssuePackageLicenseLicenseId = "Apache-2.0" - - IssuePackageLicenseLicenseIdAppS2p IssuePackageLicenseLicenseId = "App-s2p" - - IssuePackageLicenseLicenseIdArphic1999 IssuePackageLicenseLicenseId = "Arphic-1999" - - IssuePackageLicenseLicenseIdArtistic10 IssuePackageLicenseLicenseId = "Artistic-1.0" - - IssuePackageLicenseLicenseIdArtistic10Cl8 IssuePackageLicenseLicenseId = "Artistic-1.0-cl8" - - IssuePackageLicenseLicenseIdArtistic10Perl IssuePackageLicenseLicenseId = "Artistic-1.0-Perl" - - IssuePackageLicenseLicenseIdArtistic20 IssuePackageLicenseLicenseId = "Artistic-2.0" - - IssuePackageLicenseLicenseIdBSD1Clause IssuePackageLicenseLicenseId = "BSD-1-Clause" - - IssuePackageLicenseLicenseIdBSD2Clause IssuePackageLicenseLicenseId = "BSD-2-Clause" - - IssuePackageLicenseLicenseIdBSD2ClauseFreeBSD IssuePackageLicenseLicenseId = "BSD-2-Clause-FreeBSD" - - IssuePackageLicenseLicenseIdBSD2ClauseNetBSD IssuePackageLicenseLicenseId = "BSD-2-Clause-NetBSD" - - IssuePackageLicenseLicenseIdBSD2ClausePatent IssuePackageLicenseLicenseId = "BSD-2-Clause-Patent" - - IssuePackageLicenseLicenseIdBSD2ClauseViews IssuePackageLicenseLicenseId = "BSD-2-Clause-Views" - - IssuePackageLicenseLicenseIdBSD3Clause IssuePackageLicenseLicenseId = "BSD-3-Clause" - - IssuePackageLicenseLicenseIdBSD3ClauseAttribution IssuePackageLicenseLicenseId = "BSD-3-Clause-Attribution" - - IssuePackageLicenseLicenseIdBSD3ClauseClear IssuePackageLicenseLicenseId = "BSD-3-Clause-Clear" - - IssuePackageLicenseLicenseIdBSD3ClauseLBNL IssuePackageLicenseLicenseId = "BSD-3-Clause-LBNL" - - IssuePackageLicenseLicenseIdBSD3ClauseModification IssuePackageLicenseLicenseId = "BSD-3-Clause-Modification" - - IssuePackageLicenseLicenseIdBSD3ClauseNoMilitaryLicense IssuePackageLicenseLicenseId = "BSD-3-Clause-No-Military-License" - - IssuePackageLicenseLicenseIdBSD3ClauseNoNuclearLicense IssuePackageLicenseLicenseId = "BSD-3-Clause-No-Nuclear-License" - - IssuePackageLicenseLicenseIdBSD3ClauseNoNuclearLicense2014 IssuePackageLicenseLicenseId = "BSD-3-Clause-No-Nuclear-License-2014" - - IssuePackageLicenseLicenseIdBSD3ClauseNoNuclearWarranty IssuePackageLicenseLicenseId = "BSD-3-Clause-No-Nuclear-Warranty" - - IssuePackageLicenseLicenseIdBSD3ClauseOpenMPI IssuePackageLicenseLicenseId = "BSD-3-Clause-Open-MPI" - - IssuePackageLicenseLicenseIdBSD4Clause IssuePackageLicenseLicenseId = "BSD-4-Clause" - - IssuePackageLicenseLicenseIdBSD4ClauseShortened IssuePackageLicenseLicenseId = "BSD-4-Clause-Shortened" - - IssuePackageLicenseLicenseIdBSD4ClauseUC IssuePackageLicenseLicenseId = "BSD-4-Clause-UC" - - IssuePackageLicenseLicenseIdBSDProtection IssuePackageLicenseLicenseId = "BSD-Protection" - - IssuePackageLicenseLicenseIdBSDSourceCode IssuePackageLicenseLicenseId = "BSD-Source-Code" - - IssuePackageLicenseLicenseIdBSL10 IssuePackageLicenseLicenseId = "BSL-1.0" - - IssuePackageLicenseLicenseIdBUSL11 IssuePackageLicenseLicenseId = "BUSL-1.1" - - IssuePackageLicenseLicenseIdBaekmuk IssuePackageLicenseLicenseId = "Baekmuk" - - IssuePackageLicenseLicenseIdBahyph IssuePackageLicenseLicenseId = "Bahyph" - - IssuePackageLicenseLicenseIdBarr IssuePackageLicenseLicenseId = "Barr" - - IssuePackageLicenseLicenseIdBeerware IssuePackageLicenseLicenseId = "Beerware" - - IssuePackageLicenseLicenseIdBitTorrent10 IssuePackageLicenseLicenseId = "BitTorrent-1.0" - - IssuePackageLicenseLicenseIdBitTorrent11 IssuePackageLicenseLicenseId = "BitTorrent-1.1" - - IssuePackageLicenseLicenseIdBitstreamVera IssuePackageLicenseLicenseId = "Bitstream-Vera" - - IssuePackageLicenseLicenseIdBlessing IssuePackageLicenseLicenseId = "blessing" - - IssuePackageLicenseLicenseIdBlueOak100 IssuePackageLicenseLicenseId = "BlueOak-1.0.0" - - IssuePackageLicenseLicenseIdBorceux IssuePackageLicenseLicenseId = "Borceux" - - IssuePackageLicenseLicenseIdBzip2105 IssuePackageLicenseLicenseId = "bzip2-1.0.5" - - IssuePackageLicenseLicenseIdBzip2106 IssuePackageLicenseLicenseId = "bzip2-1.0.6" - - IssuePackageLicenseLicenseIdCAL10 IssuePackageLicenseLicenseId = "CAL-1.0" - - IssuePackageLicenseLicenseIdCAL10CombinedWorkException IssuePackageLicenseLicenseId = "CAL-1.0-Combined-Work-Exception" - - IssuePackageLicenseLicenseIdCATOSL11 IssuePackageLicenseLicenseId = "CATOSL-1.1" - - IssuePackageLicenseLicenseIdCC010 IssuePackageLicenseLicenseId = "CC0-1.0" - - IssuePackageLicenseLicenseIdCCBY10 IssuePackageLicenseLicenseId = "CC-BY-1.0" - - IssuePackageLicenseLicenseIdCCBY20 IssuePackageLicenseLicenseId = "CC-BY-2.0" - - IssuePackageLicenseLicenseIdCCBY25 IssuePackageLicenseLicenseId = "CC-BY-2.5" - - IssuePackageLicenseLicenseIdCCBY25AU IssuePackageLicenseLicenseId = "CC-BY-2.5-AU" - - IssuePackageLicenseLicenseIdCCBY30 IssuePackageLicenseLicenseId = "CC-BY-3.0" - - IssuePackageLicenseLicenseIdCCBY30AT IssuePackageLicenseLicenseId = "CC-BY-3.0-AT" - - IssuePackageLicenseLicenseIdCCBY30DE IssuePackageLicenseLicenseId = "CC-BY-3.0-DE" - - IssuePackageLicenseLicenseIdCCBY30IGO IssuePackageLicenseLicenseId = "CC-BY-3.0-IGO" - - IssuePackageLicenseLicenseIdCCBY30NL IssuePackageLicenseLicenseId = "CC-BY-3.0-NL" - - IssuePackageLicenseLicenseIdCCBY30US IssuePackageLicenseLicenseId = "CC-BY-3.0-US" - - IssuePackageLicenseLicenseIdCCBY40 IssuePackageLicenseLicenseId = "CC-BY-4.0" - - IssuePackageLicenseLicenseIdCCBYNC10 IssuePackageLicenseLicenseId = "CC-BY-NC-1.0" - - IssuePackageLicenseLicenseIdCCBYNC20 IssuePackageLicenseLicenseId = "CC-BY-NC-2.0" - - IssuePackageLicenseLicenseIdCCBYNC25 IssuePackageLicenseLicenseId = "CC-BY-NC-2.5" - - IssuePackageLicenseLicenseIdCCBYNC30 IssuePackageLicenseLicenseId = "CC-BY-NC-3.0" - - IssuePackageLicenseLicenseIdCCBYNC30DE IssuePackageLicenseLicenseId = "CC-BY-NC-3.0-DE" - - IssuePackageLicenseLicenseIdCCBYNC40 IssuePackageLicenseLicenseId = "CC-BY-NC-4.0" - - IssuePackageLicenseLicenseIdCCBYNCND10 IssuePackageLicenseLicenseId = "CC-BY-NC-ND-1.0" - - IssuePackageLicenseLicenseIdCCBYNCND20 IssuePackageLicenseLicenseId = "CC-BY-NC-ND-2.0" - - IssuePackageLicenseLicenseIdCCBYNCND25 IssuePackageLicenseLicenseId = "CC-BY-NC-ND-2.5" - - IssuePackageLicenseLicenseIdCCBYNCND30 IssuePackageLicenseLicenseId = "CC-BY-NC-ND-3.0" - - IssuePackageLicenseLicenseIdCCBYNCND30DE IssuePackageLicenseLicenseId = "CC-BY-NC-ND-3.0-DE" - - IssuePackageLicenseLicenseIdCCBYNCND30IGO IssuePackageLicenseLicenseId = "CC-BY-NC-ND-3.0-IGO" - - IssuePackageLicenseLicenseIdCCBYNCND40 IssuePackageLicenseLicenseId = "CC-BY-NC-ND-4.0" - - IssuePackageLicenseLicenseIdCCBYNCSA10 IssuePackageLicenseLicenseId = "CC-BY-NC-SA-1.0" - - IssuePackageLicenseLicenseIdCCBYNCSA20 IssuePackageLicenseLicenseId = "CC-BY-NC-SA-2.0" - - IssuePackageLicenseLicenseIdCCBYNCSA20FR IssuePackageLicenseLicenseId = "CC-BY-NC-SA-2.0-FR" - - IssuePackageLicenseLicenseIdCCBYNCSA20UK IssuePackageLicenseLicenseId = "CC-BY-NC-SA-2.0-UK" - - IssuePackageLicenseLicenseIdCCBYNCSA25 IssuePackageLicenseLicenseId = "CC-BY-NC-SA-2.5" - - IssuePackageLicenseLicenseIdCCBYNCSA30 IssuePackageLicenseLicenseId = "CC-BY-NC-SA-3.0" - - IssuePackageLicenseLicenseIdCCBYNCSA30DE IssuePackageLicenseLicenseId = "CC-BY-NC-SA-3.0-DE" - - IssuePackageLicenseLicenseIdCCBYNCSA30IGO IssuePackageLicenseLicenseId = "CC-BY-NC-SA-3.0-IGO" - - IssuePackageLicenseLicenseIdCCBYNCSA40 IssuePackageLicenseLicenseId = "CC-BY-NC-SA-4.0" - - IssuePackageLicenseLicenseIdCCBYND10 IssuePackageLicenseLicenseId = "CC-BY-ND-1.0" - - IssuePackageLicenseLicenseIdCCBYND20 IssuePackageLicenseLicenseId = "CC-BY-ND-2.0" - - IssuePackageLicenseLicenseIdCCBYND25 IssuePackageLicenseLicenseId = "CC-BY-ND-2.5" - - IssuePackageLicenseLicenseIdCCBYND30 IssuePackageLicenseLicenseId = "CC-BY-ND-3.0" - - IssuePackageLicenseLicenseIdCCBYND30DE IssuePackageLicenseLicenseId = "CC-BY-ND-3.0-DE" - - IssuePackageLicenseLicenseIdCCBYND40 IssuePackageLicenseLicenseId = "CC-BY-ND-4.0" - - IssuePackageLicenseLicenseIdCCBYSA10 IssuePackageLicenseLicenseId = "CC-BY-SA-1.0" - - IssuePackageLicenseLicenseIdCCBYSA20 IssuePackageLicenseLicenseId = "CC-BY-SA-2.0" - - IssuePackageLicenseLicenseIdCCBYSA20UK IssuePackageLicenseLicenseId = "CC-BY-SA-2.0-UK" - - IssuePackageLicenseLicenseIdCCBYSA21JP IssuePackageLicenseLicenseId = "CC-BY-SA-2.1-JP" - - IssuePackageLicenseLicenseIdCCBYSA25 IssuePackageLicenseLicenseId = "CC-BY-SA-2.5" - - IssuePackageLicenseLicenseIdCCBYSA30 IssuePackageLicenseLicenseId = "CC-BY-SA-3.0" - - IssuePackageLicenseLicenseIdCCBYSA30AT IssuePackageLicenseLicenseId = "CC-BY-SA-3.0-AT" - - IssuePackageLicenseLicenseIdCCBYSA30DE IssuePackageLicenseLicenseId = "CC-BY-SA-3.0-DE" - - IssuePackageLicenseLicenseIdCCBYSA40 IssuePackageLicenseLicenseId = "CC-BY-SA-4.0" - - IssuePackageLicenseLicenseIdCCPDDC IssuePackageLicenseLicenseId = "CC-PDDC" - - IssuePackageLicenseLicenseIdCDDL10 IssuePackageLicenseLicenseId = "CDDL-1.0" - - IssuePackageLicenseLicenseIdCDDL11 IssuePackageLicenseLicenseId = "CDDL-1.1" - - IssuePackageLicenseLicenseIdCDL10 IssuePackageLicenseLicenseId = "CDL-1.0" - - IssuePackageLicenseLicenseIdCDLAPermissive10 IssuePackageLicenseLicenseId = "CDLA-Permissive-1.0" - - IssuePackageLicenseLicenseIdCDLAPermissive20 IssuePackageLicenseLicenseId = "CDLA-Permissive-2.0" - - IssuePackageLicenseLicenseIdCDLASharing10 IssuePackageLicenseLicenseId = "CDLA-Sharing-1.0" - - IssuePackageLicenseLicenseIdCECILL10 IssuePackageLicenseLicenseId = "CECILL-1.0" - - IssuePackageLicenseLicenseIdCECILL11 IssuePackageLicenseLicenseId = "CECILL-1.1" - - IssuePackageLicenseLicenseIdCECILL20 IssuePackageLicenseLicenseId = "CECILL-2.0" - - IssuePackageLicenseLicenseIdCECILL21 IssuePackageLicenseLicenseId = "CECILL-2.1" - - IssuePackageLicenseLicenseIdCECILLB IssuePackageLicenseLicenseId = "CECILL-B" - - IssuePackageLicenseLicenseIdCECILLC IssuePackageLicenseLicenseId = "CECILL-C" - - IssuePackageLicenseLicenseIdCERNOHL11 IssuePackageLicenseLicenseId = "CERN-OHL-1.1" - - IssuePackageLicenseLicenseIdCERNOHL12 IssuePackageLicenseLicenseId = "CERN-OHL-1.2" - - IssuePackageLicenseLicenseIdCERNOHLP20 IssuePackageLicenseLicenseId = "CERN-OHL-P-2.0" - - IssuePackageLicenseLicenseIdCERNOHLS20 IssuePackageLicenseLicenseId = "CERN-OHL-S-2.0" - - IssuePackageLicenseLicenseIdCERNOHLW20 IssuePackageLicenseLicenseId = "CERN-OHL-W-2.0" - - IssuePackageLicenseLicenseIdCNRIJython IssuePackageLicenseLicenseId = "CNRI-Jython" - - IssuePackageLicenseLicenseIdCNRIPython IssuePackageLicenseLicenseId = "CNRI-Python" - - IssuePackageLicenseLicenseIdCNRIPythonGPLCompatible IssuePackageLicenseLicenseId = "CNRI-Python-GPL-Compatible" - - IssuePackageLicenseLicenseIdCOIL10 IssuePackageLicenseLicenseId = "COIL-1.0" - - IssuePackageLicenseLicenseIdCPAL10 IssuePackageLicenseLicenseId = "CPAL-1.0" - - IssuePackageLicenseLicenseIdCPL10 IssuePackageLicenseLicenseId = "CPL-1.0" - - IssuePackageLicenseLicenseIdCPOL102 IssuePackageLicenseLicenseId = "CPOL-1.02" - - IssuePackageLicenseLicenseIdCUAOPL10 IssuePackageLicenseLicenseId = "CUA-OPL-1.0" - - IssuePackageLicenseLicenseIdCUDA10 IssuePackageLicenseLicenseId = "C-UDA-1.0" - - IssuePackageLicenseLicenseIdCaldera IssuePackageLicenseLicenseId = "Caldera" - - IssuePackageLicenseLicenseIdCheckmk IssuePackageLicenseLicenseId = "checkmk" - - IssuePackageLicenseLicenseIdClArtistic IssuePackageLicenseLicenseId = "ClArtistic" - - IssuePackageLicenseLicenseIdCommunitySpec10 IssuePackageLicenseLicenseId = "Community-Spec-1.0" - - IssuePackageLicenseLicenseIdCondor11 IssuePackageLicenseLicenseId = "Condor-1.1" - - IssuePackageLicenseLicenseIdCopyleftNext030 IssuePackageLicenseLicenseId = "copyleft-next-0.3.0" - - IssuePackageLicenseLicenseIdCopyleftNext031 IssuePackageLicenseLicenseId = "copyleft-next-0.3.1" - - IssuePackageLicenseLicenseIdCrossword IssuePackageLicenseLicenseId = "Crossword" - - IssuePackageLicenseLicenseIdCrystalStacker IssuePackageLicenseLicenseId = "CrystalStacker" - - IssuePackageLicenseLicenseIdCube IssuePackageLicenseLicenseId = "Cube" - - IssuePackageLicenseLicenseIdCurl IssuePackageLicenseLicenseId = "curl" - - IssuePackageLicenseLicenseIdDFSL10 IssuePackageLicenseLicenseId = "D-FSL-1.0" - - IssuePackageLicenseLicenseIdDLDEBY20 IssuePackageLicenseLicenseId = "DL-DE-BY-2.0" - - IssuePackageLicenseLicenseIdDOC IssuePackageLicenseLicenseId = "DOC" - - IssuePackageLicenseLicenseIdDRL10 IssuePackageLicenseLicenseId = "DRL-1.0" - - IssuePackageLicenseLicenseIdDSDP IssuePackageLicenseLicenseId = "DSDP" - - IssuePackageLicenseLicenseIdDiffmark IssuePackageLicenseLicenseId = "diffmark" - - IssuePackageLicenseLicenseIdDotseqn IssuePackageLicenseLicenseId = "Dotseqn" - - IssuePackageLicenseLicenseIdDvipdfm IssuePackageLicenseLicenseId = "dvipdfm" - - IssuePackageLicenseLicenseIdECL10 IssuePackageLicenseLicenseId = "ECL-1.0" - - IssuePackageLicenseLicenseIdECL20 IssuePackageLicenseLicenseId = "ECL-2.0" - - IssuePackageLicenseLicenseIdECos20 IssuePackageLicenseLicenseId = "eCos-2.0" - - IssuePackageLicenseLicenseIdEFL10 IssuePackageLicenseLicenseId = "EFL-1.0" - - IssuePackageLicenseLicenseIdEFL20 IssuePackageLicenseLicenseId = "EFL-2.0" - - IssuePackageLicenseLicenseIdEGenix IssuePackageLicenseLicenseId = "eGenix" - - IssuePackageLicenseLicenseIdEPICS IssuePackageLicenseLicenseId = "EPICS" - - IssuePackageLicenseLicenseIdEPL10 IssuePackageLicenseLicenseId = "EPL-1.0" - - IssuePackageLicenseLicenseIdEPL20 IssuePackageLicenseLicenseId = "EPL-2.0" - - IssuePackageLicenseLicenseIdEUDatagrid IssuePackageLicenseLicenseId = "EUDatagrid" - - IssuePackageLicenseLicenseIdEUPL10 IssuePackageLicenseLicenseId = "EUPL-1.0" - - IssuePackageLicenseLicenseIdEUPL11 IssuePackageLicenseLicenseId = "EUPL-1.1" - - IssuePackageLicenseLicenseIdEUPL12 IssuePackageLicenseLicenseId = "EUPL-1.2" - - IssuePackageLicenseLicenseIdElastic20 IssuePackageLicenseLicenseId = "Elastic-2.0" - - IssuePackageLicenseLicenseIdEntessa IssuePackageLicenseLicenseId = "Entessa" - - IssuePackageLicenseLicenseIdErlPL11 IssuePackageLicenseLicenseId = "ErlPL-1.1" - - IssuePackageLicenseLicenseIdEtalab20 IssuePackageLicenseLicenseId = "etalab-2.0" - - IssuePackageLicenseLicenseIdEurosym IssuePackageLicenseLicenseId = "Eurosym" - - IssuePackageLicenseLicenseIdFDKAAC IssuePackageLicenseLicenseId = "FDK-AAC" - - IssuePackageLicenseLicenseIdFSFAP IssuePackageLicenseLicenseId = "FSFAP" - - IssuePackageLicenseLicenseIdFSFUL IssuePackageLicenseLicenseId = "FSFUL" - - IssuePackageLicenseLicenseIdFSFULLR IssuePackageLicenseLicenseId = "FSFULLR" - - IssuePackageLicenseLicenseIdFSFULLRWD IssuePackageLicenseLicenseId = "FSFULLRWD" - - IssuePackageLicenseLicenseIdFTL IssuePackageLicenseLicenseId = "FTL" - - IssuePackageLicenseLicenseIdFair IssuePackageLicenseLicenseId = "Fair" - - IssuePackageLicenseLicenseIdFrameworx10 IssuePackageLicenseLicenseId = "Frameworx-1.0" - - IssuePackageLicenseLicenseIdFreeBSDDOC IssuePackageLicenseLicenseId = "FreeBSD-DOC" - - IssuePackageLicenseLicenseIdFreeImage IssuePackageLicenseLicenseId = "FreeImage" - - IssuePackageLicenseLicenseIdGD IssuePackageLicenseLicenseId = "GD" - - IssuePackageLicenseLicenseIdGFDL11 IssuePackageLicenseLicenseId = "GFDL-1.1" - - IssuePackageLicenseLicenseIdGFDL11InvariantsOnly IssuePackageLicenseLicenseId = "GFDL-1.1-invariants-only" - - IssuePackageLicenseLicenseIdGFDL11InvariantsOrLater IssuePackageLicenseLicenseId = "GFDL-1.1-invariants-or-later" - - IssuePackageLicenseLicenseIdGFDL11NoInvariantsOnly IssuePackageLicenseLicenseId = "GFDL-1.1-no-invariants-only" - - IssuePackageLicenseLicenseIdGFDL11NoInvariantsOrLater IssuePackageLicenseLicenseId = "GFDL-1.1-no-invariants-or-later" - - IssuePackageLicenseLicenseIdGFDL11Only IssuePackageLicenseLicenseId = "GFDL-1.1-only" - - IssuePackageLicenseLicenseIdGFDL11OrLater IssuePackageLicenseLicenseId = "GFDL-1.1-or-later" - - IssuePackageLicenseLicenseIdGFDL12 IssuePackageLicenseLicenseId = "GFDL-1.2" - - IssuePackageLicenseLicenseIdGFDL12InvariantsOnly IssuePackageLicenseLicenseId = "GFDL-1.2-invariants-only" - - IssuePackageLicenseLicenseIdGFDL12InvariantsOrLater IssuePackageLicenseLicenseId = "GFDL-1.2-invariants-or-later" - - IssuePackageLicenseLicenseIdGFDL12NoInvariantsOnly IssuePackageLicenseLicenseId = "GFDL-1.2-no-invariants-only" - - IssuePackageLicenseLicenseIdGFDL12NoInvariantsOrLater IssuePackageLicenseLicenseId = "GFDL-1.2-no-invariants-or-later" - - IssuePackageLicenseLicenseIdGFDL12Only IssuePackageLicenseLicenseId = "GFDL-1.2-only" - - IssuePackageLicenseLicenseIdGFDL12OrLater IssuePackageLicenseLicenseId = "GFDL-1.2-or-later" - - IssuePackageLicenseLicenseIdGFDL13 IssuePackageLicenseLicenseId = "GFDL-1.3" - - IssuePackageLicenseLicenseIdGFDL13InvariantsOnly IssuePackageLicenseLicenseId = "GFDL-1.3-invariants-only" - - IssuePackageLicenseLicenseIdGFDL13InvariantsOrLater IssuePackageLicenseLicenseId = "GFDL-1.3-invariants-or-later" - - IssuePackageLicenseLicenseIdGFDL13NoInvariantsOnly IssuePackageLicenseLicenseId = "GFDL-1.3-no-invariants-only" - - IssuePackageLicenseLicenseIdGFDL13NoInvariantsOrLater IssuePackageLicenseLicenseId = "GFDL-1.3-no-invariants-or-later" - - IssuePackageLicenseLicenseIdGFDL13Only IssuePackageLicenseLicenseId = "GFDL-1.3-only" - - IssuePackageLicenseLicenseIdGFDL13OrLater IssuePackageLicenseLicenseId = "GFDL-1.3-or-later" - - IssuePackageLicenseLicenseIdGL2PS IssuePackageLicenseLicenseId = "GL2PS" - - IssuePackageLicenseLicenseIdGLWTPL IssuePackageLicenseLicenseId = "GLWTPL" - - IssuePackageLicenseLicenseIdGPL10 IssuePackageLicenseLicenseId = "GPL-1.0" - - IssuePackageLicenseLicenseIdGPL101 IssuePackageLicenseLicenseId = "GPL-1.0+" - - IssuePackageLicenseLicenseIdGPL10Only IssuePackageLicenseLicenseId = "GPL-1.0-only" - - IssuePackageLicenseLicenseIdGPL10OrLater IssuePackageLicenseLicenseId = "GPL-1.0-or-later" - - IssuePackageLicenseLicenseIdGPL20 IssuePackageLicenseLicenseId = "GPL-2.0" - - IssuePackageLicenseLicenseIdGPL201 IssuePackageLicenseLicenseId = "GPL-2.0+" - - IssuePackageLicenseLicenseIdGPL20Only IssuePackageLicenseLicenseId = "GPL-2.0-only" - - IssuePackageLicenseLicenseIdGPL20OrLater IssuePackageLicenseLicenseId = "GPL-2.0-or-later" - - IssuePackageLicenseLicenseIdGPL20WithAutoconfException IssuePackageLicenseLicenseId = "GPL-2.0-with-autoconf-exception" - - IssuePackageLicenseLicenseIdGPL20WithBisonException IssuePackageLicenseLicenseId = "GPL-2.0-with-bison-exception" - - IssuePackageLicenseLicenseIdGPL20WithClasspathException IssuePackageLicenseLicenseId = "GPL-2.0-with-classpath-exception" - - IssuePackageLicenseLicenseIdGPL20WithFontException IssuePackageLicenseLicenseId = "GPL-2.0-with-font-exception" - - IssuePackageLicenseLicenseIdGPL20WithGCCException IssuePackageLicenseLicenseId = "GPL-2.0-with-GCC-exception" - - IssuePackageLicenseLicenseIdGPL30 IssuePackageLicenseLicenseId = "GPL-3.0" - - IssuePackageLicenseLicenseIdGPL301 IssuePackageLicenseLicenseId = "GPL-3.0+" - - IssuePackageLicenseLicenseIdGPL30Only IssuePackageLicenseLicenseId = "GPL-3.0-only" - - IssuePackageLicenseLicenseIdGPL30OrLater IssuePackageLicenseLicenseId = "GPL-3.0-or-later" - - IssuePackageLicenseLicenseIdGPL30WithAutoconfException IssuePackageLicenseLicenseId = "GPL-3.0-with-autoconf-exception" - - IssuePackageLicenseLicenseIdGPL30WithGCCException IssuePackageLicenseLicenseId = "GPL-3.0-with-GCC-exception" - - IssuePackageLicenseLicenseIdGSOAP13b IssuePackageLicenseLicenseId = "gSOAP-1.3b" - - IssuePackageLicenseLicenseIdGiftware IssuePackageLicenseLicenseId = "Giftware" - - IssuePackageLicenseLicenseIdGlide IssuePackageLicenseLicenseId = "Glide" - - IssuePackageLicenseLicenseIdGlulxe IssuePackageLicenseLicenseId = "Glulxe" - - IssuePackageLicenseLicenseIdGnuplot IssuePackageLicenseLicenseId = "gnuplot" - - IssuePackageLicenseLicenseIdHPND IssuePackageLicenseLicenseId = "HPND" - - IssuePackageLicenseLicenseIdHPNDSellVariant IssuePackageLicenseLicenseId = "HPND-sell-variant" - - IssuePackageLicenseLicenseIdHTMLTIDY IssuePackageLicenseLicenseId = "HTMLTIDY" - - IssuePackageLicenseLicenseIdHaskellReport IssuePackageLicenseLicenseId = "HaskellReport" - - IssuePackageLicenseLicenseIdHippocratic21 IssuePackageLicenseLicenseId = "Hippocratic-2.1" - - IssuePackageLicenseLicenseIdIBMPibs IssuePackageLicenseLicenseId = "IBM-pibs" - - IssuePackageLicenseLicenseIdICU IssuePackageLicenseLicenseId = "ICU" - - IssuePackageLicenseLicenseIdIJG IssuePackageLicenseLicenseId = "IJG" - - IssuePackageLicenseLicenseIdIMatix IssuePackageLicenseLicenseId = "iMatix" - - IssuePackageLicenseLicenseIdIPA IssuePackageLicenseLicenseId = "IPA" - - IssuePackageLicenseLicenseIdIPL10 IssuePackageLicenseLicenseId = "IPL-1.0" - - IssuePackageLicenseLicenseIdISC IssuePackageLicenseLicenseId = "ISC" - - IssuePackageLicenseLicenseIdImageMagick IssuePackageLicenseLicenseId = "ImageMagick" - - IssuePackageLicenseLicenseIdImlib2 IssuePackageLicenseLicenseId = "Imlib2" - - IssuePackageLicenseLicenseIdInfoZIP IssuePackageLicenseLicenseId = "Info-ZIP" - - IssuePackageLicenseLicenseIdIntel IssuePackageLicenseLicenseId = "Intel" - - IssuePackageLicenseLicenseIdIntelACPI IssuePackageLicenseLicenseId = "Intel-ACPI" - - IssuePackageLicenseLicenseIdInterbase10 IssuePackageLicenseLicenseId = "Interbase-1.0" - - IssuePackageLicenseLicenseIdJPNIC IssuePackageLicenseLicenseId = "JPNIC" - - IssuePackageLicenseLicenseIdJSON IssuePackageLicenseLicenseId = "JSON" - - IssuePackageLicenseLicenseIdJam IssuePackageLicenseLicenseId = "Jam" - - IssuePackageLicenseLicenseIdJasPer20 IssuePackageLicenseLicenseId = "JasPer-2.0" - - IssuePackageLicenseLicenseIdKnuthCTAN IssuePackageLicenseLicenseId = "Knuth-CTAN" - - IssuePackageLicenseLicenseIdLAL12 IssuePackageLicenseLicenseId = "LAL-1.2" - - IssuePackageLicenseLicenseIdLAL13 IssuePackageLicenseLicenseId = "LAL-1.3" - - IssuePackageLicenseLicenseIdLGPL20 IssuePackageLicenseLicenseId = "LGPL-2.0" - - IssuePackageLicenseLicenseIdLGPL201 IssuePackageLicenseLicenseId = "LGPL-2.0+" - - IssuePackageLicenseLicenseIdLGPL20Only IssuePackageLicenseLicenseId = "LGPL-2.0-only" - - IssuePackageLicenseLicenseIdLGPL20OrLater IssuePackageLicenseLicenseId = "LGPL-2.0-or-later" - - IssuePackageLicenseLicenseIdLGPL21 IssuePackageLicenseLicenseId = "LGPL-2.1" - - IssuePackageLicenseLicenseIdLGPL211 IssuePackageLicenseLicenseId = "LGPL-2.1+" - - IssuePackageLicenseLicenseIdLGPL21Only IssuePackageLicenseLicenseId = "LGPL-2.1-only" - - IssuePackageLicenseLicenseIdLGPL21OrLater IssuePackageLicenseLicenseId = "LGPL-2.1-or-later" - - IssuePackageLicenseLicenseIdLGPL30 IssuePackageLicenseLicenseId = "LGPL-3.0" - - IssuePackageLicenseLicenseIdLGPL301 IssuePackageLicenseLicenseId = "LGPL-3.0+" - - IssuePackageLicenseLicenseIdLGPL30Only IssuePackageLicenseLicenseId = "LGPL-3.0-only" - - IssuePackageLicenseLicenseIdLGPL30OrLater IssuePackageLicenseLicenseId = "LGPL-3.0-or-later" - - IssuePackageLicenseLicenseIdLGPLLR IssuePackageLicenseLicenseId = "LGPLLR" - - IssuePackageLicenseLicenseIdLOOP IssuePackageLicenseLicenseId = "LOOP" - - IssuePackageLicenseLicenseIdLPL10 IssuePackageLicenseLicenseId = "LPL-1.0" - - IssuePackageLicenseLicenseIdLPL102 IssuePackageLicenseLicenseId = "LPL-1.02" - - IssuePackageLicenseLicenseIdLPPL10 IssuePackageLicenseLicenseId = "LPPL-1.0" - - IssuePackageLicenseLicenseIdLPPL11 IssuePackageLicenseLicenseId = "LPPL-1.1" - - IssuePackageLicenseLicenseIdLPPL12 IssuePackageLicenseLicenseId = "LPPL-1.2" - - IssuePackageLicenseLicenseIdLPPL13a IssuePackageLicenseLicenseId = "LPPL-1.3a" - - IssuePackageLicenseLicenseIdLPPL13c IssuePackageLicenseLicenseId = "LPPL-1.3c" - - IssuePackageLicenseLicenseIdLZMASDK911To920 IssuePackageLicenseLicenseId = "LZMA-SDK-9.11-to-9.20" - - IssuePackageLicenseLicenseIdLZMASDK922 IssuePackageLicenseLicenseId = "LZMA-SDK-9.22" - - IssuePackageLicenseLicenseIdLatex2e IssuePackageLicenseLicenseId = "Latex2e" - - IssuePackageLicenseLicenseIdLeptonica IssuePackageLicenseLicenseId = "Leptonica" - - IssuePackageLicenseLicenseIdLiLiQP11 IssuePackageLicenseLicenseId = "LiLiQ-P-1.1" - - IssuePackageLicenseLicenseIdLiLiQR11 IssuePackageLicenseLicenseId = "LiLiQ-R-1.1" - - IssuePackageLicenseLicenseIdLiLiQRplus11 IssuePackageLicenseLicenseId = "LiLiQ-Rplus-1.1" - - IssuePackageLicenseLicenseIdLibpng IssuePackageLicenseLicenseId = "Libpng" - - IssuePackageLicenseLicenseIdLibpng20 IssuePackageLicenseLicenseId = "libpng-2.0" - - IssuePackageLicenseLicenseIdLibselinux10 IssuePackageLicenseLicenseId = "libselinux-1.0" - - IssuePackageLicenseLicenseIdLibtiff IssuePackageLicenseLicenseId = "libtiff" - - IssuePackageLicenseLicenseIdLibutilDavidNugent IssuePackageLicenseLicenseId = "libutil-David-Nugent" - - IssuePackageLicenseLicenseIdLinuxManPagesCopyleft IssuePackageLicenseLicenseId = "Linux-man-pages-copyleft" - - IssuePackageLicenseLicenseIdLinuxOpenIB IssuePackageLicenseLicenseId = "Linux-OpenIB" - - IssuePackageLicenseLicenseIdMIT IssuePackageLicenseLicenseId = "MIT" - - IssuePackageLicenseLicenseIdMIT0 IssuePackageLicenseLicenseId = "MIT-0" - - IssuePackageLicenseLicenseIdMITAdvertising IssuePackageLicenseLicenseId = "MIT-advertising" - - IssuePackageLicenseLicenseIdMITCMU IssuePackageLicenseLicenseId = "MIT-CMU" - - IssuePackageLicenseLicenseIdMITEnna IssuePackageLicenseLicenseId = "MIT-enna" - - IssuePackageLicenseLicenseIdMITFeh IssuePackageLicenseLicenseId = "MIT-feh" - - IssuePackageLicenseLicenseIdMITModernVariant IssuePackageLicenseLicenseId = "MIT-Modern-Variant" - - IssuePackageLicenseLicenseIdMITNFA IssuePackageLicenseLicenseId = "MITNFA" - - IssuePackageLicenseLicenseIdMITOpenGroup IssuePackageLicenseLicenseId = "MIT-open-group" - - IssuePackageLicenseLicenseIdMPL10 IssuePackageLicenseLicenseId = "MPL-1.0" - - IssuePackageLicenseLicenseIdMPL11 IssuePackageLicenseLicenseId = "MPL-1.1" - - IssuePackageLicenseLicenseIdMPL20 IssuePackageLicenseLicenseId = "MPL-2.0" - - IssuePackageLicenseLicenseIdMPL20NoCopyleftException IssuePackageLicenseLicenseId = "MPL-2.0-no-copyleft-exception" - - IssuePackageLicenseLicenseIdMSLPL IssuePackageLicenseLicenseId = "MS-LPL" - - IssuePackageLicenseLicenseIdMSPL IssuePackageLicenseLicenseId = "MS-PL" - - IssuePackageLicenseLicenseIdMSRL IssuePackageLicenseLicenseId = "MS-RL" - - IssuePackageLicenseLicenseIdMTLL IssuePackageLicenseLicenseId = "MTLL" - - IssuePackageLicenseLicenseIdMakeIndex IssuePackageLicenseLicenseId = "MakeIndex" - - IssuePackageLicenseLicenseIdMinpack IssuePackageLicenseLicenseId = "Minpack" - - IssuePackageLicenseLicenseIdMirOS IssuePackageLicenseLicenseId = "MirOS" - - IssuePackageLicenseLicenseIdMotosoto IssuePackageLicenseLicenseId = "Motosoto" - - IssuePackageLicenseLicenseIdMpiPermissive IssuePackageLicenseLicenseId = "mpi-permissive" - - IssuePackageLicenseLicenseIdMpich2 IssuePackageLicenseLicenseId = "mpich2" - - IssuePackageLicenseLicenseIdMplus IssuePackageLicenseLicenseId = "mplus" - - IssuePackageLicenseLicenseIdMulanPSL10 IssuePackageLicenseLicenseId = "MulanPSL-1.0" - - IssuePackageLicenseLicenseIdMulanPSL20 IssuePackageLicenseLicenseId = "MulanPSL-2.0" - - IssuePackageLicenseLicenseIdMultics IssuePackageLicenseLicenseId = "Multics" - - IssuePackageLicenseLicenseIdMup IssuePackageLicenseLicenseId = "Mup" - - IssuePackageLicenseLicenseIdN0BSD IssuePackageLicenseLicenseId = "0BSD" - - IssuePackageLicenseLicenseIdNAIST2003 IssuePackageLicenseLicenseId = "NAIST-2003" - - IssuePackageLicenseLicenseIdNASA13 IssuePackageLicenseLicenseId = "NASA-1.3" - - IssuePackageLicenseLicenseIdNBPL10 IssuePackageLicenseLicenseId = "NBPL-1.0" - - IssuePackageLicenseLicenseIdNCGLUK20 IssuePackageLicenseLicenseId = "NCGL-UK-2.0" - - IssuePackageLicenseLicenseIdNCSA IssuePackageLicenseLicenseId = "NCSA" - - IssuePackageLicenseLicenseIdNGPL IssuePackageLicenseLicenseId = "NGPL" - - IssuePackageLicenseLicenseIdNICTA10 IssuePackageLicenseLicenseId = "NICTA-1.0" - - IssuePackageLicenseLicenseIdNISTPD IssuePackageLicenseLicenseId = "NIST-PD" - - IssuePackageLicenseLicenseIdNISTPDFallback IssuePackageLicenseLicenseId = "NIST-PD-fallback" - - IssuePackageLicenseLicenseIdNLOD10 IssuePackageLicenseLicenseId = "NLOD-1.0" - - IssuePackageLicenseLicenseIdNLOD20 IssuePackageLicenseLicenseId = "NLOD-2.0" - - IssuePackageLicenseLicenseIdNLPL IssuePackageLicenseLicenseId = "NLPL" - - IssuePackageLicenseLicenseIdNOSL IssuePackageLicenseLicenseId = "NOSL" - - IssuePackageLicenseLicenseIdNPL10 IssuePackageLicenseLicenseId = "NPL-1.0" - - IssuePackageLicenseLicenseIdNPL11 IssuePackageLicenseLicenseId = "NPL-1.1" - - IssuePackageLicenseLicenseIdNPOSL30 IssuePackageLicenseLicenseId = "NPOSL-3.0" - - IssuePackageLicenseLicenseIdNRL IssuePackageLicenseLicenseId = "NRL" - - IssuePackageLicenseLicenseIdNTP IssuePackageLicenseLicenseId = "NTP" - - IssuePackageLicenseLicenseIdNTP0 IssuePackageLicenseLicenseId = "NTP-0" - - IssuePackageLicenseLicenseIdNaumen IssuePackageLicenseLicenseId = "Naumen" - - IssuePackageLicenseLicenseIdNetCDF IssuePackageLicenseLicenseId = "NetCDF" - - IssuePackageLicenseLicenseIdNetSNMP IssuePackageLicenseLicenseId = "Net-SNMP" - - IssuePackageLicenseLicenseIdNewsletr IssuePackageLicenseLicenseId = "Newsletr" - - IssuePackageLicenseLicenseIdNokia IssuePackageLicenseLicenseId = "Nokia" - - IssuePackageLicenseLicenseIdNoweb IssuePackageLicenseLicenseId = "Noweb" - - IssuePackageLicenseLicenseIdNunit IssuePackageLicenseLicenseId = "Nunit" - - IssuePackageLicenseLicenseIdOCCTPL IssuePackageLicenseLicenseId = "OCCT-PL" - - IssuePackageLicenseLicenseIdOCLC20 IssuePackageLicenseLicenseId = "OCLC-2.0" - - IssuePackageLicenseLicenseIdODCBy10 IssuePackageLicenseLicenseId = "ODC-By-1.0" - - IssuePackageLicenseLicenseIdODbL10 IssuePackageLicenseLicenseId = "ODbL-1.0" - - IssuePackageLicenseLicenseIdOFL10 IssuePackageLicenseLicenseId = "OFL-1.0" - - IssuePackageLicenseLicenseIdOFL10NoRFN IssuePackageLicenseLicenseId = "OFL-1.0-no-RFN" - - IssuePackageLicenseLicenseIdOFL10RFN IssuePackageLicenseLicenseId = "OFL-1.0-RFN" - - IssuePackageLicenseLicenseIdOFL11 IssuePackageLicenseLicenseId = "OFL-1.1" - - IssuePackageLicenseLicenseIdOFL11NoRFN IssuePackageLicenseLicenseId = "OFL-1.1-no-RFN" - - IssuePackageLicenseLicenseIdOFL11RFN IssuePackageLicenseLicenseId = "OFL-1.1-RFN" - - IssuePackageLicenseLicenseIdOGC10 IssuePackageLicenseLicenseId = "OGC-1.0" - - IssuePackageLicenseLicenseIdOGDLTaiwan10 IssuePackageLicenseLicenseId = "OGDL-Taiwan-1.0" - - IssuePackageLicenseLicenseIdOGLCanada20 IssuePackageLicenseLicenseId = "OGL-Canada-2.0" - - IssuePackageLicenseLicenseIdOGLUK10 IssuePackageLicenseLicenseId = "OGL-UK-1.0" - - IssuePackageLicenseLicenseIdOGLUK20 IssuePackageLicenseLicenseId = "OGL-UK-2.0" - - IssuePackageLicenseLicenseIdOGLUK30 IssuePackageLicenseLicenseId = "OGL-UK-3.0" - - IssuePackageLicenseLicenseIdOGTSL IssuePackageLicenseLicenseId = "OGTSL" - - IssuePackageLicenseLicenseIdOLDAP11 IssuePackageLicenseLicenseId = "OLDAP-1.1" - - IssuePackageLicenseLicenseIdOLDAP12 IssuePackageLicenseLicenseId = "OLDAP-1.2" - - IssuePackageLicenseLicenseIdOLDAP13 IssuePackageLicenseLicenseId = "OLDAP-1.3" - - IssuePackageLicenseLicenseIdOLDAP14 IssuePackageLicenseLicenseId = "OLDAP-1.4" - - IssuePackageLicenseLicenseIdOLDAP20 IssuePackageLicenseLicenseId = "OLDAP-2.0" - - IssuePackageLicenseLicenseIdOLDAP201 IssuePackageLicenseLicenseId = "OLDAP-2.0.1" - - IssuePackageLicenseLicenseIdOLDAP21 IssuePackageLicenseLicenseId = "OLDAP-2.1" - - IssuePackageLicenseLicenseIdOLDAP22 IssuePackageLicenseLicenseId = "OLDAP-2.2" - - IssuePackageLicenseLicenseIdOLDAP221 IssuePackageLicenseLicenseId = "OLDAP-2.2.1" - - IssuePackageLicenseLicenseIdOLDAP222 IssuePackageLicenseLicenseId = "OLDAP-2.2.2" - - IssuePackageLicenseLicenseIdOLDAP23 IssuePackageLicenseLicenseId = "OLDAP-2.3" - - IssuePackageLicenseLicenseIdOLDAP24 IssuePackageLicenseLicenseId = "OLDAP-2.4" - - IssuePackageLicenseLicenseIdOLDAP25 IssuePackageLicenseLicenseId = "OLDAP-2.5" - - IssuePackageLicenseLicenseIdOLDAP26 IssuePackageLicenseLicenseId = "OLDAP-2.6" - - IssuePackageLicenseLicenseIdOLDAP27 IssuePackageLicenseLicenseId = "OLDAP-2.7" - - IssuePackageLicenseLicenseIdOLDAP28 IssuePackageLicenseLicenseId = "OLDAP-2.8" - - IssuePackageLicenseLicenseIdOML IssuePackageLicenseLicenseId = "OML" - - IssuePackageLicenseLicenseIdOPL10 IssuePackageLicenseLicenseId = "OPL-1.0" - - IssuePackageLicenseLicenseIdOPUBL10 IssuePackageLicenseLicenseId = "OPUBL-1.0" - - IssuePackageLicenseLicenseIdOSETPL21 IssuePackageLicenseLicenseId = "OSET-PL-2.1" - - IssuePackageLicenseLicenseIdOSL10 IssuePackageLicenseLicenseId = "OSL-1.0" - - IssuePackageLicenseLicenseIdOSL11 IssuePackageLicenseLicenseId = "OSL-1.1" - - IssuePackageLicenseLicenseIdOSL20 IssuePackageLicenseLicenseId = "OSL-2.0" - - IssuePackageLicenseLicenseIdOSL21 IssuePackageLicenseLicenseId = "OSL-2.1" - - IssuePackageLicenseLicenseIdOSL30 IssuePackageLicenseLicenseId = "OSL-3.0" - - IssuePackageLicenseLicenseIdOUDA10 IssuePackageLicenseLicenseId = "O-UDA-1.0" - - IssuePackageLicenseLicenseIdOpenSSL IssuePackageLicenseLicenseId = "OpenSSL" - - IssuePackageLicenseLicenseIdPDDL10 IssuePackageLicenseLicenseId = "PDDL-1.0" - - IssuePackageLicenseLicenseIdPHP30 IssuePackageLicenseLicenseId = "PHP-3.0" - - IssuePackageLicenseLicenseIdPHP301 IssuePackageLicenseLicenseId = "PHP-3.01" - - IssuePackageLicenseLicenseIdPSF20 IssuePackageLicenseLicenseId = "PSF-2.0" - - IssuePackageLicenseLicenseIdParity600 IssuePackageLicenseLicenseId = "Parity-6.0.0" - - IssuePackageLicenseLicenseIdParity700 IssuePackageLicenseLicenseId = "Parity-7.0.0" - - IssuePackageLicenseLicenseIdPlexus IssuePackageLicenseLicenseId = "Plexus" - - IssuePackageLicenseLicenseIdPolyFormNoncommercial100 IssuePackageLicenseLicenseId = "PolyForm-Noncommercial-1.0.0" - - IssuePackageLicenseLicenseIdPolyFormSmallBusiness100 IssuePackageLicenseLicenseId = "PolyForm-Small-Business-1.0.0" - - IssuePackageLicenseLicenseIdPostgreSQL IssuePackageLicenseLicenseId = "PostgreSQL" - - IssuePackageLicenseLicenseIdPsfrag IssuePackageLicenseLicenseId = "psfrag" - - IssuePackageLicenseLicenseIdPsutils IssuePackageLicenseLicenseId = "psutils" - - IssuePackageLicenseLicenseIdPython20 IssuePackageLicenseLicenseId = "Python-2.0" - - IssuePackageLicenseLicenseIdPython201 IssuePackageLicenseLicenseId = "Python-2.0.1" - - IssuePackageLicenseLicenseIdQPL10 IssuePackageLicenseLicenseId = "QPL-1.0" - - IssuePackageLicenseLicenseIdQhull IssuePackageLicenseLicenseId = "Qhull" - - IssuePackageLicenseLicenseIdRHeCos11 IssuePackageLicenseLicenseId = "RHeCos-1.1" - - IssuePackageLicenseLicenseIdRPL11 IssuePackageLicenseLicenseId = "RPL-1.1" - - IssuePackageLicenseLicenseIdRPL15 IssuePackageLicenseLicenseId = "RPL-1.5" - - IssuePackageLicenseLicenseIdRPSL10 IssuePackageLicenseLicenseId = "RPSL-1.0" - - IssuePackageLicenseLicenseIdRSAMD IssuePackageLicenseLicenseId = "RSA-MD" - - IssuePackageLicenseLicenseIdRSCPL IssuePackageLicenseLicenseId = "RSCPL" - - IssuePackageLicenseLicenseIdRdisc IssuePackageLicenseLicenseId = "Rdisc" - - IssuePackageLicenseLicenseIdRuby IssuePackageLicenseLicenseId = "Ruby" - - IssuePackageLicenseLicenseIdSAXPD IssuePackageLicenseLicenseId = "SAX-PD" - - IssuePackageLicenseLicenseIdSCEA IssuePackageLicenseLicenseId = "SCEA" - - IssuePackageLicenseLicenseIdSGIB10 IssuePackageLicenseLicenseId = "SGI-B-1.0" - - IssuePackageLicenseLicenseIdSGIB11 IssuePackageLicenseLicenseId = "SGI-B-1.1" - - IssuePackageLicenseLicenseIdSGIB20 IssuePackageLicenseLicenseId = "SGI-B-2.0" - - IssuePackageLicenseLicenseIdSHL05 IssuePackageLicenseLicenseId = "SHL-0.5" - - IssuePackageLicenseLicenseIdSHL051 IssuePackageLicenseLicenseId = "SHL-0.51" - - IssuePackageLicenseLicenseIdSISSL IssuePackageLicenseLicenseId = "SISSL" - - IssuePackageLicenseLicenseIdSISSL12 IssuePackageLicenseLicenseId = "SISSL-1.2" - - IssuePackageLicenseLicenseIdSMLNJ IssuePackageLicenseLicenseId = "SMLNJ" - - IssuePackageLicenseLicenseIdSMPPL IssuePackageLicenseLicenseId = "SMPPL" - - IssuePackageLicenseLicenseIdSNIA IssuePackageLicenseLicenseId = "SNIA" - - IssuePackageLicenseLicenseIdSPL10 IssuePackageLicenseLicenseId = "SPL-1.0" - - IssuePackageLicenseLicenseIdSSHOpenSSH IssuePackageLicenseLicenseId = "SSH-OpenSSH" - - IssuePackageLicenseLicenseIdSSHShort IssuePackageLicenseLicenseId = "SSH-short" - - IssuePackageLicenseLicenseIdSSPL10 IssuePackageLicenseLicenseId = "SSPL-1.0" - - IssuePackageLicenseLicenseIdSWL IssuePackageLicenseLicenseId = "SWL" - - IssuePackageLicenseLicenseIdSaxpath IssuePackageLicenseLicenseId = "Saxpath" - - IssuePackageLicenseLicenseIdSchemeReport IssuePackageLicenseLicenseId = "SchemeReport" - - IssuePackageLicenseLicenseIdSendmail IssuePackageLicenseLicenseId = "Sendmail" - - IssuePackageLicenseLicenseIdSendmail823 IssuePackageLicenseLicenseId = "Sendmail-8.23" - - IssuePackageLicenseLicenseIdSimPL20 IssuePackageLicenseLicenseId = "SimPL-2.0" - - IssuePackageLicenseLicenseIdSleepycat IssuePackageLicenseLicenseId = "Sleepycat" - - IssuePackageLicenseLicenseIdSpencer86 IssuePackageLicenseLicenseId = "Spencer-86" - - IssuePackageLicenseLicenseIdSpencer94 IssuePackageLicenseLicenseId = "Spencer-94" - - IssuePackageLicenseLicenseIdSpencer99 IssuePackageLicenseLicenseId = "Spencer-99" - - IssuePackageLicenseLicenseIdStandardMLNJ IssuePackageLicenseLicenseId = "StandardML-NJ" - - IssuePackageLicenseLicenseIdSugarCRM113 IssuePackageLicenseLicenseId = "SugarCRM-1.1.3" - - IssuePackageLicenseLicenseIdSymlinks IssuePackageLicenseLicenseId = "Symlinks" - - IssuePackageLicenseLicenseIdTAPROHL10 IssuePackageLicenseLicenseId = "TAPR-OHL-1.0" - - IssuePackageLicenseLicenseIdTCL IssuePackageLicenseLicenseId = "TCL" - - IssuePackageLicenseLicenseIdTCPWrappers IssuePackageLicenseLicenseId = "TCP-wrappers" - - IssuePackageLicenseLicenseIdTMate IssuePackageLicenseLicenseId = "TMate" - - IssuePackageLicenseLicenseIdTORQUE11 IssuePackageLicenseLicenseId = "TORQUE-1.1" - - IssuePackageLicenseLicenseIdTOSL IssuePackageLicenseLicenseId = "TOSL" - - IssuePackageLicenseLicenseIdTUBerlin10 IssuePackageLicenseLicenseId = "TU-Berlin-1.0" - - IssuePackageLicenseLicenseIdTUBerlin20 IssuePackageLicenseLicenseId = "TU-Berlin-2.0" - - IssuePackageLicenseLicenseIdUCL10 IssuePackageLicenseLicenseId = "UCL-1.0" - - IssuePackageLicenseLicenseIdUPL10 IssuePackageLicenseLicenseId = "UPL-1.0" - - IssuePackageLicenseLicenseIdUnicodeDFS2015 IssuePackageLicenseLicenseId = "Unicode-DFS-2015" - - IssuePackageLicenseLicenseIdUnicodeDFS2016 IssuePackageLicenseLicenseId = "Unicode-DFS-2016" - - IssuePackageLicenseLicenseIdUnicodeTOU IssuePackageLicenseLicenseId = "Unicode-TOU" - - IssuePackageLicenseLicenseIdUnlicense IssuePackageLicenseLicenseId = "Unlicense" - - IssuePackageLicenseLicenseIdVOSTROM IssuePackageLicenseLicenseId = "VOSTROM" - - IssuePackageLicenseLicenseIdVSL10 IssuePackageLicenseLicenseId = "VSL-1.0" - - IssuePackageLicenseLicenseIdVim IssuePackageLicenseLicenseId = "Vim" - - IssuePackageLicenseLicenseIdW3C IssuePackageLicenseLicenseId = "W3C" - - IssuePackageLicenseLicenseIdW3C19980720 IssuePackageLicenseLicenseId = "W3C-19980720" - - IssuePackageLicenseLicenseIdW3C20150513 IssuePackageLicenseLicenseId = "W3C-20150513" - - IssuePackageLicenseLicenseIdWTFPL IssuePackageLicenseLicenseId = "WTFPL" - - IssuePackageLicenseLicenseIdWatcom10 IssuePackageLicenseLicenseId = "Watcom-1.0" - - IssuePackageLicenseLicenseIdWsuipa IssuePackageLicenseLicenseId = "Wsuipa" - - IssuePackageLicenseLicenseIdWxWindows IssuePackageLicenseLicenseId = "wxWindows" - - IssuePackageLicenseLicenseIdX11 IssuePackageLicenseLicenseId = "X11" - - IssuePackageLicenseLicenseIdX11DistributeModificationsVariant IssuePackageLicenseLicenseId = "X11-distribute-modifications-variant" - - IssuePackageLicenseLicenseIdXFree8611 IssuePackageLicenseLicenseId = "XFree86-1.1" - - IssuePackageLicenseLicenseIdXSkat IssuePackageLicenseLicenseId = "XSkat" - - IssuePackageLicenseLicenseIdXerox IssuePackageLicenseLicenseId = "Xerox" - - IssuePackageLicenseLicenseIdXinetd IssuePackageLicenseLicenseId = "xinetd" - - IssuePackageLicenseLicenseIdXnet IssuePackageLicenseLicenseId = "Xnet" - - IssuePackageLicenseLicenseIdXpp IssuePackageLicenseLicenseId = "xpp" - - IssuePackageLicenseLicenseIdYPL10 IssuePackageLicenseLicenseId = "YPL-1.0" - - IssuePackageLicenseLicenseIdYPL11 IssuePackageLicenseLicenseId = "YPL-1.1" - - IssuePackageLicenseLicenseIdZPL11 IssuePackageLicenseLicenseId = "ZPL-1.1" - - IssuePackageLicenseLicenseIdZPL20 IssuePackageLicenseLicenseId = "ZPL-2.0" - - IssuePackageLicenseLicenseIdZPL21 IssuePackageLicenseLicenseId = "ZPL-2.1" - - IssuePackageLicenseLicenseIdZed IssuePackageLicenseLicenseId = "Zed" - - IssuePackageLicenseLicenseIdZend20 IssuePackageLicenseLicenseId = "Zend-2.0" - - IssuePackageLicenseLicenseIdZimbra13 IssuePackageLicenseLicenseId = "Zimbra-1.3" - - IssuePackageLicenseLicenseIdZimbra14 IssuePackageLicenseLicenseId = "Zimbra-1.4" - - IssuePackageLicenseLicenseIdZlib IssuePackageLicenseLicenseId = "Zlib" - - IssuePackageLicenseLicenseIdZlibAcknowledgement IssuePackageLicenseLicenseId = "zlib-acknowledgement" -) - -// Defines values for IssuePackageSourceSourceType. -const ( - IssuePackageSourceSourceTypeBitbucket IssuePackageSourceSourceType = "bitbucket" - - IssuePackageSourceSourceTypeGithub IssuePackageSourceSourceType = "github" - - IssuePackageSourceSourceTypeGitlab IssuePackageSourceSourceType = "gitlab" - - IssuePackageSourceSourceTypeOther IssuePackageSourceSourceType = "other" - - IssuePackageSourceSourceTypePrivate IssuePackageSourceSourceType = "private" -) - -// Defines values for JobStatus. -const ( - JobStatusComplete JobStatus = "complete" - - JobStatusError JobStatus = "error" - - JobStatusNew JobStatus = "new" - - JobStatusPaused JobStatus = "paused" - - JobStatusRunning JobStatus = "running" - - JobStatusTimeout JobStatus = "timeout" -) - -// Defines values for PackageIssueManifestEcosystem. -const ( - PackageIssueManifestEcosystemCargo PackageIssueManifestEcosystem = "Cargo" - - PackageIssueManifestEcosystemDebian PackageIssueManifestEcosystem = "Debian" - - PackageIssueManifestEcosystemGithubActions PackageIssueManifestEcosystem = "Github Actions" - - PackageIssueManifestEcosystemGo PackageIssueManifestEcosystem = "Go" - - PackageIssueManifestEcosystemLinux PackageIssueManifestEcosystem = "Linux" - - PackageIssueManifestEcosystemMaven PackageIssueManifestEcosystem = "Maven" - - PackageIssueManifestEcosystemNpm PackageIssueManifestEcosystem = "npm" - - PackageIssueManifestEcosystemNuGet PackageIssueManifestEcosystem = "NuGet" - - PackageIssueManifestEcosystemPyPI PackageIssueManifestEcosystem = "PyPI" - - PackageIssueManifestEcosystemRubyGems PackageIssueManifestEcosystem = "RubyGems" -) - -// Defines values for UpdateJobRequestPolicyStatus. -const ( - UpdateJobRequestPolicyStatusError UpdateJobRequestPolicyStatus = "error" - - UpdateJobRequestPolicyStatusFail UpdateJobRequestPolicyStatus = "fail" - - UpdateJobRequestPolicyStatusPass UpdateJobRequestPolicyStatus = "pass" - - UpdateJobRequestPolicyStatusUnknown UpdateJobRequestPolicyStatus = "unknown" -) - -// AnyJobResponse defines model for AnyJobResponse. -type AnyJobResponse struct { - // Embedded struct due to allOf(#/components/schemas/Job) - Job `yaml:",inline"` - // Embedded fields due to inline allOf schema - // The Job ID to use for all subsequent job operation - Id *string `json:"id,omitempty"` -} - -// ApiError defines model for ApiError. -type ApiError struct { - // An error code identifying the error - Code *ApiErrorCode `json:"code,omitempty"` - - // A descriptive message about the error meant for developer consumption - Message *string `json:"message,omitempty"` - - // Optional error specific attributes - Params *ApiError_Params `json:"params,omitempty"` - - // An optional service or domain specific error group - Type *ApiErrorType `json:"type,omitempty"` -} - -// An error code identifying the error -type ApiErrorCode string - -// Optional error specific attributes -type ApiError_Params struct { - AdditionalProperties map[string]struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` - } `json:"-"` -} - -// An optional service or domain specific error group -type ApiErrorType string - -// CreateIssueResponse defines model for CreateIssueResponse. -type CreateIssueResponse struct { - Id string `json:"id"` -} - -// CreateJobRequest defines model for CreateJobRequest. -type CreateJobRequest struct { - // Git reference path (e.g. refs/heads/main) - GitRef *string `json:"git_ref,omitempty"` - - // The based name of a git ref such as `branchName` or `tagName` - GitRefName *string `json:"git_ref_name,omitempty"` - - // Git ref type that triggered the scan - GitRefType *CreateJobRequestGitRefType `json:"git_ref_type,omitempty"` - GitSha *string `json:"git_sha,omitempty"` - - // The name of the project to associate the job - ProjectName string `json:"project_name"` - - // The source of this project - ProjectSource CreateJobRequestProjectSource `json:"project_source"` - - // The stream name against which is job and its issues to attach - StreamName string `json:"stream_name"` - ToolName string `json:"tool_name"` - - // The type of tool creating this job - ToolType CreateJobRequestToolType `json:"tool_type"` - ToolVersion string `json:"tool_version"` - - // The event that triggered the tool - TriggerEvent CreateJobRequestTriggerEvent `json:"trigger_event"` -} - -// Git ref type that triggered the scan -type CreateJobRequestGitRefType string - -// The source of this project -type CreateJobRequestProjectSource string - -// The type of tool creating this job -type CreateJobRequestToolType string - -// The event that triggered the tool -type CreateJobRequestTriggerEvent string - -// Issue defines model for Issue. -type Issue struct { - IssueType IssueIssueType `json:"issue_type"` -} - -// IssueIssueType defines model for Issue.IssueType. -type IssueIssueType string - -// Subset of OSV schema required to perform policy -// decision by various tools -type IssuePackageCommonVulnerability struct { - // Alias identifiers of the same vulnerability in - // other databases - Aliases *[]string `json:"aliases,omitempty"` - - // Vulnerability identifier - Id *string `json:"id,omitempty"` - - // Related vulnerability identifiers for similar issues - Related *[]string `json:"related,omitempty"` - Severities *[]struct { - // Normalized risk rating computed from score - Risk *IssuePackageCommonVulnerabilitySeveritiesRisk `json:"risk,omitempty"` - - // Type specific vulnerability score - Score *string `json:"score,omitempty"` - Type *IssuePackageCommonVulnerabilitySeveritiesType `json:"type,omitempty"` - } `json:"severities,omitempty"` - - // Short summary of vulnerability - Summary *string `json:"summary,omitempty"` -} - -// Normalized risk rating computed from score -type IssuePackageCommonVulnerabilitySeveritiesRisk string - -// IssuePackageCommonVulnerabilitySeveritiesType defines model for IssuePackageCommonVulnerability.Severities.Type. -type IssuePackageCommonVulnerabilitySeveritiesType string - -// IssuePackageDependency defines model for IssuePackageDependency. -type IssuePackageDependency struct { - // Embedded struct due to allOf(#/components/schemas/PackageIssue) - PackageIssue `yaml:",inline"` - // Embedded fields due to inline allOf schema - ParentPackageName *string `json:"parent_package_name,omitempty"` - ParentPackageVersion *string `json:"parent_package_version,omitempty"` -} - -// IssuePackageLicense defines model for IssuePackageLicense. -type IssuePackageLicense struct { - // Embedded struct due to allOf(#/components/schemas/PackageIssue) - PackageIssue `yaml:",inline"` - // Embedded fields due to inline allOf schema - // License SPDX code - LicenseId *IssuePackageLicenseLicenseId `json:"license_id,omitempty"` -} - -// License SPDX code -type IssuePackageLicenseLicenseId string - -// IssuePackageScorecard defines model for IssuePackageScorecard. -type IssuePackageScorecard struct { - // Embedded struct due to allOf(#/components/schemas/PackageIssue) - PackageIssue `yaml:",inline"` - // Embedded fields due to inline allOf schema - Checks *[]struct { - Details *[]string `json:"details,omitempty"` - Documentation *struct { - Short *string `json:"short,omitempty"` - Url *string `json:"url,omitempty"` - } `json:"documentation,omitempty"` - Name *string `json:"name,omitempty"` - Reason *string `json:"reason,omitempty"` - Score *int `json:"score"` - } `json:"checks,omitempty"` - Date *string `json:"date,omitempty"` - Metadata *string `json:"metadata"` - Repo *struct { - // SHA1 value of the analyzed commit expressed as hexadecimal - Commit *string `json:"commit,omitempty"` - - // respository that was analyzed - Name *string `json:"name,omitempty"` - } `json:"repo,omitempty"` - - // Aggregate score of the repository - Score *float32 `json:"score"` - Scorecard *struct { - // SHA1 value of the Scorecard commit used for analysis - Commit *string `json:"commit,omitempty"` - - // Scorecard version used for this analysis - Version *string `json:"version,omitempty"` - } `json:"scorecard,omitempty"` -} - -// IssuePackageSource defines model for IssuePackageSource. -type IssuePackageSource struct { - // Embedded struct due to allOf(#/components/schemas/PackageIssue) - PackageIssue `yaml:",inline"` - // Embedded fields due to inline allOf schema - SourceDisplayName *string `json:"source_display_name,omitempty"` - SourceForks *int `json:"source_forks,omitempty"` - SourceName *string `json:"source_name,omitempty"` - SourceStars *int `json:"source_stars,omitempty"` - SourceType *IssuePackageSourceSourceType `json:"source_type,omitempty"` - SourceUrl *string `json:"source_url,omitempty"` -} - -// IssuePackageSourceSourceType defines model for IssuePackageSource.SourceType. -type IssuePackageSourceSourceType string - -// IssuePackageVulnerability defines model for IssuePackageVulnerability. -type IssuePackageVulnerability struct { - // Embedded struct due to allOf(#/components/schemas/PackageIssue) - PackageIssue `yaml:",inline"` - // Embedded fields due to inline allOf schema - // Subset of OSV schema required to perform policy - // decision by various tools - Vulnerability *IssuePackageCommonVulnerability `json:"vulnerability,omitempty"` -} - -// Job defines model for Job. -type Job struct { - Status *JobStatus `json:"status,omitempty"` -} - -// JobStatus defines model for Job.Status. -type JobStatus string - -// PackageIssue defines model for PackageIssue. -type PackageIssue struct { - // Embedded struct due to allOf(#/components/schemas/Issue) - Issue `yaml:",inline"` - // Embedded fields due to inline allOf schema - // Case insensitive ecosystem name - ManifestEcosystem *PackageIssueManifestEcosystem `json:"manifest_ecosystem,omitempty"` - ManifestPath *string `json:"manifest_path,omitempty"` - PackageName *string `json:"package_name,omitempty"` - PackageVersion *string `json:"package_version,omitempty"` -} - -// Case insensitive ecosystem name -type PackageIssueManifestEcosystem string - -// UpdateJobRequest defines model for UpdateJobRequest. -type UpdateJobRequest struct { - // Embedded struct due to allOf(#/components/schemas/Job) - Job `yaml:",inline"` - // Embedded fields due to inline allOf schema - PolicyStatus *UpdateJobRequestPolicyStatus `json:"policy_status,omitempty"` -} - -// UpdateJobRequestPolicyStatus defines model for UpdateJobRequest.PolicyStatus. -type UpdateJobRequestPolicyStatus string - -// CreateSyncJobJSONBody defines parameters for CreateSyncJob. -type CreateSyncJobJSONBody CreateJobRequest - -// UpdateSyncJobJSONBody defines parameters for UpdateSyncJob. -type UpdateSyncJobJSONBody UpdateJobRequest - -// CreateJobIssueJSONBody defines parameters for CreateJobIssue. -type CreateJobIssueJSONBody interface{} - -// CreateSyncJobJSONRequestBody defines body for CreateSyncJob for application/json ContentType. -type CreateSyncJobJSONRequestBody CreateSyncJobJSONBody - -// UpdateSyncJobJSONRequestBody defines body for UpdateSyncJob for application/json ContentType. -type UpdateSyncJobJSONRequestBody UpdateSyncJobJSONBody - -// CreateJobIssueJSONRequestBody defines body for CreateJobIssue for application/json ContentType. -type CreateJobIssueJSONRequestBody CreateJobIssueJSONBody - -// Getter for additional properties for ApiError_Params. Returns the specified -// element and whether it was found -func (a ApiError_Params) Get(fieldName string) (value struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` -}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for ApiError_Params -func (a *ApiError_Params) Set(fieldName string, value struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` -}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` - }) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for ApiError_Params to handle AdditionalProperties -func (a *ApiError_Params) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` - }) - for fieldName, fieldBuf := range object { - var fieldVal struct { - Key *string `json:"key,omitempty"` - Value *string `json:"value,omitempty"` - } - err := json.Unmarshal(fieldBuf, &fieldVal) - if err != nil { - return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) - } - a.AdditionalProperties[fieldName] = fieldVal - } - } - return nil -} - -// Override default JSON handling for ApiError_Params to handle AdditionalProperties -func (a ApiError_Params) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - for fieldName, field := range a.AdditionalProperties { - object[fieldName], err = json.Marshal(field) - if err != nil { - return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) - } - } - return json.Marshal(object) -} diff --git a/internal/auth/trial.go b/internal/auth/trial.go deleted file mode 100644 index 11d14a4..0000000 --- a/internal/auth/trial.go +++ /dev/null @@ -1,77 +0,0 @@ -package auth - -import ( - "context" - "errors" - "fmt" - "net/http" - "time" - - "github.com/deepmap/oapi-codegen/pkg/types" - "github.com/safedep/dry/utils" - "github.com/safedep/vet/gen/cpv1trials" - "github.com/safedep/vet/pkg/common/logger" - - apierr "github.com/safedep/dry/errors" -) - -type TrialConfig struct { - Email string - ControlPlaneApiUrl string -} - -type trialRegistrationResponse struct { - Id string - ExpiresAt time.Time -} - -type trialRegistrationClient struct { - config TrialConfig -} - -func NewTrialRegistrationClient(config TrialConfig) *trialRegistrationClient { - return &trialRegistrationClient{config: config} -} - -func (client *trialRegistrationClient) Execute() (*trialRegistrationResponse, error) { - if utils.IsEmptyString(client.config.Email) { - return nil, errors.New("email is required") - } - - if utils.IsEmptyString(client.config.ControlPlaneApiUrl) { - return nil, errors.New("control plane API is required") - } - - logger.Infof("Trial registrations using Control Plane: %s", - client.config.ControlPlaneApiUrl) - - cpClient, err := cpv1trials.NewClientWithResponses(client.config.ControlPlaneApiUrl) - if err != nil { - return nil, err - } - - logger.Infof("Trial registration requesting API key for: %s", - client.config.Email) - - res, err := cpClient.RegisterTrialUserWithResponse(context.Background(), - cpv1trials.RegisterTrialUserJSONRequestBody{ - Email: types.Email(client.config.Email), - }) - if err != nil { - return nil, err - } - - if res.HTTPResponse.StatusCode != http.StatusCreated { - if err, ok := apierr.UnmarshalApiError(res.Body); ok { - return nil, err - } else { - return nil, fmt.Errorf("unexpected status code:%d from control plane", - res.HTTPResponse.StatusCode) - } - } - - return &trialRegistrationResponse{ - Id: utils.SafelyGetValue(res.JSON201.Id), - ExpiresAt: utils.SafelyGetValue(res.JSON201.ExpiresAt), - }, nil -} From 06b080a81cd3ebff4e36c804ae8ec7bca382cf5d Mon Sep 17 00:00:00 2001 From: abhisek Date: Thu, 10 Oct 2024 08:23:00 +0530 Subject: [PATCH 19/28] feat: Add API key management command --- auth.go | 4 +- cmd/cloud/key.go | 83 +++++++++++++++++++++++++++++++++++++++++ cmd/cloud/main.go | 1 + internal/auth/verify.go | 60 +++++------------------------ pkg/cloud/key.go | 47 +++++++++++++++++++++++ scan.go | 4 +- 6 files changed, 142 insertions(+), 57 deletions(-) create mode 100644 cmd/cloud/key.go create mode 100644 pkg/cloud/key.go diff --git a/auth.go b/auth.go index 5641267..cc84f75 100644 --- a/auth.go +++ b/auth.go @@ -116,9 +116,7 @@ func verifyAuthCommand() *cobra.Command { ui.PrintSuccess("Running in Community Mode") } - failOnError("auth/verify", auth.Verify(&auth.VerifyConfig{ - ControlPlaneApiUrl: authControlPlaneApiBaseUrl, - })) + failOnError("auth/verify", auth.Verify()) ui.PrintSuccess("Authentication key is valid!") return nil diff --git a/cmd/cloud/key.go b/cmd/cloud/key.go new file mode 100644 index 0000000..933fb40 --- /dev/null +++ b/cmd/cloud/key.go @@ -0,0 +1,83 @@ +package cloud + +import ( + "time" + + "github.com/safedep/vet/internal/auth" + "github.com/safedep/vet/internal/ui" + "github.com/safedep/vet/pkg/cloud" + "github.com/safedep/vet/pkg/common/logger" + "github.com/spf13/cobra" +) + +var ( + keyName string + keyDescription string + keyExpiresIn int +) + +func newKeyCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "key", + Short: "Manage API keys", + RunE: func(cmd *cobra.Command, args []string) error { + return cmd.Help() + }, + } + + cmd.AddCommand(newKeyCreateCommand()) + + return cmd +} + +func newKeyCreateCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Create a new API key", + RunE: func(cmd *cobra.Command, args []string) error { + err := executeCreateKey() + if err != nil { + logger.Errorf("Failed to create API key: %v", err) + } + + return nil + }, + } + + cmd.Flags().StringVar(&keyName, "name", "", "Name of the API key") + cmd.Flags().StringVar(&keyDescription, "description", "", "Description of the API key") + cmd.Flags().IntVar(&keyExpiresIn, "expires-in", 30, + "Number of days after which the API key will expire") + + _ = cmd.MarkFlagRequired("name") + + return cmd +} + +func executeCreateKey() error { + client, err := auth.ControlPlaneClientConnection("vet-cloud-key-create") + if err != nil { + return err + } + + keyService, err := cloud.NewApiKeyService(client) + if err != nil { + return err + } + + key, err := keyService.CreateApiKey(&cloud.CreateApiKeyRequest{ + Name: keyName, + Desc: keyDescription, + ExpiryInDays: keyExpiresIn, + }) + + if err != nil { + return err + } + + ui.PrintSuccess("API key created successfully.") + ui.PrintSuccess("Key: %s", key.Key) + ui.PrintSuccess("Expires at: %s", key.ExpiresAt.Format(time.RFC3339)) + + return nil +} diff --git a/cmd/cloud/main.go b/cmd/cloud/main.go index 9172885..e04f825 100644 --- a/cmd/cloud/main.go +++ b/cmd/cloud/main.go @@ -16,6 +16,7 @@ func NewCloudCommand() *cobra.Command { cmd.AddCommand(newQueryCommand()) cmd.AddCommand(newPingCommand()) cmd.AddCommand(newWhoamiCommand()) + cmd.AddCommand(newKeyCommand()) return cmd } diff --git a/internal/auth/verify.go b/internal/auth/verify.go index 9dfcc7b..f15d6eb 100644 --- a/internal/auth/verify.go +++ b/internal/auth/verify.go @@ -1,66 +1,24 @@ package auth -import ( - "context" - "fmt" - "net/http" +import "github.com/safedep/vet/pkg/cloud" - apierr "github.com/safedep/dry/errors" - "github.com/safedep/dry/utils" - "github.com/safedep/vet/gen/cpv1" - "github.com/safedep/vet/pkg/common/logger" -) - -type VerifyConfig struct { - ControlPlaneApiUrl string -} - -// Verify function takes config and current API key available -// from this package and returns an error if auth is invalid -func Verify(config *VerifyConfig) error { - if CommunityMode() { - logger.Infof("Skipping auth verify due to community mode enabled") - return nil - } - - if ApiKey() == "" { - return fmt.Errorf("API key is not set") - } - - logger.Infof("Verifying auth token using Control Plane: %s", config.ControlPlaneApiUrl) - - client, err := cpv1.NewClientWithResponses(config.ControlPlaneApiUrl) +// Verify authentication to the data plane using +// API key and Ping Service. +func Verify() error { + conn, err := SyncClientConnection("vet-auth-verify") if err != nil { return err } - authKeyApplier := func(ctx context.Context, req *http.Request) error { - req.Header.Set("Authorization", ApiKey()) - return nil - } - - resp, err := client.GetApiCredentialIntrospectionWithResponse(context.Background(), - authKeyApplier) + pingService, err := cloud.NewPingService(conn) if err != nil { return err } - if resp.StatusCode() != http.StatusOK { - if err, ok := apierr.UnmarshalApiError(resp.Body); ok { - return err - } else { - return fmt.Errorf("unexpected status code:%d from control plane", - resp.HTTPResponse.StatusCode) - } - + _, err = pingService.Ping() + if err != nil { + return err } - if resp.JSON200 == nil { - return fmt.Errorf("invalid nil response from server") - } - - logger.Infof("Current auth token is valid with expiry: %s", - utils.SafelyGetValue(resp.JSON200.Expiry)) - return nil } diff --git a/pkg/cloud/key.go b/pkg/cloud/key.go new file mode 100644 index 0000000..fd1987e --- /dev/null +++ b/pkg/cloud/key.go @@ -0,0 +1,47 @@ +package cloud + +import ( + "context" + "time" + + "buf.build/gen/go/safedep/api/grpc/go/safedep/services/controltower/v1/controltowerv1grpc" + controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/controltower/v1" + "google.golang.org/grpc" +) + +type apiKeyService struct { + conn *grpc.ClientConn +} + +func NewApiKeyService(conn *grpc.ClientConn) (*apiKeyService, error) { + return &apiKeyService{conn: conn}, nil +} + +type CreateApiKeyRequest struct { + Name string + Desc string + ExpiryInDays int +} + +type CreateApiKeyResponse struct { + Key string + ExpiresAt time.Time +} + +func (a *apiKeyService) CreateApiKey(req *CreateApiKeyRequest) (*CreateApiKeyResponse, error) { + keyService := controltowerv1grpc.NewApiKeyServiceClient(a.conn) + res, err := keyService.CreateApiKey(context.Background(), &controltowerv1.CreateApiKeyRequest{ + Name: req.Name, + Description: &req.Desc, + ExpiryDays: int32(req.ExpiryInDays), + }) + + if err != nil { + return nil, err + } + + return &CreateApiKeyResponse{ + Key: res.GetKey(), + ExpiresAt: res.GetExpiresAt().AsTime(), + }, nil +} diff --git a/scan.go b/scan.go index 945d1ee..700f781 100644 --- a/scan.go +++ b/scan.go @@ -178,9 +178,7 @@ func listParsersCommand() *cobra.Command { func startScan() { if !disableAuthVerifyBeforeScan { - err := auth.Verify(&auth.VerifyConfig{ - ControlPlaneApiUrl: auth.ControlTowerUrl(), - }) + err := auth.Verify() // We will fallback to community mode by default to provide // a seamless user experience From ad6340e60d9d4814132ede2e30d91d9b0614e547 Mon Sep 17 00:00:00 2001 From: abhisek Date: Thu, 10 Oct 2024 14:52:48 +0530 Subject: [PATCH 20/28] refactor: API key configuration command --- auth.go | 45 +++++++++---------------------------------- internal/auth/auth.go | 23 ++++++++++++++++------ pkg/models/models.go | 4 ++++ 3 files changed, 30 insertions(+), 42 deletions(-) diff --git a/auth.go b/auth.go index cc84f75..61b8c35 100644 --- a/auth.go +++ b/auth.go @@ -2,7 +2,6 @@ package main import ( "errors" - "fmt" "os" "github.com/AlecAivazis/survey/v2" @@ -14,11 +13,7 @@ import ( ) var ( - authInsightApiBaseUrl string - authControlPlaneApiBaseUrl string - authSyncApiBaseUrl string - authCommunity bool - authTenantDomain string + authTenantDomain string ) func newAuthCommand() *cobra.Command { @@ -30,11 +25,6 @@ func newAuthCommand() *cobra.Command { }, } - cmd.PersistentFlags().StringVarP(&authControlPlaneApiBaseUrl, "control-plane", "", - auth.ControlTowerUrl(), "Base URL of Control Plane API") - cmd.PersistentFlags().StringVarP(&authSyncApiBaseUrl, "sync", "", auth.SyncApiUrl(), - "Base URL of Sync API") - cmd.AddCommand(configureAuthCommand()) cmd.AddCommand(verifyAuthCommand()) @@ -48,21 +38,16 @@ func configureAuthCommand() *cobra.Command { var key string var err error - if !authCommunity { - err = survey.AskOne(&survey.Password{ - Message: "Enter the API key", - }, &key) - } else { - authInsightApiBaseUrl = auth.DefaultCommunityApiUrl() - } - + err = survey.AskOne(&survey.Password{ + Message: "Enter the API key", + }, &key) if err != nil { logger.Fatalf("Failed to setup auth: %v", err) } if auth.TenantDomain() != "" && auth.TenantDomain() != authTenantDomain { - ui.PrintWarning(fmt.Sprintf("Tenant domain mismatch. Existing: %s, New: %s, continue? ", - auth.TenantDomain(), authTenantDomain)) + ui.PrintWarning("Tenant domain mismatch. Existing: %s, New: %s, continue? ", + auth.TenantDomain(), authTenantDomain) var confirm bool err = survey.AskOne(&survey.Confirm{ @@ -78,15 +63,7 @@ func configureAuthCommand() *cobra.Command { } } - err = auth.Configure(auth.Config{ - ApiUrl: authInsightApiBaseUrl, - ApiKey: string(key), - ControlPlaneApiUrl: authControlPlaneApiBaseUrl, - SyncApiUrl: authSyncApiBaseUrl, - Community: authCommunity, - TenantDomain: authTenantDomain, - }) - + err = auth.PersistApiKey(key, authTenantDomain) if err != nil { logger.Fatalf("Failed to configure auth: %v", err) } @@ -96,14 +73,10 @@ func configureAuthCommand() *cobra.Command { }, } - cmd.Flags().StringVarP(&authTenantDomain, "tenant-domain", "", "", + cmd.Flags().StringVarP(&authTenantDomain, "tenant", "", "", "Tenant domain for SafeDep Cloud") - cmd.Flags().StringVarP(&authInsightApiBaseUrl, "api", "", auth.DefaultApiUrl(), - "Base URL of Insights API") - cmd.Flags().BoolVarP(&authCommunity, "community", "", false, - "Use community API endpoint for Insights") - _ = cmd.MarkFlagRequired("tenant-domain") + _ = cmd.MarkFlagRequired("tenant") return cmd } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 2600abe..c42df18 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -61,8 +61,19 @@ func DefaultConfig() Config { } } -func Configure(m Config) error { - globalConfig = &m +func PersistApiKey(key, domain string) error { + if globalConfig == nil { + c := DefaultConfig() + globalConfig = &c + } + + if domain != "" { + globalConfig.TenantDomain = domain + } + + globalConfig.ApiUrl = defaultApiUrl + globalConfig.ApiKey = key + return persistConfiguration() } @@ -169,14 +180,14 @@ func ApiUrl() string { return url } - if globalConfig != nil { - return globalConfig.ApiUrl - } - if CommunityMode() { return defaultCommunityApiUrl } + if globalConfig != nil { + return globalConfig.ApiUrl + } + return defaultApiUrl } diff --git a/pkg/models/models.go b/pkg/models/models.go index 4e8c1bf..6910e22 100644 --- a/pkg/models/models.go +++ b/pkg/models/models.go @@ -122,6 +122,10 @@ func (pm *PackageManifest) GetControlTowerSpecEcosystem() packagev1.Ecosystem { return packagev1.Ecosystem_ECOSYSTEM_MAVEN case EcosystemNpm: return packagev1.Ecosystem_ECOSYSTEM_NPM + case EcosystemRubyGems: + return packagev1.Ecosystem_ECOSYSTEM_RUBYGEMS + case EcosystemPyPI: + return packagev1.Ecosystem_ECOSYSTEM_PYPI default: return packagev1.Ecosystem_ECOSYSTEM_UNSPECIFIED } From 69e32d99ccca4d319f745958ffc600ab631dc62b Mon Sep 17 00:00:00 2001 From: abhisek Date: Fri, 11 Oct 2024 10:07:01 +0530 Subject: [PATCH 21/28] fix: Tenant domain handling in cloud commands --- cmd/cloud/login.go | 10 ++-------- cmd/cloud/main.go | 16 +++++++++++++++- internal/auth/auth.go | 18 ++++++++++++++---- internal/auth/grpc.go | 11 ++--------- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/cmd/cloud/login.go b/cmd/cloud/login.go index 39bd6ff..9166178 100644 --- a/cmd/cloud/login.go +++ b/cmd/cloud/login.go @@ -12,10 +12,6 @@ import ( "github.com/spf13/cobra" ) -var ( - loginTenantDomain string -) - func newCloudLoginCommand() *cobra.Command { cmd := &cobra.Command{ Use: "login", @@ -30,9 +26,6 @@ func newCloudLoginCommand() *cobra.Command { }, } - cmd.Flags().StringVar(&loginTenantDomain, "tenant", "", - "Domain of the tenant to login to for existing users") - return cmd } @@ -59,5 +52,6 @@ func executeDeviceAuthFlow() error { return fmt.Errorf("failed to authenticate: %w", err) } - return auth.PersistCloudTokens(token.Token, token.RefreshToken, loginTenantDomain) + return auth.PersistCloudTokens(token.Token, + token.RefreshToken, tenantDomain) } diff --git a/cmd/cloud/main.go b/cmd/cloud/main.go index e04f825..b1c2f6b 100644 --- a/cmd/cloud/main.go +++ b/cmd/cloud/main.go @@ -1,6 +1,11 @@ package cloud -import "github.com/spf13/cobra" +import ( + "github.com/safedep/vet/internal/auth" + "github.com/spf13/cobra" +) + +var tenantDomain string func NewCloudCommand() *cobra.Command { cmd := &cobra.Command{ @@ -11,6 +16,9 @@ func NewCloudCommand() *cobra.Command { }, } + cmd.PersistentFlags().StringVar(&tenantDomain, "tenant", "", + "Tenant domain to use for the command") + cmd.AddCommand(newCloudLoginCommand()) cmd.AddCommand(newRegisterCommand()) cmd.AddCommand(newQueryCommand()) @@ -18,5 +26,11 @@ func NewCloudCommand() *cobra.Command { cmd.AddCommand(newWhoamiCommand()) cmd.AddCommand(newKeyCommand()) + cmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { + if tenantDomain != "" { + auth.SetRuntimeCloudTenant(tenantDomain) + } + } + return cmd } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index c42df18..343d8bf 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -11,10 +11,11 @@ import ( ) const ( - apiUrlEnvKey = "VET_INSIGHTS_API_URL" - apiKeyEnvKey = "VET_INSIGHTS_API_KEY" - apiKeyAlternateEnvKey = "VET_API_KEY" - communityModeEnvKey = "VET_COMMUNITY_MODE" + apiUrlEnvKey = "VET_INSIGHTS_API_URL" + apiKeyEnvKey = "VET_INSIGHTS_API_KEY" + apiKeyAlternateEnvKey = "VET_API_KEY" + communityModeEnvKey = "VET_COMMUNITY_MODE" + controlTowerTenantEnvKey = "VET_CONTROL_TOWER_TENANT_ID" defaultApiUrl = "https://api.safedep.io/insights/v1" defaultCommunityApiUrl = "https://api.safedep.io/insights-community/v1" @@ -168,6 +169,11 @@ func ControlTowerUrl() string { } func TenantDomain() string { + tenantFromEnv := os.Getenv(controlTowerTenantEnvKey) + if tenantFromEnv != "" { + return tenantFromEnv + } + if globalConfig != nil { return globalConfig.TenantDomain } @@ -226,6 +232,10 @@ func SetRuntimeCommunityMode() { os.Setenv(communityModeEnvKey, "true") } +func SetRuntimeCloudTenant(domain string) { + os.Setenv(controlTowerTenantEnvKey, domain) +} + func loadConfiguration() error { path, err := os.UserHomeDir() if err != nil { diff --git a/internal/auth/grpc.go b/internal/auth/grpc.go index d970286..fe096d0 100644 --- a/internal/auth/grpc.go +++ b/internal/auth/grpc.go @@ -35,17 +35,10 @@ func cloudClientConnection(name, loc, tok string) (*grpc.ClientConn, error) { logger.Debugf("ControlTower host: %s, port: %s", host, port) - vetTenantId := TenantDomain() - tenantIdOverride := os.Getenv("VET_CONTROL_TOWER_TENANT_ID") - - if tenantIdOverride != "" { - vetTenantId = tenantIdOverride - } - headers := http.Header{} - headers.Set("x-tenant-id", vetTenantId) + headers.Set("x-tenant-id", TenantDomain()) - vetTenantMockUser := os.Getenv("VET_CONTROL_TOWER_MOCK_USER") + vetTenantMockUser := os.Getenv(controlTowerTenantEnvKey) if vetTenantMockUser != "" { headers.Set("x-mock-user", vetTenantMockUser) } From 18af8d54e13a35695fd73460929e8c9927154a5e Mon Sep 17 00:00:00 2001 From: abhisek Date: Fri, 11 Oct 2024 16:54:36 +0530 Subject: [PATCH 22/28] fix: Package manifest namespace and path handling --- cmd/cloud/query.go | 4 ++ go.mod | 4 +- go.sum | 8 +++ internal/auth/grpc.go | 5 +- pkg/models/models.go | 97 ++++++++++++++++++++++++++++++++---- pkg/readers/github_reader.go | 5 +- pkg/reporter/ci/git.go | 1 + pkg/reporter/sync.go | 9 ++-- 8 files changed, 114 insertions(+), 19 deletions(-) create mode 100644 pkg/reporter/ci/git.go diff --git a/cmd/cloud/query.go b/cmd/cloud/query.go index f5fac05..f9f8f22 100644 --- a/cmd/cloud/query.go +++ b/cmd/cloud/query.go @@ -2,11 +2,13 @@ package cloud import ( "errors" + "fmt" "os" "sort" "github.com/jedib0t/go-pretty/v6/table" "github.com/safedep/vet/internal/auth" + "github.com/safedep/vet/internal/ui" "github.com/safedep/vet/pkg/cloud/query" "github.com/safedep/vet/pkg/common/logger" "github.com/spf13/cobra" @@ -82,6 +84,8 @@ func renderQueryResponseAsTable(response *query.QueryResponse) error { return nil } + ui.PrintSuccess(fmt.Sprintf("Query returned %d results", response.Count())) + // Header headers := []string{} response.GetRow(0).ForEachField(func(key string, _ interface{}) { diff --git a/go.mod b/go.mod index 8afee65..9ac7fea 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/safedep/vet go 1.22.1 require ( - buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241009065537-4ffd9786549f.1 - buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241009065537-4ffd9786549f.1 + buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241011110723-95b33664baad.1 + buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241011110723-95b33664baad.1 github.com/AlecAivazis/survey/v2 v2.3.7 github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/anchore/syft v1.11.1 diff --git a/go.sum b/go.sum index afe04c0..56b3b61 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,17 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.1-20240508200655-46a4cf4ba109.1 h1:PvjTFY+MqrYYulH74R8ddQodrEP1sThjkba8kcqO2dM= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.1-20240508200655-46a4cf4ba109.1/go.mod h1:Duw/9JoXkXIydyASnLYIiufkzySThoqavOsF+IihqvM= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241008111718-480f2b42b425.1 h1:ofDpCRg/yPfD0UMny+yaq4G5sHLNFhBH2DtIN9orEzQ= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241008111718-480f2b42b425.1/go.mod h1:DGREO91B1aVG1+zfN4gT/ZQZ0Ykcv+TZGf18SeGDcMc= buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241009065537-4ffd9786549f.1 h1:7+y3t/2/6sEf63xCX9ErNdsuFzB0Q18PIT14aAxz5wo= buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241009065537-4ffd9786549f.1/go.mod h1:Io32CuF5oJZDSkWJVgKvfOBTqSHnC7mqh9dpqq/PSNA= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241011110723-95b33664baad.1 h1:bUOILp76S06U58bp3EWI6qsoeEEBGGQJeMFdQ5Otc34= +buf.build/gen/go/safedep/api/grpc/go v1.5.1-20241011110723-95b33664baad.1/go.mod h1:LSghi5M4Z+uYLyo85Bs6lVpzit6ZoSph8YOyvpHL3mY= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241008111718-480f2b42b425.1 h1:IziBLru8MusSLO2lNDzSxbVxKu0dGI8zE8vG+tCMYjI= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241008111718-480f2b42b425.1/go.mod h1:WCxZaBpYxgWnSpauuzVhzbJawAp6uPXJPN5tbDpceQ0= buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241009065537-4ffd9786549f.1 h1:F4fk9nhlB2ZU8odF5S/w/nS8r0htIbu6eKDKDBP+kzQ= buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241009065537-4ffd9786549f.1/go.mod h1:WCxZaBpYxgWnSpauuzVhzbJawAp6uPXJPN5tbDpceQ0= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241011110723-95b33664baad.1 h1:HMED4kNSQJgrmFZXorIP1mpVbnKxzvhMgc3BOawTtGw= +buf.build/gen/go/safedep/api/protocolbuffers/go v1.35.1-20241011110723-95b33664baad.1/go.mod h1:WCxZaBpYxgWnSpauuzVhzbJawAp6uPXJPN5tbDpceQ0= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= diff --git a/internal/auth/grpc.go b/internal/auth/grpc.go index fe096d0..e2de9df 100644 --- a/internal/auth/grpc.go +++ b/internal/auth/grpc.go @@ -33,12 +33,13 @@ func cloudClientConnection(name, loc, tok string) (*grpc.ClientConn, error) { port = "443" } - logger.Debugf("ControlTower host: %s, port: %s", host, port) + logger.Debugf("Establishing grpc connection for: %s host: %s, port: %s", + name, host, port) headers := http.Header{} headers.Set("x-tenant-id", TenantDomain()) - vetTenantMockUser := os.Getenv(controlTowerTenantEnvKey) + vetTenantMockUser := os.Getenv("VET_CONTROL_TOWER_MOCK_USER") if vetTenantMockUser != "" { headers.Set("x-mock-user", vetTenantMockUser) } diff --git a/pkg/models/models.go b/pkg/models/models.go index 6910e22..e609807 100644 --- a/pkg/models/models.go +++ b/pkg/models/models.go @@ -3,6 +3,7 @@ package models import ( "fmt" "hash/fnv" + "path/filepath" "strconv" "strings" "sync" @@ -29,17 +30,59 @@ const ( EcosystemSpdxSBOM = "SpdxSbom" ) +type ManifestSourceType string + +const ( + ManifestSourceLocal = ManifestSourceType("local") + ManifestSourceGitRepository = ManifestSourceType("git_repository") +) + +// We now have different sources from where a package +// manifest can be identified. For example, local, github, +// and may be in future within containers or archives like +// JAR. So we need to store additional internal metadata +type PackageManifestSource struct { + // The source type of this package namespace + Type ManifestSourceType + + // The namespace of the package manifest. Examples: + // - Directory when source is local + // - GitHub repo URL when source is GitHub + Namespace string + + // The namespace relative path of the package manifest + Path string + + // Explicit override the display path + DisplayPath string +} + +func (ps PackageManifestSource) GetDisplayPath() string { + switch ps.Type { + case ManifestSourceLocal: + return filepath.Join(ps.Namespace, ps.Path) + default: + return ps.DisplayPath + } +} + +func (ps PackageManifestSource) GetNamespace() string { + return ps.Namespace +} + +func (ps PackageManifestSource) GetPath() string { + return ps.Path +} + // Represents a package manifest that contains a list // of packages. Example: pom.xml, requirements.txt type PackageManifest struct { + // The source of the package manifest + Source PackageManifestSource `json:"source"` + // Filesystem path of this manifest Path string `json:"path"` - // When we scan non-path entities like Github org / repo - // then only path doesn't make sense, which is more local - // temporary file path - DisplayPath string `json:"display_path"` - // Ecosystem to interpret this manifest Ecosystem string `json:"ecosystem"` @@ -53,8 +96,30 @@ type PackageManifest struct { m sync.Mutex } +// Deprecated: Use NewPackageManifest* initializers func NewPackageManifest(path, ecosystem string) *PackageManifest { + return NewPackageManifestFromLocal(path, ecosystem) +} + +func NewPackageManifestFromLocal(path, ecosystem string) *PackageManifest { + return newPackageManifest(PackageManifestSource{ + Type: ManifestSourceLocal, + Namespace: filepath.Dir(path), + Path: filepath.Base(path), + }, path, ecosystem) +} + +func NewPackageManifestFromGitHub(repo, repoRelativePath, realPath, ecosystem string) *PackageManifest { + return newPackageManifest(PackageManifestSource{ + Type: ManifestSourceGitRepository, + Namespace: repo, + Path: repoRelativePath, + }, realPath, ecosystem) +} + +func newPackageManifest(source PackageManifestSource, path, ecosystem string) *PackageManifest { return &PackageManifest{ + Source: source, Path: path, Ecosystem: ecosystem, Packages: make([]*Package, 0), @@ -62,6 +127,16 @@ func NewPackageManifest(path, ecosystem string) *PackageManifest { } } +// Parsers usually create a package manifest from file, readers +// have the context to set the source correct. Example: GitHub reader +func (p *PackageManifest) UpdateSourceAsGitRepository(repo, repoRelativePath string) { + p.Source = PackageManifestSource{ + Type: ManifestSourceGitRepository, + Namespace: repo, + Path: repoRelativePath, + } +} + func (pm *PackageManifest) AddPackage(pkg *Package) { pm.m.Lock() defer pm.m.Unlock() @@ -74,22 +149,22 @@ func (pm *PackageManifest) AddPackage(pkg *Package) { pm.DependencyGraph.AddNode(pkg) } +func (pm *PackageManifest) GetSource() PackageManifestSource { + return pm.Source +} + func (pm *PackageManifest) GetPath() string { return pm.Path } func (pm *PackageManifest) SetDisplayPath(path string) { - pm.DisplayPath = path + pm.Source.DisplayPath = path } // GetDisplayPath returns the [DisplayPath] if available or fallsback // to [Path] func (pm *PackageManifest) GetDisplayPath() string { - if len(pm.DisplayPath) > 0 { - return pm.DisplayPath - } - - return pm.GetPath() + return pm.Source.GetDisplayPath() } // GetPackages returns the list of packages in this manifest diff --git a/pkg/readers/github_reader.go b/pkg/readers/github_reader.go index 21c7b37..665293f 100644 --- a/pkg/readers/github_reader.go +++ b/pkg/readers/github_reader.go @@ -129,7 +129,9 @@ func (p *githubReader) processTopLevelLockfiles(ctx context.Context, client *git return err } - pm.SetDisplayPath(gitUrl.GetHttpCloneURL()) + pm.UpdateSourceAsGitRepository(gitUrl.GetHttpCloneURL(), entry.GetPath()) + pm.SetDisplayPath(entry.GetURL()) + err = handler(pm, NewManifestModelReader(pm)) if err != nil { return err @@ -179,6 +181,7 @@ func (p *githubReader) processRemoteDependencyGraph(ctx context.Context, client // Override the display path because local path of the downloaded // SBOM does not actually have a meaning + manifest.UpdateSourceAsGitRepository(gitUrl.GetHttpCloneURL(), "") manifest.SetDisplayPath(gitUrl.GetHttpCloneURL()) return handler(manifest, NewManifestModelReader(manifest)) diff --git a/pkg/reporter/ci/git.go b/pkg/reporter/ci/git.go new file mode 100644 index 0000000..006e04c --- /dev/null +++ b/pkg/reporter/ci/git.go @@ -0,0 +1 @@ +package ci diff --git a/pkg/reporter/sync.go b/pkg/reporter/sync.go index 285cf77..853d917 100644 --- a/pkg/reporter/sync.go +++ b/pkg/reporter/sync.go @@ -151,6 +151,8 @@ func NewSyncReporter(config SyncReporterConfig) (Reporter, error) { trigger := controltowerv1.ToolTrigger_TOOL_TRIGGER_MANUAL source := packagev1.ProjectSourceType_PROJECT_SOURCE_TYPE_UNSPECIFIED + // A multi-project sync is required for cases like GitHub org where + // we are scanning multiple repositories if !config.EnableMultiProjectSync { logger.Debugf("Report Sync: Creating tool session for project: %s, version: %s", config.ProjectName, config.ProjectVersion) @@ -197,7 +199,7 @@ func (s *syncReporter) Name() string { func (s *syncReporter) AddManifest(manifest *models.PackageManifest) { manifestSessionKey := manifest.Path if s.config.EnableMultiProjectSync && !s.sessions.hasKeyedSession(manifestSessionKey) { - projectName := manifest.GetDisplayPath() + projectName := manifest.GetSource().GetNamespace() projectVersion := "main" source := packagev1.ProjectSourceType_PROJECT_SOURCE_TYPE_UNSPECIFIED @@ -341,6 +343,7 @@ func (s *syncReporter) syncEvent(event *analyzer.AnalyzerEvent) error { logger.Warnf("unsupported check type: %s", filter.GetCheckType()) } + namespace := pkg.Manifest.GetSource().GetNamespace() req := controltowerv1.PublishPolicyViolationRequest{ ToolSession: &controltowerv1.ToolSession{ ToolSessionId: session.sessionId, @@ -348,8 +351,8 @@ func (s *syncReporter) syncEvent(event *analyzer.AnalyzerEvent) error { Manifest: &packagev1.PackageManifest{ Ecosystem: pkg.Manifest.GetControlTowerSpecEcosystem(), - Namespace: &pkg.Manifest.Path, - Name: pkg.Manifest.GetDisplayPath(), + Namespace: &namespace, + Name: pkg.Manifest.GetSource().GetPath(), }, PackageVersion: &packagev1.PackageVersion{ From 6ec6cf2b035bf4795ae4461a3be4f058dcc77493 Mon Sep 17 00:00:00 2001 From: abhisek Date: Fri, 11 Oct 2024 17:27:21 +0530 Subject: [PATCH 23/28] fix: sarif test case --- pkg/reporter/sarif_test.go | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/pkg/reporter/sarif_test.go b/pkg/reporter/sarif_test.go index 2deff37..ef860e9 100644 --- a/pkg/reporter/sarif_test.go +++ b/pkg/reporter/sarif_test.go @@ -34,12 +34,16 @@ var events []analyzer.AnalyzerEvent = []analyzer.AnalyzerEvent{ CheckType: checks.CheckType_CheckTypeLicense, }, Manifest: &models.PackageManifest{ - DisplayPath: "displayPath1", + Source: models.PackageManifestSource{ + DisplayPath: "displayPath1", + }, }, Package: &models.Package{ PackageDetails: models.NewPackageDetail("ecosystem1", "name1", "version1"), Manifest: &models.PackageManifest{ - DisplayPath: "displayPath1", + Source: models.PackageManifestSource{ + DisplayPath: "displayPath1", + }, }, Insights: &insightapi.PackageVersionInsight{ Licenses: &licenses, @@ -55,12 +59,16 @@ var events []analyzer.AnalyzerEvent = []analyzer.AnalyzerEvent{ CheckType: checks.CheckType_CheckTypeVulnerability, }, Manifest: &models.PackageManifest{ - DisplayPath: "displayPath2", + Source: models.PackageManifestSource{ + DisplayPath: "displayPath1", + }, }, Package: &models.Package{ PackageDetails: models.NewPackageDetail("ecosystem2", "name2", "version2"), Manifest: &models.PackageManifest{ - DisplayPath: "displayPath2", + Source: models.PackageManifestSource{ + DisplayPath: "displayPath1", + }, }, Insights: &insightapi.PackageVersionInsight{ Vulnerabilities: &[]insightapi.PackageVulnerability{ @@ -81,12 +89,16 @@ var events []analyzer.AnalyzerEvent = []analyzer.AnalyzerEvent{ CheckType: checks.CheckType_CheckTypePopularity, }, Manifest: &models.PackageManifest{ - DisplayPath: "displayPath3", + Source: models.PackageManifestSource{ + DisplayPath: "displayPath2", + }, }, Package: &models.Package{ PackageDetails: models.NewPackageDetail("ecosystem3", "name3", "version3"), Manifest: &models.PackageManifest{ - DisplayPath: "displayPath3", + Source: models.PackageManifestSource{ + DisplayPath: "displayPath3", + }, }, Insights: &insightapi.PackageVersionInsight{ Projects: &[]insightapi.PackageProjectInfo{ From bda53d085766941fc43dd6e883a25f668ee19aa1 Mon Sep 17 00:00:00 2001 From: abhisek Date: Fri, 11 Oct 2024 17:29:12 +0530 Subject: [PATCH 24/28] fix: Fix E2E test case --- test/scenarios/all.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/scenarios/all.sh b/test/scenarios/all.sh index bcffcf3..1a267f2 100755 --- a/test/scenarios/all.sh +++ b/test/scenarios/all.sh @@ -7,8 +7,6 @@ export E2E_ROOT="$E2E_THIS_DIR/../../" export E2E_FIXTURES="$E2E_THIS_DIR/fixtures" export E2E_VET_BINARY="$E2E_ROOT/vet" -$E2E_VET_BINARY auth configure --community - bash $E2E_THIS_DIR/scenario-1-vet-scans-vet.sh bash $E2E_THIS_DIR/scenario-2-vet-scan-demo-client-java.sh bash $E2E_THIS_DIR/scenario-3-filter-fail-fast.sh From 0df926159849c5fc8d3c90b2664330f4ea974cad Mon Sep 17 00:00:00 2001 From: abhisek Date: Fri, 11 Oct 2024 17:37:20 +0530 Subject: [PATCH 25/28] fix: Verify auth before persisting --- auth.go | 8 ++++++++ internal/auth/auth.go | 8 ++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/auth.go b/auth.go index 61b8c35..4214f39 100644 --- a/auth.go +++ b/auth.go @@ -63,6 +63,14 @@ func configureAuthCommand() *cobra.Command { } } + auth.SetRuntimeCloudTenant(authTenantDomain) + auth.SetRuntimeApiKey(key) + + err = auth.Verify() + if err != nil { + logger.Fatalf("Failed to verify auth: %v", err) + } + err = auth.PersistApiKey(key, authTenantDomain) if err != nil { logger.Fatalf("Failed to configure auth: %v", err) diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 343d8bf..23f5f1e 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -12,8 +12,8 @@ import ( const ( apiUrlEnvKey = "VET_INSIGHTS_API_URL" - apiKeyEnvKey = "VET_INSIGHTS_API_KEY" - apiKeyAlternateEnvKey = "VET_API_KEY" + apiKeyEnvKey = "VET_API_KEY" + apiKeyAlternateEnvKey = "VET_INSIGHTS_API_KEY" communityModeEnvKey = "VET_COMMUNITY_MODE" controlTowerTenantEnvKey = "VET_CONTROL_TOWER_TENANT_ID" @@ -236,6 +236,10 @@ func SetRuntimeCloudTenant(domain string) { os.Setenv(controlTowerTenantEnvKey, domain) } +func SetRuntimeApiKey(key string) { + os.Setenv(apiKeyEnvKey, key) +} + func loadConfiguration() error { path, err := os.UserHomeDir() if err != nil { From 59967ca8cf18535b3875b5f033de72de581b1711 Mon Sep 17 00:00:00 2001 From: abhisek Date: Fri, 11 Oct 2024 19:48:28 +0530 Subject: [PATCH 26/28] Update production identity service info --- internal/auth/auth.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 23f5f1e..1c9dc28 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -26,12 +26,11 @@ const ( homeRelativeConfigPath = ".safedep/vet-auth.yml" - // https://dev-dkwn3e2k4k1fornc.us.auth0.com/.well-known/openid-configuration - cloudIdentityServiceClientId = "xidzYke2rDMJmNyXId2dLpNs4DLm4yZX" // gitleaks:allow + cloudIdentityServiceClientId = "QtXHUN3hOdbJbCiGU8FiNCnC2KtuROCu" // gitleaks:allow cloudIdentityServiceAudience = "https://cloud.safedep.io" - cloudIdentityServiceBaseUrl = "https://dev-dkwn3e2k4k1fornc.us.auth0.com" - cloudIdentityServiceDeviceCodeUrl = "https://dev-dkwn3e2k4k1fornc.us.auth0.com/oauth/device/code" - cloudIdentityServiceTokenUrl = "https://dev-dkwn3e2k4k1fornc.us.auth0.com/oauth/token" + cloudIdentityServiceBaseUrl = "https://auth.safedep.io" + cloudIdentityServiceDeviceCodeUrl = "https://auth.safedep.io/oauth/device/code" + cloudIdentityServiceTokenUrl = "https://auth.safedep.io/oauth/token" ) type Config struct { From 4f1cb39e56f82a81a393929d8519186c20a28d0a Mon Sep 17 00:00:00 2001 From: abhisek Date: Fri, 11 Oct 2024 20:51:34 +0530 Subject: [PATCH 27/28] fix: Update README --- README.md | 16 ++++++++++------ cmd/cloud/query.go | 3 +-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 9a4a2de..2ad11c9 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,6 @@

SafeDep Vet

-

- 🙌 Refer to https://safedep.io/docs for the documentation 📖 -

[![Go Report Card](https://goreportcard.com/badge/github.com/safedep/vet)](https://goreportcard.com/report/github.com/safedep/vet) ![License](https://img.shields.io/github/license/safedep/vet) @@ -16,13 +13,13 @@ [![vet banner](docs/static/img/vet/vet-banner.png)](https://safedep.io/docs) -## Automate Open Source Package Vetting in CI/CD +## Policy as Code for Open Source Software Supply Chain `vet` is a tool for identifying risks in open source software supply chain. It goes beyond just vulnerabilities and provides visibility on OSS package risks due to it's license, popularity, security hygiene, and more. `vet` is designed -with the goal of enabling trusted OSS package consumption by integrating with -CI/CD and `policy as code` as guardrails. +with the goal of helping software development teams consume safe and trusted +OSS components through automated vetting in CI/CD. * [🔥 vet in action](#-vet-in-action) * [Getting Started](#getting-started) @@ -43,6 +40,7 @@ CI/CD and `policy as code` as guardrails. * [📖 Documentation](#-documentation) * [🎊 Community](#-community) * [💻 Development](#-development) +* [Support](#support) * [Star History](#star-history) * [🔖 References](#-references) @@ -281,6 +279,12 @@ First of all, thank you so much for showing interest in `vet`, we appreciate it Refer to [CONTRIBUTING.md](CONTRIBUTING.md) +## Support + +[SafeDep](https://safedep.io) provides enterprise support for `vet` +deployments. Check out [SafeDep Cloud](https://safedep.io) for large scale +deployment and management of `vet` in your organization. + ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=safedep/vet&type=Date)](https://star-history.com/#safedep/vet&Date) diff --git a/cmd/cloud/query.go b/cmd/cloud/query.go index f9f8f22..3b98f62 100644 --- a/cmd/cloud/query.go +++ b/cmd/cloud/query.go @@ -2,7 +2,6 @@ package cloud import ( "errors" - "fmt" "os" "sort" @@ -84,7 +83,7 @@ func renderQueryResponseAsTable(response *query.QueryResponse) error { return nil } - ui.PrintSuccess(fmt.Sprintf("Query returned %d results", response.Count())) + ui.PrintSuccess("Query returned %d results", response.Count()) // Header headers := []string{} From 82217aeb07c3db03d1d0b2d8363b0641f3e5fd27 Mon Sep 17 00:00:00 2001 From: abhisek Date: Fri, 11 Oct 2024 20:59:21 +0530 Subject: [PATCH 28/28] docs: Update README for maintenance attribution --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 2ad11c9..0aae6e2 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ SafeDep Vet +

+ Created and maintained by https://safedep.io with contributions from the community 🚀 +

+ [![Go Report Card](https://goreportcard.com/badge/github.com/safedep/vet)](https://goreportcard.com/report/github.com/safedep/vet) ![License](https://img.shields.io/github/license/safedep/vet) ![Release](https://img.shields.io/github/v/release/safedep/vet)