From c788a8d92c12fb180bbd01e782925f80c49ef423 Mon Sep 17 00:00:00 2001 From: sozercan Date: Mon, 9 Oct 2023 20:41:58 +0000 Subject: [PATCH] deploy: e87aec9c57aaa06d2953c653f1387617e27927fe --- website/404.html | 4 ++-- website/assets/js/0480b142.2492b96e.js | 1 + website/assets/js/0480b142.468c62ac.js | 1 - .../{runtime~main.74f728c5.js => runtime~main.2d3b4c1c.js} | 2 +- website/code-of-conduct.html | 4 ++-- website/contributing.html | 4 ++-- website/design.html | 4 ++-- website/faq.html | 4 ++-- website/github-action.html | 4 ++-- website/index.html | 4 ++-- website/installation.html | 4 ++-- website/next.html | 4 ++-- website/next/code-of-conduct.html | 4 ++-- website/next/contributing.html | 4 ++-- website/next/design.html | 4 ++-- website/next/faq.html | 6 +++--- website/next/github-action.html | 4 ++-- website/next/installation.html | 4 ++-- website/next/output.html | 4 ++-- website/next/quick-start.html | 4 ++-- website/next/release.html | 4 ++-- website/next/troubleshooting.html | 4 ++-- website/quick-start.html | 4 ++-- website/release.html | 4 ++-- website/troubleshooting.html | 4 ++-- website/v0.1.x.html | 4 ++-- website/v0.1.x/code-of-conduct.html | 4 ++-- website/v0.1.x/contributing.html | 4 ++-- website/v0.1.x/design.html | 4 ++-- website/v0.1.x/faq.html | 4 ++-- website/v0.1.x/installation.html | 4 ++-- website/v0.1.x/quick-start.html | 4 ++-- website/v0.2.x.html | 4 ++-- website/v0.2.x/code-of-conduct.html | 4 ++-- website/v0.2.x/contributing.html | 4 ++-- website/v0.2.x/design.html | 4 ++-- website/v0.2.x/faq.html | 4 ++-- website/v0.2.x/installation.html | 4 ++-- website/v0.2.x/quick-start.html | 4 ++-- website/v0.3.x.html | 4 ++-- website/v0.3.x/code-of-conduct.html | 4 ++-- website/v0.3.x/contributing.html | 4 ++-- website/v0.3.x/design.html | 4 ++-- website/v0.3.x/faq.html | 4 ++-- website/v0.3.x/installation.html | 4 ++-- website/v0.3.x/quick-start.html | 4 ++-- 46 files changed, 89 insertions(+), 89 deletions(-) create mode 100644 website/assets/js/0480b142.2492b96e.js delete mode 100644 website/assets/js/0480b142.468c62ac.js rename website/assets/js/{runtime~main.74f728c5.js => runtime~main.2d3b4c1c.js} (98%) diff --git a/website/404.html b/website/404.html index 83358a95..597978a2 100644 --- a/website/404.html +++ b/website/404.html @@ -7,13 +7,13 @@ - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/website/assets/js/0480b142.2492b96e.js b/website/assets/js/0480b142.2492b96e.js new file mode 100644 index 00000000..63868657 --- /dev/null +++ b/website/assets/js/0480b142.2492b96e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[836],{3905:(e,t,a)=>{a.d(t,{Zo:()=>s,kt:()=>h});var n=a(7294);function i(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function r(e){for(var t=1;t=0||(i[a]=e[a]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(i[a]=e[a])}return i}var c=n.createContext({}),p=function(e){var t=n.useContext(c),a=t;return e&&(a="function"==typeof e?e(t):r(r({},t),e)),a},s=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var a=e.components,i=e.mdxType,o=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),u=p(a),m=i,h=u["".concat(c,".").concat(m)]||u[m]||d[m]||o;return a?n.createElement(h,r(r({ref:t},s),{},{components:a})):n.createElement(h,r({ref:t},s))}));function h(e,t){var a=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=a.length,r=new Array(o);r[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[u]="string"==typeof e?e:i,r[1]=l;for(var p=2;p{a.r(t),a.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var n=a(7462),i=(a(7294),a(3905));const o={title:"FAQ"},r=void 0,l={unversionedId:"faq",id:"faq",title:"FAQ",description:"What kind of vulnerabilities can Copa patch?",source:"@site/docs/faq.md",sourceDirName:".",slug:"/faq",permalink:"/copacetic/website/next/faq",draft:!1,tags:[],version:"current",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Design",permalink:"/copacetic/website/next/design"},next:{title:"Contributing",permalink:"/copacetic/website/next/contributing"}},c={},p=[{value:"What kind of vulnerabilities can Copa patch?",id:"what-kind-of-vulnerabilities-can-copa-patch",level:2},{value:"What kind of vulnerabilities can Copa not patch?",id:"what-kind-of-vulnerabilities-can-copa-not-patch",level:2},{value:"Can I replace the package repositories in the image with my own?",id:"can-i-replace-the-package-repositories-in-the-image-with-my-own",level:2}],s={toc:p};function u(e){let{components:t,...a}=e;return(0,i.kt)("wrapper",(0,n.Z)({},s,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"what-kind-of-vulnerabilities-can-copa-patch"},"What kind of vulnerabilities can Copa patch?"),(0,i.kt)("p",null,'Copa is capable of patching "OS level" vulnerabilities. This includes packages (like ',(0,i.kt)("inlineCode",{parentName:"p"},"openssl"),") in the image that are managed by a package manager such as ",(0,i.kt)("inlineCode",{parentName:"p"},"apt")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"yum"),'. Copa is not currently capable of patching vulnerabilities at the "application level" such as Python packages or Go modules (see ',(0,i.kt)("a",{parentName:"p",href:"#what-kind-of-vulnerabilities-can-copa-not-patch"},"below")," for more details)."),(0,i.kt)("h2",{id:"what-kind-of-vulnerabilities-can-copa-not-patch"},"What kind of vulnerabilities can Copa not patch?"),(0,i.kt)("p",null,'Copa is not capable of patching vulnerabilities for compiled languages, like Go, at the "application level", for instance, Go modules. If your application uses a vulnerable version of the ',(0,i.kt)("inlineCode",{parentName:"p"},"golang.org/x/net")," module, Copa will be unable to patch it. This is because Copa doesn't have access to the application's source code or the knowledge of how to build it, such as compiler flags, preventing it from patching vulnerabilities at the application level."),(0,i.kt)("p",null,"To patch vulnerabilities for applications, you can package these applications and consume them from package repositories, like ",(0,i.kt)("inlineCode",{parentName:"p"},"http://archive.ubuntu.com/ubuntu/")," for Ubuntu, and ensure Trivy can scan and report vulnerabilities for these packages. This way, Copa can patch the applications as a whole, though it cannot patch specific modules within the applications."),(0,i.kt)("h2",{id:"can-i-replace-the-package-repositories-in-the-image-with-my-own"},"Can I replace the package repositories in the image with my own?"),(0,i.kt)("admonition",{type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"Experimental: This feature might change without preserving backwards compatibility.")),(0,i.kt)("p",null,"Copa does not support replacing the repositories in the package managers with alternatives. Images must already use the intended package repositories. For example, for debian, updating ",(0,i.kt)("inlineCode",{parentName:"p"},"/etc/apt/sources.list")," from ",(0,i.kt)("inlineCode",{parentName:"p"},"http://archive.ubuntu.com/ubuntu/")," to a mirror, such as ",(0,i.kt)("inlineCode",{parentName:"p"},"https://mirrors.wikimedia.org/ubuntu/"),"."),(0,i.kt)("p",null,"If you need the tooling image to use a different package repository, you can create a source policy to define a replacement image and/or pin to a digest. For example, the following source policy replaces ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/debian:11-slim")," image with ",(0,i.kt)("inlineCode",{parentName:"p"},"foo.io/bar/baz:latest@sha256:42d3e6bc186572245aded5a0be381012adba6d89355fa9486dd81b0c634695b5"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},'cat < source-policy.json\n{\n "rules": [\n {\n "action": "CONVERT",\n "selector": {\n "identifier": "docker-image://docker.io/library/debian:11-slim"\n },\n "updates": {\n "identifier": "docker-image://foo.io/bar/baz:latest@sha256:42d3e6bc186572245aded5a0be381012adba6d89355fa9486dd81b0c634695b5"\n }\n }\n ]\n}\nEOF\n\nexport EXPERIMENTAL_BUILDKIT_SOURCE_POLICY=source-policy.json\n')),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"Tooling image for Debian-based images are ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/debian:11-slim")," and RPM-based repos are ",(0,i.kt)("inlineCode",{parentName:"p"},"mcr.microsoft.com/cbl-mariner/base/core:2.0"),".")),(0,i.kt)("p",null,"For more information on source policies, see ",(0,i.kt)("a",{parentName:"p",href:"https://docs.docker.com/build/building/env-vars/#experimental_buildkit_source_policy"},"Buildkit Source Policies"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/website/assets/js/0480b142.468c62ac.js b/website/assets/js/0480b142.468c62ac.js deleted file mode 100644 index 7ebd0441..00000000 --- a/website/assets/js/0480b142.468c62ac.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[836],{3905:(e,t,n)=>{n.d(t,{Zo:()=>s,kt:()=>b});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),l=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},s=function(e){var t=l(e.components);return a.createElement(p.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,p=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),u=l(n),m=r,b=u["".concat(p,".").concat(m)]||u[m]||d[m]||i;return n?a.createElement(b,o(o({ref:t},s),{},{components:n})):a.createElement(b,o({ref:t},s))}));function b(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,o=new Array(i);o[0]=m;var c={};for(var p in t)hasOwnProperty.call(t,p)&&(c[p]=t[p]);c.originalType=e,c[u]="string"==typeof e?e:r,o[1]=c;for(var l=2;l{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var a=n(7462),r=(n(7294),n(3905));const i={title:"FAQ"},o=void 0,c={unversionedId:"faq",id:"faq",title:"FAQ",description:"What kind of vulnerabilities can Copa patch?",source:"@site/docs/faq.md",sourceDirName:".",slug:"/faq",permalink:"/copacetic/website/next/faq",draft:!1,tags:[],version:"current",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Design",permalink:"/copacetic/website/next/design"},next:{title:"Contributing",permalink:"/copacetic/website/next/contributing"}},p={},l=[{value:"What kind of vulnerabilities can Copa patch?",id:"what-kind-of-vulnerabilities-can-copa-patch",level:2},{value:"Can I replace the package repositories in the image with my own?",id:"can-i-replace-the-package-repositories-in-the-image-with-my-own",level:2}],s={toc:l};function u(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},s,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"what-kind-of-vulnerabilities-can-copa-patch"},"What kind of vulnerabilities can Copa patch?"),(0,r.kt)("p",null,'Copa is capable of patching "OS level" vulnerabilities. This includes packages (like ',(0,r.kt)("inlineCode",{parentName:"p"},"openssl"),") in the image that are managed by a package manager such as ",(0,r.kt)("inlineCode",{parentName:"p"},"apt")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"yum"),'. Copa is not currently capable of patching vulnerabilities at the "application level" such as Python packages or Go modules.'),(0,r.kt)("h2",{id:"can-i-replace-the-package-repositories-in-the-image-with-my-own"},"Can I replace the package repositories in the image with my own?"),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Experimental: This feature might change without preserving backwards compatibility.")),(0,r.kt)("p",null,"Copa does not support replacing the repositories in the package managers with alternatives. Images must already use the intended package repositories. For example, for debian, updating ",(0,r.kt)("inlineCode",{parentName:"p"},"/etc/apt/sources.list")," from ",(0,r.kt)("inlineCode",{parentName:"p"},"http://archive.ubuntu.com/ubuntu/")," to a mirror, such as ",(0,r.kt)("inlineCode",{parentName:"p"},"https://mirrors.wikimedia.org/ubuntu/"),"."),(0,r.kt)("p",null,"If you need the tooling image to use a different package repository, you can create a source policy to define a replacement image and/or pin to a digest. For example, the following source policy replaces ",(0,r.kt)("inlineCode",{parentName:"p"},"docker.io/library/debian:11-slim")," image with ",(0,r.kt)("inlineCode",{parentName:"p"},"foo.io/bar/baz:latest@sha256:42d3e6bc186572245aded5a0be381012adba6d89355fa9486dd81b0c634695b5"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},'cat < source-policy.json\n{\n "rules": [\n {\n "action": "CONVERT",\n "selector": {\n "identifier": "docker-image://docker.io/library/debian:11-slim"\n },\n "updates": {\n "identifier": "docker-image://foo.io/bar/baz:latest@sha256:42d3e6bc186572245aded5a0be381012adba6d89355fa9486dd81b0c634695b5"\n }\n }\n ]\n}\nEOF\n\nexport EXPERIMENTAL_BUILDKIT_SOURCE_POLICY=source-policy.json\n')),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"Tooling image for Debian-based images are ",(0,r.kt)("inlineCode",{parentName:"p"},"docker.io/library/debian:11-slim")," and RPM-based repos are ",(0,r.kt)("inlineCode",{parentName:"p"},"mcr.microsoft.com/cbl-mariner/base/core:2.0"),".")),(0,r.kt)("p",null,"For more information on source policies, see ",(0,r.kt)("a",{parentName:"p",href:"https://docs.docker.com/build/building/env-vars/#experimental_buildkit_source_policy"},"Buildkit Source Policies"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/website/assets/js/runtime~main.74f728c5.js b/website/assets/js/runtime~main.2d3b4c1c.js similarity index 98% rename from website/assets/js/runtime~main.74f728c5.js rename to website/assets/js/runtime~main.2d3b4c1c.js index 12461e22..90ad2cb9 100644 --- a/website/assets/js/runtime~main.74f728c5.js +++ b/website/assets/js/runtime~main.2d3b4c1c.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,t,f,r,b={},c={};function d(e){var a=c[e];if(void 0!==a)return a.exports;var t=c[e]={id:e,loaded:!1,exports:{}};return b[e].call(t.exports,t,t.exports,d),t.loaded=!0,t.exports}d.m=b,d.c=c,e=[],d.O=(a,t,f,r)=>{if(!t){var b=1/0;for(i=0;i=r)&&Object.keys(d.O).every((e=>d.O[e](t[o])))?t.splice(o--,1):(c=!1,r0&&e[i-1][2]>r;i--)e[i]=e[i-1];e[i]=[t,f,r]},d.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return d.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var r=Object.create(null);d.r(r);var b={};a=a||[null,t({}),t([]),t(t)];for(var c=2&f&&e;"object"==typeof c&&!~a.indexOf(c);c=t(c))Object.getOwnPropertyNames(c).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,d.d(r,b),r},d.d=(e,a)=>{for(var t in a)d.o(a,t)&&!d.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce(((a,t)=>(d.f[t](e,a),a)),[])),d.u=e=>"assets/js/"+({4:"d9461b6c",53:"935f2afb",267:"86b9c768",335:"053b5658",414:"0aeccac2",494:"f3bd9382",722:"7e72de0f",836:"0480b142",1087:"fcc13998",1201:"040fbf97",1220:"f9459e94",2088:"4cb9f763",2676:"1b7d20b2",2702:"2a636ef6",3200:"bab6f5ab",3217:"3b8c55ea",3242:"3fcb412e",3296:"e8c0720c",3480:"9f65b58a",4073:"05a474a1",4128:"a09c2993",4925:"b407a98a",4993:"c698fe77",5145:"299b5310",5737:"2133a534",5897:"14aa7e32",5964:"22539a87",6325:"c12dc9fd",6352:"dea0f9ea",6705:"c5934ffc",6948:"0c380bb3",7059:"b5d5e16b",7071:"804a5934",7080:"4d54d076",7114:"b9421f89",7239:"72e14192",7262:"9e350ec0",7451:"6173fde8",7835:"ea9eabff",7845:"c13ba925",7918:"17896441",8163:"934782ba",8644:"d2339658",8765:"57b2432c",8838:"6bd0979b",9212:"48ae5635",9360:"9d9f8394",9514:"1be78505",9691:"0a7bb60d",9925:"89eebbd3"}[e]||e)+"."+{4:"cfb2e633",53:"26437c0c",267:"6a1c76ae",335:"14dee349",414:"008fdaae",494:"a6d7730a",722:"46d6e17a",836:"468c62ac",1087:"5e4b93fa",1201:"f9ab363d",1220:"d4932d2b",2088:"c7fd5bba",2676:"716b56fa",2702:"aa75de3e",3200:"1dcf3cff",3217:"6657802e",3242:"2f660f8e",3296:"1451a9f7",3480:"3374a93f",4073:"dc9b52ff",4128:"bb1d0948",4925:"7eeb3207",4972:"9374abde",4993:"251983c8",5145:"a01d158f",5737:"f95c97ab",5897:"f1613ec2",5964:"5472682f",6325:"13b3a5d3",6352:"0cbf81a5",6705:"0e15e6c8",6948:"90242cf8",7059:"0cb143ee",7071:"e1bcf12f",7080:"d1735fae",7114:"ff2afd52",7239:"e848c794",7262:"53af148c",7451:"55493801",7835:"6d2cdf3d",7845:"13a08293",7918:"bd1b9c94",8163:"e90f3e37",8644:"3f5cadcb",8765:"ba8a447b",8838:"2824c577",9212:"557c06f7",9360:"c902505e",9514:"61acc940",9691:"238534bf",9925:"f1022e5a"}[e]+".js",d.miniCssF=e=>{},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),f={},r="website:",d.l=(e,a,t,b)=>{if(f[e])f[e].push(a);else{var c,o;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{c.onerror=c.onload=null,clearTimeout(s);var r=f[e];if(delete f[e],c.parentNode&&c.parentNode.removeChild(c),r&&r.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:c}),12e4);c.onerror=l.bind(null,c.onerror),c.onload=l.bind(null,c.onload),o&&document.head.appendChild(c)}},d.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.p="/copacetic/website/",d.gca=function(e){return e={17896441:"7918",d9461b6c:"4","935f2afb":"53","86b9c768":"267","053b5658":"335","0aeccac2":"414",f3bd9382:"494","7e72de0f":"722","0480b142":"836",fcc13998:"1087","040fbf97":"1201",f9459e94:"1220","4cb9f763":"2088","1b7d20b2":"2676","2a636ef6":"2702",bab6f5ab:"3200","3b8c55ea":"3217","3fcb412e":"3242",e8c0720c:"3296","9f65b58a":"3480","05a474a1":"4073",a09c2993:"4128",b407a98a:"4925",c698fe77:"4993","299b5310":"5145","2133a534":"5737","14aa7e32":"5897","22539a87":"5964",c12dc9fd:"6325",dea0f9ea:"6352",c5934ffc:"6705","0c380bb3":"6948",b5d5e16b:"7059","804a5934":"7071","4d54d076":"7080",b9421f89:"7114","72e14192":"7239","9e350ec0":"7262","6173fde8":"7451",ea9eabff:"7835",c13ba925:"7845","934782ba":"8163",d2339658:"8644","57b2432c":"8765","6bd0979b":"8838","48ae5635":"9212","9d9f8394":"9360","1be78505":"9514","0a7bb60d":"9691","89eebbd3":"9925"}[e]||e,d.p+d.u(e)},(()=>{var e={1303:0,532:0};d.f.j=(a,t)=>{var f=d.o(e,a)?e[a]:void 0;if(0!==f)if(f)t.push(f[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var r=new Promise(((t,r)=>f=e[a]=[t,r]));t.push(f[2]=r);var b=d.p+d.u(a),c=new Error;d.l(b,(t=>{if(d.o(e,a)&&(0!==(f=e[a])&&(e[a]=void 0),f)){var r=t&&("load"===t.type?"missing":t.type),b=t&&t.target&&t.target.src;c.message="Loading chunk "+a+" failed.\n("+r+": "+b+")",c.name="ChunkLoadError",c.type=r,c.request=b,f[1](c)}}),"chunk-"+a,a)}},d.O.j=a=>0===e[a];var a=(a,t)=>{var f,r,b=t[0],c=t[1],o=t[2],n=0;if(b.some((a=>0!==e[a]))){for(f in c)d.o(c,f)&&(d.m[f]=c[f]);if(o)var i=o(d)}for(a&&a(t);n{"use strict";var e,a,t,f,r,b={},c={};function d(e){var a=c[e];if(void 0!==a)return a.exports;var t=c[e]={id:e,loaded:!1,exports:{}};return b[e].call(t.exports,t,t.exports,d),t.loaded=!0,t.exports}d.m=b,d.c=c,e=[],d.O=(a,t,f,r)=>{if(!t){var b=1/0;for(i=0;i=r)&&Object.keys(d.O).every((e=>d.O[e](t[o])))?t.splice(o--,1):(c=!1,r0&&e[i-1][2]>r;i--)e[i]=e[i-1];e[i]=[t,f,r]},d.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return d.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var r=Object.create(null);d.r(r);var b={};a=a||[null,t({}),t([]),t(t)];for(var c=2&f&&e;"object"==typeof c&&!~a.indexOf(c);c=t(c))Object.getOwnPropertyNames(c).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,d.d(r,b),r},d.d=(e,a)=>{for(var t in a)d.o(a,t)&&!d.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce(((a,t)=>(d.f[t](e,a),a)),[])),d.u=e=>"assets/js/"+({4:"d9461b6c",53:"935f2afb",267:"86b9c768",335:"053b5658",414:"0aeccac2",494:"f3bd9382",722:"7e72de0f",836:"0480b142",1087:"fcc13998",1201:"040fbf97",1220:"f9459e94",2088:"4cb9f763",2676:"1b7d20b2",2702:"2a636ef6",3200:"bab6f5ab",3217:"3b8c55ea",3242:"3fcb412e",3296:"e8c0720c",3480:"9f65b58a",4073:"05a474a1",4128:"a09c2993",4925:"b407a98a",4993:"c698fe77",5145:"299b5310",5737:"2133a534",5897:"14aa7e32",5964:"22539a87",6325:"c12dc9fd",6352:"dea0f9ea",6705:"c5934ffc",6948:"0c380bb3",7059:"b5d5e16b",7071:"804a5934",7080:"4d54d076",7114:"b9421f89",7239:"72e14192",7262:"9e350ec0",7451:"6173fde8",7835:"ea9eabff",7845:"c13ba925",7918:"17896441",8163:"934782ba",8644:"d2339658",8765:"57b2432c",8838:"6bd0979b",9212:"48ae5635",9360:"9d9f8394",9514:"1be78505",9691:"0a7bb60d",9925:"89eebbd3"}[e]||e)+"."+{4:"cfb2e633",53:"26437c0c",267:"6a1c76ae",335:"14dee349",414:"008fdaae",494:"a6d7730a",722:"46d6e17a",836:"2492b96e",1087:"5e4b93fa",1201:"f9ab363d",1220:"d4932d2b",2088:"c7fd5bba",2676:"716b56fa",2702:"aa75de3e",3200:"1dcf3cff",3217:"6657802e",3242:"2f660f8e",3296:"1451a9f7",3480:"3374a93f",4073:"dc9b52ff",4128:"bb1d0948",4925:"7eeb3207",4972:"9374abde",4993:"251983c8",5145:"a01d158f",5737:"f95c97ab",5897:"f1613ec2",5964:"5472682f",6325:"13b3a5d3",6352:"0cbf81a5",6705:"0e15e6c8",6948:"90242cf8",7059:"0cb143ee",7071:"e1bcf12f",7080:"d1735fae",7114:"ff2afd52",7239:"e848c794",7262:"53af148c",7451:"55493801",7835:"6d2cdf3d",7845:"13a08293",7918:"bd1b9c94",8163:"e90f3e37",8644:"3f5cadcb",8765:"ba8a447b",8838:"2824c577",9212:"557c06f7",9360:"c902505e",9514:"61acc940",9691:"238534bf",9925:"f1022e5a"}[e]+".js",d.miniCssF=e=>{},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),f={},r="website:",d.l=(e,a,t,b)=>{if(f[e])f[e].push(a);else{var c,o;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{c.onerror=c.onload=null,clearTimeout(s);var r=f[e];if(delete f[e],c.parentNode&&c.parentNode.removeChild(c),r&&r.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:c}),12e4);c.onerror=l.bind(null,c.onerror),c.onload=l.bind(null,c.onload),o&&document.head.appendChild(c)}},d.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.p="/copacetic/website/",d.gca=function(e){return e={17896441:"7918",d9461b6c:"4","935f2afb":"53","86b9c768":"267","053b5658":"335","0aeccac2":"414",f3bd9382:"494","7e72de0f":"722","0480b142":"836",fcc13998:"1087","040fbf97":"1201",f9459e94:"1220","4cb9f763":"2088","1b7d20b2":"2676","2a636ef6":"2702",bab6f5ab:"3200","3b8c55ea":"3217","3fcb412e":"3242",e8c0720c:"3296","9f65b58a":"3480","05a474a1":"4073",a09c2993:"4128",b407a98a:"4925",c698fe77:"4993","299b5310":"5145","2133a534":"5737","14aa7e32":"5897","22539a87":"5964",c12dc9fd:"6325",dea0f9ea:"6352",c5934ffc:"6705","0c380bb3":"6948",b5d5e16b:"7059","804a5934":"7071","4d54d076":"7080",b9421f89:"7114","72e14192":"7239","9e350ec0":"7262","6173fde8":"7451",ea9eabff:"7835",c13ba925:"7845","934782ba":"8163",d2339658:"8644","57b2432c":"8765","6bd0979b":"8838","48ae5635":"9212","9d9f8394":"9360","1be78505":"9514","0a7bb60d":"9691","89eebbd3":"9925"}[e]||e,d.p+d.u(e)},(()=>{var e={1303:0,532:0};d.f.j=(a,t)=>{var f=d.o(e,a)?e[a]:void 0;if(0!==f)if(f)t.push(f[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var r=new Promise(((t,r)=>f=e[a]=[t,r]));t.push(f[2]=r);var b=d.p+d.u(a),c=new Error;d.l(b,(t=>{if(d.o(e,a)&&(0!==(f=e[a])&&(e[a]=void 0),f)){var r=t&&("load"===t.type?"missing":t.type),b=t&&t.target&&t.target.src;c.message="Loading chunk "+a+" failed.\n("+r+": "+b+")",c.name="ChunkLoadError",c.type=r,c.request=b,f[1](c)}}),"chunk-"+a,a)}},d.O.j=a=>0===e[a];var a=(a,t)=>{var f,r,b=t[0],c=t[1],o=t[2],n=0;if(b.some((a=>0!==e[a]))){for(f in c)d.o(c,f)&&(d.m[f]=c[f]);if(o)var i=o(d)}for(a&&a(t);n - + @@ -62,7 +62,7 @@ Mozilla's code of conduct enforcement ladder.

For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.

- + \ No newline at end of file diff --git a/website/contributing.html b/website/contributing.html index ab1af4e5..756c662f 100644 --- a/website/contributing.html +++ b/website/contributing.html @@ -7,7 +7,7 @@ - + @@ -27,7 +27,7 @@ personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.

Contributors sign-off that they adhere to these requirements by adding a Signed-off-by line to commit messages.

This is my commit message

Signed-off-by: Random J Developer <random@developer.example.org>

Git even has a -s command line option to append this automatically to your commit message:

git commit -s -m 'This is my commit message'

Pull requests that do not contain a valid Signed-off-by line cannot be merged.

I didn't sign my commit, now what?

No worries - You can easily amend your commit with a sign-off and force push the change to your submitting branch:

git switch <branch-name>
git commit --amend --no-edit --signoff
git push --force-with-lease <remote-name> <branch-name>

Code of Conduct

This project has adopted the Contributor Covenant Code of Conduct.

- + \ No newline at end of file diff --git a/website/design.html b/website/design.html index 7a76726c..8c6f7e14 100644 --- a/website/design.html +++ b/website/design.html @@ -7,13 +7,13 @@ - +
Version: v0.4.x

Design

Design Tenets

  • Copa is intended to accelerate container patching by eliminating waiting on base image dependency chains to update. This is a raison d’etre for the Copa project, so if we figured out a different way to patch containers that still relied on waiting for base images to be rebuilt and republished, we would consider spinning that off into a different project instead of making it part of Copa.

  • Copa is intended to work with the existing ecosystem of container images. The project should have a strong preference for solutions that do not require image producers to create or modify their images in special ways to use Copa.

  • Copa is intended to allow parties other than the image authors to address container vulnerabilities. Copa should require a minimum of special knowledge about the lineage and construction of an image from the user to patch it successfully.

  • Copa is intended to do one thing well and be composable with other tools and processes. Copa does not have to be a universal multitool for container patching. For example, it is preferable that it integrates with popular container scanning tools rather than incorporating custom container scanning into the project itself. Similarly, it does not need to become a general container manipulation tool in the vein of crane.

Design Reasoning

The design of copa arises from the application of those tenets to the observed issues in previous efforts directly update container images via rebasing, for example, the experimental crane rebase:

  • Rebasing requires that all actors involved in creation of the image are coordinated so that some layers can be switched out without breaking the image. Attempting to switch out layers in the container overlay structure is brittle because most existing containers are created by writing over shared configuration files and data stores in base images. For example, an apt install during image creation will overwrite the dpkg status file in the base image, which will mask any package updates in a rebased layer. Since many existing container scanners rely on the reported package status to find vulnerable package versions, this can cause new vulnerabilities to not be reported or for patched binaries not to be recognized by the scanners.

    To avoid breaking integration with the existing container ecosystem, copa patches the filesystem bundle as a whole instead of as a collection of layers so that the resulting image state is consistent. This strategy also allows copa to patch vulnerabilties introduced at any layer in the image, including OS packages added in the app layers that is not addressed by a simple rebase. It also supports the core tenet of supporting patching without requiring coordination with all the publishers of the base images that a given image transitively depends on.

  • Rebasing also requires that the user knows a priori what base image (or transitive base image) is in the target image to determine which appropriate rebase image to use. This makes it very difficult for anyone not intimately involved with authoring the image from being able to remediate it, which is one of our tenets.

    While it is possible to embed extra metadata or annotations into the target image to facilitate this base image (or transitive base image) lookup, that would require that the images to be patched be modified or created especially to support updates, which goes against another of our tenets to be able to patch images without requiring them to be customized explicitly for that purpose.

    The design of copa addresses this by reframing the problem of updating containers and understanding the structure or lineage of a container image to the more specific problem of what packages in a given container image need to be updated. This allows copa to tap into the expertise embedded in the much more robust ecosystem for detecting and remediating vulnerabilities at the package level that already exists today. By making copa an additional remediation step that can be run after a container scan in existing workflows, we avoid both of those issues with an additional benefit: it incurs no additional work on the part of base image publishers to support patching of images based on their base images, the existing channels for publishing update packages is sufficient to service those container images as well.

Architecture

The requirements presented encourage an extensible model in order to support broad applicability. Specifically, there are two areas that the tool will need to accommodate multiple implementations to support more use cases:

  • The data schema of various vulnerability scanners producing the input vulnerability report.
  • The state management of various package managers and process for applying patches appropriately through them.

Effectively, copa patch can be considered a command that bridges an extensible Parse action with an extensible Apply action as illustrated in the diagram; the implementation can be thought of as an engine that uses this abstract Go interface to apply security update packages:

type UpdatePackage struct {
Name string
Version string
}

type UpdateManifest struct {
OSType string
OSVersion string
Arch string
Updates []UpdatePackage
}

type ScanReportParser interface {
Parse(reportPath string) (*UpdateManifest, error)
}

type PackageManager interface {
Apply(imagePath string, report *UpdateManifest) error
}

Implementation

copa is a pseudo-frontend to buildkit implemented as a CLI tool. Effectively, instead of taking a container definition to create from scratch, it takes the reference to the target image to patch and a container scan report and builds a series of LLB graphs for buildkit to execute:

  1. Actions to probe the image as a filesystem bundle, for example, retrieving the package manager status in the image.
    • Within each distribution type identified by the scanner report (e.g. Debian) there can be different ways of applying patches to the target image (e.g. distroless), which can be differentiated through these actions.
  2. Actions to fetch and deploy tools that can be injected into the target image to perform the patching.
    • In cases where the package tools are not available in the target image, a standard version of the OS container matching the target image's is used to stage the necessary tooling for patches.
    • In the case of distroless images for example, where there is no valid package status file in the target image, the tooling container is also used to pull down and process the necessary package updates for copy to the target image.
    • Although not pictured, this can also be used to obtain tools (e.g. busybox) to be used in the image probing stage as well.
  3. Actions to deploy the required patch packages to the target image.
    • copa integrates with buildkit at the API level because it uses the diff and merge graph operations directly so that it can stage all the necessary tooling in the target image while producing a resulting image that only contains the original image plus a new layer with all the deployed patches.

Tradeoffs

  • The core architectural choice of relying on packages as the unit of patching creates a couple of constraints:
    • By relying on existing vulnerability scanner behavior that only detects vulnerabilities via presence/absence of vulnerable packages, copa is limited in the kinds of vulnerabilities it can address and false positive/negatives from scanners flow downstream to copa.
    • copa depends on individual package manager adapters to correctly deploy patches to the target images, but there is a long tail of compatibility issues that arise depending on the target image itself (e.g. outdated package manager config/keys, invalid/missing package graph, etc.). Overall, the maintenance cost of the project is expected to be non-trivial to address this.
  • No support for windows containers given the dependency on buildkit.
- + \ No newline at end of file diff --git a/website/faq.html b/website/faq.html index 986d9898..a2ac9f0e 100644 --- a/website/faq.html +++ b/website/faq.html @@ -7,13 +7,13 @@ - +
Version: v0.4.x

FAQ

What kind of vulnerabilities can Copa patch?

Copa is capable of patching "OS level" vulnerabilities. This includes packages (like openssl) in the image that are managed by a package manager such as apt or yum. Copa is not currently capable of patching vulnerabilities at the "application level" such as Python packages or Go modules.

- + \ No newline at end of file diff --git a/website/github-action.html b/website/github-action.html index 8eb557bb..462d7171 100644 --- a/website/github-action.html +++ b/website/github-action.html @@ -7,13 +7,13 @@ - +
Version: v0.4.x

Copa Github Action

Overview

The Copa Github Action allows you patch vulnerable containers in your workflows using Copa.

Inputs

image

Required The image reference to patch.

image-report

Required The trivy json vulnerability report of the image to patch.

patched-tag

Required The new patched image tag.

buildkit-version

Optional The buildkit version used in the action, default is latest.

copa-version

Optional The Copa version used in the action, default is latest.

Output

patched-image

Image reference of the resulting patched image.

Example Workflow

on: [push]

jobs:
test:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
# provide relevant list of images to scan on each run
images: ['docker.io/library/nginx:1.21.6', 'docker.io/openpolicyagent/opa:0.46.0', 'docker.io/library/hello-world:latest']

steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@dedd61cf5d839122591f5027c89bf3ad27691d18

- name: Generate Trivy Report
uses: aquasecurity/trivy-action@69cbbc0cbbf6a2b0bab8dcf0e9f2d7ead08e87e4
with:
scan-type: 'image'
format: 'json'
output: 'report.json'
ignore-unfixed: true
vuln-type: 'os'
image-ref: ${{ matrix.images }}

- name: Check Vuln Count
id: vuln_count
run: |
report_file="report.json"
vuln_count=$(jq '.Results | length' "$report_file")
echo "vuln_count=$vuln_count" >> $GITHUB_OUTPUT

- name: Copa Action
if: steps.vuln_count.outputs.vuln_count != '0'
id: copa
uses: project-copacetic/copa-action@v1
with:
image: ${{ matrix.images }}
image-report: 'report.json'
patched-tag: 'patched'
buildkit-version: 'v0.11.6'
# optional, default is latest
copa-version: '0.4.1'

- name: Login to Docker Hub
if: steps.copa.conclusion == 'success'
id: login
uses: docker/login-action@b4bedf8053341df3b5a9f9e0f2cf4e79e27360c6
with:
username: 'user'
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Docker Push Patched Image
if: steps.login.conclusion == 'success'
run: |
docker push ${{ steps.copa.outputs.patched-image }}

- + \ No newline at end of file diff --git a/website/index.html b/website/index.html index eb596f71..4ca15e25 100644 --- a/website/index.html +++ b/website/index.html @@ -7,13 +7,13 @@ - +
Version: v0.4.x

Project Copacetic: Directly patch container image vulnerabilities

copa is a CLI tool written in Go and based on buildkit that can be used to directly patch container images given the vulnerability scanning results from popular tools like Trivy.

Why?

We needed the ability to patch containers quickly without going upstream for a full rebuild. As the window between vulnerability disclosure and active exploitation continues to narrow, there is a growing operational need to patch critical security vulnerabilities in container images so they can be quickly redeployed into production. The need is especially acute when those vulnerabilities are:

  • inherited from base images several levels deep and waiting on updated releases to percolate through the supply chain is not an option
  • found in 3rd party app images you don't maintain with update cadences that don't meet your security SLAs.

In addition to filling the operational gap not met by left-shift security practices and tools, the ability of copa to patch a container without requiring a rebuild of the container image provides other benefits:

  • Allows users other than the image publishers to also patch container images, such as DevSecOps engineers.
  • Reduces the storage and transmission costs of redistributing patched images by only creating an additional patch layer, instead of rebuilding the entire image which usually results in different layer hashes that break layer caching.
  • Reduces the turnaround time for patching a container image by not having to wait for base image updates and being a faster operation than a full image rebuild.
  • Reduces the complexity of patching the image from running a rebuild pipeline to running a single tool on the image.

How?

The copa tool is an extensible engine that:

  1. Parses the needed update packages from the container image’s vulnerability report produced by a scanner like Trivy. New adapters can be written to accommodate more report formats.
  2. Obtains and processes the needed update packages using the appropriate package manager tools such as apt, apk, etc. New adapters can be written to support more package managers.
  3. Applies the resulting update binaries to the container image using buildkit.

This approach is motivated by the core principles of making direct container patching broadly applicable and accessible:

  • Copa supports patching existing container images.
    • Devs don't need to build their images using specific tools or modify them in some way just to support container patching.
  • Copa works with the existing vulnerability scanning and mitigation ecosystems.
    • Image publishers don't need to create new workflows for container patching since Copa supports patching container images using the security update packages already being published today.
    • Consumers do not need to migrate to a new and potentially more limited support ecosystem for custom distros or change their container vulnerability scanning pipelines to include remediation, since Copa can be integrated seamlessly as an extra step to patch containers based on those scanning reports.
  • Copa reduces the technical expertise needed and waiting on dependencies needed to patch an image.
    • For OS package vulnerabilities, no specialized knowledge about a specific image is needed to be patch it as Copa relies on the vulnerability remediation knowledge already embedded in the reports produced by popular container scanning tools today.

For more details, refer to the copa design documentation.

- + \ No newline at end of file diff --git a/website/installation.html b/website/installation.html index 5850b68f..43a3e43b 100644 --- a/website/installation.html +++ b/website/installation.html @@ -7,13 +7,13 @@ - +
Version: v0.4.x

Installation

Homebrew

On macOS and Linux, copa can be installed via Homebrew:

brew install copa

GitHub

You can download the latest and previous versions of copa from the GitHub releases page.

Development Setup

The following instructions are for Ubuntu 22.04 with the dependency versions supported as part of the dev container environment we use for builds and tests. For other distributions and OS, refer to the appropriate installation instructions for each of the components instead.

git clone https://github.com/project-copacetic/copacetic
cd copacetic
make
# OPTIONAL: install copa to a pathed folder
sudo mv dist/linux_amd64/release/copa /usr/local/bin/
- + \ No newline at end of file diff --git a/website/next.html b/website/next.html index effea783..aa01b6bb 100644 --- a/website/next.html +++ b/website/next.html @@ -7,13 +7,13 @@ - +
Version: Next

Project Copacetic: Directly patch container image vulnerabilities

copa is a CLI tool written in Go and based on buildkit that can be used to directly patch container images given the vulnerability scanning results from popular tools like Trivy.

Why?

We needed the ability to patch containers quickly without going upstream for a full rebuild. As the window between vulnerability disclosure and active exploitation continues to narrow, there is a growing operational need to patch critical security vulnerabilities in container images so they can be quickly redeployed into production. The need is especially acute when those vulnerabilities are:

  • inherited from base images several levels deep and waiting on updated releases to percolate through the supply chain is not an option
  • found in 3rd party app images you don't maintain with update cadences that don't meet your security SLAs.

In addition to filling the operational gap not met by left-shift security practices and tools, the ability of copa to patch a container without requiring a rebuild of the container image provides other benefits:

  • Allows users other than the image publishers to also patch container images, such as DevSecOps engineers.
  • Reduces the storage and transmission costs of redistributing patched images by only creating an additional patch layer, instead of rebuilding the entire image which usually results in different layer hashes that break layer caching.
  • Reduces the turnaround time for patching a container image by not having to wait for base image updates and being a faster operation than a full image rebuild.
  • Reduces the complexity of patching the image from running a rebuild pipeline to running a single tool on the image.

How?

The copa tool is an extensible engine that:

  1. Parses the needed update packages from the container image’s vulnerability report produced by a scanner like Trivy. New adapters can be written to accommodate more report formats.
  2. Obtains and processes the needed update packages using the appropriate package manager tools such as apt, apk, etc. New adapters can be written to support more package managers.
  3. Applies the resulting update binaries to the container image using buildkit.

This approach is motivated by the core principles of making direct container patching broadly applicable and accessible:

  • Copa supports patching existing container images.
    • Devs don't need to build their images using specific tools or modify them in some way just to support container patching.
  • Copa works with the existing vulnerability scanning and mitigation ecosystems.
    • Image publishers don't need to create new workflows for container patching since Copa supports patching container images using the security update packages already being published today.
    • Consumers do not need to migrate to a new and potentially more limited support ecosystem for custom distros or change their container vulnerability scanning pipelines to include remediation, since Copa can be integrated seamlessly as an extra step to patch containers based on those scanning reports.
  • Copa reduces the technical expertise needed and waiting on dependencies needed to patch an image.
    • For OS package vulnerabilities, no specialized knowledge about a specific image is needed to be patch it as Copa relies on the vulnerability remediation knowledge already embedded in the reports produced by popular container scanning tools today.

For more details, refer to the copa design documentation.

- + \ No newline at end of file diff --git a/website/next/code-of-conduct.html b/website/next/code-of-conduct.html index fc1f5c0a..2ce5945b 100644 --- a/website/next/code-of-conduct.html +++ b/website/next/code-of-conduct.html @@ -7,7 +7,7 @@ - + @@ -62,7 +62,7 @@ Mozilla's code of conduct enforcement ladder.

For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.

- + \ No newline at end of file diff --git a/website/next/contributing.html b/website/next/contributing.html index 0db4b5d2..dcfa293c 100644 --- a/website/next/contributing.html +++ b/website/next/contributing.html @@ -7,7 +7,7 @@ - + @@ -27,7 +27,7 @@ personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.

Contributors sign-off that they adhere to these requirements by adding a Signed-off-by line to commit messages.

This is my commit message

Signed-off-by: Random J Developer <random@developer.example.org>

Git even has a -s command line option to append this automatically to your commit message:

git commit -s -m 'This is my commit message'

Pull requests that do not contain a valid Signed-off-by line cannot be merged.

I didn't sign my commit, now what?

No worries - You can easily amend your commit with a sign-off and force push the change to your submitting branch:

git switch <branch-name>
git commit --amend --no-edit --signoff
git push --force-with-lease <remote-name> <branch-name>

Code of Conduct

This project has adopted the Contributor Covenant Code of Conduct.

- + \ No newline at end of file diff --git a/website/next/design.html b/website/next/design.html index 957fea05..c7c162e9 100644 --- a/website/next/design.html +++ b/website/next/design.html @@ -7,13 +7,13 @@ - +
Version: Next

Design

Design Tenets

  • Copa is intended to accelerate container patching by eliminating waiting on base image dependency chains to update. This is a raison d’etre for the Copa project, so if we figured out a different way to patch containers that still relied on waiting for base images to be rebuilt and republished, we would consider spinning that off into a different project instead of making it part of Copa.

  • Copa is intended to work with the existing ecosystem of container images. The project should have a strong preference for solutions that do not require image producers to create or modify their images in special ways to use Copa.

  • Copa is intended to allow parties other than the image authors to address container vulnerabilities. Copa should require a minimum of special knowledge about the lineage and construction of an image from the user to patch it successfully.

  • Copa is intended to do one thing well and be composable with other tools and processes. Copa does not have to be a universal multitool for container patching. For example, it is preferable that it integrates with popular container scanning tools rather than incorporating custom container scanning into the project itself. Similarly, it does not need to become a general container manipulation tool in the vein of crane.

Design Reasoning

The design of copa arises from the application of those tenets to the observed issues in previous efforts directly update container images via rebasing, for example, the experimental crane rebase:

  • Rebasing requires that all actors involved in creation of the image are coordinated so that some layers can be switched out without breaking the image. Attempting to switch out layers in the container overlay structure is brittle because most existing containers are created by writing over shared configuration files and data stores in base images. For example, an apt install during image creation will overwrite the dpkg status file in the base image, which will mask any package updates in a rebased layer. Since many existing container scanners rely on the reported package status to find vulnerable package versions, this can cause new vulnerabilities to not be reported or for patched binaries not to be recognized by the scanners.

    To avoid breaking integration with the existing container ecosystem, copa patches the filesystem bundle as a whole instead of as a collection of layers so that the resulting image state is consistent. This strategy also allows copa to patch vulnerabilties introduced at any layer in the image, including OS packages added in the app layers that is not addressed by a simple rebase. It also supports the core tenet of supporting patching without requiring coordination with all the publishers of the base images that a given image transitively depends on.

  • Rebasing also requires that the user knows a priori what base image (or transitive base image) is in the target image to determine which appropriate rebase image to use. This makes it very difficult for anyone not intimately involved with authoring the image from being able to remediate it, which is one of our tenets.

    While it is possible to embed extra metadata or annotations into the target image to facilitate this base image (or transitive base image) lookup, that would require that the images to be patched be modified or created especially to support updates, which goes against another of our tenets to be able to patch images without requiring them to be customized explicitly for that purpose.

    The design of copa addresses this by reframing the problem of updating containers and understanding the structure or lineage of a container image to the more specific problem of what packages in a given container image need to be updated. This allows copa to tap into the expertise embedded in the much more robust ecosystem for detecting and remediating vulnerabilities at the package level that already exists today. By making copa an additional remediation step that can be run after a container scan in existing workflows, we avoid both of those issues with an additional benefit: it incurs no additional work on the part of base image publishers to support patching of images based on their base images, the existing channels for publishing update packages is sufficient to service those container images as well.

Architecture

The requirements presented encourage an extensible model in order to support broad applicability. Specifically, there are two areas that the tool will need to accommodate multiple implementations to support more use cases:

  • The data schema of various vulnerability scanners producing the input vulnerability report.
  • The state management of various package managers and process for applying patches appropriately through them.

Effectively, copa patch can be considered a command that bridges an extensible Parse action with an extensible Apply action as illustrated in the diagram; the implementation can be thought of as an engine that uses this abstract Go interface to apply security update packages:

type UpdatePackage struct {
Name string
Version string
}

type UpdateManifest struct {
OSType string
OSVersion string
Arch string
Updates []UpdatePackage
}

type ScanReportParser interface {
Parse(reportPath string) (*UpdateManifest, error)
}

type PackageManager interface {
Apply(imagePath string, report *UpdateManifest) error
}

Implementation

copa is a pseudo-frontend to buildkit implemented as a CLI tool. Effectively, instead of taking a container definition to create from scratch, it takes the reference to the target image to patch and a container scan report and builds a series of LLB graphs for buildkit to execute:

  1. Actions to probe the image as a filesystem bundle, for example, retrieving the package manager status in the image.
    • Within each distribution type identified by the scanner report (e.g. Debian) there can be different ways of applying patches to the target image (e.g. distroless), which can be differentiated through these actions.
  2. Actions to fetch and deploy tools that can be injected into the target image to perform the patching.
    • In cases where the package tools are not available in the target image, a standard version of the OS container matching the target image's is used to stage the necessary tooling for patches.
    • In the case of distroless images for example, where there is no valid package status file in the target image, the tooling container is also used to pull down and process the necessary package updates for copy to the target image.
    • Although not pictured, this can also be used to obtain tools (e.g. busybox) to be used in the image probing stage as well.
  3. Actions to deploy the required patch packages to the target image.
    • copa integrates with buildkit at the API level because it uses the diff and merge graph operations directly so that it can stage all the necessary tooling in the target image while producing a resulting image that only contains the original image plus a new layer with all the deployed patches.

Tradeoffs

  • The core architectural choice of relying on packages as the unit of patching creates a couple of constraints:
    • By relying on existing vulnerability scanner behavior that only detects vulnerabilities via presence/absence of vulnerable packages, copa is limited in the kinds of vulnerabilities it can address and false positive/negatives from scanners flow downstream to copa.
    • copa depends on individual package manager adapters to correctly deploy patches to the target images, but there is a long tail of compatibility issues that arise depending on the target image itself (e.g. outdated package manager config/keys, invalid/missing package graph, etc.). Overall, the maintenance cost of the project is expected to be non-trivial to address this.
  • No support for windows containers given the dependency on buildkit.
- + \ No newline at end of file diff --git a/website/next/faq.html b/website/next/faq.html index 251fc445..950b137c 100644 --- a/website/next/faq.html +++ b/website/next/faq.html @@ -7,13 +7,13 @@ - +
-
Version: Next

FAQ

What kind of vulnerabilities can Copa patch?

Copa is capable of patching "OS level" vulnerabilities. This includes packages (like openssl) in the image that are managed by a package manager such as apt or yum. Copa is not currently capable of patching vulnerabilities at the "application level" such as Python packages or Go modules.

Can I replace the package repositories in the image with my own?

caution

Experimental: This feature might change without preserving backwards compatibility.

Copa does not support replacing the repositories in the package managers with alternatives. Images must already use the intended package repositories. For example, for debian, updating /etc/apt/sources.list from http://archive.ubuntu.com/ubuntu/ to a mirror, such as https://mirrors.wikimedia.org/ubuntu/.

If you need the tooling image to use a different package repository, you can create a source policy to define a replacement image and/or pin to a digest. For example, the following source policy replaces docker.io/library/debian:11-slim image with foo.io/bar/baz:latest@sha256:42d3e6bc186572245aded5a0be381012adba6d89355fa9486dd81b0c634695b5:

cat <<EOF > source-policy.json
{
"rules": [
{
"action": "CONVERT",
"selector": {
"identifier": "docker-image://docker.io/library/debian:11-slim"
},
"updates": {
"identifier": "docker-image://foo.io/bar/baz:latest@sha256:42d3e6bc186572245aded5a0be381012adba6d89355fa9486dd81b0c634695b5"
}
}
]
}
EOF

export EXPERIMENTAL_BUILDKIT_SOURCE_POLICY=source-policy.json

Tooling image for Debian-based images are docker.io/library/debian:11-slim and RPM-based repos are mcr.microsoft.com/cbl-mariner/base/core:2.0.

For more information on source policies, see Buildkit Source Policies.

- +
Version: Next

FAQ

What kind of vulnerabilities can Copa patch?

Copa is capable of patching "OS level" vulnerabilities. This includes packages (like openssl) in the image that are managed by a package manager such as apt or yum. Copa is not currently capable of patching vulnerabilities at the "application level" such as Python packages or Go modules (see below for more details).

What kind of vulnerabilities can Copa not patch?

Copa is not capable of patching vulnerabilities for compiled languages, like Go, at the "application level", for instance, Go modules. If your application uses a vulnerable version of the golang.org/x/net module, Copa will be unable to patch it. This is because Copa doesn't have access to the application's source code or the knowledge of how to build it, such as compiler flags, preventing it from patching vulnerabilities at the application level.

To patch vulnerabilities for applications, you can package these applications and consume them from package repositories, like http://archive.ubuntu.com/ubuntu/ for Ubuntu, and ensure Trivy can scan and report vulnerabilities for these packages. This way, Copa can patch the applications as a whole, though it cannot patch specific modules within the applications.

Can I replace the package repositories in the image with my own?

caution

Experimental: This feature might change without preserving backwards compatibility.

Copa does not support replacing the repositories in the package managers with alternatives. Images must already use the intended package repositories. For example, for debian, updating /etc/apt/sources.list from http://archive.ubuntu.com/ubuntu/ to a mirror, such as https://mirrors.wikimedia.org/ubuntu/.

If you need the tooling image to use a different package repository, you can create a source policy to define a replacement image and/or pin to a digest. For example, the following source policy replaces docker.io/library/debian:11-slim image with foo.io/bar/baz:latest@sha256:42d3e6bc186572245aded5a0be381012adba6d89355fa9486dd81b0c634695b5:

cat <<EOF > source-policy.json
{
"rules": [
{
"action": "CONVERT",
"selector": {
"identifier": "docker-image://docker.io/library/debian:11-slim"
},
"updates": {
"identifier": "docker-image://foo.io/bar/baz:latest@sha256:42d3e6bc186572245aded5a0be381012adba6d89355fa9486dd81b0c634695b5"
}
}
]
}
EOF

export EXPERIMENTAL_BUILDKIT_SOURCE_POLICY=source-policy.json

Tooling image for Debian-based images are docker.io/library/debian:11-slim and RPM-based repos are mcr.microsoft.com/cbl-mariner/base/core:2.0.

For more information on source policies, see Buildkit Source Policies.

+ \ No newline at end of file diff --git a/website/next/github-action.html b/website/next/github-action.html index 05261aaa..8b1a56f8 100644 --- a/website/next/github-action.html +++ b/website/next/github-action.html @@ -7,13 +7,13 @@ - +
Version: Next

Copa Github Action

Overview

The Copa Github Action allows you patch vulnerable containers in your workflows using Copa.

Inputs

image

Required The image reference to patch.

image-report

Required The trivy json vulnerability report of the image to patch.

patched-tag

Required The new patched image tag.

buildkit-version

Optional The buildkit version used in the action, default is latest.

copa-version

Optional The Copa version used in the action, default is latest.

Output

patched-image

Image reference of the resulting patched image.

Example Workflow

on: [push]

jobs:
test:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
# provide relevant list of images to scan on each run
images: ['docker.io/library/nginx:1.21.6', 'docker.io/openpolicyagent/opa:0.46.0', 'docker.io/library/hello-world:latest']

steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@dedd61cf5d839122591f5027c89bf3ad27691d18

- name: Generate Trivy Report
uses: aquasecurity/trivy-action@69cbbc0cbbf6a2b0bab8dcf0e9f2d7ead08e87e4
with:
scan-type: 'image'
format: 'json'
output: 'report.json'
ignore-unfixed: true
vuln-type: 'os'
image-ref: ${{ matrix.images }}

- name: Check Vuln Count
id: vuln_count
run: |
report_file="report.json"
vuln_count=$(jq '.Results | length' "$report_file")
echo "vuln_count=$vuln_count" >> $GITHUB_OUTPUT

- name: Copa Action
if: steps.vuln_count.outputs.vuln_count != '0'
id: copa
uses: project-copacetic/copa-action@v1
with:
image: ${{ matrix.images }}
image-report: 'report.json'
patched-tag: 'patched'
buildkit-version: 'v0.11.6'
# optional, default is latest
copa-version: '0.4.1'

- name: Login to Docker Hub
if: steps.copa.conclusion == 'success'
id: login
uses: docker/login-action@b4bedf8053341df3b5a9f9e0f2cf4e79e27360c6
with:
username: 'user'
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Docker Push Patched Image
if: steps.login.conclusion == 'success'
run: |
docker push ${{ steps.copa.outputs.patched-image }}

- + \ No newline at end of file diff --git a/website/next/installation.html b/website/next/installation.html index e440ca25..df73af72 100644 --- a/website/next/installation.html +++ b/website/next/installation.html @@ -7,13 +7,13 @@ - +
Version: Next

Installation

Homebrew

On macOS and Linux, copa can be installed via Homebrew:

brew install copa

GitHub

You can download the latest and previous versions of copa from the GitHub releases page.

Development Setup

The following instructions are for Ubuntu 22.04 with the dependency versions supported as part of the dev container environment we use for builds and tests. For other distributions and OS, refer to the appropriate installation instructions for each of the components instead.

git clone https://github.com/project-copacetic/copacetic
cd copacetic
make
# OPTIONAL: install copa to a pathed folder
sudo mv dist/linux_amd64/release/copa /usr/local/bin/
- + \ No newline at end of file diff --git a/website/next/output.html b/website/next/output.html index 01ac4af9..4f609d16 100644 --- a/website/next/output.html +++ b/website/next/output.html @@ -7,13 +7,13 @@ - +
Version: Next

Output

caution

Experimental: This feature might change without preserving backwards compatibility.

Copa optionally outputs a Vulnerability Exploitability eXchange (VEX) file as a result of the patching process to surface the vulnerabilities and packages that were patched.

Currently, Copa supports the OpenVEX format, but it can be extended to support other formats.

OpenVEX

OpenVEX is an implementation of Vulnerability Exploitability eXchange (VEX) format. For more information, see OpenVEX specification.

tip
  • Use COPA_VEX_AUTHOR environment variable to set the author of the VEX document. If it's not set, the author will default to Project Copacetic.

  • A VEX document must contain at least one VEX statement. If there are no fixed vulnerabilities, Copa will not generate a VEX document.

To generate a VEX document using OpenVEX, use --format="openvex" flag, and use --output to specify a file path. For example:

copa patch -i docker.io/library/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched --format="openvex" --output "nginx.1.21.6-vex.json"

This will generate a VEX Document that looks like:

{
"@context": "https://openvex.dev/ns",
"@id": "https://openvex.dev/docs/public/vex-6f15c26e0410a4d44e0af4062f4b883fbc19a98e57baf131715d942213e5002a",
"author": "Project Copacetic",
"timestamp": "2023-08-25T21:40:23.891230545Z",
"version": 1,
"tooling": "Project Copacetic",
"statements": [
{
"vulnerability": {
"@id": "CVE-2021-3995"
},
"products": [
{
"@id": "pkg:deb/debian/bsdutils@1:2.36.1-8?arch=amd64"
},
{
"@id": "pkg:deb/debian/libblkid1@2.36.1-8?arch=amd64"
},
{
"@id": "pkg:deb/debian/libmount1@2.36.1-8?arch=amd64"
},
{
"@id": "pkg:deb/debian/libsmartcols1@2.36.1-8?arch=amd64"
},
{
"@id": "pkg:deb/debian/libuuid1@2.36.1-8?arch=amd64"
},
{
"@id": "pkg:deb/debian/mount@2.36.1-8?arch=amd64"
},
{
"@id": "pkg:deb/debian/util-linux@2.36.1-8?arch=amd64"
}
],
"status": "fixed"
},
...
}
- + \ No newline at end of file diff --git a/website/next/quick-start.html b/website/next/quick-start.html index 89185ff1..a19ae8d2 100644 --- a/website/next/quick-start.html +++ b/website/next/quick-start.html @@ -7,7 +7,7 @@ - + @@ -16,7 +16,7 @@ You may need to specify a custom address using the --addr flag. Here are the supported formats:

  • unix:///path/to/buildkit.sock - Connect to buildkit over unix socket.
  • tcp://$BUILDKIT_ADDR:$PORT - Connect to buildkit over TCP. (not recommended for security reasons)
  • docker://<docker connection spec> - Connect to docker, currently only unix sockets are supported, e.g. docker://unix:///var/run/docker.sock (or just docker://).
  • docker-container://my-buildkit-container - Connect to a buildkitd running in a docker container.
  • buildx://my-builder - Connect to a buildx builder (or buildx:// for the currently selected builder). Note: only container-backed buildx instances are currently supported
  • nerdctl-container://my-container-name - Similar to docker-container but uses nerdctl.
  • podman-container://my-container-name - Similar to docker-container but uses podman.
  • ssh://myhost - Connect to a buildkit instance over SSH. Format of the host spec should mimic the SSH command.
  • kubepod://mypod - Connect to buildkit running in a Kubernetes pod. Can also specify kubectl context and pod namespace (kubepod://mypod?context=foo&namespace=notdefault).

Buildkit Connection Examples

Example: Connect using defaults:

copa patch -i docker.io/library/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched

Example: Connect to buildx

docker buildx create --name demo
copa patch -i docker.io/library/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched --addr buildx://demo

Example: Buildkit in a container

export BUILDKIT_VERSION=v0.12.0
docker run \
--detach \
--rm \
--privileged \
--name buildkitd \
--entrypoint buildkitd \
"moby/buildkit:$BUILDKIT_VERSION"

copa patch -i docker.io/library/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched --addr docker-container://buildkitd

Example: Buildkit over TCP

export BUILDKIT_VERSION=v0.12.0
export BUILDKIT_PORT=8888
docker run \
--detach \
--rm \
--privileged \
-p 127.0.0.1:$BUILDKIT_PORT:$BUILDKIT_PORT/tcp \
--name buildkitd \
--entrypoint buildkitd \
"moby/buildkit:$BUILDKIT_VERSION" \
--addr tcp://0.0.0.0:$BUILDKIT_PORT
copa patch \
-i docker.io/library/nginx:1.21.6 \
-r nginx.1.21.6.json \
-t 1.21.6-patched \
-a tcp://0.0.0.0:$BUILDKIT_PORT

In either case, copa is non-destructive and exports a new image with the specified 1.21.6-patched label to the local Docker daemon.

NOTE: if you're running this sample against an image from a private registry instead, ensure that the credentials are configured in the default Docker config.json before running copa patch, for example, via sudo docker login -u <user> -p <password> <registry>.

  • Scan the patched image and verify that the vulnerabilities have been patched:

    trivy image --vuln-type os --ignore-unfixed docker.io/library/nginx:1.21.6-patched

    You can also inspect the structure of the patched image with docker history to see the new patch layer appended to the image:

    $ docker history docker.io/library/nginx:1.21.6-patched
    IMAGE CREATED CREATED BY SIZE COMMENT
    a372df41e06d 1 minute ago mount / from exec sh -c apt install --no-ins… 26.1MB buildkit.exporter.image.v0
    <missing> 3 months ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
    <missing> 3 months ago STOPSIGNAL SIGQUIT 0B buildkit.dockerfile.v0
    <missing> 3 months ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
    <missing> 3 months ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B buildkit.dockerfile.v0
    <missing> 3 months ago COPY 30-tune-worker-processes.sh /docker-ent… 4.61kB buildkit.dockerfile.v0
    <missing> 3 months ago COPY 20-envsubst-on-templates.sh /docker-ent… 1.04kB buildkit.dockerfile.v0
    <missing> 3 months ago COPY 10-listen-on-ipv6-by-default.sh /docker… 1.96kB buildkit.dockerfile.v0
    <missing> 3 months ago COPY docker-entrypoint.sh / # buildkit 1.2kB buildkit.dockerfile.v0
    <missing> 3 months ago RUN /bin/sh -c set -x && addgroup --syst… 61.1MB buildkit.dockerfile.v0
    <missing> 3 months ago ENV PKG_RELEASE=1~bullseye 0B buildkit.dockerfile.v0
    <missing> 3 months ago ENV NJS_VERSION=0.7.0 0B buildkit.dockerfile.v0
    <missing> 3 months ago ENV NGINX_VERSION=1.20.2 0B buildkit.dockerfile.v0
    <missing> 3 months ago LABEL maintainer=NGINX Docker Maintainers <d… 0B buildkit.dockerfile.v0
    <missing> 4 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
    <missing> 4 months ago /bin/sh -c #(nop) ADD file:09675d11695f65c55… 80.4MB
  • Run the container to verify that the image has no regressions:

    $ docker run -it --rm --name nginx-test docker.io/library/nginx:1.21.6-patched
    /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
    /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
    /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
    10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
    10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
    /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
    /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
    /docker-entrypoint.sh: Configuration complete; ready for start up
    2022/05/16 18:00:17 [notice] 1#1: using the "epoll" event method
    2022/05/16 18:00:17 [notice] 1#1: nginx/1.20.2
    2022/05/16 18:00:17 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
    2022/05/16 18:00:17 [notice] 1#1: OS: Linux 5.10.102.1-microsoft-standard-WSL2
    2022/05/16 18:00:17 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
    2022/05/16 18:00:17 [notice] 1#1: start worker processes
    2022/05/16 18:00:17 [notice] 1#1: start worker process 31
    2022/05/16 18:00:17 [notice] 1#1: start worker process 32
    2022/05/16 18:00:17 [notice] 1#1: start worker process 33
    2022/05/16 18:00:17 [notice] 1#1: start worker process 34
    2022/05/16 18:00:17 [notice] 1#1: start worker process 35
    2022/05/16 18:00:17 [notice] 1#1: start worker process 36
    2022/05/16 18:00:17 [notice] 1#1: start worker process 37
    2022/05/16 18:00:17 [notice] 1#1: start worker process 38
    2022/05/16 18:00:17 [notice] 38#38: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 36#36: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 33#33: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 32#32: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 34#34: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 35#35: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 37#37: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 1#1: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 31#31: signal 28 (SIGWINCH) received

    You can stop the container by opening a new shell instance and running: docker stop nginx-test

  • - + \ No newline at end of file diff --git a/website/next/release.html b/website/next/release.html index 748ae50d..200cae93 100644 --- a/website/next/release.html +++ b/website/next/release.html @@ -7,13 +7,13 @@ - +
    Version: Next

    Release Process

    Overview

    The release process for Copacetic uses GoReleaser.

    Once you are ready to cut a new release, checkout the release branch and tag it with the respective version.

    ```
    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
    ```

    Publishing

    1. GoReleaser will create a new release, review and edit it at https://github.com/project-copacetic/copacetic/releases
    2. Review the respective copa-action image at: https://github.com/orgs/project-copacetic/packages/container/package/copa-action
    - + \ No newline at end of file diff --git a/website/next/troubleshooting.html b/website/next/troubleshooting.html index 4c0ffae8..479508de 100644 --- a/website/next/troubleshooting.html +++ b/website/next/troubleshooting.html @@ -7,13 +7,13 @@ - +
    Version: Next

    Troubleshooting

    Filtering Vulnerabilities

    You might want to filter/ignore some of the vulnerabilities while patching. To do so, you need to first filter those undesired vulnerabilities from your scanner output.

    For Trivy, vulnerabilities can be filtered by the following 2 ways:

    Rego Policy

    An example rego file which demonstrates how to ignore certain Vulnerability IDs or Package Names:

    $ cat trivy_ignore.rego

    package trivy

    import data.lib.trivy

    default ignore = false


    # Ignore the following Vulnerability IDs
    ignore_vulnerability_ids := {
    "CVE-2018-14618"
    }
    # Ignore the following Package Names
    ignore_pkgs := {"bash", "vim"}


    # For ignoring vulnID
    ignore {
    input.VulnerabilityID == ignore_vulnerability_ids[_]
    }
    # For ignoring pkgName
    ignore {
    input.PkgName == ignore_pkgs[_]
    }

    After adding the above rego file, run the image scan with the --ignore-policy flag followed by the file name to ignore them while scanning:

    trivy image --ignore-policy trivy_ignore.rego ruby:2.4.0

    In the above example, the vulnerability "CVE-2018-14618" and the packages "bash" & "vim" are ignored while scanning, and hence patching the image.

    Ignore File

    Use a .trivyignore file to list all the vulnerabilities you want to ignore.

    Example:

    $ cat .trivyignore

    # Accept the risk
    CVE-2018-14618

    In the above example, the vulnerability CVE-2018-14618 is ignored while scanning, and hence while patching the image.

    For a more detailed explanation on how to ignore certain vulnerabilities with Trivy, please refer to the official documentation here.

    - + \ No newline at end of file diff --git a/website/quick-start.html b/website/quick-start.html index 214a2741..d7360f86 100644 --- a/website/quick-start.html +++ b/website/quick-start.html @@ -7,7 +7,7 @@ - + @@ -16,7 +16,7 @@ You may need to specify a custom address using the --addr flag. Here are the supported formats:

    • unix:///path/to/buildkit.sock - Connect to buildkit over unix socket.
    • tcp://$BUILDKIT_ADDR:$PORT - Connec to buildkit over TCP. (not recommended for security reasons)
    • docker://<docker connection spec> - Connect to docker, currently only unix sockets are supported, e.g. docker://unix:///var/run/docker.sock (or just docker://).
    • docker-container://my-buildkit-container - Connect to a buildkitd running in a docker container.
    • buildx://my-builder - Connect to a buildx builder (or buildx:// for the currently selected builder). Note: only container-backed buildx instances are currently supported
    • nerdctl-container://my-container-name - Similar to docker-container but uses nerdctl.
    • podman-container://my-container-name - Similar to docker-container but uses podman.
    • ssh://myhost - Connect to a buildkit instance over SSH. Format of the host spec should mimic the SSH command.
    • kubepod://mypod - Connect to buildkit running in a Kubernetes pod. Can also specify kubectl context and pod namespace (kubepod://mypod?context=foo&namespace=notdefault).

    Buildkit Connection Examples

    Example: Connect using defaults:

    copa patch -i mcr.microsoft.com/oss/nginx/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched

    Example: Connect to buildx

    docker buildx create --name demo
    copa patch -i mcr.microsoft.com/oss/nginx/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched --addr buildx://demo

    Example: Buildkit in a container

    export BUILDKIT_VERSION=v0.12.0
    docker run \
    --detach \
    --rm \
    --privileged \
    --name buildkitd \
    --entrypoint buildkitd \
    "moby/buildkit:$BUILDKIT_VERSION"

    copa patch -i mcr.microsoft.com/oss/nginx/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched --addr docker-container://buildkitd

    Example: Buildkit over TCP

    export BUILDKIT_VERSION=v0.12.0
    export BUILDKIT_PORT=8888
    docker run \
    --detach \
    --rm \
    --privileged \
    -p 127.0.0.1:$BUILDKIT_PORT:$BUILDKIT_PORT/tcp \
    --name buildkitd \
    --entrypoint buildkitd \
    "moby/buildkit:$BUILDKIT_VERSION" \
    --addr tcp://0.0.0.0:$BUILDKIT_PORT
    copa patch \
    -i mcr.microsoft.com/oss/nginx/nginx:1.21.6 \
    -r nginx.1.21.6.json \
    -t 1.21.6-patched \
    -a tcp://0.0.0.0:$BUILDKIT_PORT

    In either case, copa is non-destructive and exports a new image with the specified 1.21.6-patched label to the local Docker daemon.

    NOTE: if you're running this sample against an image from a private registry instead, ensure that the credentials are configured in the default Docker config.json before running copa patch, for example, via sudo docker login -u <user> -p <password> <registry>.

  • Scan the patched image and verify that the vulnerabilities have been patched:

    trivy image --vuln-type os --ignore-unfixed mcr.microsoft.com/oss/nginx/nginx:1.21.6-patched

    You can also inspect the structure of the patched image with docker history to see the new patch layer appended to the image:

    $ docker history mcr.microsoft.com/oss/nginx/nginx:1.21.6-patched
    IMAGE CREATED CREATED BY SIZE COMMENT
    a372df41e06d 1 minute ago mount / from exec sh -c apt install --no-ins… 26.1MB buildkit.exporter.image.v0
    <missing> 3 months ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
    <missing> 3 months ago STOPSIGNAL SIGQUIT 0B buildkit.dockerfile.v0
    <missing> 3 months ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
    <missing> 3 months ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B buildkit.dockerfile.v0
    <missing> 3 months ago COPY 30-tune-worker-processes.sh /docker-ent… 4.61kB buildkit.dockerfile.v0
    <missing> 3 months ago COPY 20-envsubst-on-templates.sh /docker-ent… 1.04kB buildkit.dockerfile.v0
    <missing> 3 months ago COPY 10-listen-on-ipv6-by-default.sh /docker… 1.96kB buildkit.dockerfile.v0
    <missing> 3 months ago COPY docker-entrypoint.sh / # buildkit 1.2kB buildkit.dockerfile.v0
    <missing> 3 months ago RUN /bin/sh -c set -x && addgroup --syst… 61.1MB buildkit.dockerfile.v0
    <missing> 3 months ago ENV PKG_RELEASE=1~bullseye 0B buildkit.dockerfile.v0
    <missing> 3 months ago ENV NJS_VERSION=0.7.0 0B buildkit.dockerfile.v0
    <missing> 3 months ago ENV NGINX_VERSION=1.20.2 0B buildkit.dockerfile.v0
    <missing> 3 months ago LABEL maintainer=NGINX Docker Maintainers <d… 0B buildkit.dockerfile.v0
    <missing> 4 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
    <missing> 4 months ago /bin/sh -c #(nop) ADD file:09675d11695f65c55… 80.4MB
  • Run the container to verify that the image has no regressions:

    $ docker run -it --rm --name nginx-test mcr.microsoft.com/oss/nginx/nginx:1.21.6-patched
    /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
    /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
    /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
    10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
    10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
    /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
    /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
    /docker-entrypoint.sh: Configuration complete; ready for start up
    2022/05/16 18:00:17 [notice] 1#1: using the "epoll" event method
    2022/05/16 18:00:17 [notice] 1#1: nginx/1.20.2
    2022/05/16 18:00:17 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
    2022/05/16 18:00:17 [notice] 1#1: OS: Linux 5.10.102.1-microsoft-standard-WSL2
    2022/05/16 18:00:17 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
    2022/05/16 18:00:17 [notice] 1#1: start worker processes
    2022/05/16 18:00:17 [notice] 1#1: start worker process 31
    2022/05/16 18:00:17 [notice] 1#1: start worker process 32
    2022/05/16 18:00:17 [notice] 1#1: start worker process 33
    2022/05/16 18:00:17 [notice] 1#1: start worker process 34
    2022/05/16 18:00:17 [notice] 1#1: start worker process 35
    2022/05/16 18:00:17 [notice] 1#1: start worker process 36
    2022/05/16 18:00:17 [notice] 1#1: start worker process 37
    2022/05/16 18:00:17 [notice] 1#1: start worker process 38
    2022/05/16 18:00:17 [notice] 38#38: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 36#36: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 33#33: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 32#32: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 34#34: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 35#35: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 37#37: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 1#1: signal 28 (SIGWINCH) received
    2022/05/16 18:00:17 [notice] 31#31: signal 28 (SIGWINCH) received

    You can stop the container by opening a new shell instance and running: docker stop nginx-test

  • - + \ No newline at end of file diff --git a/website/release.html b/website/release.html index 8ba4b074..4bc6c941 100644 --- a/website/release.html +++ b/website/release.html @@ -7,13 +7,13 @@ - +
    Version: v0.4.x

    Release Process

    Overview

    The release process for Copacetic uses GoReleaser.

    Once you are ready to cut a new release, checkout the release branch and tag it with the respective version.

    ```
    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
    ```

    Publishing

    1. GoReleaser will create a new release, review and edit it at https://github.com/project-copacetic/copacetic/releases
    2. Review the respective copa-action image at: https://github.com/orgs/project-copacetic/packages/container/package/copa-action
    - + \ No newline at end of file diff --git a/website/troubleshooting.html b/website/troubleshooting.html index da0ccadc..340690d1 100644 --- a/website/troubleshooting.html +++ b/website/troubleshooting.html @@ -7,13 +7,13 @@ - +
    Version: v0.4.x

    Troubleshooting

    Filtering Vulnerabilities

    You might want to filter/ignore some of the vulnerabilities while patching. To do so, you need to first filter those undesired vulnerabilities from your scanner output.

    For Trivy, vulnerabilities can be filtered by the following 2 ways:

    Rego Policy

    An example rego file which demonstrates how to ignore certain Vulnerability IDs or Package Names:

    $ cat trivy_ignore.rego

    package trivy

    import data.lib.trivy

    default ignore = false


    # Ignore the following Vulnerability IDs
    ignore_vulnerability_ids := {
    "CVE-2018-14618"
    }
    # Ignore the following Package Names
    ignore_pkgs := {"bash", "vim"}


    # For ignoring vulnID
    ignore {
    input.VulnerabilityID == ignore_vulnerability_ids[_]
    }
    # For ignoring pkgName
    ignore {
    input.PkgName == ignore_pkgs[_]
    }

    After adding the above rego file, run the image scan with the --ignore-policy flag followed by the file name to ignore them while scanning:

    trivy image --ignore-policy trivy_ignore.rego ruby:2.4.0

    In the above example, the vulnerability "CVE-2018-14618" and the packages "bash" & "vim" are ignored while scanning, and hence patching the image.

    Ignore File

    Use a .trivyignore file to list all the vulnerabilities you want to ignore.

    Example:

    $ cat .trivyignore

    # Accept the risk
    CVE-2018-14618

    In the above example, the vulnerability CVE-2018-14618 is ignored while scanning, and hence while patching the image.

    For a more detailed explanation on how to ignore certain vulnerabilities with Trivy, please refer to the official documentation here.

    - + \ No newline at end of file diff --git a/website/v0.1.x.html b/website/v0.1.x.html index 89b21cd3..85ec8d27 100644 --- a/website/v0.1.x.html +++ b/website/v0.1.x.html @@ -7,13 +7,13 @@ - +
    Version: v0.1.x

    Project Copacetic: Directly patch container image vulnerabilities

    copa is a CLI tool written in Go and based on buildkit that can be used to directly patch container images given the vulnerability scanning results from popular tools like Trivy.

    Why?

    We needed the ability to patch containers quickly without going upstream for a full rebuild. As the window between vulnerability disclosure and active exploitation continues to narrow, there is a growing operational need to patch critical security vulnerabilities in container images so they can be quickly redeployed into production. The need is especially acute when those vulnerabilities are:

    • inherited from base images several levels deep and waiting on updated releases to percolate through the supply chain is not an option
    • found in 3rd party app images you don't maintain with update cadences that don't meet your security SLAs.

    In addition to filling the operational gap not met by left-shift security practices and tools, the ability of copa to patch a container without requiring a rebuild of the container image provides other benefits:

    • Allows users other than the image publishers to also patch container images, such as DevSecOps engineers.
    • Reduces the storage and transmission costs of redistributing patched images by only creating an additional patch layer, instead of rebuilding the entire image which usually results in different layer hashes that break layer caching.
    • Reduces the turnaround time for patching a container image by not having to wait for base image updates and being a faster operation than a full image rebuild.
    • Reduces the complexity of patching the image from running a rebuild pipeline to running a single tool on the image.

    How?

    The copa tool is an extensible engine that:

    1. Parses the needed update packages from the container image’s vulnerability report produced by a scanner like Trivy. New adapters can be written to accommodate more report formats.
    2. Obtains and processes the needed update packages using the appropriate package manager tools such as apt, apk, etc. New adapters can be written to support more package managers.
    3. Applies the resulting update binaries to the container image using buildkit.

    This approach is motivated by the core principles of making direct container patching broadly applicable and accessible:

    • Copa supports patching existing container images.
      • Devs don't need to build their images using specific tools or modify them in some way just to support container patching.
    • Copa works with the existing vulnerability scanning and mitigation ecosystems.
      • Image publishers don't need to create new workflows for container patching since Copa supports patching container images using the security update packages already being published today.
      • Consumers do not need to migrate to a new and potentially more limited support ecosystem for custom distros or change their container vulnerability scanning pipelines to include remediation, since Copa can be integrated seamlessly as an extra step to patch containers based on those scanning reports.
    • Copa reduces the technical expertise needed and waiting on dependencies needed to patch an image.
      • For OS package vulnerabilities, no specialized knowledge about a specific image is needed to be patch it as Copa relies on the vulnerability remediation knowledge already embedded in the reports produced by popular container scanning tools today.

    For more details, refer to the copa design documentation.

    - + \ No newline at end of file diff --git a/website/v0.1.x/code-of-conduct.html b/website/v0.1.x/code-of-conduct.html index fe176072..f28aeb41 100644 --- a/website/v0.1.x/code-of-conduct.html +++ b/website/v0.1.x/code-of-conduct.html @@ -7,7 +7,7 @@ - + @@ -62,7 +62,7 @@ Mozilla's code of conduct enforcement ladder.

    For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.

    - + \ No newline at end of file diff --git a/website/v0.1.x/contributing.html b/website/v0.1.x/contributing.html index e696d0a3..5d718cb1 100644 --- a/website/v0.1.x/contributing.html +++ b/website/v0.1.x/contributing.html @@ -7,7 +7,7 @@ - + @@ -27,7 +27,7 @@ personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.

    Contributors sign-off that they adhere to these requirements by adding a Signed-off-by line to commit messages.

    This is my commit message

    Signed-off-by: Random J Developer <random@developer.example.org>

    Git even has a -s command line option to append this automatically to your commit message:

    git commit -s -m 'This is my commit message'

    Pull requests that do not contain a valid Signed-off-by line cannot be merged.

    I didn't sign my commit, now what?

    No worries - You can easily amend your commit with a sign-off and force push the change to your submitting branch:

    git switch <branch-name>
    git commit --amend --no-edit --signoff
    git push --force-with-lease <remote-name> <branch-name>

    Code of Conduct

    This project has adopted the Contributor Covenant Code of Conduct.

    - + \ No newline at end of file diff --git a/website/v0.1.x/design.html b/website/v0.1.x/design.html index 68e5b66a..bc0ac83a 100644 --- a/website/v0.1.x/design.html +++ b/website/v0.1.x/design.html @@ -7,13 +7,13 @@ - +
    Version: v0.1.x

    Design

    Design Tenets

    • Copa is intended to accelerate container patching by eliminating waiting on base image dependency chains to update. This is a raison d’etre for the Copa project, so if we figured out a different way to patch containers that still relied on waiting for base images to be rebuilt and republished, we would consider spinning that off into a different project instead of making it part of Copa.

    • Copa is intended to work with the existing ecosystem of container images. The project should have a strong preference for solutions that do not require image producers to create or modify their images in special ways to use Copa.

    • Copa is intended to allow parties other than the image authors to address container vulnerabilities. Copa should require a minimum of special knowledge about the lineage and construction of an image from the user to patch it successfully.

    • Copa is intended to do one thing well and be composable with other tools and processes. Copa does not have to be a universal multitool for container patching. For example, it is preferable that it integrates with popular container scanning tools rather than incorporating custom container scanning into the project itself. Similarly, it does not need to become a general container manipulation tool in the vein of crane.

    Design Reasoning

    The design of copa arises from the application of those tenets to the observed issues in previous efforts directly update container images via rebasing, for example, the experimental crane rebase:

    • Rebasing requires that all actors involved in creation of the image are coordinated so that some layers can be switched out without breaking the image. Attempting to switch out layers in the container overlay structure is brittle because most existing containers are created by writing over shared configuration files and data stores in base images. For example, an apt install during image creation will overwrite the dpkg status file in the base image, which will mask any package updates in a rebased layer. Since many existing container scanners rely on the reported package status to find vulnerable package versions, this can cause new vulnerabilities to not be reported or for patched binaries not to be recognized by the scanners.

      To avoid breaking integration with the existing container ecosystem, copa patches the filesystem bundle as a whole instead of as a collection of layers so that the resulting image state is consistent. This strategy also allows copa to patch vulnerabilties introduced at any layer in the image, including OS packages added in the app layers that is not addressed by a simple rebase. It also supports the core tenet of supporting patching without requiring coordination with all the publishers of the base images that a given image transitively depends on.

    • Rebasing also requires that the user knows a priori what base image (or transitive base image) is in the target image to determine which appropriate rebase image to use. This makes it very difficult for anyone not intimately involved with authoring the image from being able to remediate it, which is one of our tenets.

      While it is possible to embed extra metadata or annotations into the target image to facilitate this base image (or transitive base image) lookup, that would require that the images to be patched be modified or created especially to support updates, which goes against another of our tenets to be able to patch images without requiring them to be customized explicitly for that purpose.

      The design of copa addresses this by reframing the problem of updating containers and understanding the structure or lineage of a container image to the more specific problem of what packages in a given container image need to be updated. This allows copa to tap into the expertise embedded in the much more robust ecosystem for detecting and remediating vulnerabilities at the package level that already exists today. By making copa an additional remediation step that can be run after a container scan in existing workflows, we avoid both of those issues with an additional benefit: it incurs no additional work on the part of base image publishers to support patching of images based on their base images, the existing channels for publishing update packages is sufficient to service those container images as well.

    Architecture

    The requirements presented encourage an extensible model in order to support broad applicability. Specifically, there are two areas that the tool will need to accommodate multiple implementations to support more use cases:

    • The data schema of various vulnerability scanners producing the input vulnerability report.
    • The state management of various package managers and process for applying patches appropriately through them.

    Effectively, copa patch can be considered a command that bridges an extensible Parse action with an extensible Apply action as illustrated in the diagram; the implementation can be thought of as an engine that uses this abstract Go interface to apply security update packages:

    type UpdatePackage struct {
    Name string
    Version string
    }

    type UpdateManifest struct {
    OSType string
    OSVersion string
    Arch string
    Updates []UpdatePackage
    }

    type ScanReportParser interface {
    Parse(reportPath string) (*UpdateManifest, error)
    }

    type PackageManager interface {
    Apply(imagePath string, report *UpdateManifest) error
    }

    Implementation

    copa is a pseudo-frontend to buildkit implemented as a CLI tool. Effectively, instead of taking a container definition to create from scratch, it takes the reference to the target image to patch and a container scan report and builds a series of LLB graphs for buildkit to execute:

    1. Actions to probe the image as a filesystem bundle, for example, retrieving the package manager status in the image.
      • Within each distribution type identified by the scanner report (e.g. Debian) there can be different ways of applying patches to the target image (e.g. distroless), which can be differentiated through these actions.
    2. Actions to fetch and deploy tools that can be injected into the target image to perform the patching.
      • In cases where the package tools are not available in the target image, a standard version of the OS container matching the target image's is used to stage the necessary tooling for patches.
      • In the case of distroless images for example, where there is no valid package status file in the target image, the tooling container is also used to pull down and process the necessary package updates for copy to the target image.
      • Although not pictured, this can also be used to obtain tools (e.g. busybox) to be used in the image probing stage as well.
    3. Actions to deploy the required patch packages to the target image.
      • copa integrates with buildkit at the API level because it uses the diff and merge graph operations directly so that it can stage all the necessary tooling in the target image while producing a resulting image that only contains the original image plus a new layer with all the deployed patches.

    Tradeoffs

    • The core architectural choice of relying on packages as the unit of patching creates a couple of constraints:
      • By relying on existing vulnerability scanner behavior that only detects vulnerabilities via presence/absence of vulnerable packages, copa is limited in the kinds of vulnerabilities it can address and false positive/negatives from scanners flow downstream to copa.
      • copa depends on individual package manager adapters to correctly deploy patches to the target images, but there is a long tail of compatibility issues that arise depending on the target image itself (e.g. outdated package manager config/keys, invalid/missing package graph, etc.). Overall, the maintenance cost of the project is expected to be non-trivial to address this.
    • No support for windows containers given the dependency on buildkit.
    - + \ No newline at end of file diff --git a/website/v0.1.x/faq.html b/website/v0.1.x/faq.html index 18758777..c9cbef2d 100644 --- a/website/v0.1.x/faq.html +++ b/website/v0.1.x/faq.html @@ -7,13 +7,13 @@ - +
    Version: v0.1.x

    FAQ

    What kind of vulnerabilities can Copa patch?

    Copa is capable of patching "OS level" vulnerabilities. This includes packages (like openssl) in the image that are managed by a package manager such as apt or yum. Copa is not currently capable of patching vulnerabilities at the "application level" such as Python packages or Go modules.

    - + \ No newline at end of file diff --git a/website/v0.1.x/installation.html b/website/v0.1.x/installation.html index ce6fefe4..c99a4f99 100644 --- a/website/v0.1.x/installation.html +++ b/website/v0.1.x/installation.html @@ -7,13 +7,13 @@ - +
    Version: v0.1.x

    Installation

    Homebrew

    On macOS and Linux, copa can be installed via Homebrew:

    brew install copa

    GitHub

    You can download the latest and previous versions of copa from the GitHub releases page.

    Development Setup

    The following instructions are for Ubuntu 22.04 with the dependency versions supported as part of the dev container environment we use for builds and tests. For other distributions and OS, refer to the appropriate installation instructions for each of the components instead.

    git clone https://github.com/project-copacetic/copacetic
    cd copacetic
    make
    # OPTIONAL: install copa to a pathed folder
    sudo mv dist/linux_amd64/release/copa /usr/local/bin/
    - + \ No newline at end of file diff --git a/website/v0.1.x/quick-start.html b/website/v0.1.x/quick-start.html index 225e8ce8..f97d1f1f 100644 --- a/website/v0.1.x/quick-start.html +++ b/website/v0.1.x/quick-start.html @@ -7,7 +7,7 @@ - + @@ -15,7 +15,7 @@
    Version: v0.1.x

    Quick Start

    This sample illustrates how to patch containers using vulnerability reports with copa.

    Prerequisites

    Sample Steps

    1. Scan the container image for patchable OS vulnerabilities, outputting the results to a JSON file:

      trivy image --vuln-type os --ignore-unfixed -f json -o nginx.1.21.6.json docker.io/library/nginx:1.21.6

      You can also see the existing patchable vulnerabilities in table form on the shell with:

      trivy image --vuln-type os --ignore-unfixed docker.io/library/nginx:1.21.6

    2. Patch the image using the Trivy report. You will need to start buildkitd if it is not already running:

      sudo buildkitd &
      sudo copa patch -i docker.io/library/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched

      Alternatively, you can run buildkitd in a container, which allows copa to be run without root access to the local buildkit socket:

      export BUILDKIT_VERSION=v0.11.4
      export BUILDKIT_PORT=8888
      docker run \
      --detach \
      --rm \
      --privileged \
      -p 127.0.0.1:$BUILDKIT_PORT:$BUILDKIT_PORT/tcp \
      --name buildkitd \
      --entrypoint buildkitd \
      "moby/buildkit:$BUILDKIT_VERSION" \
      --addr tcp://0.0.0.0:$BUILDKIT_PORT
      copa patch \
      -i docker.io/library/nginx:1.21.6 \
      -r nginx.1.21.6.json \
      -t 1.21.6-patched \
      -a tcp://0.0.0.0:$BUILDKIT_PORT

      In either case, copa is non-destructive and exports a new image with the specified 1.21.6-patched label to the local Docker daemon.

      NOTE: if you're running this sample against an image from a private registry instead, ensure that the credentials are configured in the default Docker config.json before running copa patch, for example, via sudo docker login -u <user> -p <password> <registry>.

    3. Scan the patched image and verify that the vulnerabilities have been patched:

      trivy image --vuln-type os --ignore-unfixed docker.io/library/nginx:1.21.6-patched

      You can also inspect the structure of the patched image with docker history to see the new patch layer appended to the image:

      $ docker history docker.io/library/nginx:1.21.6-patched
      IMAGE CREATED CREATED BY SIZE COMMENT
      a372df41e06d 1 minute ago mount / from exec sh -c apt install --no-ins… 26.1MB buildkit.exporter.image.v0
      <missing> 3 months ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
      <missing> 3 months ago STOPSIGNAL SIGQUIT 0B buildkit.dockerfile.v0
      <missing> 3 months ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
      <missing> 3 months ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B buildkit.dockerfile.v0
      <missing> 3 months ago COPY 30-tune-worker-processes.sh /docker-ent… 4.61kB buildkit.dockerfile.v0
      <missing> 3 months ago COPY 20-envsubst-on-templates.sh /docker-ent… 1.04kB buildkit.dockerfile.v0
      <missing> 3 months ago COPY 10-listen-on-ipv6-by-default.sh /docker… 1.96kB buildkit.dockerfile.v0
      <missing> 3 months ago COPY docker-entrypoint.sh / # buildkit 1.2kB buildkit.dockerfile.v0
      <missing> 3 months ago RUN /bin/sh -c set -x && addgroup --syst… 61.1MB buildkit.dockerfile.v0
      <missing> 3 months ago ENV PKG_RELEASE=1~bullseye 0B buildkit.dockerfile.v0
      <missing> 3 months ago ENV NJS_VERSION=0.7.0 0B buildkit.dockerfile.v0
      <missing> 3 months ago ENV NGINX_VERSION=1.20.2 0B buildkit.dockerfile.v0
      <missing> 3 months ago LABEL maintainer=NGINX Docker Maintainers <d… 0B buildkit.dockerfile.v0
      <missing> 4 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
      <missing> 4 months ago /bin/sh -c #(nop) ADD file:09675d11695f65c55… 80.4MB
    4. Run the container to verify that the image has no regressions:

      $ docker run -it --rm --name nginx-test docker.io/library/nginx:1.21.6-patched
      /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
      /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
      10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
      10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
      /docker-entrypoint.sh: Configuration complete; ready for start up
      2022/05/16 18:00:17 [notice] 1#1: using the "epoll" event method
      2022/05/16 18:00:17 [notice] 1#1: nginx/1.20.2
      2022/05/16 18:00:17 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
      2022/05/16 18:00:17 [notice] 1#1: OS: Linux 5.10.102.1-microsoft-standard-WSL2
      2022/05/16 18:00:17 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
      2022/05/16 18:00:17 [notice] 1#1: start worker processes
      2022/05/16 18:00:17 [notice] 1#1: start worker process 31
      2022/05/16 18:00:17 [notice] 1#1: start worker process 32
      2022/05/16 18:00:17 [notice] 1#1: start worker process 33
      2022/05/16 18:00:17 [notice] 1#1: start worker process 34
      2022/05/16 18:00:17 [notice] 1#1: start worker process 35
      2022/05/16 18:00:17 [notice] 1#1: start worker process 36
      2022/05/16 18:00:17 [notice] 1#1: start worker process 37
      2022/05/16 18:00:17 [notice] 1#1: start worker process 38
      2022/05/16 18:00:17 [notice] 38#38: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 36#36: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 33#33: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 32#32: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 34#34: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 35#35: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 37#37: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 1#1: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 31#31: signal 28 (SIGWINCH) received

      You can stop the container by opening a new shell instance and running: docker stop nginx-test

    - + \ No newline at end of file diff --git a/website/v0.2.x.html b/website/v0.2.x.html index 4006833c..718537b3 100644 --- a/website/v0.2.x.html +++ b/website/v0.2.x.html @@ -7,13 +7,13 @@ - +
    Version: v0.2.x

    Project Copacetic: Directly patch container image vulnerabilities

    copa is a CLI tool written in Go and based on buildkit that can be used to directly patch container images given the vulnerability scanning results from popular tools like Trivy.

    Why?

    We needed the ability to patch containers quickly without going upstream for a full rebuild. As the window between vulnerability disclosure and active exploitation continues to narrow, there is a growing operational need to patch critical security vulnerabilities in container images so they can be quickly redeployed into production. The need is especially acute when those vulnerabilities are:

    • inherited from base images several levels deep and waiting on updated releases to percolate through the supply chain is not an option
    • found in 3rd party app images you don't maintain with update cadences that don't meet your security SLAs.

    In addition to filling the operational gap not met by left-shift security practices and tools, the ability of copa to patch a container without requiring a rebuild of the container image provides other benefits:

    • Allows users other than the image publishers to also patch container images, such as DevSecOps engineers.
    • Reduces the storage and transmission costs of redistributing patched images by only creating an additional patch layer, instead of rebuilding the entire image which usually results in different layer hashes that break layer caching.
    • Reduces the turnaround time for patching a container image by not having to wait for base image updates and being a faster operation than a full image rebuild.
    • Reduces the complexity of patching the image from running a rebuild pipeline to running a single tool on the image.

    How?

    The copa tool is an extensible engine that:

    1. Parses the needed update packages from the container image’s vulnerability report produced by a scanner like Trivy. New adapters can be written to accommodate more report formats.
    2. Obtains and processes the needed update packages using the appropriate package manager tools such as apt, apk, etc. New adapters can be written to support more package managers.
    3. Applies the resulting update binaries to the container image using buildkit.

    This approach is motivated by the core principles of making direct container patching broadly applicable and accessible:

    • Copa supports patching existing container images.
      • Devs don't need to build their images using specific tools or modify them in some way just to support container patching.
    • Copa works with the existing vulnerability scanning and mitigation ecosystems.
      • Image publishers don't need to create new workflows for container patching since Copa supports patching container images using the security update packages already being published today.
      • Consumers do not need to migrate to a new and potentially more limited support ecosystem for custom distros or change their container vulnerability scanning pipelines to include remediation, since Copa can be integrated seamlessly as an extra step to patch containers based on those scanning reports.
    • Copa reduces the technical expertise needed and waiting on dependencies needed to patch an image.
      • For OS package vulnerabilities, no specialized knowledge about a specific image is needed to be patch it as Copa relies on the vulnerability remediation knowledge already embedded in the reports produced by popular container scanning tools today.

    For more details, refer to the copa design documentation.

    - + \ No newline at end of file diff --git a/website/v0.2.x/code-of-conduct.html b/website/v0.2.x/code-of-conduct.html index 58989c4f..4b188339 100644 --- a/website/v0.2.x/code-of-conduct.html +++ b/website/v0.2.x/code-of-conduct.html @@ -7,7 +7,7 @@ - + @@ -62,7 +62,7 @@ Mozilla's code of conduct enforcement ladder.

    For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.

    - + \ No newline at end of file diff --git a/website/v0.2.x/contributing.html b/website/v0.2.x/contributing.html index 2c092dfe..90b3d8da 100644 --- a/website/v0.2.x/contributing.html +++ b/website/v0.2.x/contributing.html @@ -7,7 +7,7 @@ - + @@ -27,7 +27,7 @@ personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.

    Contributors sign-off that they adhere to these requirements by adding a Signed-off-by line to commit messages.

    This is my commit message

    Signed-off-by: Random J Developer <random@developer.example.org>

    Git even has a -s command line option to append this automatically to your commit message:

    git commit -s -m 'This is my commit message'

    Pull requests that do not contain a valid Signed-off-by line cannot be merged.

    I didn't sign my commit, now what?

    No worries - You can easily amend your commit with a sign-off and force push the change to your submitting branch:

    git switch <branch-name>
    git commit --amend --no-edit --signoff
    git push --force-with-lease <remote-name> <branch-name>

    Code of Conduct

    This project has adopted the Contributor Covenant Code of Conduct.

    - + \ No newline at end of file diff --git a/website/v0.2.x/design.html b/website/v0.2.x/design.html index 015893c8..2f3ce9ea 100644 --- a/website/v0.2.x/design.html +++ b/website/v0.2.x/design.html @@ -7,13 +7,13 @@ - +
    Version: v0.2.x

    Design

    Design Tenets

    • Copa is intended to accelerate container patching by eliminating waiting on base image dependency chains to update. This is a raison d’etre for the Copa project, so if we figured out a different way to patch containers that still relied on waiting for base images to be rebuilt and republished, we would consider spinning that off into a different project instead of making it part of Copa.

    • Copa is intended to work with the existing ecosystem of container images. The project should have a strong preference for solutions that do not require image producers to create or modify their images in special ways to use Copa.

    • Copa is intended to allow parties other than the image authors to address container vulnerabilities. Copa should require a minimum of special knowledge about the lineage and construction of an image from the user to patch it successfully.

    • Copa is intended to do one thing well and be composable with other tools and processes. Copa does not have to be a universal multitool for container patching. For example, it is preferable that it integrates with popular container scanning tools rather than incorporating custom container scanning into the project itself. Similarly, it does not need to become a general container manipulation tool in the vein of crane.

    Design Reasoning

    The design of copa arises from the application of those tenets to the observed issues in previous efforts directly update container images via rebasing, for example, the experimental crane rebase:

    • Rebasing requires that all actors involved in creation of the image are coordinated so that some layers can be switched out without breaking the image. Attempting to switch out layers in the container overlay structure is brittle because most existing containers are created by writing over shared configuration files and data stores in base images. For example, an apt install during image creation will overwrite the dpkg status file in the base image, which will mask any package updates in a rebased layer. Since many existing container scanners rely on the reported package status to find vulnerable package versions, this can cause new vulnerabilities to not be reported or for patched binaries not to be recognized by the scanners.

      To avoid breaking integration with the existing container ecosystem, copa patches the filesystem bundle as a whole instead of as a collection of layers so that the resulting image state is consistent. This strategy also allows copa to patch vulnerabilties introduced at any layer in the image, including OS packages added in the app layers that is not addressed by a simple rebase. It also supports the core tenet of supporting patching without requiring coordination with all the publishers of the base images that a given image transitively depends on.

    • Rebasing also requires that the user knows a priori what base image (or transitive base image) is in the target image to determine which appropriate rebase image to use. This makes it very difficult for anyone not intimately involved with authoring the image from being able to remediate it, which is one of our tenets.

      While it is possible to embed extra metadata or annotations into the target image to facilitate this base image (or transitive base image) lookup, that would require that the images to be patched be modified or created especially to support updates, which goes against another of our tenets to be able to patch images without requiring them to be customized explicitly for that purpose.

      The design of copa addresses this by reframing the problem of updating containers and understanding the structure or lineage of a container image to the more specific problem of what packages in a given container image need to be updated. This allows copa to tap into the expertise embedded in the much more robust ecosystem for detecting and remediating vulnerabilities at the package level that already exists today. By making copa an additional remediation step that can be run after a container scan in existing workflows, we avoid both of those issues with an additional benefit: it incurs no additional work on the part of base image publishers to support patching of images based on their base images, the existing channels for publishing update packages is sufficient to service those container images as well.

    Architecture

    The requirements presented encourage an extensible model in order to support broad applicability. Specifically, there are two areas that the tool will need to accommodate multiple implementations to support more use cases:

    • The data schema of various vulnerability scanners producing the input vulnerability report.
    • The state management of various package managers and process for applying patches appropriately through them.

    Effectively, copa patch can be considered a command that bridges an extensible Parse action with an extensible Apply action as illustrated in the diagram; the implementation can be thought of as an engine that uses this abstract Go interface to apply security update packages:

    type UpdatePackage struct {
    Name string
    Version string
    }

    type UpdateManifest struct {
    OSType string
    OSVersion string
    Arch string
    Updates []UpdatePackage
    }

    type ScanReportParser interface {
    Parse(reportPath string) (*UpdateManifest, error)
    }

    type PackageManager interface {
    Apply(imagePath string, report *UpdateManifest) error
    }

    Implementation

    copa is a pseudo-frontend to buildkit implemented as a CLI tool. Effectively, instead of taking a container definition to create from scratch, it takes the reference to the target image to patch and a container scan report and builds a series of LLB graphs for buildkit to execute:

    1. Actions to probe the image as a filesystem bundle, for example, retrieving the package manager status in the image.
      • Within each distribution type identified by the scanner report (e.g. Debian) there can be different ways of applying patches to the target image (e.g. distroless), which can be differentiated through these actions.
    2. Actions to fetch and deploy tools that can be injected into the target image to perform the patching.
      • In cases where the package tools are not available in the target image, a standard version of the OS container matching the target image's is used to stage the necessary tooling for patches.
      • In the case of distroless images for example, where there is no valid package status file in the target image, the tooling container is also used to pull down and process the necessary package updates for copy to the target image.
      • Although not pictured, this can also be used to obtain tools (e.g. busybox) to be used in the image probing stage as well.
    3. Actions to deploy the required patch packages to the target image.
      • copa integrates with buildkit at the API level because it uses the diff and merge graph operations directly so that it can stage all the necessary tooling in the target image while producing a resulting image that only contains the original image plus a new layer with all the deployed patches.

    Tradeoffs

    • The core architectural choice of relying on packages as the unit of patching creates a couple of constraints:
      • By relying on existing vulnerability scanner behavior that only detects vulnerabilities via presence/absence of vulnerable packages, copa is limited in the kinds of vulnerabilities it can address and false positive/negatives from scanners flow downstream to copa.
      • copa depends on individual package manager adapters to correctly deploy patches to the target images, but there is a long tail of compatibility issues that arise depending on the target image itself (e.g. outdated package manager config/keys, invalid/missing package graph, etc.). Overall, the maintenance cost of the project is expected to be non-trivial to address this.
    • No support for windows containers given the dependency on buildkit.
    - + \ No newline at end of file diff --git a/website/v0.2.x/faq.html b/website/v0.2.x/faq.html index 8a383a43..2fe16603 100644 --- a/website/v0.2.x/faq.html +++ b/website/v0.2.x/faq.html @@ -7,13 +7,13 @@ - +
    Version: v0.2.x

    FAQ

    What kind of vulnerabilities can Copa patch?

    Copa is capable of patching "OS level" vulnerabilities. This includes packages (like openssl) in the image that are managed by a package manager such as apt or yum. Copa is not currently capable of patching vulnerabilities at the "application level" such as Python packages or Go modules.

    - + \ No newline at end of file diff --git a/website/v0.2.x/installation.html b/website/v0.2.x/installation.html index 4b288634..5b116758 100644 --- a/website/v0.2.x/installation.html +++ b/website/v0.2.x/installation.html @@ -7,13 +7,13 @@ - +
    Version: v0.2.x

    Installation

    Homebrew

    On macOS and Linux, copa can be installed via Homebrew:

    brew install copa

    GitHub

    You can download the latest and previous versions of copa from the GitHub releases page.

    Development Setup

    The following instructions are for Ubuntu 22.04 with the dependency versions supported as part of the dev container environment we use for builds and tests. For other distributions and OS, refer to the appropriate installation instructions for each of the components instead.

    git clone https://github.com/project-copacetic/copacetic
    cd copacetic
    make
    # OPTIONAL: install copa to a pathed folder
    sudo mv dist/linux_amd64/release/copa /usr/local/bin/
    - + \ No newline at end of file diff --git a/website/v0.2.x/quick-start.html b/website/v0.2.x/quick-start.html index 55aa5d0b..7abc927d 100644 --- a/website/v0.2.x/quick-start.html +++ b/website/v0.2.x/quick-start.html @@ -7,7 +7,7 @@ - + @@ -15,7 +15,7 @@
    Version: v0.2.x

    Quick Start

    This sample illustrates how to patch containers using vulnerability reports with copa.

    Prerequisites

    Sample Steps

    1. Scan the container image for patchable OS vulnerabilities, outputting the results to a JSON file:

      trivy image --vuln-type os --ignore-unfixed -f json -o nginx.1.21.6.json docker.io/library/nginx:1.21.6

      You can also see the existing patchable vulnerabilities in table form on the shell with:

      trivy image --vuln-type os --ignore-unfixed docker.io/library/nginx:1.21.6

    2. Patch the image using the Trivy report. You will need to start buildkitd if it is not already running:

      sudo buildkitd &
      sudo copa patch -i docker.io/library/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched

      Alternatively, you can run buildkitd in a container, which allows copa to be run without root access to the local buildkit socket:

      export BUILDKIT_VERSION=v0.11.4
      export BUILDKIT_PORT=8888
      docker run \
      --detach \
      --rm \
      --privileged \
      -p 127.0.0.1:$BUILDKIT_PORT:$BUILDKIT_PORT/tcp \
      --name buildkitd \
      --entrypoint buildkitd \
      "moby/buildkit:$BUILDKIT_VERSION" \
      --addr tcp://0.0.0.0:$BUILDKIT_PORT
      copa patch \
      -i docker.io/library/nginx:1.21.6 \
      -r nginx.1.21.6.json \
      -t 1.21.6-patched \
      -a tcp://0.0.0.0:$BUILDKIT_PORT

      In either case, copa is non-destructive and exports a new image with the specified 1.21.6-patched label to the local Docker daemon.

      NOTE: if you're running this sample against an image from a private registry instead, ensure that the credentials are configured in the default Docker config.json before running copa patch, for example, via sudo docker login -u <user> -p <password> <registry>.

    3. Scan the patched image and verify that the vulnerabilities have been patched:

      trivy image --vuln-type os --ignore-unfixed docker.io/library/nginx:1.21.6-patched

      You can also inspect the structure of the patched image with docker history to see the new patch layer appended to the image:

      $ docker history docker.io/library/nginx:1.21.6-patched
      IMAGE CREATED CREATED BY SIZE COMMENT
      a372df41e06d 1 minute ago mount / from exec sh -c apt install --no-ins… 26.1MB buildkit.exporter.image.v0
      <missing> 3 months ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
      <missing> 3 months ago STOPSIGNAL SIGQUIT 0B buildkit.dockerfile.v0
      <missing> 3 months ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
      <missing> 3 months ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B buildkit.dockerfile.v0
      <missing> 3 months ago COPY 30-tune-worker-processes.sh /docker-ent… 4.61kB buildkit.dockerfile.v0
      <missing> 3 months ago COPY 20-envsubst-on-templates.sh /docker-ent… 1.04kB buildkit.dockerfile.v0
      <missing> 3 months ago COPY 10-listen-on-ipv6-by-default.sh /docker… 1.96kB buildkit.dockerfile.v0
      <missing> 3 months ago COPY docker-entrypoint.sh / # buildkit 1.2kB buildkit.dockerfile.v0
      <missing> 3 months ago RUN /bin/sh -c set -x && addgroup --syst… 61.1MB buildkit.dockerfile.v0
      <missing> 3 months ago ENV PKG_RELEASE=1~bullseye 0B buildkit.dockerfile.v0
      <missing> 3 months ago ENV NJS_VERSION=0.7.0 0B buildkit.dockerfile.v0
      <missing> 3 months ago ENV NGINX_VERSION=1.20.2 0B buildkit.dockerfile.v0
      <missing> 3 months ago LABEL maintainer=NGINX Docker Maintainers <d… 0B buildkit.dockerfile.v0
      <missing> 4 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
      <missing> 4 months ago /bin/sh -c #(nop) ADD file:09675d11695f65c55… 80.4MB
    4. Run the container to verify that the image has no regressions:

      $ docker run -it --rm --name nginx-test docker.io/library/nginx:1.21.6-patched
      /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
      /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
      10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
      10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
      /docker-entrypoint.sh: Configuration complete; ready for start up
      2022/05/16 18:00:17 [notice] 1#1: using the "epoll" event method
      2022/05/16 18:00:17 [notice] 1#1: nginx/1.20.2
      2022/05/16 18:00:17 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
      2022/05/16 18:00:17 [notice] 1#1: OS: Linux 5.10.102.1-microsoft-standard-WSL2
      2022/05/16 18:00:17 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
      2022/05/16 18:00:17 [notice] 1#1: start worker processes
      2022/05/16 18:00:17 [notice] 1#1: start worker process 31
      2022/05/16 18:00:17 [notice] 1#1: start worker process 32
      2022/05/16 18:00:17 [notice] 1#1: start worker process 33
      2022/05/16 18:00:17 [notice] 1#1: start worker process 34
      2022/05/16 18:00:17 [notice] 1#1: start worker process 35
      2022/05/16 18:00:17 [notice] 1#1: start worker process 36
      2022/05/16 18:00:17 [notice] 1#1: start worker process 37
      2022/05/16 18:00:17 [notice] 1#1: start worker process 38
      2022/05/16 18:00:17 [notice] 38#38: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 36#36: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 33#33: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 32#32: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 34#34: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 35#35: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 37#37: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 1#1: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 31#31: signal 28 (SIGWINCH) received

      You can stop the container by opening a new shell instance and running: docker stop nginx-test

    - + \ No newline at end of file diff --git a/website/v0.3.x.html b/website/v0.3.x.html index 95133e86..e6f96112 100644 --- a/website/v0.3.x.html +++ b/website/v0.3.x.html @@ -7,13 +7,13 @@ - +
    Version: v0.3.x

    Project Copacetic: Directly patch container image vulnerabilities

    copa is a CLI tool written in Go and based on buildkit that can be used to directly patch container images given the vulnerability scanning results from popular tools like Trivy.

    Why?

    We needed the ability to patch containers quickly without going upstream for a full rebuild. As the window between vulnerability disclosure and active exploitation continues to narrow, there is a growing operational need to patch critical security vulnerabilities in container images so they can be quickly redeployed into production. The need is especially acute when those vulnerabilities are:

    • inherited from base images several levels deep and waiting on updated releases to percolate through the supply chain is not an option
    • found in 3rd party app images you don't maintain with update cadences that don't meet your security SLAs.

    In addition to filling the operational gap not met by left-shift security practices and tools, the ability of copa to patch a container without requiring a rebuild of the container image provides other benefits:

    • Allows users other than the image publishers to also patch container images, such as DevSecOps engineers.
    • Reduces the storage and transmission costs of redistributing patched images by only creating an additional patch layer, instead of rebuilding the entire image which usually results in different layer hashes that break layer caching.
    • Reduces the turnaround time for patching a container image by not having to wait for base image updates and being a faster operation than a full image rebuild.
    • Reduces the complexity of patching the image from running a rebuild pipeline to running a single tool on the image.

    How?

    The copa tool is an extensible engine that:

    1. Parses the needed update packages from the container image’s vulnerability report produced by a scanner like Trivy. New adapters can be written to accommodate more report formats.
    2. Obtains and processes the needed update packages using the appropriate package manager tools such as apt, apk, etc. New adapters can be written to support more package managers.
    3. Applies the resulting update binaries to the container image using buildkit.

    This approach is motivated by the core principles of making direct container patching broadly applicable and accessible:

    • Copa supports patching existing container images.
      • Devs don't need to build their images using specific tools or modify them in some way just to support container patching.
    • Copa works with the existing vulnerability scanning and mitigation ecosystems.
      • Image publishers don't need to create new workflows for container patching since Copa supports patching container images using the security update packages already being published today.
      • Consumers do not need to migrate to a new and potentially more limited support ecosystem for custom distros or change their container vulnerability scanning pipelines to include remediation, since Copa can be integrated seamlessly as an extra step to patch containers based on those scanning reports.
    • Copa reduces the technical expertise needed and waiting on dependencies needed to patch an image.
      • For OS package vulnerabilities, no specialized knowledge about a specific image is needed to be patch it as Copa relies on the vulnerability remediation knowledge already embedded in the reports produced by popular container scanning tools today.

    For more details, refer to the copa design documentation.

    - + \ No newline at end of file diff --git a/website/v0.3.x/code-of-conduct.html b/website/v0.3.x/code-of-conduct.html index 7fd4acb4..a76b52fe 100644 --- a/website/v0.3.x/code-of-conduct.html +++ b/website/v0.3.x/code-of-conduct.html @@ -7,7 +7,7 @@ - + @@ -62,7 +62,7 @@ Mozilla's code of conduct enforcement ladder.

    For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.

    - + \ No newline at end of file diff --git a/website/v0.3.x/contributing.html b/website/v0.3.x/contributing.html index 2cb545fc..6bc6f360 100644 --- a/website/v0.3.x/contributing.html +++ b/website/v0.3.x/contributing.html @@ -7,7 +7,7 @@ - + @@ -27,7 +27,7 @@ personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.

    Contributors sign-off that they adhere to these requirements by adding a Signed-off-by line to commit messages.

    This is my commit message

    Signed-off-by: Random J Developer <random@developer.example.org>

    Git even has a -s command line option to append this automatically to your commit message:

    git commit -s -m 'This is my commit message'

    Pull requests that do not contain a valid Signed-off-by line cannot be merged.

    I didn't sign my commit, now what?

    No worries - You can easily amend your commit with a sign-off and force push the change to your submitting branch:

    git switch <branch-name>
    git commit --amend --no-edit --signoff
    git push --force-with-lease <remote-name> <branch-name>

    Code of Conduct

    This project has adopted the Contributor Covenant Code of Conduct.

    - + \ No newline at end of file diff --git a/website/v0.3.x/design.html b/website/v0.3.x/design.html index 64ed3699..4f056fb5 100644 --- a/website/v0.3.x/design.html +++ b/website/v0.3.x/design.html @@ -7,13 +7,13 @@ - +
    Version: v0.3.x

    Design

    Design Tenets

    • Copa is intended to accelerate container patching by eliminating waiting on base image dependency chains to update. This is a raison d’etre for the Copa project, so if we figured out a different way to patch containers that still relied on waiting for base images to be rebuilt and republished, we would consider spinning that off into a different project instead of making it part of Copa.

    • Copa is intended to work with the existing ecosystem of container images. The project should have a strong preference for solutions that do not require image producers to create or modify their images in special ways to use Copa.

    • Copa is intended to allow parties other than the image authors to address container vulnerabilities. Copa should require a minimum of special knowledge about the lineage and construction of an image from the user to patch it successfully.

    • Copa is intended to do one thing well and be composable with other tools and processes. Copa does not have to be a universal multitool for container patching. For example, it is preferable that it integrates with popular container scanning tools rather than incorporating custom container scanning into the project itself. Similarly, it does not need to become a general container manipulation tool in the vein of crane.

    Design Reasoning

    The design of copa arises from the application of those tenets to the observed issues in previous efforts directly update container images via rebasing, for example, the experimental crane rebase:

    • Rebasing requires that all actors involved in creation of the image are coordinated so that some layers can be switched out without breaking the image. Attempting to switch out layers in the container overlay structure is brittle because most existing containers are created by writing over shared configuration files and data stores in base images. For example, an apt install during image creation will overwrite the dpkg status file in the base image, which will mask any package updates in a rebased layer. Since many existing container scanners rely on the reported package status to find vulnerable package versions, this can cause new vulnerabilities to not be reported or for patched binaries not to be recognized by the scanners.

      To avoid breaking integration with the existing container ecosystem, copa patches the filesystem bundle as a whole instead of as a collection of layers so that the resulting image state is consistent. This strategy also allows copa to patch vulnerabilties introduced at any layer in the image, including OS packages added in the app layers that is not addressed by a simple rebase. It also supports the core tenet of supporting patching without requiring coordination with all the publishers of the base images that a given image transitively depends on.

    • Rebasing also requires that the user knows a priori what base image (or transitive base image) is in the target image to determine which appropriate rebase image to use. This makes it very difficult for anyone not intimately involved with authoring the image from being able to remediate it, which is one of our tenets.

      While it is possible to embed extra metadata or annotations into the target image to facilitate this base image (or transitive base image) lookup, that would require that the images to be patched be modified or created especially to support updates, which goes against another of our tenets to be able to patch images without requiring them to be customized explicitly for that purpose.

      The design of copa addresses this by reframing the problem of updating containers and understanding the structure or lineage of a container image to the more specific problem of what packages in a given container image need to be updated. This allows copa to tap into the expertise embedded in the much more robust ecosystem for detecting and remediating vulnerabilities at the package level that already exists today. By making copa an additional remediation step that can be run after a container scan in existing workflows, we avoid both of those issues with an additional benefit: it incurs no additional work on the part of base image publishers to support patching of images based on their base images, the existing channels for publishing update packages is sufficient to service those container images as well.

    Architecture

    The requirements presented encourage an extensible model in order to support broad applicability. Specifically, there are two areas that the tool will need to accommodate multiple implementations to support more use cases:

    • The data schema of various vulnerability scanners producing the input vulnerability report.
    • The state management of various package managers and process for applying patches appropriately through them.

    Effectively, copa patch can be considered a command that bridges an extensible Parse action with an extensible Apply action as illustrated in the diagram; the implementation can be thought of as an engine that uses this abstract Go interface to apply security update packages:

    type UpdatePackage struct {
    Name string
    Version string
    }

    type UpdateManifest struct {
    OSType string
    OSVersion string
    Arch string
    Updates []UpdatePackage
    }

    type ScanReportParser interface {
    Parse(reportPath string) (*UpdateManifest, error)
    }

    type PackageManager interface {
    Apply(imagePath string, report *UpdateManifest) error
    }

    Implementation

    copa is a pseudo-frontend to buildkit implemented as a CLI tool. Effectively, instead of taking a container definition to create from scratch, it takes the reference to the target image to patch and a container scan report and builds a series of LLB graphs for buildkit to execute:

    1. Actions to probe the image as a filesystem bundle, for example, retrieving the package manager status in the image.
      • Within each distribution type identified by the scanner report (e.g. Debian) there can be different ways of applying patches to the target image (e.g. distroless), which can be differentiated through these actions.
    2. Actions to fetch and deploy tools that can be injected into the target image to perform the patching.
      • In cases where the package tools are not available in the target image, a standard version of the OS container matching the target image's is used to stage the necessary tooling for patches.
      • In the case of distroless images for example, where there is no valid package status file in the target image, the tooling container is also used to pull down and process the necessary package updates for copy to the target image.
      • Although not pictured, this can also be used to obtain tools (e.g. busybox) to be used in the image probing stage as well.
    3. Actions to deploy the required patch packages to the target image.
      • copa integrates with buildkit at the API level because it uses the diff and merge graph operations directly so that it can stage all the necessary tooling in the target image while producing a resulting image that only contains the original image plus a new layer with all the deployed patches.

    Tradeoffs

    • The core architectural choice of relying on packages as the unit of patching creates a couple of constraints:
      • By relying on existing vulnerability scanner behavior that only detects vulnerabilities via presence/absence of vulnerable packages, copa is limited in the kinds of vulnerabilities it can address and false positive/negatives from scanners flow downstream to copa.
      • copa depends on individual package manager adapters to correctly deploy patches to the target images, but there is a long tail of compatibility issues that arise depending on the target image itself (e.g. outdated package manager config/keys, invalid/missing package graph, etc.). Overall, the maintenance cost of the project is expected to be non-trivial to address this.
    • No support for windows containers given the dependency on buildkit.
    - + \ No newline at end of file diff --git a/website/v0.3.x/faq.html b/website/v0.3.x/faq.html index cb2730c5..b1c59593 100644 --- a/website/v0.3.x/faq.html +++ b/website/v0.3.x/faq.html @@ -7,13 +7,13 @@ - +
    Version: v0.3.x

    FAQ

    What kind of vulnerabilities can Copa patch?

    Copa is capable of patching "OS level" vulnerabilities. This includes packages (like openssl) in the image that are managed by a package manager such as apt or yum. Copa is not currently capable of patching vulnerabilities at the "application level" such as Python packages or Go modules.

    - + \ No newline at end of file diff --git a/website/v0.3.x/installation.html b/website/v0.3.x/installation.html index cd9ee21a..6d9a0b6c 100644 --- a/website/v0.3.x/installation.html +++ b/website/v0.3.x/installation.html @@ -7,13 +7,13 @@ - +
    Version: v0.3.x

    Installation

    Homebrew

    On macOS and Linux, copa can be installed via Homebrew:

    brew install copa

    GitHub

    You can download the latest and previous versions of copa from the GitHub releases page.

    Development Setup

    The following instructions are for Ubuntu 22.04 with the dependency versions supported as part of the dev container environment we use for builds and tests. For other distributions and OS, refer to the appropriate installation instructions for each of the components instead.

    git clone https://github.com/project-copacetic/copacetic
    cd copacetic
    make
    # OPTIONAL: install copa to a pathed folder
    sudo mv dist/linux_amd64/release/copa /usr/local/bin/
    - + \ No newline at end of file diff --git a/website/v0.3.x/quick-start.html b/website/v0.3.x/quick-start.html index dff78f60..ed1215a6 100644 --- a/website/v0.3.x/quick-start.html +++ b/website/v0.3.x/quick-start.html @@ -7,7 +7,7 @@ - + @@ -15,7 +15,7 @@
    Version: v0.3.x

    Quick Start

    This sample illustrates how to patch containers using vulnerability reports with copa.

    Prerequisites

    Sample Steps

    1. Scan the container image for patchable OS vulnerabilities, outputting the results to a JSON file:

      trivy image --vuln-type os --ignore-unfixed -f json -o nginx.1.21.6.json docker.io/library/nginx:1.21.6

      You can also see the existing patchable vulnerabilities in table form on the shell with:

      trivy image --vuln-type os --ignore-unfixed docker.io/library/nginx:1.21.6

    2. Patch the image using the Trivy report. You will need to start buildkitd if it is not already running:

      sudo buildkitd &
      sudo copa patch -i docker.io/library/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched

      Alternatively, you can run buildkitd in a container, which allows copa to be run without root access to the local buildkit socket:

      export BUILDKIT_VERSION=v0.11.4
      export BUILDKIT_PORT=8888
      docker run \
      --detach \
      --rm \
      --privileged \
      -p 127.0.0.1:$BUILDKIT_PORT:$BUILDKIT_PORT/tcp \
      --name buildkitd \
      --entrypoint buildkitd \
      "moby/buildkit:$BUILDKIT_VERSION" \
      --addr tcp://0.0.0.0:$BUILDKIT_PORT
      copa patch \
      -i docker.io/library/nginx:1.21.6 \
      -r nginx.1.21.6.json \
      -t 1.21.6-patched \
      -a tcp://0.0.0.0:$BUILDKIT_PORT

      In either case, copa is non-destructive and exports a new image with the specified 1.21.6-patched label to the local Docker daemon.

      NOTE: if you're running this sample against an image from a private registry instead, ensure that the credentials are configured in the default Docker config.json before running copa patch, for example, via sudo docker login -u <user> -p <password> <registry>.

    3. Scan the patched image and verify that the vulnerabilities have been patched:

      trivy image --vuln-type os --ignore-unfixed docker.io/library/nginx:1.21.6-patched

      You can also inspect the structure of the patched image with docker history to see the new patch layer appended to the image:

      $ docker history docker.io/library/nginx:1.21.6-patched
      IMAGE CREATED CREATED BY SIZE COMMENT
      a372df41e06d 1 minute ago mount / from exec sh -c apt install --no-ins… 26.1MB buildkit.exporter.image.v0
      <missing> 3 months ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
      <missing> 3 months ago STOPSIGNAL SIGQUIT 0B buildkit.dockerfile.v0
      <missing> 3 months ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
      <missing> 3 months ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B buildkit.dockerfile.v0
      <missing> 3 months ago COPY 30-tune-worker-processes.sh /docker-ent… 4.61kB buildkit.dockerfile.v0
      <missing> 3 months ago COPY 20-envsubst-on-templates.sh /docker-ent… 1.04kB buildkit.dockerfile.v0
      <missing> 3 months ago COPY 10-listen-on-ipv6-by-default.sh /docker… 1.96kB buildkit.dockerfile.v0
      <missing> 3 months ago COPY docker-entrypoint.sh / # buildkit 1.2kB buildkit.dockerfile.v0
      <missing> 3 months ago RUN /bin/sh -c set -x && addgroup --syst… 61.1MB buildkit.dockerfile.v0
      <missing> 3 months ago ENV PKG_RELEASE=1~bullseye 0B buildkit.dockerfile.v0
      <missing> 3 months ago ENV NJS_VERSION=0.7.0 0B buildkit.dockerfile.v0
      <missing> 3 months ago ENV NGINX_VERSION=1.20.2 0B buildkit.dockerfile.v0
      <missing> 3 months ago LABEL maintainer=NGINX Docker Maintainers <d… 0B buildkit.dockerfile.v0
      <missing> 4 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
      <missing> 4 months ago /bin/sh -c #(nop) ADD file:09675d11695f65c55… 80.4MB
    4. Run the container to verify that the image has no regressions:

      $ docker run -it --rm --name nginx-test docker.io/library/nginx:1.21.6-patched
      /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
      /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
      10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
      10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
      /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
      /docker-entrypoint.sh: Configuration complete; ready for start up
      2022/05/16 18:00:17 [notice] 1#1: using the "epoll" event method
      2022/05/16 18:00:17 [notice] 1#1: nginx/1.20.2
      2022/05/16 18:00:17 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
      2022/05/16 18:00:17 [notice] 1#1: OS: Linux 5.10.102.1-microsoft-standard-WSL2
      2022/05/16 18:00:17 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
      2022/05/16 18:00:17 [notice] 1#1: start worker processes
      2022/05/16 18:00:17 [notice] 1#1: start worker process 31
      2022/05/16 18:00:17 [notice] 1#1: start worker process 32
      2022/05/16 18:00:17 [notice] 1#1: start worker process 33
      2022/05/16 18:00:17 [notice] 1#1: start worker process 34
      2022/05/16 18:00:17 [notice] 1#1: start worker process 35
      2022/05/16 18:00:17 [notice] 1#1: start worker process 36
      2022/05/16 18:00:17 [notice] 1#1: start worker process 37
      2022/05/16 18:00:17 [notice] 1#1: start worker process 38
      2022/05/16 18:00:17 [notice] 38#38: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 36#36: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 33#33: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 32#32: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 34#34: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 35#35: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 37#37: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 1#1: signal 28 (SIGWINCH) received
      2022/05/16 18:00:17 [notice] 31#31: signal 28 (SIGWINCH) received

      You can stop the container by opening a new shell instance and running: docker stop nginx-test

    - + \ No newline at end of file