Skip to main content

Snyk

通过我们的 Snyk 集成,您可以根据您的映射和定义,将 Snyk 账户中的 "组织"、"目标"、"项目 "和 "问题 "导入 Port。

常见被用于情况

  • 在您的 Snyk 环境中映射 "组织"、"目标"、"项目 "和 "问题"。
  • 实时观察对象更改(创建/更新/删除),并自动将更改应用到 Port 中的实体。
  • 使用自助操作创建/删除 Snyk 对象。

先决条件

To install the integration, you need a Kubernetes cluster that the integration's container chart will be deployed to.

Please make sure that you have kubectl and helm installed on your machine, and that your kubectl CLI is connected to the Kubernetes cluster where you plan to install the integration.

安装

从以下安装方法中选择一种:

使用该安装选项意味着集成将能使用 webhook 实时更新 Port。

本表总结了安装时可用的参数,请在下面的脚本中按自己的需要进行设置,然后复制并在终端运行:

ParameterDescriptionRequired
port.clientIdYour Port client id
port.clientSecretYour Port client secret
port.baseUrlYour Port base url, relevant only if not using the default Port app
integration.identifierChange the identifier to describe your integration
integration.typeThe integration type
integration.eventListener.typeThe event listener type
integration.secrets.tokenThe Snyk API token
integration.config.organizationIdThe Snyk organization ID. Fetches data for this organization when provided
integration.config.groupsA comma-separated list of Snyk group ids to filter data for. Fetches data for organizations within the specified groups
integration.config.apiUrlThe Snyk API URL. If not specified, the default will be https://api.snyk.io
integration.config.appHostThe host of the Port Ocean app. Used to set up the integration endpoint as the target for Webhooks created in Snyk
integration.secret.webhookSecretThis is a password you create, that Snyk uses to sign webhook events to Port
scheduledResyncIntervalThe number of minutes between each resync
initializePortResourcesDefault true, When set to true the integration will create default blueprints and the port App config Mapping

To install the integration using ArgoCD, follow these steps:

  1. 在 git 仓库的argocd/my-ocean-snyk-integration中创建内容为values.yaml的文件:
默认行为 默认情况下,集成会获取与 Provider Snyk 令牌相关联的所有组织。

记住要替换 SNYK_TOKEN 的占位符。

initializePortResources: true
scheduledResyncInterval: 120
integration:
identifier: my-ocean-snyk-integration
type: snyk
eventListener:
type: POLLING
secrets:
token: SNYK_TOKEN

如果您希望自定义访问权限,可以使用以下配置:

  • organizationId 键被用于来限制对特定组织的访问。如果在 values.yaml 文件中指定,集成将只获取 Providers 组织的数据。
配置变量替换 请记住替换 SNYK_TOKENSNYK_ORGANIZATION_ID 的占位符。
initializePortResources: true
scheduledResyncInterval: 120
integration:
identifier: my-ocean-snyk-integration
type: snyk
eventListener:
type: POLLING
config:
organizationId: SNYK_ORGANIZATION_ID
secrets:
token: SNYK_TOKEN

  • groups "键被用于来限制对特定 Snyk 组内所有组织的访问。在 values.yaml 文件中,为 groups 键提供一个以逗号分隔的 Snyk 组 ID 列表,集成将过滤组内所有组织的数据。
配置变量替换 请记住替换 SNYK_TOKENSNYK_GROUPS 的占位符。
initializePortResources: true
scheduledResyncInterval: 120
integration:
identifier: my-ocean-snyk-integration
type: snyk
eventListener:
type: POLLING
config:
groups: SNYK_GROUPS
secrets:
token: SNYK_TOKEN

2.创建下面的 "my-ocean-snyk-integration.yaml "配置清单,安装 "my-ocean-snyk-integration "ArgoCD应用程序:

配置变量替换 请记住替换 YOUR_PORT_CLIENT_ID YOUR_PORT_CLIENT_SECRETYOUR_GIT_REPO_URL 的占位符。

多种来源的 ArgoCD 文档可在here 上找到。

