diff --git a/Dockerfile b/Dockerfile index 19bae9a975673cab944f6b8e20e2274fe1e51814..ee6e4762f5e1aa77d83531f18fc2785f9afee320 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ -ARG BASE_REGISTRY=registry1.dsop.io -ARG BASE_IMAGE=ironbank/opensource/nodejs/nodejs12 -ARG BASE_TAG=12.20.0 +ARG BASE_REGISTRY=registry1.dso.mil +ARG BASE_IMAGE=ironbank/opensource/nodejs/nodejs14 +ARG BASE_TAG=14.15.5 -FROM renovate/renovate:24.4.0-slim as builder +FROM renovate/renovate:24.119.5-slim as builder FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} @@ -29,7 +29,8 @@ RUN tar -zxf /helm-docs.tar.gz -C /usr/local/bin helm-docs && \ echo "api.set('ironbank', ironbank);";} >> /usr/src/app/node_modules/renovate/dist/manager/api.generated.js && \ rm -f /home/node/node_modules/node-gyp/test/fixtures/*.key && \ chmod -s /usr/libexec/openssh/ssh-keysign && \ - rm -f /usr/src/app/node_modules/node-gyp/test/fixtures/*.key + rm -f /usr/src/app/node_modules/node-gyp/test/fixtures/*.key && \ + rm -f /usr/src/app/node_modules/@aws-sdk/node-http-handler/fixtures/test-server-key.pem WORKDIR /usr/src/app USER 1001 diff --git a/README.md b/README.md index 984e1b58985730af0768f09e27e7844451400a5a..2e594feb56008ea73b6622c4e3f5504a2ec2758d 100644 --- a/README.md +++ b/README.md @@ -7,107 +7,104 @@ The pluggable constructs in Renovate include: * **manager**: extracts dependencies and assigns a datasource. * **datasource**: fetches releases for a dependency -Renovate handles opening pull requests for out-of-date dependencies and can be customized for individual projects. +Renovate handles opening Gitlab Merge Requests for out-of-date dependencies and can be customized for individual projects. -## Background +--- -In addition to the `Dockerfile`, there are custom Ironbank files that need to be updated when a new version is discovered. +## How we use Renovate in Ironbank -* **download.yaml** -* **greylist** -* **Jenkinsfile** +Renovate is an opensource project which we have implemented in Repo1's Gitlab. Our renovate-bot runs daily so any vendor that wants to create their own configuration of Renovate is free to do so. The follow subsequent sections outline how we utilize Renovate on opensource projects that are mangaged by the Container Hardening Team to watch for updates to upstream resouces in those projects. Ultimately, the vendor is responsible for the updating of their container in Ironbank, the use of Renovate is not required but is an option we provide for their use. -### download.yaml +Renonvate has a capability set of updating dependancies from a wide range of sources, however, due to the nature of our container hardening process we utilize a very narrow subset of Renovate's capabilites. Gitlab projects in Repo1 do not contain any of the application source code, only the process of how that application is hardened into a container image. Therefore, managers and datasource that are targeted at updating source code depenancies are not used. -Ironbank requires contributors to define external dependencies in a `download.yaml` file. The build pipeline executes within a disconnected environment, so dependencies are fetched and added to the build context beforehand. Versions, tags, and digests must be updated for a new release. +The Ironbank pipeline requires all upstream resouces to be declared in the hardening_manifest. Due to this we use Renovate, more specifically a custom manager call `Ironbank` and the `Regex Manager`, to parse the hardening_manifest for declared versions and check for updates using the supported datasources in our `Ironbank Manager` or what is outlined in the renovate.json file for the `Regex Manager`. -```yaml -resources: - - url: "docker://docker.io/argoproj/argocd@sha256:60edd3283acbfc83cc6e23218c3882d512273f4a3073940b1619f8d8be9c6a1e" - tag: "argoproj/argocd:v1.5.3" - - url: "docker://docker.io/amazon/aws-cli@sha256:01d89b3599685d9f0171ba42486907723833105b447d6413e1944944295bcd6f" - tag: "amazon/aws-cli:2.0.10" -``` +--- +**Note** -### greylist + There is a limitation for this usage. Your upstream resource must be stored in a location for which renovate has a datasoure (a full list of supported datasources can be found [here](https://docs.renovatebot.com/modules/datasource/) ). Unfortunatly, this is a limiting factor for some projects. -The pipeline uses the greylist to inject the `BASE_IMAGE` and `BASE_TAG` build arguments. These image tags must also be updated. + -- -```json -{ - "image_name": "opensource/keycloak/keycloak", - "image_tag": "10.0.0", - "image_parent_name": "opensource/openjdk/openjdk11", - "image_parent_tag": "1.11", - "container_owner": "melissari_sean@bah.com", - "authorized_approvers": [ - "nicolas.m.chaillan.civ@mail.mil" - ], - "whitelisted_vulnerabilities": [] -} -``` + It is important to remove any references to a specific application version in the filename of the hardening_manifest.yaml file when downloading artifacts that are not images. This way, if the artifact version is bumped, the COPY statement included in the Dockerfile will be able to handle this updated version, without failing because it attempts to copy an older version which is no longer being downloaded. -### Jenkinsfile + For example, use the filename kubernetes.tar.gz instead of the filename kubernetes-1.18.3 because the Dockerfile COPY kubernetes-1.18.3.tar.gz statement will throw an error that a resource cannot be found if the Kubernetes artifact version is bumped to 1.18.4. COPY kubernetes.tar.gz will handle any version bumps that occur and result in successful copying of the hardening_manifest.yaml artifact for the build. -The Jenkinsfile defines the output image tag. Renovate can be used to track an upstream dependency to mirror version tags. +--- -``` -@Library('DCCSCR@master') _ -dccscrPipeline(version: "10.0.0") -``` +### Hardening_manifest + +Specifically, there are three pieces of data in the `hardening_manifest` that Renovate needs to watch and update. -## Additional Changes + - tags + - labels + - resources -It is important to remove any references to a specific application version in the filename of the `download.yaml` file when downloading artifacts that are not images. This way, if the artifact version is bumped, the COPY statement included in the Dockerfile will be able to handle this updated version, without failing because it attempts to copy an older version which is no longer being downloaded. +*The following are example snippits from the ArgoCD project hardening_manifest that identify these:* -For example, use the filename `kubernetes.tar.gz` instead of the filename `kubernetes-1.18.3` because the Dockerfile `COPY kubernetes-1.18.3.tar.gz` statement will throw an error that a resource cannot be found if the Kubernetes artifact version is bumped to `1.18.4`. `COPY kubernetes.tar.gz` will handle any version bumps that occur and result in successful copying of the `download.yaml` artifact for the build. +```yaml +tags: +- "v1.8.7" -Renovate is also configured to run on the `development` branch of each project so that the versions on `master` are not updated without going through the Iron Bank approval process. It is necessary to change the default branch (Project Settings > Repository > Default branch) to the `development` branch in order for Renovate to function correctly. +labels: + org.opencontainers.image.version: "v1.8.7" -## Implementation +resources: +- url: "docker://docker.io/argoproj/argocd@sha256:ce34acd7bac34d5a4fdbf96faf11fa5e01a7f96a27041d4472ca498886000cbf" + tag: "argoproj/argocd:v1.8.7" + +``` ### Ironbank Manager -A custom **manager** is developed for Ironbank to handle extracting dependencies and datasources from the `download.yaml` file. +The `Ironbank Manager` is a custom **manager** that was developed for use in Repo1 to handle extracting dependencies from the `hardening_manifest.yaml` file resource section. + +`docker`, `github-releases`, `github-tags`, `ruby-gems`, and `pypi`**datasources** are currently supported, but other native datasources can be added as well. The manager parses the `url` key to determine the type of dependency. -`docker` and `github-releases`**datasources** are supported, but other native datasources can be added as well. The manager parses the `url` key to determine the type of dependency. ```yaml - url: docker://{registry}/{repo}@{digest} - url: https://github.com/${repo}/releases/download/${version}/${archive} +- url: https://rubygems.org/downloads/{import}-{version}.gem +- url: https://files.pythonhosted.org/../.../{import}-{version}...whl ``` -### Regex Manager +--- +**Note** -Renovate includes a regex **manager** that can extract dependencies with a regular expression. This is useful for file formats that do not have an associated manager. Within Ironbank, the regex manager is used to handle updating the `Jenkinsfile` and `.greylist`. + In order for you to take advantage of the custom Ironbank Manager you only need to have an empty renovate.json file in the base of your Gitlab project. The Ironbank Manager will parse the hardening_manifest (if it exists) and check for updates for supported sources by default without any additional configuration. -The example `renovate.json` below will update the **version:** string if there is an update to the jboss/keycloak docker image found on docker.io. -```json -{ - "fileMatch": ["^Jenkinsfile$"], - "matchStrings": [ - "version:\\s+\"(?.*?)\"" - ], - "depNameTemplate": "jboss/keycloak", - "datasourceTemplate": "docker" -} -``` +--- -Notice the `depNameTemplate` and `datasourceTemplate` that defines the dependency metadata. The `Jenkinsfile` does not include the dependency name or source, so it must be defined in the manager configuration. +### Regex Manager -## Usage +Renovate includes a regex **manager** that can extract dependencies with a regular expression. This is useful for file formats that do not have an associated manager. Within Ironbank, the regex manager is used to handle updating the `hardening_manifest` tags and labels section. -A `renovate-bot` account is created in GitLab and added as a developer for Ironbank. +The example `renovate.json` below will update the **tags:** and **labels:** strings if there is an update to the argocd docker image found on docker.io. -A Jenkins job for each repository is created under the `renovate` folder. Each job is configured to run on a schedule such as `H H/4 * * *` (runs once every 4 hours). -```shell -RENOVATE_AUTODISCOVER="false" -RENOVATE_ENDPOINT="https://repo1.dsop.io/api/v1" -RENOVATE_PLATFORM="gitlab" -RENOVATE_TOKEN="${env.RENOVATE_TOKEN}" -RENOVATE_REPOSITORIES="dsop/opensource/coredns/coredns" +```json + { + "fileMatch": [ + "^hardening_manifest.yaml$" + ], + "matchStrings": [ + "org\\.opencontainers\\.image\\.version:\\s+\"(?.+?)\"" + ], + "depNameTemplate": "argoproj/argocd", + "datasourceTemplate": "docker" + }, + { + "fileMatch": [ + "^hardening_manifest.yaml$" + ], + "matchStrings": [ + "tags:\\s+-\\s+\"(?.+?)\"" + ], + "depNameTemplate": "argoproj/argocd", + "datasourceTemplate": "docker" + } ``` -A single job for all repositories can also be configured. Other scheduling mechanisms such as a Kubernetes `CronJob` could be used instead as well. +Notice the `depNameTemplate` and `datasourceTemplate` that defines the dependency metadata. ### Major Versions @@ -115,167 +112,71 @@ Repositories that a pinned to a major version (i.e. `dsop/opensource/redis/redis ```json { - "major": { - "enabled": false - } + "major": { + "enabled": false + } } ``` ### Reviewers Add reviewers for each repository so `MAINTAINERS` will be notified of a new pull request. Renovate can also be configured to automerge pull requests. -```json -{ - "reviewers": [ - "jeason" - ] -} -``` - -## Examples - -Renovate configurations for the following examples are provided below. - -* [Docker](#docker) -* [GitHub](#github) -* [YUM](#yum) - -### Docker - -![renovate_docker](img/renovate_argocd.png) - -#### download.yaml - -Renovate updates the **download.yaml** `url` and `tag`. - -```yaml -resources: - - url: "docker://docker.io/argoproj/argocd@sha256:60edd3283acbfc83cc6e23218c3882d512273f4a3073940b1619f8d8be9c6a1e" - tag: "argoproj/argocd:v1.5.3" -``` - -#### dsop/opensource/argoproj/argocd/renovate.json - -Renovate updates the **Dockerfile** `LABEL version=1.5.3` and **Jenkinsfile** `dccscrPipeline(version: 1.5.3)` lines. ```json { - "regexManagers": [{ - "fileMatch": ["^Dockerfile$"], - "matchStrings": [ - "version=\"(?.*?)\"" - ], - "depNameTemplate": "argoproj/argocd", - "datasourceTemplate": "docker" - }, { - "fileMatch": ["^Jenkinsfile$"], - "matchStrings": [ - "version:\\s+\"(?.*?)\"" - ], - "depNameTemplate": "argoproj/argocd", - "datasourceTemplate": "docker" - }] + "reviewers": [ + "jeason" + ] } ``` -#### dccscr-whitelist/renovate.json - -Renovate updates the **argocd.greylist** `"image_tag": "v1.5.3"` line. - -```json -"regexManagers": [ - { - "fileMatch": ["^argocd.greylist$"], - "matchStrings": [ - "\"image_tag\": \"(?.*?)\"" - ], - "depNameTemplate": "argoproj/argocd", - "datasourceTemplate": "docker" - } -] -``` - -### GitHub - -![renovate_github](img/renovate_etcd.png) +--- -#### download.yaml +**Note** +For more indepth documentation and configuration options you can visit the official documentation [here](https://docs.renovatebot.com/configuration-options/). -Renovate updates the **download.yaml** `url` and `validation.value`. +--- -```yaml -resources: - - url: "https://github.com/etcd-io/etcd/releases/download/v3.4.6/etcd-v3.4.6-linux-amd64.tar.gz" - filename: etcd.tar.gz - validation: - type: sha256 - value: a3a332a68fe8dedf20149c1a4b8746fe8061b72d75d3a5850b17e04de9ed7942 -``` +## Renovate Workflow -#### dsop/opensource/etcd/etcd/renovate.json +In order to begin using Renovate in your project you must create a renovate.json file in the base of your project. Any project with a renovate.json file the renovate-bot will detect and run against it. -Renovate updates the **Dockerfile** `LABEL version=3.4.6` and **Jenkinsfile** `dccscrPipeline(version: 3.4.6)` lines. +If an update is detected a merge request will be created with those changes. An Issue will be created and associated with that merge request. It is then required that the normal container hardening process if followed with that merge request. The pipeline must pass, merged into development, and any new CVEs must be justified before requesting it to be merged to master. -```json -{ - "regexManagers": [{ - "fileMatch": ["^Dockerfile$"], - "matchStrings": [ - "version=\"(?.*?)\"" - ], - "depNameTemplate": "etcd-io/etcd", - "datasourceTemplate": "github-releases" - }, { - "fileMatch": ["^Jenkinsfile$"], - "matchStrings": [ - "version:\\s+\"(?.*?)\"" - ], - "depNameTemplate": "etcd-io/etcd", - "datasourceTemplate": "github-releases" - }] -} -``` +## Limitations -#### dccscr-whitelist/renovate.json +### Renovate Datasources -Renovate updates the **etcd.greylist** `"image_tag": "3.4.6"` line. +The base image in this repository does not support many of the native Renovate datasources. The image provides support for the minimum feature set required by Ironbank (docker, github-releases). -```json -"regexManagers": [ - { - "fileMatch": ["^etcd.greylist$"], - "matchStrings": [ - "\"image_tag\": \"(?.*?)\"" - ], - "depNameTemplate": "etcd-io/etcd", - "datasourceTemplate": "github-releases" - } -] -``` +Also metioned before your upstream resource must be stored in a location for which renovate has a datasoure. Renovate ships with several datasources such as docker, github-releases, rubygems, and pypi. A vendor's upstream resource may not publish to one of these supported platforms and as such could be a limiting factor for the use of Renovate. A custom datasource would have to be implemented to support fetching release information for these resources. -### YUM +### YUM Renovate does not currently support package managers. An open feature request can be found [here](https://github.com/renovatebot/renovate/issues/6188). One challenge with package manager support is dealing with **transitive** dependencies. In the Dockerfile below, installing `java-11-openjdk-headless` with `dnf` will include any of its dependencies as well. -```shell -RUN dnf install -y java-11-openjdk-headless && \ - dnf clean all && \ - rm -rf /var/cache/dnf -``` + + ```shell + RUN dnf install -y java-11-openjdk-headless && \ + dnf clean all && \ + rm -rf /var/cache/dnf + ``` In this example, Renovate needs to gather dependency metadata to handle upgrades. But where should it get this data? There are a few approaches that can be applied to solve this issue: 1. Do no use Renovate! Trigger a new build periodically with `dnf update -y` regardless of whether or not a dependency has been updated. This mechanism could be extended to first pull the existing image and check for updates before triggering a build: + ```shell -docker run --rm --entrypoint=/bin/bash -it [repository]/[image]:[tag] dnf list updates + docker run --rm --entrypoint=/bin/bash -it [repository]/[image]:[tag] dnf list updates ``` 2. Define a manifest for the image and include it within the repository. Renovate could trigger updates for each dependency in the manifest. For example: dsop/opensource/openjdk/openjdk11/packages/manifest.txt + ``` ... copy-jdk-configs-3.7-1.el8.noarch @@ -300,13 +201,9 @@ java-11-openjdk-headless-11.0.7.10-1.el8_1.x86_64 Automated dependency updates present some challenges. -1. Software upgrades are not always as simple as bumping a version. A `Dockerfile` may require additional changes that accompany a version bump. - - - How are we made aware of these changes? - - How can we keep these changes in sync? +Software upgrades are not always as simple as bumping a version. A `Dockerfile` may require additional changes that accompany a version bump. -2. No datasource for vendor supply chain. Renovate ships with several datasources such as docker, github-releases, and pypi. A vendor may not publish to one of these supported platforms. A custom datasource must be implemented to support fetching release information. + - How are we made aware of these changes? + - How can we keep these changes in sync? -## Limitations - -The base image in this repository does not support many of the native Renovate datasources. The image provides support for the minimum feature set required by Ironbank (docker, github-releases). +Renovate is one tool that can be used to solve some of these issues but additional work needs to be done to move those updats through the hardening diff --git a/dist/.DS_Store b/dist/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5ccfead81abd99889d3c7da596b3b256f2bb0aac Binary files /dev/null and b/dist/.DS_Store differ diff --git a/dist/manager/ironbank/artifacts.d.ts b/dist/manager/ironbank/artifacts.d.ts index 8698bb7c43b7fd2c24ea4c621644558b758d0f29..a3569c76b1e5a116d6785639a66049b6255f7f80 100644 --- a/dist/manager/ironbank/artifacts.d.ts +++ b/dist/manager/ironbank/artifacts.d.ts @@ -1,2 +1,2 @@ -import { UpdateArtifact, UpdateArtifactsResult } from '../common'; +import { UpdateArtifact, UpdateArtifactsResult } from '../types'; export declare function updateArtifacts({ packageFileName, updatedDeps, newPackageFileContent, config, }: UpdateArtifact): Promise; diff --git a/dist/manager/ironbank/artifacts.js b/dist/manager/ironbank/artifacts.js index 4e84bec78b18f174635a2f60941e2495c15a7f4c..fac6ea5c0249dc2e3d4292e568f04c21ade28da8 100644 --- a/dist/manager/ironbank/artifacts.js +++ b/dist/manager/ironbank/artifacts.js @@ -6,11 +6,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.updateArtifacts = void 0; const is_1 = __importDefault(require("@sindresorhus/is")); const js_yaml_1 = __importDefault(require("js-yaml")); +const upath_1 = require("upath"); const logger_1 = require("../../logger"); const exec_1 = require("../../util/exec"); const fs_1 = require("../../util/fs"); const git_1 = require("../../util/git"); -const upath_1 = require("upath"); async function postUpgrade(url, path) { logger_1.logger.debug(`ironbank.postUpgrade(${url}, ${path})`); try { @@ -25,41 +25,44 @@ async function postUpgrade(url, path) { return true; } async function updateArtifacts({ packageFileName, updatedDeps, newPackageFileContent, config, }) { + var _a, _b; logger_1.logger.debug(`ironbank.updateArtifacts(${packageFileName})`); if (!is_1.default.nonEmptyArray(updatedDeps)) { return null; } - let manifest; + let manifests; try { - manifest = js_yaml_1.default.safeLoad(newPackageFileContent, { json: true }); + manifests = js_yaml_1.default.safeLoadAll(newPackageFileContent, null, { json: true }); } catch (err) { logger_1.logger.error('Failed to parse hardening_manifest.yaml'); return null; } - if (!(manifest && is_1.default.array(manifest.resources))) { - return null; - } - if (!(manifest.resources[0].url && manifest.resources[0].url.startsWith('helm://'))) { - return null; - } - let charts = new Map(); - for (const item of manifest.resources) { - if (item.url && item.url.startsWith('helm://')) { - charts.set(item.name, 'https://' + item.url.substring(7)); + for (const manifest of manifests) { + if (!(manifest && is_1.default.array(manifest.resources))) { + return null; } - } - for (const dep of updatedDeps) { - logger_1.logger.debug(`updatedDep(${dep})`); - if (charts.has(dep)) { - const result = await postUpgrade(charts.get(dep), upath_1.join(config.localDir, dep)); - if (!result) { - return null; + if (!((_a = manifest.resources[0].url) === null || _a === void 0 ? void 0 : _a.startsWith('helm://'))) { + return null; + } + const charts = new Map(); + for (const item of manifest.resources) { + if ((_b = item.url) === null || _b === void 0 ? void 0 : _b.startsWith('helm://')) { + charts.set(item.name, `${String('https://')}${String(item.url.substring(7))}`); + } + } + for (const dep of updatedDeps) { + logger_1.logger.debug(`updatedDep(${dep})`); + if (charts.has(dep)) { + const result = await postUpgrade(charts.get(dep), upath_1.join(config.localDir, dep)); + if (!result) { + return null; + } } } } const res = []; - let status = await git_1.getRepoStatus(); + const status = await git_1.getRepoStatus(); for (const f of status.modified.concat(status.not_added)) { res.push({ file: { diff --git a/dist/manager/ironbank/artifacts.js.map b/dist/manager/ironbank/artifacts.js.map index 4e6c30d090a7bdc81a40b800bebe00673b03f383..b99f0bdf6f926bfeccceab6561ab9233c7fc30a0 100644 --- a/dist/manager/ironbank/artifacts.js.map +++ b/dist/manager/ironbank/artifacts.js.map @@ -1 +1 @@ -{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../../lib/manager/ironbank/artifacts.ts"],"names":[],"mappings":"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","sourcesContent":["import is from '@sindresorhus/is';\nimport yaml from 'js-yaml';\nimport { logger } from '../../logger';\nimport { exec } from '../../util/exec';\nimport { readLocalFile } from '../../util/fs';\nimport { getRepoStatus } from '../../util/git';\nimport { UpdateArtifact, UpdateArtifactsResult } from '../common';\nimport { join } from 'upath';\n\nasync function postUpgrade(url: string, path: string): Promise {\n logger.debug(`ironbank.postUpgrade(${url}, ${path})`);\n try {\n const cmd = 'ironbank-helm.sh'\n const args = '--directory ' + path + ' --url ' + url;\n await exec(`${cmd} ${args}`);\n } catch (err) {\n logger.error(err);\n return false;\n }\n return true;\n}\n\nexport async function updateArtifacts({\n packageFileName,\n updatedDeps,\n newPackageFileContent,\n config,\n}: UpdateArtifact): Promise {\n logger.debug(`ironbank.updateArtifacts(${packageFileName})`);\n if (!is.nonEmptyArray(updatedDeps)) {\n return null;\n }\n\n let manifest;\n try {\n manifest = yaml.safeLoad(newPackageFileContent, { json: true });\n } catch (err) {\n logger.error('Failed to parse hardening_manifest.yaml');\n return null;\n }\n\n if (!(manifest && is.array(manifest.resources))) {\n return null;\n }\n\n if (!(manifest.resources[0].url && manifest.resources[0].url.startsWith('helm://'))) {\n return null;\n }\n\n let charts = new Map();\n for (const item of manifest.resources) {\n if (item.url && item.url.startsWith('helm://')) {\n charts.set(item.name, 'https://' + item.url.substring(7));\n }\n }\n\n for (const dep of updatedDeps) {\n logger.debug(`updatedDep(${dep})`);\n if (charts.has(dep)) {\n const result = await postUpgrade(charts.get(dep), join(config.localDir, dep));\n if (!result) {\n return null;\n }\n }\n }\n\n const res = [];\n let status = await getRepoStatus();\n\n for (const f of status.modified.concat(status.not_added)) {\n res.push({\n file: {\n name: f,\n contents: await readLocalFile(f),\n },\n });\n }\n\n for (const f of status.deleted || [] ) {\n res.push({\n file: {\n name: '|delete|',\n contents: f,\n },\n });\n }\n\n return res;\n}\n"]} \ No newline at end of file +{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../../lib/manager/ironbank/artifacts.ts"],"names":[],"mappings":"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","sourcesContent":["import is from '@sindresorhus/is';\nimport yaml from 'js-yaml';\nimport { join } from 'upath';\nimport { logger } from '../../logger';\nimport { exec } from '../../util/exec';\nimport { readLocalFile } from '../../util/fs';\nimport { getRepoStatus } from '../../util/git';\nimport { UpdateArtifact, UpdateArtifactsResult } from '../types';\nimport { HardeningManifest } from './extract';\n\nasync function postUpgrade(url: string, path: string): Promise {\n logger.debug(`ironbank.postUpgrade(${url}, ${path})`);\n try {\n const cmd = 'ironbank-helm.sh';\n const args = '--directory ' + path + ' --url ' + url;\n await exec(`${cmd} ${args}`);\n } catch (err) {\n logger.error(err);\n return false;\n }\n return true;\n}\n\nexport async function updateArtifacts({\n packageFileName,\n updatedDeps,\n newPackageFileContent,\n config,\n}: UpdateArtifact): Promise {\n logger.debug(`ironbank.updateArtifacts(${packageFileName})`);\n if (!is.nonEmptyArray(updatedDeps)) {\n return null;\n }\n\n let manifests: HardeningManifest[];\n try {\n manifests = yaml.safeLoadAll(newPackageFileContent, null, { json: true });\n } catch (err) {\n logger.error('Failed to parse hardening_manifest.yaml');\n return null;\n }\n\n for (const manifest of manifests) {\n if (!(manifest && is.array(manifest.resources))) {\n return null;\n }\n\n if (!manifest.resources[0].url?.startsWith('helm://')) {\n return null;\n }\n\n const charts = new Map();\n for (const item of manifest.resources) {\n if (item.url?.startsWith('helm://')) {\n charts.set(\n item.name,\n `${String('https://')}${String(item.url.substring(7))}`\n );\n }\n }\n\n for (const dep of updatedDeps) {\n logger.debug(`updatedDep(${dep})`);\n if (charts.has(dep)) {\n const result = await postUpgrade(\n charts.get(dep),\n join(config.localDir, dep)\n );\n if (!result) {\n return null;\n }\n }\n }\n }\n\n const res = [];\n const status = await getRepoStatus();\n\n for (const f of status.modified.concat(status.not_added)) {\n res.push({\n file: {\n name: f,\n contents: await readLocalFile(f),\n },\n });\n }\n\n for (const f of status.deleted || []) {\n res.push({\n file: {\n name: '|delete|',\n contents: f,\n },\n });\n }\n\n return res;\n}\n"]} \ No newline at end of file diff --git a/dist/manager/ironbank/extract.d.ts b/dist/manager/ironbank/extract.d.ts index 025be2830bdf31f15e372af82c491749f991f7ff..823b9f929935ce09b1c00227ca329d2952dec809 100644 --- a/dist/manager/ironbank/extract.d.ts +++ b/dist/manager/ironbank/extract.d.ts @@ -1,2 +1,43 @@ -import { PackageFile } from '../common'; +import { PackageFile } from '../types'; +export interface HardeningManifest { + apiVersion: string; + name: string; + tags: string[]; + args: Args; + labels: Labels; + resources: Resource[]; + maintainers: Maintainer[]; +} +export interface Args { + BASE_IMAGE: string; + BASE_TAG: string; +} +export interface Labels { + 'org.opencontainers.image.title': string; + 'org.opencontainers.image.description': string; + 'org.opencontainers.image.licenses': string; + 'org.opencontainers.image.url': string; + 'org.opencontainers.image.vendor': string; + 'org.opencontainers.image.version': string; + 'mil.dso.ironbank.image.keywords': string; + 'mil.dso.ironbank.image.type': string; + 'mil.dso.ironbank.product.name': string; +} +export interface Maintainer { + name: string; + username: string; + email: string; + cht_member: boolean; +} +export interface Resource { + tag?: string; + url: string; + name?: string; + filename?: string; + validation?: Validation; +} +export interface Validation { + type: string; + value: string; +} export declare function extractPackageFile(content: string): PackageFile; diff --git a/dist/manager/ironbank/extract.js b/dist/manager/ironbank/extract.js index d5f2f15c78dea39d6f97c7564891dc39259c5f21..3c494a76c7c076a2f29a3eb194bc239413421df7 100644 --- a/dist/manager/ironbank/extract.js +++ b/dist/manager/ironbank/extract.js @@ -23,20 +23,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractPackageFile = void 0; -const is_1 = __importDefault(require("@sindresorhus/is")); const url_1 = require("url"); +const is_1 = __importDefault(require("@sindresorhus/is")); const js_yaml_1 = __importDefault(require("js-yaml")); -const logger_1 = require("../../logger"); const datasourceDocker = __importStar(require("../../datasource/docker")); const datasourceGithubReleases = __importStar(require("../../datasource/github-releases")); const datasourceGithubTags = __importStar(require("../../datasource/github-tags")); -const datasourceRubyGems = __importStar(require("../../datasource/rubygems")); const datasourceHelm = __importStar(require("../../datasource/helm")); +const datasourcePypi = __importStar(require("../../datasource/pypi")); +const datasourceRubyGems = __importStar(require("../../datasource/rubygems")); +const logger_1 = require("../../logger"); const dockerVersioning = __importStar(require("../../versioning/docker")); -function getDatasourceId(lookupName) { +function getDatasourceId(lookupName, url) { if (lookupName === 'antirez/redis') { return datasourceGithubTags.id; } + if (url.includes('archive')) { + return datasourceGithubTags.id; + } return datasourceGithubReleases.id; } function parseUrl(urlString) { @@ -65,73 +69,92 @@ function parseUrl(urlString) { } function extractPackageFile(content) { const deps = []; - let manifest; + let manifests; try { - manifest = js_yaml_1.default.safeLoad(content, { json: true }); + manifests = js_yaml_1.default.safeLoadAll(content, null, { json: true }); } catch (err) { logger_1.logger.debug('Failed to parse hardening_manifest.yaml'); return null; } - if (!(manifest && is_1.default.array(manifest.resources))) { - logger_1.logger.debug('hardening_manifest.yaml has no dependencies'); - return null; - } - for (const item of manifest.resources) { - const dep = { managerData: { item } }; - if (item.url) { - // docker - if (item.url.startsWith('docker://')) { - const currentDigest = item.url.split('@')[1]; - const [lookupName, currentValue] = item.tag.split(':'); - dep.depType = 'ironbank-docker'; - dep.depName = lookupName; - dep.datasource = datasourceDocker.id; - dep.versioning = dockerVersioning.id; - dep.lookupName = lookupName; - dep.currentDigest = currentDigest; - dep.currentValue = currentValue; - deps.push(dep); - } - // github-releases - else if (item.url.includes('github.com')) { - const parsedUrl = parseUrl(item.url); - dep.depType = 'ironbank-github'; - dep.depName = parsedUrl.repo; - dep.repo = parsedUrl.repo; - dep.currentValue = parsedUrl.currentValue; - dep.datasource = getDatasourceId(dep.repo); - dep.lookupName = dep.repo; - deps.push(dep); - } - // helm - else if (item.url.startsWith('helm://')) { - const regex = 'helm:\/\/(?.*\/)(?.*?)-(?.*?).tgz'; - const groups = item.url.match(regex).groups; - if (groups && groups.registryUrl && groups.lookupName && groups.currentValue) { - logger_1.logger.info(groups.registryUrl); - dep.depType = 'ironbank-helm'; - dep.depName = item.name; - dep.datasource = datasourceHelm.id; - dep.registryUrls = ['https://' + groups.registryUrl]; - dep.lookupName = groups.lookupName; - dep.currentValue = groups.currentValue; + for (const manifest of manifests) { + if (!(manifest && is_1.default.array(manifest.resources))) { + logger_1.logger.debug('hardening_manifest.yaml has no dependencies'); + return null; + } + for (const item of manifest.resources) { + const dep = { managerData: { item } }; + if (item.url) { + // docker + if (item.url.startsWith('docker://')) { + const currentDigest = item.url.split('@')[1]; + const [lookupName, currentValue] = item.tag.split(':'); + dep.depType = 'ironbank-docker'; + dep.depName = lookupName; + dep.datasource = datasourceDocker.id; + dep.versioning = dockerVersioning.id; + dep.lookupName = lookupName; + dep.currentDigest = currentDigest; + dep.currentValue = currentValue; deps.push(dep); } - } - // rubygems - else if (item.url.includes('rubygems.org')) { - const regex = 'https:\/\/(?.*\/)(?.*?)-(?.*?).gem'; - const groups = item.url.match(regex).groups; - if (groups && groups.registryUrl && groups.lookupName && groups.currentValue) { - dep.depType = 'ironbank-rubygem'; - dep.depName = groups.lookupName; - dep.lookupName = groups.lookupName; - dep.datasource = datasourceRubyGems.id; - dep.currentValue = groups.currentValue; - dep.registryUrls = ['https://' + groups.registryUrl]; + // github-releases + else if (item.url.startsWith('https://github.com')) { + const parsedUrl = parseUrl(item.url); + dep.depType = 'ironbank-github'; + dep.depName = parsedUrl.repo; + dep.repo = parsedUrl.repo; + dep.currentValue = parsedUrl.currentValue; + dep.datasource = getDatasourceId(dep.repo, item.url); + dep.lookupName = dep.repo; deps.push(dep); } + // helm + else if (item.url.startsWith('helm://')) { + const regex = new RegExp('helm://(?.*/)(?.*?)-(?.*?).tgz'); + const groups = regex.exec(item.url).groups; + if ((groups === null || groups === void 0 ? void 0 : groups.registryUrl) && groups.lookupName && groups.currentValue) { + logger_1.logger.info(groups.registryUrl); + dep.depType = 'ironbank-helm'; + dep.depName = item.name; + dep.datasource = datasourceHelm.id; + dep.registryUrls = [ + `${String('https://')}${String(groups.registryUrl)}`, + ]; + dep.lookupName = groups.lookupName; + dep.currentValue = groups.currentValue; + deps.push(dep); + } + } + // rubygems + else if (item.url.startsWith('https://rubygems.org')) { + const regex = new RegExp('https://(?.*)/(.*/)(?.*-?)-(?.*?).gem'); + const groups = regex.exec(item.url).groups; + if ((groups === null || groups === void 0 ? void 0 : groups.registryUrl) && groups.lookupName && groups.currentValue) { + dep.depType = 'ironbank-rubygems'; + dep.depName = groups.lookupName; + dep.lookupName = groups.lookupName; + dep.datasource = datasourceRubyGems.id; + dep.currentValue = groups.currentValue; + dep.registryUrls = [ + `${String('https://')}${String(groups.registryUrl)}`, + ]; + deps.push(dep); + } + } + else if (item.url.startsWith('https://files.pythonhosted.org')) { + const regex = new RegExp('https://(.*)/(.*)/(.*)/(.*)/(.*)/(?.*?)-(?.*?)-(.*)'); + const group = regex.exec(item.url).groups; + if (group.lookupName && group.version) { + dep.depType = 'ironbank-pypi'; + dep.currentDigest = item.validation.value; + dep.currentValue = group.version; + dep.depName = group.lookupName; + dep.datasource = datasourcePypi.id; + dep.lookupName = group.lookupName; + deps.push(dep); + } + } } } } diff --git a/dist/manager/ironbank/extract.js.map b/dist/manager/ironbank/extract.js.map index fc851f5fc965cafb2d97de35cb9f963ca48ce2f0..c9dc82026d756afd82bb44bba17b0726fd5b06a3 100644 --- a/dist/manager/ironbank/extract.js.map +++ b/dist/manager/ironbank/extract.js.map @@ -1 +1 @@ -{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../../lib/manager/ironbank/extract.ts"],"names":[],"mappings":"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","sourcesContent":["import is from '@sindresorhus/is';\nimport { parse as _parse } from 'url';\nimport yaml from 'js-yaml';\nimport { logger } from '../../logger';\nimport { PackageDependency, PackageFile } from '../common';\nimport * as datasourceDocker from '../../datasource/docker';\nimport * as datasourceGithubReleases from '../../datasource/github-releases';\nimport * as datasourceGithubTags from '../../datasource/github-tags';\nimport * as datasourceRubyGems from '../../datasource/rubygems';\nimport * as datasourceHelm from '../../datasource/helm';\nimport * as dockerVersioning from '../../versioning/docker';\n\n\ninterface UrlParsedResult {\n repo: string;\n currentValue: string;\n}\n\nfunction getDatasourceId(lookupName: string): string {\n if (lookupName === 'antirez/redis') {\n return datasourceGithubTags.id;\n }\n return datasourceGithubReleases.id;\n}\n\nfunction parseUrl(urlString: string): UrlParsedResult | null {\n // istanbul ignore if\n if (!urlString) {\n return null;\n }\n const url = _parse(urlString);\n if (url.host !== 'github.com') {\n return null;\n }\n const path = url.path.split('/').slice(1);\n const repo = path[0] + '/' + path[1];\n let currentValue: string = null;\n if (path[2] === 'releases' && path[3] === 'download') {\n currentValue = path[4];\n }\n if (path[2] === 'archive') {\n currentValue = path[3].replace(/\\.tar\\.gz$/, '');\n }\n if (currentValue) {\n return { repo, currentValue };\n }\n // istanbul ignore next\n return null;\n}\n\nexport function extractPackageFile(content: string): PackageFile {\n const deps: PackageDependency[] = [];\n let manifest;\n\n try {\n manifest = yaml.safeLoad(content, { json: true });\n } catch (err) {\n logger.debug('Failed to parse hardening_manifest.yaml');\n return null;\n }\n\n if (!(manifest && is.array(manifest.resources))) {\n logger.debug('hardening_manifest.yaml has no dependencies');\n return null;\n }\n\n for (const item of manifest.resources) {\n const dep: PackageDependency = { managerData: { item } };\n if (item.url) {\n // docker\n if (item.url.startsWith('docker://')) {\n const currentDigest = item.url.split('@')[1];\n const [lookupName, currentValue] = item.tag.split(':');\n dep.depType = 'ironbank-docker';\n dep.depName = lookupName;\n dep.datasource = datasourceDocker.id;\n dep.versioning = dockerVersioning.id;\n dep.lookupName = lookupName;\n dep.currentDigest = currentDigest;\n dep.currentValue = currentValue;\n deps.push(dep);\n }\n // github-releases\n else if (item.url.includes('github.com')) {\n const parsedUrl = parseUrl(item.url);\n dep.depType = 'ironbank-github';\n dep.depName = parsedUrl.repo;\n dep.repo = parsedUrl.repo;\n dep.currentValue = parsedUrl.currentValue;\n dep.datasource = getDatasourceId(dep.repo);\n dep.lookupName = dep.repo;\n deps.push(dep);\n }\n // helm\n else if (item.url.startsWith('helm://')) {\n const regex = 'helm:\\/\\/(?.*\\/)(?.*?)-(?.*?).tgz';\n const groups = item.url.match(regex).groups;\n if (groups && groups.registryUrl && groups.lookupName && groups.currentValue) {\n logger.info(groups.registryUrl);\n dep.depType = 'ironbank-helm';\n dep.depName = item.name;\n dep.datasource = datasourceHelm.id;\n dep.registryUrls = ['https://' + groups.registryUrl];\n dep.lookupName = groups.lookupName;\n dep.currentValue = groups.currentValue;\n deps.push(dep);\n }\n }\n // rubygems\n else if (item.url.includes('rubygems.org')) {\n const regex = 'https:\\/\\/(?.*\\/)(?.*?)-(?.*?).gem';\n const groups = item.url.match(regex).groups;\n if (groups && groups.registryUrl && groups.lookupName && groups.currentValue) {\n dep.depType = 'ironbank-rubygem';\n dep.depName = groups.lookupName;\n dep.lookupName = groups.lookupName;\n dep.datasource = datasourceRubyGems.id;\n dep.currentValue = groups.currentValue;\n dep.registryUrls = ['https://' + groups.registryUrl];\n deps.push(dep);\n }\n }\n }\n }\n\n if (!deps.length) {\n return null;\n }\n return { deps };\n}\n"]} \ No newline at end of file +{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../../lib/manager/ironbank/extract.ts"],"names":[],"mappings":"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","sourcesContent":["import { parse as _parse } from 'url';\nimport is from '@sindresorhus/is';\nimport yaml from 'js-yaml';\nimport * as datasourceDocker from '../../datasource/docker';\nimport * as datasourceGithubReleases from '../../datasource/github-releases';\nimport * as datasourceGithubTags from '../../datasource/github-tags';\nimport * as datasourceHelm from '../../datasource/helm';\nimport * as datasourcePypi from '../../datasource/pypi';\nimport * as datasourceRubyGems from '../../datasource/rubygems';\nimport { logger } from '../../logger';\nimport * as dockerVersioning from '../../versioning/docker';\nimport { PackageDependency, PackageFile } from '../types';\n\nexport interface HardeningManifest {\n apiVersion: string;\n name: string;\n tags: string[];\n args: Args;\n labels: Labels;\n resources: Resource[];\n maintainers: Maintainer[];\n}\n\nexport interface Args {\n BASE_IMAGE: string;\n BASE_TAG: string;\n}\n\nexport interface Labels {\n 'org.opencontainers.image.title': string;\n 'org.opencontainers.image.description': string;\n 'org.opencontainers.image.licenses': string;\n 'org.opencontainers.image.url': string;\n 'org.opencontainers.image.vendor': string;\n 'org.opencontainers.image.version': string;\n 'mil.dso.ironbank.image.keywords': string;\n 'mil.dso.ironbank.image.type': string;\n 'mil.dso.ironbank.product.name': string;\n}\n\nexport interface Maintainer {\n name: string;\n username: string;\n email: string;\n cht_member: boolean;\n}\n\nexport interface Resource {\n tag?: string;\n url: string;\n name?: string;\n filename?: string;\n validation?: Validation;\n}\n\nexport interface Validation {\n type: string;\n value: string;\n}\n\ninterface UrlParsedResult {\n repo: string;\n currentValue: string;\n}\n\nfunction getDatasourceId(lookupName: string, url: string): string {\n if (lookupName === 'antirez/redis') {\n return datasourceGithubTags.id;\n }\n if (url.includes('archive')) {\n return datasourceGithubTags.id;\n }\n\n return datasourceGithubReleases.id;\n}\n\nfunction parseUrl(urlString: string): UrlParsedResult | null {\n // istanbul ignore if\n if (!urlString) {\n return null;\n }\n const url = _parse(urlString);\n if (url.host !== 'github.com') {\n return null;\n }\n const path = url.path.split('/').slice(1);\n const repo = path[0] + '/' + path[1];\n let currentValue: string = null;\n if (path[2] === 'releases' && path[3] === 'download') {\n currentValue = path[4];\n }\n if (path[2] === 'archive') {\n currentValue = path[3].replace(/\\.tar\\.gz$/, '');\n }\n if (currentValue) {\n return { repo, currentValue };\n }\n // istanbul ignore next\n return null;\n}\n\nexport function extractPackageFile(content: string): PackageFile {\n const deps: PackageDependency[] = [];\n let manifests: HardeningManifest[];\n\n try {\n manifests = yaml.safeLoadAll(content, null, { json: true });\n } catch (err) {\n logger.debug('Failed to parse hardening_manifest.yaml');\n return null;\n }\n\n for (const manifest of manifests) {\n if (!(manifest && is.array(manifest.resources))) {\n logger.debug('hardening_manifest.yaml has no dependencies');\n return null;\n }\n\n for (const item of manifest.resources) {\n const dep: PackageDependency = { managerData: { item } };\n if (item.url) {\n // docker\n if (item.url.startsWith('docker://')) {\n const currentDigest = item.url.split('@')[1];\n const [lookupName, currentValue] = item.tag.split(':');\n dep.depType = 'ironbank-docker';\n dep.depName = lookupName;\n dep.datasource = datasourceDocker.id;\n dep.versioning = dockerVersioning.id;\n dep.lookupName = lookupName;\n dep.currentDigest = currentDigest;\n dep.currentValue = currentValue;\n deps.push(dep);\n }\n // github-releases\n else if (item.url.startsWith('https://github.com')) {\n const parsedUrl = parseUrl(item.url);\n dep.depType = 'ironbank-github';\n dep.depName = parsedUrl.repo;\n dep.repo = parsedUrl.repo;\n dep.currentValue = parsedUrl.currentValue;\n dep.datasource = getDatasourceId(dep.repo, item.url);\n dep.lookupName = dep.repo;\n deps.push(dep);\n }\n // helm\n else if (item.url.startsWith('helm://')) {\n const regex = new RegExp(\n 'helm://(?.*/)(?.*?)-(?.*?).tgz'\n );\n const groups = regex.exec(item.url).groups;\n if (groups?.registryUrl && groups.lookupName && groups.currentValue) {\n logger.info(groups.registryUrl);\n dep.depType = 'ironbank-helm';\n dep.depName = item.name;\n dep.datasource = datasourceHelm.id;\n dep.registryUrls = [\n `${String('https://')}${String(groups.registryUrl)}`,\n ];\n dep.lookupName = groups.lookupName;\n dep.currentValue = groups.currentValue;\n deps.push(dep);\n }\n }\n // rubygems\n else if (item.url.startsWith('https://rubygems.org')) {\n const regex = new RegExp(\n 'https://(?.*)/(.*/)(?.*-?)-(?.*?).gem'\n );\n const groups = regex.exec(item.url).groups;\n if (groups?.registryUrl && groups.lookupName && groups.currentValue) {\n dep.depType = 'ironbank-rubygems';\n dep.depName = groups.lookupName;\n dep.lookupName = groups.lookupName;\n dep.datasource = datasourceRubyGems.id;\n dep.currentValue = groups.currentValue;\n dep.registryUrls = [\n `${String('https://')}${String(groups.registryUrl)}`,\n ];\n deps.push(dep);\n }\n } else if (item.url.startsWith('https://files.pythonhosted.org')) {\n const regex = new RegExp(\n 'https://(.*)/(.*)/(.*)/(.*)/(.*)/(?.*?)-(?.*?)-(.*)'\n );\n const group = regex.exec(item.url).groups;\n\n if (group.lookupName && group.version) {\n dep.depType = 'ironbank-pypi';\n dep.currentDigest = item.validation.value;\n dep.currentValue = group.version;\n dep.depName = group.lookupName;\n dep.datasource = datasourcePypi.id;\n dep.lookupName = group.lookupName;\n\n deps.push(dep);\n }\n }\n }\n }\n }\n\n if (!deps.length) {\n return null;\n }\n return { deps };\n}\n"]} \ No newline at end of file diff --git a/dist/manager/ironbank/index.js.map b/dist/manager/ironbank/index.js.map index 24ddac53990d12eddf2d949a8436bd980ce5ba3f..d7f7e018539289600fb40006ec411077097fe809 100644 --- a/dist/manager/ironbank/index.js.map +++ b/dist/manager/ironbank/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/manager/ironbank/index.ts"],"names":[],"mappings":";;;AAAA,2CAA8C;AAIE,gGAJvC,2BAAe,OAIuC;AAH/D,uCAA+C;AAGtC,mGAHA,4BAAkB,OAGA;AAF3B,qCAA4C;AAEd,iGAFrB,yBAAgB,OAEqB;AAEjC,QAAA,aAAa,GAAG;IAC3B,SAAS,EAAE,CAAC,qBAAqB,EAAE,+BAA+B,CAAC;CACpE,CAAC","sourcesContent":["import { updateArtifacts } from './artifacts';\nimport { extractPackageFile } from './extract';\nimport { updateDependency } from './update';\n\nexport { extractPackageFile , updateDependency, updateArtifacts };\n\nexport const defaultConfig = {\n fileMatch: ['(^|/)download.yaml$', '(^|/)hardening_manifest.yaml$'],\n};\n"]} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/manager/ironbank/index.ts"],"names":[],"mappings":";;;AAAA,2CAA8C;AAIC,gGAJtC,2BAAe,OAIsC;AAH9D,uCAA+C;AAGtC,mGAHA,4BAAkB,OAGA;AAF3B,qCAA4C;AAEf,iGAFpB,yBAAgB,OAEoB;AAEhC,QAAA,aAAa,GAAG;IAC3B,SAAS,EAAE,CAAC,qBAAqB,EAAE,+BAA+B,CAAC;CACpE,CAAC","sourcesContent":["import { updateArtifacts } from './artifacts';\nimport { extractPackageFile } from './extract';\nimport { updateDependency } from './update';\n\nexport { extractPackageFile, updateDependency, updateArtifacts };\n\nexport const defaultConfig = {\n fileMatch: ['(^|/)download.yaml$', '(^|/)hardening_manifest.yaml$'],\n};\n"]} \ No newline at end of file diff --git a/dist/manager/ironbank/update.d.ts b/dist/manager/ironbank/update.d.ts index 9cf4f81f768b3e977e8e0adfa1a0e4238318e1c6..e52a8cddaaed256fc6d00d34b9ea3788d1772e62 100644 --- a/dist/manager/ironbank/update.d.ts +++ b/dist/manager/ironbank/update.d.ts @@ -1,2 +1,2 @@ -import { UpdateDependencyConfig } from '../common'; +import { UpdateDependencyConfig } from '../types'; export declare function updateDependency({ fileContent, upgrade, }: UpdateDependencyConfig): Promise; diff --git a/dist/manager/ironbank/update.js b/dist/manager/ironbank/update.js index a884f4c2909c920612f1778837485c886141b34d..b2d99f26c0120893e1061645bd3c72d516f89e56 100644 --- a/dist/manager/ironbank/update.js +++ b/dist/manager/ironbank/update.js @@ -4,19 +4,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.updateDependency = void 0; +const path_1 = __importDefault(require("path")); +const url_1 = require("url"); const hasha_1 = require("hasha"); const logger_1 = require("../../logger"); const http_1 = require("../../util/http"); -const url_1 = require("url"); -const path_1 = __importDefault(require("path")); const http = new http_1.Http('ironbank'); async function getHashFromFile(url, filename) { - logger_1.logger.debug("getHashFromFile: " + url + " " + filename); + logger_1.logger.debug('getHashFromFile: ' + url + ' ' + filename); try { const result = await http.get(url); if (result.body) { - const regex = '(?[A-Fa-f0-9]{64})\\s+' + filename.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - const groups = result.body.match(regex).groups; + const regex = new RegExp('(?[A-Fa-f0-9]{64})\\s+' + + filename.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')); + const groups = regex.exec(result.body).groups; if (groups) { return groups.hash; } @@ -49,47 +50,104 @@ async function getHashFromUrl(url) { return null; } } -async function updateDependency({ fileContent, upgrade, }) { - if (upgrade.depType === 'ironbank-docker') { - const oldTag = upgrade.lookupName + ':' + upgrade.currentValue; - const newTag = upgrade.lookupName + ':' + upgrade.newValue; - let newContent = fileContent.replace(upgrade.currentDigest, upgrade.newDigest); - return newContent.replace(oldTag, newTag); - } - else if (upgrade.depType === 'ironbank-github' && - upgrade.currentValue && - upgrade.newValue) { - const currentValue = upgrade.currentValue.replace(/^v/, ''); - const newValue = upgrade.newValue.replace(/^v/, ''); - const oldUrl = upgrade.managerData.item.url; - const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue); - const hash = await getHashFromUrl(newUrl); - let newContent = fileContent; - if (hash) { - newContent = newContent.replace(upgrade.managerData.item.validation.value, hash); +async function getPypiData(url) { + logger_1.logger.debug(`${'getPypiData:'} ${url} ${'filename'}`); + try { + const result = await http.get(url); + if (result.body) { + const results = JSON.parse(result.body); + for (let i = 0; i < results.urls.length; i += 1) { + if (results.urls[i].filename.endsWith('whl')) { + const output = { + sha: results.urls[i].digests.sha256, + updatedUrl: results.urls[i].url, + }; + return output; + } + } } - return newContent.replace(oldUrl, newUrl); + return null; } - else if (upgrade.depType == 'ironbank-helm' && - upgrade.currentValue && - upgrade.newValue) { - return fileContent.replace(upgrade.currentValue, upgrade.newValue); + catch (err) /* istanbul ignore next */ { + return null; } - else if (upgrade.depType == 'ironbank-rubygem' && - upgrade.currentValue && - upgrade.newValue) { - const currentValue = upgrade.currentValue; - const newValue = upgrade.newValue; - const oldUrl = upgrade.managerData.item.url; - const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue); - const hash = await getHashFromUrl(newUrl); - let newContent = fileContent; - if (hash) { - newContent = newContent.replace(upgrade.managerData.item.validation.value, hash); +} +async function updateDependency({ fileContent, upgrade, }) { + // let newContent = fileContent; + switch (upgrade.depType) { + case 'ironbank-docker': { + const oldTag = upgrade.lookupName + ':' + upgrade.currentValue; + const newTag = upgrade.lookupName + ':' + upgrade.newValue; + const oldUrl = upgrade.managerData.item.url; + const newUrl = `${String(upgrade.managerData.item.url.split('@')[0])}@${upgrade.newDigest}`; + if (oldUrl === newUrl || oldTag === newTag) { + return null; + } + let newContent = fileContent; + newContent = newContent.replace(oldTag, newTag); + newContent = newContent.replace(oldUrl, newUrl); + return newContent; + } + case 'ironbank-github': { + if (!upgrade.currentValue && !upgrade.newValue) { + logger_1.logger.warn(`${'issue updating ironbank-github for'} ${upgrade.lookupName}`); + return null; + } + const currentValue = upgrade.currentValue.replace(/^v/, ''); + const newValue = upgrade.newValue.replace(/^v/, ''); + const oldUrl = upgrade.managerData.item.url; + const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue); + const hash = await getHashFromUrl(newUrl); + let newContent = fileContent; + if (hash) { + newContent = newContent.replace(upgrade.managerData.item.validation.value, hash); + newContent = newContent.replace(oldUrl, newUrl); + } + return newContent; + } + case 'ironbank-helm': { + if (!upgrade.currentValue && !upgrade.newValue) { + logger_1.logger.warn(`${'issue updating ironbank-helm for'} ${upgrade.depName}`); + return null; + } + return fileContent.replace(upgrade.currentValue, upgrade.newValue); + } + case 'ironbank-rubygems': { + if (!upgrade.currentValue && !upgrade.newValue) { + logger_1.logger.warn(`${'issue updating ironbank-rubygems for'} ${upgrade.depName}`); + return null; + } + const currentValue = upgrade.currentValue; + const newValue = upgrade.newValue; + const oldUrl = upgrade.managerData.item.url; + const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue); + const hash = await getHashFromUrl(newUrl); + let newContent = fileContent; + if (hash) { + newContent = newContent.replace(upgrade.managerData.item.validation.value, hash); + newContent = newContent.replace(oldUrl, newUrl); + } + return newContent; + } + case 'ironbank-pypi': { + if (!upgrade.newValue) { + logger_1.logger.warn(`${'issue updating ironbank-pypi for'} ${upgrade.depName}`); + return null; + } + const newValue = upgrade.newValue; + const oldUrl = upgrade.managerData.item.url; + const searchURL = `https://pypi.org/pypi/${upgrade.depName}/${newValue}/json`; + const updatedData = getPypiData(searchURL); + let newContent = fileContent; + if ((await updatedData).sha && (await updatedData).updatedUrl) { + newContent = newContent.replace(upgrade.managerData.item.validation.value, (await updatedData).sha); + newContent = newContent.replace(oldUrl, (await updatedData).updatedUrl); + } + return newContent; } - return newContent.replace(oldUrl, newUrl); + default: + return null; } - return null; } exports.updateDependency = updateDependency; //# sourceMappingURL=update.js.map \ No newline at end of file diff --git a/dist/manager/ironbank/update.js.map b/dist/manager/ironbank/update.js.map index fabad33998acf0bc1344b8d8b651e6ee68e8ff76..2529268c1ec2b94d93ba21c312d9212eb2212ca9 100644 --- a/dist/manager/ironbank/update.js.map +++ b/dist/manager/ironbank/update.js.map @@ -1 +1 @@ -{"version":3,"file":"update.js","sourceRoot":"","sources":["../../../lib/manager/ironbank/update.ts"],"names":[],"mappings":"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","sourcesContent":["import { fromStream } from 'hasha';\nimport { logger } from '../../logger';\nimport { Http } from '../../util/http';\nimport { UpdateDependencyConfig } from '../common';\nimport { parse as _parse } from 'url';\nimport path from 'path';\n\nconst http = new Http('ironbank');\n\nasync function getHashFromFile(url: string, filename: string) : Promise {\n logger.debug(\"getHashFromFile: \" + url + \" \" + filename);\n try {\n const result = await http.get(url);\n if (result.body) {\n const regex = '(?[A-Fa-f0-9]{64})\\\\s+' + filename.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const groups = result.body.match(regex).groups;\n if (groups) {\n return groups.hash;\n }\n }\n return null;\n } catch (err) /* istanbul ignore next */ {\n return null;\n }\n}\n\nasync function getHashFromUrl(url: string): Promise {\n try {\n const parsedUrl = _parse(url);\n const filename = path.basename(parsedUrl.pathname);\n\n let hash;\n hash = await getHashFromFile(filename + '.sha256', filename);\n if (hash) {\n return hash;\n }\n hash = await getHashFromFile(url.replace(filename, 'SHA256SUMS'), filename);\n if (hash) {\n return hash;\n }\n hash = await fromStream(http.stream(url), {\n algorithm: 'sha256',\n });\n return hash;\n } catch (err) /* istanbul ignore next */ {\n return null;\n }\n}\n\nexport async function updateDependency({\n fileContent,\n upgrade,\n}: UpdateDependencyConfig): Promise {\n\n if (upgrade.depType === 'ironbank-docker') {\n const oldTag = upgrade.lookupName + ':' + upgrade.currentValue;\n const newTag = upgrade.lookupName + ':' + upgrade.newValue;\n let newContent = fileContent.replace(upgrade.currentDigest, upgrade.newDigest);\n return newContent.replace(oldTag, newTag);\n } else if (\n upgrade.depType === 'ironbank-github' &&\n upgrade.currentValue &&\n upgrade.newValue\n ) {\n const currentValue = upgrade.currentValue.replace(/^v/, '');\n const newValue = upgrade.newValue.replace(/^v/, '');\n const oldUrl = upgrade.managerData.item.url;\n const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue);\n const hash = await getHashFromUrl(newUrl);\n let newContent = fileContent;\n if (hash) {\n newContent = newContent.replace(upgrade.managerData.item.validation.value, hash);\n }\n return newContent.replace(oldUrl, newUrl);\n } else if (\n upgrade.depType == 'ironbank-helm' &&\n upgrade.currentValue &&\n upgrade.newValue\n ) {\n return fileContent.replace(upgrade.currentValue, upgrade.newValue);\n } else if (\n upgrade.depType == 'ironbank-rubygem' &&\n upgrade.currentValue &&\n upgrade.newValue\n ) {\n const currentValue = upgrade.currentValue;\n const newValue = upgrade.newValue;\n const oldUrl = upgrade.managerData.item.url;\n const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue);\n const hash = await getHashFromUrl(newUrl);\n let newContent = fileContent;\n if (hash) {\n newContent = newContent.replace(upgrade.managerData.item.validation.value, hash);\n }\n return newContent.replace(oldUrl, newUrl);\n } \n\n return null;\n}\n"]} \ No newline at end of file +{"version":3,"file":"update.js","sourceRoot":"","sources":["../../../lib/manager/ironbank/update.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,6BAAsC;AACtC,iCAAmC;AACnC,yCAAsC;AACtC,0CAAuC;AAGvC,MAAM,IAAI,GAAG,IAAI,WAAI,CAAC,UAAU,CAAC,CAAC;AAElC,KAAK,UAAU,eAAe,CAC5B,GAAW,EACX,QAAgB;IAEhB,eAAM,CAAC,KAAK,CAAC,mBAAmB,GAAG,GAAG,GAAG,GAAG,GAAG,QAAQ,CAAC,CAAC;IACzD,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,MAAM,CAAC,IAAI,EAAE;YACf,MAAM,KAAK,GAAG,IAAI,MAAM,CACtB,8BAA8B;gBAC5B,QAAQ,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAClD,CAAC;YACF,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;YAC9C,IAAI,MAAM,EAAE;gBACV,OAAO,MAAM,CAAC,IAAI,CAAC;aACpB;SACF;QACD,OAAO,IAAI,CAAC;KACb;IAAC,OAAO,GAAG,EAAE,0BAA0B,CAAC;QACvC,OAAO,IAAI,CAAC;KACb;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,GAAW;IACvC,IAAI;QACF,MAAM,SAAS,GAAG,WAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,QAAQ,GAAG,cAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAEnD,IAAI,IAAY,CAAC;QACjB,IAAI,GAAG,MAAM,eAAe,CAAC,QAAQ,GAAG,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC7D,IAAI,IAAI,EAAE;YACR,OAAO,IAAI,CAAC;SACb;QACD,IAAI,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC5E,IAAI,IAAI,EAAE;YACR,OAAO,IAAI,CAAC;SACb;QACD,IAAI,GAAG,MAAM,kBAAU,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YACxC,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;KACb;IAAC,OAAO,GAAG,EAAE,0BAA0B,CAAC;QACvC,OAAO,IAAI,CAAC;KACb;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,GAAW;IAEX,eAAM,CAAC,KAAK,CAAC,GAAG,cAAc,IAAI,GAAG,IAAI,UAAU,EAAE,CAAC,CAAC;IACvD,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,MAAM,CAAC,IAAI,EAAE;YACf,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAExC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE;gBAC/C,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;oBAC5C,MAAM,MAAM,GAAG;wBACb,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM;wBACnC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG;qBAChC,CAAC;oBAEF,OAAO,MAAM,CAAC;iBACf;aACF;SACF;QACD,OAAO,IAAI,CAAC;KACb;IAAC,OAAO,GAAG,EAAE,0BAA0B,CAAC;QACvC,OAAO,IAAI,CAAC;KACb;AACH,CAAC;AAEM,KAAK,UAAU,gBAAgB,CAAC,EACrC,WAAW,EACX,OAAO,GACgB;IACvB,gCAAgC;IAEhC,QAAQ,OAAO,CAAC,OAAO,EAAE;QACvB,KAAK,iBAAiB,CAAC,CAAC;YACtB,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC;YAC/D,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;YAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;YAC5C,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAClE,OAAO,CAAC,SACV,EAAE,CAAC;YAEH,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE;gBAC1C,OAAO,IAAI,CAAC;aACb;YAED,IAAI,UAAU,GAAG,WAAW,CAAC;YAC7B,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAChD,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAEhD,OAAO,UAAU,CAAC;SACnB;QACD,KAAK,iBAAiB,CAAC,CAAC;YACtB,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;gBAC9C,eAAM,CAAC,IAAI,CACT,GAAG,oCAAoC,IAAI,OAAO,CAAC,UAAU,EAAE,CAChE,CAAC;gBACF,OAAO,IAAI,CAAC;aACb;YAED,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACpD,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;YAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;YACvE,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;YAC1C,IAAI,UAAU,GAAG,WAAW,CAAC;YAC7B,IAAI,IAAI,EAAE;gBACR,UAAU,GAAG,UAAU,CAAC,OAAO,CAC7B,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EACzC,IAAI,CACL,CAAC;gBACF,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;aACjD;YACD,OAAO,UAAU,CAAC;SACnB;QACD,KAAK,eAAe,CAAC,CAAC;YACpB,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;gBAC9C,eAAM,CAAC,IAAI,CAAC,GAAG,kCAAkC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;gBACxE,OAAO,IAAI,CAAC;aACb;YAED,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;SACpE;QACD,KAAK,mBAAmB,CAAC,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;gBAC9C,eAAM,CAAC,IAAI,CACT,GAAG,sCAAsC,IAAI,OAAO,CAAC,OAAO,EAAE,CAC/D,CAAC;gBACF,OAAO,IAAI,CAAC;aACb;YAED,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;YAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;YAClC,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;YAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;YACvE,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;YAC1C,IAAI,UAAU,GAAG,WAAW,CAAC;YAC7B,IAAI,IAAI,EAAE;gBACR,UAAU,GAAG,UAAU,CAAC,OAAO,CAC7B,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EACzC,IAAI,CACL,CAAC;gBACF,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;aACjD;YACD,OAAO,UAAU,CAAC;SACnB;QACD,KAAK,eAAe,CAAC,CAAC;YACpB,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;gBACrB,eAAM,CAAC,IAAI,CAAC,GAAG,kCAAkC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;gBACxE,OAAO,IAAI,CAAC;aACb;YAED,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;YAClC,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;YAC5C,MAAM,SAAS,GAAG,yBAAyB,OAAO,CAAC,OAAO,IAAI,QAAQ,OAAO,CAAC;YAC9E,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;YAE3C,IAAI,UAAU,GAAG,WAAW,CAAC;YAC7B,IAAI,CAAC,MAAM,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,WAAW,CAAC,CAAC,UAAU,EAAE;gBAC7D,UAAU,GAAG,UAAU,CAAC,OAAO,CAC7B,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EACzC,CAAC,MAAM,WAAW,CAAC,CAAC,GAAG,CACxB,CAAC;gBACF,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,MAAM,WAAW,CAAC,CAAC,UAAU,CAAC,CAAC;aACzE;YACD,OAAO,UAAU,CAAC;SACnB;QACD;YACE,OAAO,IAAI,CAAC;KACf;AACH,CAAC;AAvGD,4CAuGC","sourcesContent":["import path from 'path';\nimport { parse as _parse } from 'url';\nimport { fromStream } from 'hasha';\nimport { logger } from '../../logger';\nimport { Http } from '../../util/http';\nimport { UpdateDependencyConfig } from '../types';\n\nconst http = new Http('ironbank');\n\nasync function getHashFromFile(\n url: string,\n filename: string\n): Promise {\n logger.debug('getHashFromFile: ' + url + ' ' + filename);\n try {\n const result = await http.get(url);\n if (result.body) {\n const regex = new RegExp(\n '(?[A-Fa-f0-9]{64})\\\\s+' +\n filename.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n );\n const groups = regex.exec(result.body).groups;\n if (groups) {\n return groups.hash;\n }\n }\n return null;\n } catch (err) /* istanbul ignore next */ {\n return null;\n }\n}\n\nasync function getHashFromUrl(url: string): Promise {\n try {\n const parsedUrl = _parse(url);\n const filename = path.basename(parsedUrl.pathname);\n\n let hash: string;\n hash = await getHashFromFile(filename + '.sha256', filename);\n if (hash) {\n return hash;\n }\n hash = await getHashFromFile(url.replace(filename, 'SHA256SUMS'), filename);\n if (hash) {\n return hash;\n }\n hash = await fromStream(http.stream(url), {\n algorithm: 'sha256',\n });\n return hash;\n } catch (err) /* istanbul ignore next */ {\n return null;\n }\n}\n\nasync function getPypiData(\n url: string\n): Promise<{ sha: string; updatedUrl: string }> {\n logger.debug(`${'getPypiData:'} ${url} ${'filename'}`);\n try {\n const result = await http.get(url);\n if (result.body) {\n const results = JSON.parse(result.body);\n\n for (let i = 0; i < results.urls.length; i += 1) {\n if (results.urls[i].filename.endsWith('whl')) {\n const output = {\n sha: results.urls[i].digests.sha256,\n updatedUrl: results.urls[i].url,\n };\n\n return output;\n }\n }\n }\n return null;\n } catch (err) /* istanbul ignore next */ {\n return null;\n }\n}\n\nexport async function updateDependency({\n fileContent,\n upgrade,\n}: UpdateDependencyConfig): Promise {\n // let newContent = fileContent;\n\n switch (upgrade.depType) {\n case 'ironbank-docker': {\n const oldTag = upgrade.lookupName + ':' + upgrade.currentValue;\n const newTag = upgrade.lookupName + ':' + upgrade.newValue;\n const oldUrl = upgrade.managerData.item.url;\n const newUrl = `${String(upgrade.managerData.item.url.split('@')[0])}@${\n upgrade.newDigest\n }`;\n\n if (oldUrl === newUrl || oldTag === newTag) {\n return null;\n }\n\n let newContent = fileContent;\n newContent = newContent.replace(oldTag, newTag);\n newContent = newContent.replace(oldUrl, newUrl);\n\n return newContent;\n }\n case 'ironbank-github': {\n if (!upgrade.currentValue && !upgrade.newValue) {\n logger.warn(\n `${'issue updating ironbank-github for'} ${upgrade.lookupName}`\n );\n return null;\n }\n\n const currentValue = upgrade.currentValue.replace(/^v/, '');\n const newValue = upgrade.newValue.replace(/^v/, '');\n const oldUrl = upgrade.managerData.item.url;\n const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue);\n const hash = await getHashFromUrl(newUrl);\n let newContent = fileContent;\n if (hash) {\n newContent = newContent.replace(\n upgrade.managerData.item.validation.value,\n hash\n );\n newContent = newContent.replace(oldUrl, newUrl);\n }\n return newContent;\n }\n case 'ironbank-helm': {\n if (!upgrade.currentValue && !upgrade.newValue) {\n logger.warn(`${'issue updating ironbank-helm for'} ${upgrade.depName}`);\n return null;\n }\n\n return fileContent.replace(upgrade.currentValue, upgrade.newValue);\n }\n case 'ironbank-rubygems': {\n if (!upgrade.currentValue && !upgrade.newValue) {\n logger.warn(\n `${'issue updating ironbank-rubygems for'} ${upgrade.depName}`\n );\n return null;\n }\n\n const currentValue = upgrade.currentValue;\n const newValue = upgrade.newValue;\n const oldUrl = upgrade.managerData.item.url;\n const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue);\n const hash = await getHashFromUrl(newUrl);\n let newContent = fileContent;\n if (hash) {\n newContent = newContent.replace(\n upgrade.managerData.item.validation.value,\n hash\n );\n newContent = newContent.replace(oldUrl, newUrl);\n }\n return newContent;\n }\n case 'ironbank-pypi': {\n if (!upgrade.newValue) {\n logger.warn(`${'issue updating ironbank-pypi for'} ${upgrade.depName}`);\n return null;\n }\n\n const newValue = upgrade.newValue;\n const oldUrl = upgrade.managerData.item.url;\n const searchURL = `https://pypi.org/pypi/${upgrade.depName}/${newValue}/json`;\n const updatedData = getPypiData(searchURL);\n\n let newContent = fileContent;\n if ((await updatedData).sha && (await updatedData).updatedUrl) {\n newContent = newContent.replace(\n upgrade.managerData.item.validation.value,\n (await updatedData).sha\n );\n newContent = newContent.replace(oldUrl, (await updatedData).updatedUrl);\n }\n return newContent;\n }\n default:\n return null;\n }\n}\n"]} \ No newline at end of file diff --git a/hardening_manifest.yaml b/hardening_manifest.yaml index 2f9ac02fe3083f481bc9a13d663fda2f098c9f90..6c8165d0da64c2c13d128db8f7e37c732a19d3a3 100644 --- a/hardening_manifest.yaml +++ b/hardening_manifest.yaml @@ -8,13 +8,13 @@ name: "container-hardening-tools/renovate/renovate" # The most specific version should be the first tag and will be shown # on ironbank.dsop.io tags: -- "24.4.0" +- "24.119.5" - "latest" # Build args passed to Dockerfile ARGs args: - BASE_IMAGE: "opensource/nodejs/nodejs12" - BASE_TAG: "12.20.0" + BASE_IMAGE: "opensource/nodejs/nodejs14" + BASE_TAG: "14.16.1" # Docker image labels labels: @@ -27,7 +27,7 @@ labels: org.opencontainers.image.url: "https://github.com/renovatebot/renovate" ## Name of the distributing entity, organization or individual org.opencontainers.image.vendor: "WhiteSource" - org.opencontainers.image.version: "24.4.0" + org.opencontainers.image.version: "24.119.5" ## Keywords to help with search (ex. "cicd,gitops,golang") mil.dso.ironbank.image.keywords: "automation,dependency,updates" ## This value can be "opensource" or "commercial" @@ -37,23 +37,23 @@ labels: # List of resources to make available to the offline build context resources: -- tag: renovate/renovate:24.4.0-slim - url: docker://docker.io/renovate/renovate@sha256:117e0bc5cfa6aa9ca65d37462029a4005e123848e1afcc4a9ab5c5154911c0a8 +- tag: renovate/renovate:24.119.5-slim + url: docker://docker.io/renovate/renovate@sha256:18e6630668bbc6cdf7f953a30b7ecbe101b07cb012347d7afc0bbec12eceeeb0 - filename: helm-docs.tar.gz - url: https://github.com/norwoodj/helm-docs/releases/download/v1.4.0/helm-docs_1.4.0_Linux_x86_64.tar.gz + url: https://github.com/norwoodj/helm-docs/releases/download/v1.5.0/helm-docs_1.5.0_Linux_x86_64.tar.gz validation: type: sha256 - value: 5f64db165af74c48804502ccdb3a0c5d220bf71853a2d7dfa1a58b04c345c79c + value: a352e13a8438045b8ed138b821cb757c177acd999c1af77345152d7a64b0ddb7 - filename: yq - url: https://github.com/mikefarah/yq/releases/download/3.4.1/yq_linux_amd64 + url: https://github.com/mikefarah/yq/releases/download/v4.6.2/yq_linux_amd64 validation: type: sha256 - value: adbc6dd027607718ac74ceac15f74115ac1f3caef68babfb73246929d4ffb23c + value: ddc532d3ecace34e30fcfd0a623d539f9cb013ea555e7e63733c208a30a0fd66 - filename: kpt.tar.gz - url: https://github.com/GoogleContainerTools/kpt/releases/download/v0.37.0/kpt_linux_amd64-0.37.0.tar.gz + url: https://github.com/GoogleContainerTools/kpt/releases/download/v0.38.1/kpt_linux_amd64-0.38.1.tar.gz validation: type: sha256 - value: bd12bf1177325830ecb476ea39bad3560e80205dadc60b31ab851ff9d230dd08 + value: e2f6d3b1558f103d2ede455b3c6335631f02e865929a02dc56a89d52684fc652 # List of project maintainers maintainers: diff --git a/lib/.DS_Store b/lib/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..758fd7a6a02aaff1509c875c38a08e87ebaf4dba Binary files /dev/null and b/lib/.DS_Store differ diff --git a/lib/manager/ironbank/__fixtures__/download.yaml b/lib/manager/ironbank/__fixtures__/download.yaml deleted file mode 100644 index 92409f7ba336ab7f415a646086109605c9a9901a..0000000000000000000000000000000000000000 --- a/lib/manager/ironbank/__fixtures__/download.yaml +++ /dev/null @@ -1,28 +0,0 @@ -resources: - - url: "docker://docker.io/jboss/keycloak@sha256:3720b5ace316b5790a58ce838f46e8cd44cedbdb7e35d3866311ddc5a5e71466" - tag: "jboss/keycloak:10.0.2" - - url: "https://github.com/etcd-io/etcd/releases/download/v3.4.8/etcd-v3.4.8-linux-amd64.tar.gz" - filename: etcd.tar.gz - validation: - type: sha256 - value: a3a332a68fe8dedf20149c1a4b8746fe8061b72d75d3a5850b17e04de9ed7942 - - url: "https://github.com/fluent/fluentd/archive/v1.10.3.tar.gz" - filename: fluentd.tar.gz - validation: - type: sha256 - value: c2b5bbb6c2236f73310b22c748e32a88f25288f3e6e1bd272f3dccc6a2322160 - - url: "https://github.com/jaegertracing/jaeger/releases/download/v1.17.0/jaeger-1.17.0-linux-amd64.tar.gz" - filename: jaeger.tar.gz - validation: - type: sha256 - value: 7e675f71460c522370d6608380aaa54863dcef17d0c9315fd2a7af877165487c - - url: "https://github.com/godaddy/kubernetes-external-secrets/archive/3.2.0.tar.gz" - filename: kubernetes-external-secrets.tar.gz - validation: - type: sha256 - value: 639df8697febd1917dd73f08b6c4f1003e09e965bfb7ff581038cde24c008493 - - url: "https://github.com/apache/maven/archive/maven-3.6.2.tar.gz" - filename: maven.tar.gz - validation: - type: sha256 - value: 9dfab7ff5c9f49201631512f9a8c5148f50ba92776dd2b86b36077bd7eefbf2e diff --git a/lib/manager/ironbank/__fixtures__/hardening_manifest.yaml b/lib/manager/ironbank/__fixtures__/hardening_manifest.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a4f1613ea728d8ca6399e646f8c5cd704effef91 --- /dev/null +++ b/lib/manager/ironbank/__fixtures__/hardening_manifest.yaml @@ -0,0 +1,23 @@ +resources: + - url: "docker://docker.io/jboss/keycloak@sha256:3720b5ace316b5790a58ce838f46e8cd44cedbdb7e35d3866311ddc5a5e71466" + tag: "jboss/keycloak:12.0.3" + - url: "https://github.com/etcd-io/etcd/releases/download/v3.4.8/etcd-v3.4.8-linux-amd64.tar.gz" + filename: etcd.tar.gz + validation: + type: sha256 + value: a3a332a68fe8dedf20149c1a4b8746fe8061b72d75d3a5850b17e04de9ed7942 + - url: "https://github.com/fluent/fluentd/archive/v1.10.3.tar.gz" + filename: fluentd.tar.gz + validation: + type: sha256 + value: c2b5bbb6c2236f73310b22c748e32a88f25288f3e6e1bd272f3dccc6a2322160 + - filename: urllib3-1.25.10-py2.py3-none-any.whl + url: https://files.pythonhosted.org/packages/9f/f0/a391d1463ebb1b233795cabfc0ef38d3db4442339de68f847026199e69d7/urllib3-1.25.10-py2.py3-none-any.whl + validation: + type: sha256 + value: e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461 + - filename: gitlab-triage-1.15.0.gem + url: https://rubygems.org/downloads/gitlab-triage-1.15.0.gem + validation: + type: sha256 + value: e516d720a67c9e3447db858775b48f44aae210b184dd96f7a20fe4fbb4022834 diff --git a/lib/manager/ironbank/__snapshots__/extract.spec.ts.snap b/lib/manager/ironbank/__snapshots__/extract.spec.ts.snap index 786aed06f42b57563d2bb9003db9e396ddb07429..fd3531b217e2cf53ca48b67d6573ee0a68ff702c 100644 --- a/lib/manager/ironbank/__snapshots__/extract.spec.ts.snap +++ b/lib/manager/ironbank/__snapshots__/extract.spec.ts.snap @@ -1,14 +1,95 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`lib/manager/dsop/extract extractPackageFile() extracts single image lines 1`] = ` +exports[`lib/manager/ironbank/extract extractPackageFile() extracts single image lines 1`] = ` Array [ Object { - "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", - "currentDigest": "sha256:ed18c13b2c1d55895cc82f8ed80c93f2ec1122f133c723aa65684884a9bd6448", - "currentValue": "10.0.0", + "currentDigest": "sha256:3720b5ace316b5790a58ce838f46e8cd44cedbdb7e35d3866311ddc5a5e71466", + "currentValue": "12.0.3", "datasource": "docker", - "depName": "docker.io/jboss/keycloak", - "replaceString": "docker.io/jboss/keycloak:10.0.0@sha256:ed18c13b2c1d55895cc82f8ed80c93f2ec1122f133c723aa65684884a9bd6448", + "depName": "jboss/keycloak", + "depType": "ironbank-docker", + "lookupName": "jboss/keycloak", + "managerData": Object { + "item": Object { + "tag": "jboss/keycloak:12.0.3", + "url": "docker://docker.io/jboss/keycloak@sha256:3720b5ace316b5790a58ce838f46e8cd44cedbdb7e35d3866311ddc5a5e71466", + }, + }, + "versioning": "docker", + }, + Object { + "currentValue": "v3.4.8", + "datasource": "github-releases", + "depName": "etcd-io/etcd", + "depType": "ironbank-github", + "lookupName": "etcd-io/etcd", + "managerData": Object { + "item": Object { + "filename": "etcd.tar.gz", + "url": "https://github.com/etcd-io/etcd/releases/download/v3.4.8/etcd-v3.4.8-linux-amd64.tar.gz", + "validation": Object { + "type": "sha256", + "value": "a3a332a68fe8dedf20149c1a4b8746fe8061b72d75d3a5850b17e04de9ed7942", + }, + }, + }, + "repo": "etcd-io/etcd", + }, + Object { + "currentValue": "v1.10.3", + "datasource": "github-tags", + "depName": "fluent/fluentd", + "depType": "ironbank-github", + "lookupName": "fluent/fluentd", + "managerData": Object { + "item": Object { + "filename": "fluentd.tar.gz", + "url": "https://github.com/fluent/fluentd/archive/v1.10.3.tar.gz", + "validation": Object { + "type": "sha256", + "value": "c2b5bbb6c2236f73310b22c748e32a88f25288f3e6e1bd272f3dccc6a2322160", + }, + }, + }, + "repo": "fluent/fluentd", + }, + Object { + "currentDigest": "e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461", + "currentValue": "1.25.10", + "datasource": "pypi", + "depName": "urllib3", + "depType": "ironbank-pypi", + "lookupName": "urllib3", + "managerData": Object { + "item": Object { + "filename": "urllib3-1.25.10-py2.py3-none-any.whl", + "url": "https://files.pythonhosted.org/packages/9f/f0/a391d1463ebb1b233795cabfc0ef38d3db4442339de68f847026199e69d7/urllib3-1.25.10-py2.py3-none-any.whl", + "validation": Object { + "type": "sha256", + "value": "e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461", + }, + }, + }, + }, + Object { + "currentValue": "1.15.0", + "datasource": "rubygems", + "depName": "gitlab-triage", + "depType": "ironbank-rubygems", + "lookupName": "gitlab-triage", + "managerData": Object { + "item": Object { + "filename": "gitlab-triage-1.15.0.gem", + "url": "https://rubygems.org/downloads/gitlab-triage-1.15.0.gem", + "validation": Object { + "type": "sha256", + "value": "e516d720a67c9e3447db858775b48f44aae210b184dd96f7a20fe4fbb4022834", + }, + }, + }, + "registryUrls": Array [ + "https://rubygems.org", + ], }, ] `; diff --git a/lib/manager/ironbank/artifacts.ts b/lib/manager/ironbank/artifacts.ts index 767a0984970147ee8a0abc5179896ed368f7231d..ee1b55c3467406b8602cdbad556b41e89d3a06b4 100644 --- a/lib/manager/ironbank/artifacts.ts +++ b/lib/manager/ironbank/artifacts.ts @@ -1,16 +1,17 @@ import is from '@sindresorhus/is'; import yaml from 'js-yaml'; +import { join } from 'upath'; import { logger } from '../../logger'; import { exec } from '../../util/exec'; import { readLocalFile } from '../../util/fs'; import { getRepoStatus } from '../../util/git'; -import { UpdateArtifact, UpdateArtifactsResult } from '../common'; -import { join } from 'upath'; +import { UpdateArtifact, UpdateArtifactsResult } from '../types'; +import { HardeningManifest } from './extract'; async function postUpgrade(url: string, path: string): Promise { logger.debug(`ironbank.postUpgrade(${url}, ${path})`); try { - const cmd = 'ironbank-helm.sh' + const cmd = 'ironbank-helm.sh'; const args = '--directory ' + path + ' --url ' + url; await exec(`${cmd} ${args}`); } catch (err) { @@ -31,41 +32,49 @@ export async function updateArtifacts({ return null; } - let manifest; + let manifests: HardeningManifest[]; try { - manifest = yaml.safeLoad(newPackageFileContent, { json: true }); + manifests = yaml.safeLoadAll(newPackageFileContent, null, { json: true }); } catch (err) { logger.error('Failed to parse hardening_manifest.yaml'); return null; } - if (!(manifest && is.array(manifest.resources))) { - return null; - } + for (const manifest of manifests) { + if (!(manifest && is.array(manifest.resources))) { + return null; + } - if (!(manifest.resources[0].url && manifest.resources[0].url.startsWith('helm://'))) { - return null; - } + if (!manifest.resources[0].url?.startsWith('helm://')) { + return null; + } - let charts = new Map(); - for (const item of manifest.resources) { - if (item.url && item.url.startsWith('helm://')) { - charts.set(item.name, 'https://' + item.url.substring(7)); + const charts = new Map(); + for (const item of manifest.resources) { + if (item.url?.startsWith('helm://')) { + charts.set( + item.name, + `${String('https://')}${String(item.url.substring(7))}` + ); + } } - } - for (const dep of updatedDeps) { - logger.debug(`updatedDep(${dep})`); - if (charts.has(dep)) { - const result = await postUpgrade(charts.get(dep), join(config.localDir, dep)); - if (!result) { - return null; + for (const dep of updatedDeps) { + logger.debug(`updatedDep(${dep})`); + if (charts.has(dep)) { + const result = await postUpgrade( + charts.get(dep), + join(config.localDir, dep) + ); + if (!result) { + return null; + } } } } const res = []; - let status = await getRepoStatus(); + const status = await getRepoStatus(); for (const f of status.modified.concat(status.not_added)) { res.push({ @@ -76,7 +85,7 @@ export async function updateArtifacts({ }); } - for (const f of status.deleted || [] ) { + for (const f of status.deleted || []) { res.push({ file: { name: '|delete|', diff --git a/lib/manager/ironbank/extract.spec.ts b/lib/manager/ironbank/extract.spec.ts index 54dcae814459de86200670be6203a55ff7ca060a..74a447a6d91280923b46f9b61e886ac025076667 100644 --- a/lib/manager/ironbank/extract.spec.ts +++ b/lib/manager/ironbank/extract.spec.ts @@ -2,11 +2,11 @@ import { readFileSync } from 'fs'; import { extractPackageFile } from './extract'; const yamlFile = readFileSync( - 'lib/manager/dsop/__fixtures__/download.yaml', + 'lib/manager/ironbank/__fixtures__/hardening_manifest.yaml', 'utf8' ); -describe('lib/manager/dsop/extract', () => { +describe('lib/manager/ironbank/extract', () => { describe('extractPackageFile()', () => { it('returns null for empty', () => { expect(extractPackageFile('nothing here')).toBeNull(); @@ -14,7 +14,7 @@ describe('lib/manager/dsop/extract', () => { it('extracts single image lines', () => { const res = extractPackageFile(yamlFile); expect(res.deps).toMatchSnapshot(); - expect(res.deps).toHaveLength(1); + expect(res.deps).toHaveLength(5); }); }); }); diff --git a/lib/manager/ironbank/extract.ts b/lib/manager/ironbank/extract.ts index 1329875fe40047d9d0332d2788bd6d594cbf17db..8a583603c11afdffbd1c3d1a3ea0592ad13f4b0b 100644 --- a/lib/manager/ironbank/extract.ts +++ b/lib/manager/ironbank/extract.ts @@ -1,25 +1,76 @@ -import is from '@sindresorhus/is'; import { parse as _parse } from 'url'; +import is from '@sindresorhus/is'; import yaml from 'js-yaml'; -import { logger } from '../../logger'; -import { PackageDependency, PackageFile } from '../common'; import * as datasourceDocker from '../../datasource/docker'; import * as datasourceGithubReleases from '../../datasource/github-releases'; import * as datasourceGithubTags from '../../datasource/github-tags'; -import * as datasourceRubyGems from '../../datasource/rubygems'; import * as datasourceHelm from '../../datasource/helm'; +import * as datasourcePypi from '../../datasource/pypi'; +import * as datasourceRubyGems from '../../datasource/rubygems'; +import { logger } from '../../logger'; import * as dockerVersioning from '../../versioning/docker'; +import { PackageDependency, PackageFile } from '../types'; + +export interface HardeningManifest { + apiVersion: string; + name: string; + tags: string[]; + args: Args; + labels: Labels; + resources: Resource[]; + maintainers: Maintainer[]; +} + +export interface Args { + BASE_IMAGE: string; + BASE_TAG: string; +} +export interface Labels { + 'org.opencontainers.image.title': string; + 'org.opencontainers.image.description': string; + 'org.opencontainers.image.licenses': string; + 'org.opencontainers.image.url': string; + 'org.opencontainers.image.vendor': string; + 'org.opencontainers.image.version': string; + 'mil.dso.ironbank.image.keywords': string; + 'mil.dso.ironbank.image.type': string; + 'mil.dso.ironbank.product.name': string; +} + +export interface Maintainer { + name: string; + username: string; + email: string; + cht_member: boolean; +} + +export interface Resource { + tag?: string; + url: string; + name?: string; + filename?: string; + validation?: Validation; +} + +export interface Validation { + type: string; + value: string; +} interface UrlParsedResult { repo: string; currentValue: string; } -function getDatasourceId(lookupName: string): string { +function getDatasourceId(lookupName: string, url: string): string { if (lookupName === 'antirez/redis') { return datasourceGithubTags.id; } + if (url.includes('archive')) { + return datasourceGithubTags.id; + } + return datasourceGithubReleases.id; } @@ -50,76 +101,102 @@ function parseUrl(urlString: string): UrlParsedResult | null { export function extractPackageFile(content: string): PackageFile { const deps: PackageDependency[] = []; - let manifest; + let manifests: HardeningManifest[]; try { - manifest = yaml.safeLoad(content, { json: true }); + manifests = yaml.safeLoadAll(content, null, { json: true }); } catch (err) { logger.debug('Failed to parse hardening_manifest.yaml'); return null; } - if (!(manifest && is.array(manifest.resources))) { - logger.debug('hardening_manifest.yaml has no dependencies'); - return null; - } + for (const manifest of manifests) { + if (!(manifest && is.array(manifest.resources))) { + logger.debug('hardening_manifest.yaml has no dependencies'); + return null; + } - for (const item of manifest.resources) { - const dep: PackageDependency = { managerData: { item } }; - if (item.url) { - // docker - if (item.url.startsWith('docker://')) { - const currentDigest = item.url.split('@')[1]; - const [lookupName, currentValue] = item.tag.split(':'); - dep.depType = 'ironbank-docker'; - dep.depName = lookupName; - dep.datasource = datasourceDocker.id; - dep.versioning = dockerVersioning.id; - dep.lookupName = lookupName; - dep.currentDigest = currentDigest; - dep.currentValue = currentValue; - deps.push(dep); - } - // github-releases - else if (item.url.includes('github.com')) { - const parsedUrl = parseUrl(item.url); - dep.depType = 'ironbank-github'; - dep.depName = parsedUrl.repo; - dep.repo = parsedUrl.repo; - dep.currentValue = parsedUrl.currentValue; - dep.datasource = getDatasourceId(dep.repo); - dep.lookupName = dep.repo; - deps.push(dep); - } - // helm - else if (item.url.startsWith('helm://')) { - const regex = 'helm:\/\/(?.*\/)(?.*?)-(?.*?).tgz'; - const groups = item.url.match(regex).groups; - if (groups && groups.registryUrl && groups.lookupName && groups.currentValue) { - logger.info(groups.registryUrl); - dep.depType = 'ironbank-helm'; - dep.depName = item.name; - dep.datasource = datasourceHelm.id; - dep.registryUrls = ['https://' + groups.registryUrl]; - dep.lookupName = groups.lookupName; - dep.currentValue = groups.currentValue; + for (const item of manifest.resources) { + const dep: PackageDependency = { managerData: { item } }; + if (item.url) { + // docker + if (item.url.startsWith('docker://')) { + const currentDigest = item.url.split('@')[1]; + const [lookupName, currentValue] = item.tag.split(':'); + dep.depType = 'ironbank-docker'; + dep.depName = lookupName; + dep.datasource = datasourceDocker.id; + dep.versioning = dockerVersioning.id; + dep.lookupName = lookupName; + dep.currentDigest = currentDigest; + dep.currentValue = currentValue; deps.push(dep); } - } - // rubygems - else if (item.url.includes('rubygems.org')) { - const regex = 'https:\/\/(?.*\/)(?.*?)-(?.*?).gem'; - const groups = item.url.match(regex).groups; - if (groups && groups.registryUrl && groups.lookupName && groups.currentValue) { - dep.depType = 'ironbank-rubygem'; + // github-releases + else if (item.url.startsWith('https://github.com')) { + const parsedUrl = parseUrl(item.url); + dep.depType = 'ironbank-github'; + dep.depName = parsedUrl.repo; + dep.repo = parsedUrl.repo; + dep.currentValue = parsedUrl.currentValue; + dep.datasource = getDatasourceId(dep.repo, item.url); + dep.lookupName = dep.repo; + deps.push(dep); + } + // helm + else if (item.url.startsWith('helm://')) { + const regex = new RegExp( + 'helm://(?.*/)(?.*?)-(?.*?).tgz' + ); + const groups = regex.exec(item.url).groups; + if (groups?.registryUrl && groups.lookupName && groups.currentValue) { + logger.info(groups.registryUrl); + dep.depType = 'ironbank-helm'; + dep.depName = item.name; + dep.datasource = datasourceHelm.id; + dep.registryUrls = [ + `${String('https://')}${String(groups.registryUrl)}`, + ]; + dep.lookupName = groups.lookupName; + dep.currentValue = groups.currentValue; + deps.push(dep); + } + } + // rubygems + else if (item.url.startsWith('https://rubygems.org')) { + const regex = new RegExp( + 'https://(?.*)/(.*/)(?.*-?)-(?.*?).gem' + ); + const groups = regex.exec(item.url).groups; + if (groups?.registryUrl && groups.lookupName && groups.currentValue) { + dep.depType = 'ironbank-rubygems'; dep.depName = groups.lookupName; dep.lookupName = groups.lookupName; dep.datasource = datasourceRubyGems.id; dep.currentValue = groups.currentValue; - dep.registryUrls = ['https://' + groups.registryUrl]; + dep.registryUrls = [ + `${String('https://')}${String(groups.registryUrl)}`, + ]; deps.push(dep); } - } + } else if (item.url.startsWith('https://files.pythonhosted.org')) { + const regex = new RegExp( + 'https://(.*)/(.*)/(.*)/(.*)/(.*)/(?.*?)-(?.*?)-(.*)' + ); + const group = regex.exec(item.url).groups; + + if (group.lookupName && group.version) { + dep.depType = 'ironbank-pypi'; + dep.currentDigest = item.validation.value; + dep.currentValue = group.version; + dep.depName = group.lookupName; + dep.datasource = datasourcePypi.id; + dep.lookupName = group.lookupName; + + deps.push(dep); + } + } + } } } diff --git a/lib/manager/ironbank/index.ts b/lib/manager/ironbank/index.ts index bc2d5ad19eb7b7db4739b91beba83c5aba726871..3cb26c178b3c1e5544bdd9f9bc3a21fb82e8031c 100644 --- a/lib/manager/ironbank/index.ts +++ b/lib/manager/ironbank/index.ts @@ -2,7 +2,7 @@ import { updateArtifacts } from './artifacts'; import { extractPackageFile } from './extract'; import { updateDependency } from './update'; -export { extractPackageFile , updateDependency, updateArtifacts }; +export { extractPackageFile, updateDependency, updateArtifacts }; export const defaultConfig = { fileMatch: ['(^|/)download.yaml$', '(^|/)hardening_manifest.yaml$'], diff --git a/lib/manager/ironbank/update.ts b/lib/manager/ironbank/update.ts index 2b9d01a30c954e162100b02b9cf1eb74c6d6a521..2c20aedaf9dc13fcf38d5ff926bfc9caefb98056 100644 --- a/lib/manager/ironbank/update.ts +++ b/lib/manager/ironbank/update.ts @@ -1,19 +1,25 @@ +import path from 'path'; +import { parse as _parse } from 'url'; import { fromStream } from 'hasha'; import { logger } from '../../logger'; import { Http } from '../../util/http'; -import { UpdateDependencyConfig } from '../common'; -import { parse as _parse } from 'url'; -import path from 'path'; +import { UpdateDependencyConfig } from '../types'; const http = new Http('ironbank'); -async function getHashFromFile(url: string, filename: string) : Promise { - logger.debug("getHashFromFile: " + url + " " + filename); +async function getHashFromFile( + url: string, + filename: string +): Promise { + logger.debug('getHashFromFile: ' + url + ' ' + filename); try { const result = await http.get(url); if (result.body) { - const regex = '(?[A-Fa-f0-9]{64})\\s+' + filename.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - const groups = result.body.match(regex).groups; + const regex = new RegExp( + '(?[A-Fa-f0-9]{64})\\s+' + + filename.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ); + const groups = regex.exec(result.body).groups; if (groups) { return groups.hash; } @@ -24,12 +30,12 @@ async function getHashFromFile(url: string, filename: string) : Promise { +async function getHashFromUrl(url: string): Promise { try { const parsedUrl = _parse(url); const filename = path.basename(parsedUrl.pathname); - let hash; + let hash: string; hash = await getHashFromFile(filename + '.sha256', filename); if (hash) { return hash; @@ -47,53 +53,133 @@ async function getHashFromUrl(url: string): Promise { } } +async function getPypiData( + url: string +): Promise<{ sha: string; updatedUrl: string }> { + logger.debug(`${'getPypiData:'} ${url} ${'filename'}`); + try { + const result = await http.get(url); + if (result.body) { + const results = JSON.parse(result.body); + + for (let i = 0; i < results.urls.length; i += 1) { + if (results.urls[i].filename.endsWith('whl')) { + const output = { + sha: results.urls[i].digests.sha256, + updatedUrl: results.urls[i].url, + }; + + return output; + } + } + } + return null; + } catch (err) /* istanbul ignore next */ { + return null; + } +} + export async function updateDependency({ fileContent, upgrade, }: UpdateDependencyConfig): Promise { + // let newContent = fileContent; - if (upgrade.depType === 'ironbank-docker') { - const oldTag = upgrade.lookupName + ':' + upgrade.currentValue; - const newTag = upgrade.lookupName + ':' + upgrade.newValue; - let newContent = fileContent.replace(upgrade.currentDigest, upgrade.newDigest); - return newContent.replace(oldTag, newTag); - } else if ( - upgrade.depType === 'ironbank-github' && - upgrade.currentValue && - upgrade.newValue - ) { - const currentValue = upgrade.currentValue.replace(/^v/, ''); - const newValue = upgrade.newValue.replace(/^v/, ''); - const oldUrl = upgrade.managerData.item.url; - const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue); - const hash = await getHashFromUrl(newUrl); - let newContent = fileContent; - if (hash) { - newContent = newContent.replace(upgrade.managerData.item.validation.value, hash); + switch (upgrade.depType) { + case 'ironbank-docker': { + const oldTag = upgrade.lookupName + ':' + upgrade.currentValue; + const newTag = upgrade.lookupName + ':' + upgrade.newValue; + const oldUrl = upgrade.managerData.item.url; + const newUrl = `${String(upgrade.managerData.item.url.split('@')[0])}@${ + upgrade.newDigest + }`; + + if (oldUrl === newUrl || oldTag === newTag) { + return null; + } + + let newContent = fileContent; + newContent = newContent.replace(oldTag, newTag); + newContent = newContent.replace(oldUrl, newUrl); + + return newContent; } - return newContent.replace(oldUrl, newUrl); - } else if ( - upgrade.depType == 'ironbank-helm' && - upgrade.currentValue && - upgrade.newValue - ) { - return fileContent.replace(upgrade.currentValue, upgrade.newValue); - } else if ( - upgrade.depType == 'ironbank-rubygem' && - upgrade.currentValue && - upgrade.newValue - ) { - const currentValue = upgrade.currentValue; - const newValue = upgrade.newValue; - const oldUrl = upgrade.managerData.item.url; - const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue); - const hash = await getHashFromUrl(newUrl); - let newContent = fileContent; - if (hash) { - newContent = newContent.replace(upgrade.managerData.item.validation.value, hash); + case 'ironbank-github': { + if (!upgrade.currentValue && !upgrade.newValue) { + logger.warn( + `${'issue updating ironbank-github for'} ${upgrade.lookupName}` + ); + return null; + } + + const currentValue = upgrade.currentValue.replace(/^v/, ''); + const newValue = upgrade.newValue.replace(/^v/, ''); + const oldUrl = upgrade.managerData.item.url; + const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue); + const hash = await getHashFromUrl(newUrl); + let newContent = fileContent; + if (hash) { + newContent = newContent.replace( + upgrade.managerData.item.validation.value, + hash + ); + newContent = newContent.replace(oldUrl, newUrl); + } + return newContent; } - return newContent.replace(oldUrl, newUrl); - } + case 'ironbank-helm': { + if (!upgrade.currentValue && !upgrade.newValue) { + logger.warn(`${'issue updating ironbank-helm for'} ${upgrade.depName}`); + return null; + } - return null; + return fileContent.replace(upgrade.currentValue, upgrade.newValue); + } + case 'ironbank-rubygems': { + if (!upgrade.currentValue && !upgrade.newValue) { + logger.warn( + `${'issue updating ironbank-rubygems for'} ${upgrade.depName}` + ); + return null; + } + + const currentValue = upgrade.currentValue; + const newValue = upgrade.newValue; + const oldUrl = upgrade.managerData.item.url; + const newUrl = oldUrl.replace(new RegExp(currentValue, 'g'), newValue); + const hash = await getHashFromUrl(newUrl); + let newContent = fileContent; + if (hash) { + newContent = newContent.replace( + upgrade.managerData.item.validation.value, + hash + ); + newContent = newContent.replace(oldUrl, newUrl); + } + return newContent; + } + case 'ironbank-pypi': { + if (!upgrade.newValue) { + logger.warn(`${'issue updating ironbank-pypi for'} ${upgrade.depName}`); + return null; + } + + const newValue = upgrade.newValue; + const oldUrl = upgrade.managerData.item.url; + const searchURL = `https://pypi.org/pypi/${upgrade.depName}/${newValue}/json`; + const updatedData = getPypiData(searchURL); + + let newContent = fileContent; + if ((await updatedData).sha && (await updatedData).updatedUrl) { + newContent = newContent.replace( + upgrade.managerData.item.validation.value, + (await updatedData).sha + ); + newContent = newContent.replace(oldUrl, (await updatedData).updatedUrl); + } + return newContent; + } + default: + return null; + } } diff --git a/renovate.json b/renovate.json index 3b955b768f42f76c6f4cab7c8ec9aef3c9881304..ed8f1758acd58e73cf37fd51fbd9efa73bb3ebe6 100644 --- a/renovate.json +++ b/renovate.json @@ -16,6 +16,15 @@ "major": { "enabled": true } + }, + { + "datasources": [ + "docker" + ], + "packageNames": [ + "registry1.dso.mil/ironbank/opensource/nodejs/nodejs14" + ], + "prBodyNotes": ["This is an upstream base image update"] } ], "regexManagers": [ @@ -48,6 +57,16 @@ ], "depNameTemplate": "renovate/renovate", "datasourceTemplate": "docker" + }, + { + "fileMatch": [ + "^hardening_manifest.yaml$" + ], + "matchStrings": [ + "BASE_TAG: \"(?.*?)\"" + ], + "depNameTemplate": "registry1.dso.mil/ironbank/opensource/nodejs/nodejs14", + "datasourceTemplate": "docker" } ] -} \ No newline at end of file +}