ArgoCD Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-ocean-snyk-integration
namespace: argocd
spec:
destination:
namespace: my-ocean-snyk-integration
server: https://kubernetes.default.svc
project: default
sources:
- repoURL: 'https://port-labs.github.io/helm-charts/'
chart: port-ocean
targetRevision: 0.1.14
helm:
valueFiles:
- $values/argocd/my-ocean-snyk-integration/values.yaml
parameters:
- name: port.clientId
value: YOUR_PORT_CLIENT_ID
- name: port.clientSecret
value: YOUR_PORT_CLIENT_SECRET
- repoURL: YOUR_GIT_REPO_URL
targetRevision: main
ref: values
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

3.使用 kubectl 配置应用程序清单:

kubectl apply -f my-ocean-snyk-integration.yaml
高级集成配置

有关代理或自签名证书等高级配置,click here

接收 Snyk 对象

Snyk 集成使用 YAML 配置来描述将数据加载到开发者门户的过程。

下面是配置中的一个示例片段,演示了从 Snyk 获取 "项目 "数据的过程:

createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: project
selector:
query: "true"
port:
entity:
mappings:
identifier: .id
title: .attributes.name
blueprint: '"snykProject"'
properties:
url: ("https://app.snyk.io/org/" + .relationships.organization.data.id + "/project/" + .id | tostring)
owner: .__owner.email
businessCriticality: .attributes.business_criticality
environment: .attributes.environment
lifeCycle: .attributes.lifecycle
highOpenVulnerabilities: .meta.latest_issue_counts.high
mediumOpenVulnerabilities: .meta.latest_issue_counts.medium
lowOpenVulnerabilities: .meta.latest_issue_counts.low
criticalOpenVulnerabilities: .meta.latest_issue_counts.critical
importedBy: .__importer.email
tags: .attributes.tags

该集成利用JQ JSON processor 对来自 Snyk API 事件的现有字段和 Values 进行选择、修改、连接、转换和其他操作。

配置结构

集成配置决定了将从 Snyk 查询哪些资源,以及将在 Port 中创建哪些实体和属性。

支持的资源 以下资源可被用于来映射来自 Snyk 的数据,可以引用出现在下面链接的 API 响应中的任何字段来进行映射配置。
  • 集成配置的根密钥是 "资源 "密钥:

    resources:
    - kind: project
    selector:
    ...
  • 类型 "键是 Snyk 对象的指定符:

      resources:
    - kind: project
    selector:
    ...
  • 通过 "选择器 "和 "查询 "键,您可以过滤哪些指定 "类型 "的对象将被录入软件目录:

    resources:
    - kind: project
    selector:
    query: "true" # JQ boolean expression. If evaluated to false - this object will be skipped.
    port:
  • Port"、"实体 "和 "映射 "键被用来将 Snyk 对象字段映射到Port实体。要创建多个同类映射,可在 resources 数组中添加另一项;

    resources:
    - kind: project
    selector:
    query: "true"
    port:
    entity:
    mappings: # Mappings between one Snyk object to a Port entity. Each value is a JQ query.
    identifier: .id
    title: .attributes.name
    blueprint: '"snykProject"'
    properties:
    url: ("https://app.snyk.io/org/" + .relationships.organization.data.id + "/project/" + .id | tostring)
    owner: .__owner.email
    businessCriticality: .attributes.business_criticality
    environment: .attributes.environment
    lifeCycle: .attributes.lifecycle
    highOpenVulnerabilities: .meta.latest_issue_counts.high
    mediumOpenVulnerabilities: .meta.latest_issue_counts.medium
    lowOpenVulnerabilities: .meta.latest_issue_counts.low
    criticalOpenVulnerabilities: .meta.latest_issue_counts.critical
    importedBy: .__importer.email
    tags: .attributes.tags
    - kind: project # In this instance project is mapped again with a different filter
    selector:
    query: '.name == "MyProjectName"'
    port:
    entity:
    mappings: ...
蓝图键 注意 blueprint 键的值 - 如果要使用硬编码字符串,需要用 2 组引号封装,例如使用一对单引号 ('),然后再用一对双引号 ("):

将数据输入Port

要使用integration configuration 引用 Snyk 对象,可以按照以下步骤操作:

  1. 转到 DevPortal Builder 页面。
  2. 选择要被 Snyk 引用的蓝图。
  3. 从菜单中选择采集数据选项。
  4. 在 "代码质量和安全 Provider "类别下选择 Snyk。
  5. 根据您的需要修改configuration
  6. 单击 Resync

示例

蓝图和相关集成配置示例:

组织

Organization blueprint
{
"identifier": "snykOrganization",
"title": "Snyk Organization",
"icon": "Snyk",
"schema": {
"properties": {
"url": {
"type": "string",
"title": "URL",
"format": "url",
"icon": "Snyk"
},
"slug": {
"type": "string",
"title": "Slug"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {}
}
Integration configuration
- kind: organization
selector:
query: 'true'
port:
entity:
mappings:
identifier: .id
title: .name
blueprint: '"snykOrganization"'
properties:
slug: .slug
url: ("https://app.snyk.io/org/" + .slug | tostring)

目标

Target blueprint
{
"identifier": "snykTarget",
"title": "Snyk Target",
"icon": "Snyk",
"schema": {
"properties": {
"criticalOpenVulnerabilities": {
"icon": "Vulnerability",
"type": "number",
"title": "Open Critical Vulnerabilities"
},
"highOpenVulnerabilities": {
"icon": "Vulnerability",
"type": "number",
"title": "Open High Vulnerabilities"
},
"mediumOpenVulnerabilities": {
"icon": "Vulnerability",
"type": "number",
"title": "Open Medium Vulnerabilities"
},
"lowOpenVulnerabilities": {
"icon": "Vulnerability",
"type": "number",
"title": "Open Low Vulnerabilities"
},
"origin": {
"title": "Target Origin",
"type": "string",
"enum": [
"artifactory-cr",
"aws-config",
"aws-lambda",
"azure-functions",
"azure-repos",
"bitbucket-cloud",
"bitbucket-server",
"cli",
"cloud-foundry",
"digitalocean-cr",
"docker-hub",
"ecr",
"gcr",
"github",
"github-cr",
"github-enterprise",
"gitlab",
"gitlab-cr",
"google-artifact-cr",
"harbor-cr",
"heroku",
"ibm-cloud",
"kubernetes",
"nexus-cr",
"pivotal",
"quay-cr",
"terraform-cloud"
]
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Integration configuration
- kind: target
selector:
query: "true"
port:
entity:
mappings:
identifier: .attributes.displayName
title: .attributes.displayName
blueprint: '"snykTarget"'
properties:
origin: .attributes.origin
highOpenVulnerabilities: "[.__projects[].meta.latest_issue_counts.high] | add"
mediumOpenVulnerabilities: "[.__projects[].meta.latest_issue_counts.medium] | add"
lowOpenVulnerabilities: "[.__projects[].meta.latest_issue_counts.low] | add"
criticalOpenVulnerabilities: "[.__projects[].meta.latest_issue_counts.critical] | add"

项目

Project blueprint
{
"identifier": "snykProject",
"title": "Snyk Project",
"icon": "Snyk",
"schema": {
"properties": {
"url": {
"type": "string",
"title": "URL",
"format": "url",
"icon": "Snyk"
},
"owner": {
"type": "string",
"title": "Owner",
"format": "user",
"icon": "TwoUsers"
},
"businessCriticality": {
"title": "Business Criticality",
"type": "array",
"items": {
"type": "string",
"enum": [
"critical",
"high",
"medium",
"low"
]
},
"icon": "DefaultProperty"
},
"environment": {
"items": {
"type": "string",
"enum": [
"frontend",
"backend",
"internal",
"external",
"mobile",
"saas",
"onprem",
"hosted",
"distributed"
]
},
"icon": "Environment",
"title": "Environment",
"type": "array"
},
"lifeCycle": {
"title": "Life Cycle",
"type": "array",
"items": {
"type": "string",
"enum": [
"development",
"sandbox",
"production"
]
},
"icon": "DefaultProperty"
},
"highOpenVulnerabilities": {
"icon": "Vulnerability",
"type": "number",
"title": "Open High Vulnerabilities"
},
"mediumOpenVulnerabilities": {
"icon": "Vulnerability",
"type": "number",
"title": "Open Medium Vulnerabilities"
},
"lowOpenVulnerabilities": {
"icon": "Vulnerability",
"type": "number",
"title": "Open Low Vulnerabilities"
},
"importedBy": {
"icon": "TwoUsers",
"type": "string",
"title": "Imported By",
"format": "user"
},
"tags": {
"type": "array",
"title": "Tags",
"icon": "DefaultProperty"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {
"snykVulnerabilities": {
"title": "Snyk Vulnerabilities",
"target": "snykVulnerability",
"required": false,
"many": true
},
"snykOrganization": {
"title": "Snyk Organization",
"target": "snykOrganization",
"required": true,
"many": false
}
}
}
Integration configuration
- kind: project
selector:
query: 'true'
port:
entity:
mappings:
identifier: .id
title: .attributes.name
blueprint: '"snykProject"'
properties:
url: ("https://app.snyk.io/org/" + .relationships.organization.data.id + "/project/" + .id | tostring)
owner: .__owner.email
businessCriticality: .attributes.business_criticality
environment: .attributes.environment
lifeCycle: .attributes.lifecycle
highOpenVulnerabilities: .meta.latest_issue_counts.high
mediumOpenVulnerabilities: .meta.latest_issue_counts.medium
lowOpenVulnerabilities: .meta.latest_issue_counts.low
criticalOpenVulnerabilities: .meta.latest_issue_counts.critical
importedBy: .__importer.email
tags: .attributes.tags
relations:
snykVulnerabilities: '[.__issues[] | select(.issueType == "vuln").issueData.id]'
snykOrganization: .relationships.organization.data.id

漏洞

Vulnerability blueprint
{
"identifier": "snykVulnerability",
"title": "Snyk Vulnerability",
"icon": "Snyk",
"schema": {
"properties": {
"score": {
"icon": "Star",
"type": "number",
"title": "Score"
},
"packageName": {
"type": "string",
"title": "Package Name",
"icon": "DefaultProperty"
},
"packageVersions": {
"icon": "Package",
"title": "Package Versions",
"type": "array"
},
"type": {
"type": "string",
"title": "Type",
"enum": [
"vuln",
"license",
"configuration"
],
"icon": "DefaultProperty"
},
"severity": {
"icon": "Alert",
"title": "Issue Severity",
"type": "string",
"enum": [
"low",
"medium",
"high",
"critical"
],
"enumColors": {
"low": "green",
"medium": "yellow",
"high": "red",
"critical": "red"
}
},
"url": {
"icon": "Link",
"type": "string",
"title": "Issue URL",
"format": "url"
},
"language": {
"type": "string",
"title": "Language",
"icon": "DefaultProperty"
},
"publicationTime": {
"type": "string",
"format": "date-time",
"title": "Publication Time",
"icon": "DefaultProperty"
},
"isPatched": {
"type": "boolean",
"title": "Is Patched",
"icon": "DefaultProperty"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Integration configuration
- kind: issue
selector:
query: '.issueType == "vuln"'
port:
entity:
mappings:
identifier: .issueData.id
title: .issueData.title
blueprint: '"snykVulnerability"'
properties:
score: .priorityScore
packageName: .pkgName
packageVersions: .pkgVersions
type: .issueType
severity: .issueData.severity
url: .issueData.url
language: .issueData.language // .issueType
publicationTime: .issueData.publicationTime
isPatched: .isPatched

通过 webhook 进行替代安装

虽然上述 Ocean 集成是推荐的安装方法,但您可能更喜欢使用 webhook 从 Snyk 引用数据。 如果是这样,请使用以下说明:

Webhook installation (click to expand)

在本示例中,您将在Snyk 和 Port 之间创建 Webhook 集成,将 Snyk 代码和基础架构漏洞实体导入 Port。

Port configuration

创建以下蓝图定义:

Snyk vulnerability blueprint
{
"identifier": "snykVulnerability",
"description": "This blueprint represents a Snyk vulnerability in our software catalog",
"title": "Snyk Vulnerability",
"icon": "Snyk",
"schema": {
"properties": {
"organizationUrl": {
"type": "string",
"format": "url",
"title": "Organization URL"
},
"organizationName": {
"type": "string",
"title": "Organization Name"
},
"projectName": {
"type": "string",
"title": "Project Name"
},
"projectOrigin": {
"type": "string",
"title": "Project Origin"
},
"branchName": {
"type": "string",
"title": "Branch Name"
},
"pkgName": {
"type": "string",
"title": "Package Name"
},
"issueType": {
"type": "string",
"title": "Issue Type"
},
"issueSeverity": {
"type": "string",
"title": "Issue Severity"
},
"issueURL": {
"type": "string",
"format": "url",
"title": "Issue URL"
},
"issueStatus": {
"type": "string",
"title": "Issue Status",
"enum": ["added", "removed"],
"enumColors": {
"added": "red",
"removed": "green"
}
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}

创建以下 webhook 配置using Port UI

Snyk vulnerability webhook configuration
  1. 基本信息 选项卡 - 填写以下详细信息: 1.title: Snyk Mapper; 2.标识符 : snyk_mapper; 3.Description : 将 Snyk 漏洞映射到 Port 的 webhook 配置; 4.图标 : Snyk
  2. 集成配置选项卡 - 填写以下 JQ 映射:
    [
    {
    "blueprint": "snykVulnerability",
    "itemsToParse": ".body.newIssues",
    "filter": ".body.newIssues | length > 0",
    "entity": {
    "identifier": ".item.id",
    "title": ".item.issueData.title",
    "properties": {
    "organizationUrl": ".body.org.url",
    "organizationName": ".body.org.name",
    "projectName": ".body.project.name",
    "projectOrigin": ".body.project.origin",
    "branchName": ".body.project.branch",
    "issueType": ".item.issueType",
    "pkgName": ".item.pkgName",
    "issueSeverity": ".item.issueData.severity",
    "issueURL": ".item.issueData.url",
    "issueStatus": "'added'"
    }
    }
    },
    {
    "blueprint": "snykVulnerability",
    "itemsToParse": ".body.removedIssues",
    "filter": ".body.removedIssues | length > 0",
    "entity": {
    "identifier": ".item.id",
    "title": ".item.issueData.title",
    "properties": {
    "organizationUrl": ".body.org.url",
    "organizationName": ".body.org.name",
    "projectName": ".body.project.name",
    "projectOrigin": ".body.project.origin",
    "branchName": ".body.project.branch",
    "issueType": ".item.issueType",
    "pkgName": ".item.pkgName",
    "issueSeverity": ".item.issueData.severity",
    "issueURL": ".item.issueData.url",
    "issueStatus": "'removed'"
    }
    }
    }
    ]

3.向下滚动到 高级设置,输入以下详细信息:

  1. secret: WEBHOOK_SECRET; 2.签名头名称: x-hub-signature; 3.签名算法: 从下拉选项中选择 sha256; 4.签名前缀 : sha256=. 5.点击页面底部的保存

切记将 WEBHOOK_SECRET 替换为在 Snyk 中创建 webhook 时指定的真实secret。

Create a webhook in Snyk

  1. 进入Snyk ,选择要配置 webhook 的账户;

  2. 点击页面左侧的设置,在组织 ID 部分下复制您的组织 ID;

  3. 导航至Snyk accounts page 并复制您的 API 令牌。您将使用此值授权 REST API;

  4. 打开任何 REST API 客户端(如 POSTMAN),进行以下 API 调用以创建 webhook:

    1. API URL - 被用于 https://api.snyk.io/v1/org/`YOUR_ORG_ID`/webhooks;
    2. Method - 选择 POST
    3. Authorization - API 标记应在授权标头中以 Authorization: token YOUR_API_KEY 的形式提供;
    4. Request Body - 请求正文应为 JSON 格式。在正文中填写以下信息
    {
    "url": "https://ingest.getport.io/<YOUR_PORT_WEBHOOK_KEY>",
    "secret": "WEBHOOK_SECRET"
    }
  5. Click Send to create your Snyk webhook;

您也可以使用下面的 curl 命令创建 Snyk webhook:
curl -X POST \
-H "Authorization: token YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://ingest.getport.io/<YOUR_PORT_WEBHOOK_KEY>", "secret": "WEBHOOK_SECRET"}' \
https://api.snyk.io/v1/org/<YOUR_ORG_ID>/webhooks

完成!在源代码中检测到的任何漏洞都会触发一个 webhook 事件,并将其发送到 Port 提供的 webhook URL。 Port 将根据映射解析这些事件,并相应地更新目录实体。