From 4b43e566eed3eb6a82980d4fffef1a0b60e62a16 Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Wed, 9 Apr 2025 16:25:47 +0100 Subject: [PATCH 01/12] Rename plugin-template to plugin-github-settings --- go.mod | 3 +- go.sum | 116 ++++++++++++++++---------------------------------------- main.go | 2 +- 3 files changed, 34 insertions(+), 87 deletions(-) diff --git a/go.mod b/go.mod index a221c3d..a51341b 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/compliance-framework/plugin-template +module github.com/compliance-framework/plugin-github-settings go 1.23.6 @@ -14,7 +14,6 @@ require ( ) require ( - github.com/OneOfOne/xxhash v1.2.8 // indirect github.com/agnivade/levenshtein v1.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect diff --git a/go.sum b/go.sum index df46b0a..96055cd 100644 --- a/go.sum +++ b/go.sum @@ -6,14 +6,10 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= -github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY= -github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= @@ -26,18 +22,14 @@ github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HV github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/compliance-framework/agent v0.1.1 h1:uQ4idgwOMqrgM0JeYCtBv20HZoMymsH2nownrkl457w= -github.com/compliance-framework/agent v0.1.1/go.mod h1:jy/26xgTx9+at64ipTV1oo80pTVyhtlZaSMViQ3cVVQ= github.com/compliance-framework/agent v0.1.2 h1:XIn6ccsSXh040boPKEcvObNAkCKHrN+krzfiPbTZuJ4= github.com/compliance-framework/agent v0.1.2/go.mod h1:jy/26xgTx9+at64ipTV1oo80pTVyhtlZaSMViQ3cVVQ= github.com/compliance-framework/configuration-service v0.1.1 h1:p/r5vq1FLe0S8j/kLhth4Dvda8xajVPOBjnO9QauMjM= github.com/compliance-framework/configuration-service v0.1.1/go.mod h1:tLKJKXbQbY9Pg/e3BJtJVkqxaejXJMHoE8Yp0NW4lDE= -github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA= -github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= +github.com/containerd/containerd v1.7.26 h1:3cs8K2RHlMQaPifLqgRyI4VBkoldNdEw62cb7qQga7k= +github.com/containerd/containerd v1.7.26/go.mod h1:m4JU0E+h0ebbo9yXD7Hyt+sWnc8tChm7MudCjj4jRvQ= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= @@ -50,10 +42,10 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/defenseunicorns/go-oscal v0.6.2 h1:oLkMAJYVMq73Rm+9efcyaKq5SLMditjB6wv7o3XXpq8= github.com/defenseunicorns/go-oscal v0.6.2/go.mod h1:UHp2yK9ty2mYJDun7oNhbstCq6SAAwP4YGbw9n7uG6o= -github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= -github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgraph-io/badger/v4 v4.5.1 h1:7DCIXrQjo1LKmM96YD+hLVJ2EEsyyoWxJfpdd56HLps= +github.com/dgraph-io/badger/v4 v4.5.1/go.mod h1:qn3Be0j3TfV4kPbVoK0arXCD1/nr1ftth6sbL5jxdoA= +github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= +github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= @@ -67,8 +59,6 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -110,35 +100,27 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= -github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= -github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v24.12.23+incompatible h1:ubBKR94NR4pXUCY/MUsRVzd9umNW7ht7EG9hHfS9FX8= +github.com/google/flatbuffers v24.12.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog= -github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= @@ -165,13 +147,10 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= @@ -194,12 +173,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/open-policy-agent/opa v1.0.0 h1:fZsEwxg1knpPvUn0YDJuJZBcbVg4G3zKpWa3+CnYK+I= -github.com/open-policy-agent/opa v1.0.0/go.mod h1:+JyoH12I0+zqyC1iX7a2tmoQlipwAEGvOhVJMhmy+rM= github.com/open-policy-agent/opa v1.2.0 h1:88NDVCM0of1eO6Z4AFeL3utTEtMuwloFmWWU7dRV1z0= github.com/open-policy-agent/opa v1.2.0/go.mod h1:30euUmOvuBoebRCcJ7DMF42bRBOPznvt0ACUMYDUGVY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -213,18 +188,12 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= -github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk= github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.57.0 h1:Ro/rKjwdq9mZn1K5QPctzh+MA4Lp0BuYk5ZZEVhoNcY= -github.com/prometheus/common v0.57.0/go.mod h1:7uRPFSUTbfZWsJ7MHY56sqt7hLQu3bxXHDnNhl8E9qI= github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -248,8 +217,6 @@ github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM= github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A= github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg= -github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= -github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= github.com/tchap/go-patricia/v2 v2.3.2 h1:xTHFutuitO2zqKAQ5rCROYgUb7Or/+IC3fts9/Yc7nM= github.com/tchap/go-patricia/v2 v2.3.2/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= github.com/testcontainers/testcontainers-go v0.35.0 h1:uADsZpTKFAtp8SLK+hMwSaa+X+JiERHtd4sQAFmXeMo= @@ -284,78 +251,59 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= -go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= -go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA= -go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= -go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= -go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= -go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= -go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg= -go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= -google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= -google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= -google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= -google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= -google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/main.go b/main.go index 967c18f..4aa7c9b 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,7 @@ import ( "github.com/compliance-framework/agent/runner" "github.com/compliance-framework/agent/runner/proto" - "github.com/compliance-framework/plugin-template/internal" + "github.com/compliance-framework/plugin-github-settings/internal" "github.com/hashicorp/go-hclog" goplugin "github.com/hashicorp/go-plugin" ) From d95d1ecbfcec38f10d53e24ccce5cbb32b6712fa Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Wed, 9 Apr 2025 16:26:03 +0100 Subject: [PATCH 02/12] Validate configuration coming in on-the-wire Logic is stored within a validator map that can be changed. At some point we should add some more complex structures within it to check if it is required on the wire and if we can add sensible defaults. e.g. for api_url, default to https://api.github.com/ References BCH-868 --- main.go | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 4aa7c9b..6904957 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,8 @@ package main import ( "context" "fmt" + "net/url" + "regexp" "github.com/compliance-framework/agent/runner" "github.com/compliance-framework/agent/runner/proto" @@ -16,6 +18,37 @@ type CompliancePlugin struct { config map[string]string } +type ConfigValidatorFn func(value string) error + +var GithubConfigValidators = map[string]ConfigValidatorFn{ + "api_url": func(value string) error { + if len(value) == 0 { + return fmt.Errorf("api_url cannot be empty") + } + _, err := url.ParseRequestURI(value) + if err != nil { + return err + } + return nil + }, + "api_key": func(value string) error { + if len(value) == 0 { + return fmt.Errorf("api_key cannot be empty") + } + return nil + }, + "organization": func(value string) error { + if len(value) == 0 { + return fmt.Errorf("organization cannot be empty") + } + regex := regexp.MustCompile("^[A-Za-z0-9._-]+$") + if !regex.MatchString(value) { + return fmt.Errorf("organization formatted incorrectly, please check") + } + return nil + }, +} + // Configure, and Eval are called at different times during the plugin execution lifecycle, // and are responsible for different tasks: // @@ -49,7 +82,28 @@ func (l *CompliancePlugin) Configure(req *proto.ConfigureRequest) (*proto.Config // In this method, you should save any configuration values to your plugin struct, so you can later // re-use them in PrepareForEval and Eval. - l.config = req.GetConfig() + passed_config := req.GetConfig() + + l.logger.Info("Validating configuration") + errored := false + for config_key, validator := range GithubConfigValidators { + value, ok := passed_config[config_key] + if !ok { + l.logger.Error("Config Validator faliled", "key", config_key, "value", value, "not_set", true) + errored = true + continue + } + if err := validator(value); err != nil { + l.logger.Error("Config Validator faliled", "key", config_key, "value", value, "error", err) + errored = true + } + } + if errored { + l.logger.Error("Invalid configuration for the plugin. Check logs for the issues found") + } else { + l.logger.Info("Config Validator passed - continuing") + } + l.config = passed_config return &proto.ConfigureResponse{}, nil } From 86431b9062ddb0ed5cf04a1557304f7bbf161898 Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Thu, 10 Apr 2025 09:10:11 +0100 Subject: [PATCH 03/12] Fix spelling mistakes in log messages --- main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 6904957..f25f970 100644 --- a/main.go +++ b/main.go @@ -89,12 +89,12 @@ func (l *CompliancePlugin) Configure(req *proto.ConfigureRequest) (*proto.Config for config_key, validator := range GithubConfigValidators { value, ok := passed_config[config_key] if !ok { - l.logger.Error("Config Validator faliled", "key", config_key, "value", value, "not_set", true) + l.logger.Error("Config Validator failed", "key", config_key, "value", value, "not_set", true) errored = true continue } if err := validator(value); err != nil { - l.logger.Error("Config Validator faliled", "key", config_key, "value", value, "error", err) + l.logger.Error("Config Validator failed", "key", config_key, "value", value, "error", err) errored = true } } From 682c1727d1a4369658b61a4501fc5920f61d8b59 Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Thu, 10 Apr 2025 15:24:03 +0100 Subject: [PATCH 04/12] Pull information and run a test policy against Firstly, opted against re-inventing the wheel by querying the APIs manually, as going forward, it will help with rate limiting and other queries we can pass into the functions A unit test has also been created to simulate the output from the /org/{org} endpoint so we can replicate items uniformly. In the future, proper fixtures should be put in place so we can test unauthenticated responses from GH which will fail a lot of the audit rules due to the sensitive nature Finally, A single test rego policy is in place just to aide with testing. Future policies will be created in an isolated repository References BCH-868 --- examples/policies/gh_org_mfa_enabled.rego | 9 ++ go.mod | 2 + go.sum | 6 ++ internal/data.go | 30 ++++++- internal/eval.go | 46 +++++----- internal/eval_test.go | 104 ++++++++++++++++++++++ 6 files changed, 170 insertions(+), 27 deletions(-) create mode 100644 examples/policies/gh_org_mfa_enabled.rego create mode 100644 internal/eval_test.go diff --git a/examples/policies/gh_org_mfa_enabled.rego b/examples/policies/gh_org_mfa_enabled.rego new file mode 100644 index 0000000..fa1e6f0 --- /dev/null +++ b/examples/policies/gh_org_mfa_enabled.rego @@ -0,0 +1,9 @@ +package compliance_framework.mfa_enabled + +violation[{ + "title": "Two Factor Authentication is required at an organization level", + "description": "Two factor authentication should be enabled and enforced for all users within the Github Organization to make it harder for malicious actors to gain access to the organizations settings and repositories & settings", + "remarks": "More information from Github can be found here: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization" +}] if { + input.organization.two_factor_requirement_enabled == false +} \ No newline at end of file diff --git a/go.mod b/go.mod index a51341b..640b286 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ toolchain go1.24.1 require ( github.com/compliance-framework/agent v0.1.2 github.com/compliance-framework/configuration-service v0.1.1 + github.com/google/go-github/v71 v71.0.0 github.com/google/uuid v1.6.0 github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/go-plugin v1.6.3 @@ -24,6 +25,7 @@ require ( github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/hashicorp/yamux v0.1.2 // indirect github.com/mattn/go-colorable v0.1.14 // indirect diff --git a/go.sum b/go.sum index 96055cd..b4c1047 100644 --- a/go.sum +++ b/go.sum @@ -108,9 +108,14 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/flatbuffers v24.12.23+incompatible h1:ubBKR94NR4pXUCY/MUsRVzd9umNW7ht7EG9hHfS9FX8= github.com/google/flatbuffers v24.12.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-github/v71 v71.0.0 h1:Zi16OymGKZZMm8ZliffVVJ/Q9YZreDKONCr+WUd0Z30= +github.com/google/go-github/v71 v71.0.0/go.mod h1:URZXObp2BLlMjwu0O8g4y6VBneUj2bCHgnI8FfgZ51M= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -298,6 +303,7 @@ golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= diff --git a/internal/data.go b/internal/data.go index 034c092..982b1be 100644 --- a/internal/data.go +++ b/internal/data.go @@ -1,7 +1,10 @@ package internal import ( + "context" + "github.com/compliance-framework/agent/runner/proto" + "github.com/google/go-github/v71/github" "github.com/hashicorp/go-hclog" ) @@ -21,12 +24,31 @@ func (df DataFetcher) FetchData() (map[string]any, []*proto.Step, error) { steps := make([]*proto.Step, 0) steps = append(steps, &proto.Step{ - Title: "Fetch some data", - Description: "Fetch some data with more details. This should be replaced with the detailed steps you undertake to fetch data in your actual plugin.", - Remarks: StringAddressed("Put any remarks here"), + Title: "Configure the Github Client with the Personal Access Token", + Description: "Using the helper functions within the client, creates a Github API client that can query the API", }) + steps = append(steps, &proto.Step{ + Title: "Query the organization endpoint", + Description: "Using the client's native APIs, Get all the information from the organization endpoint", + Remarks: StringAddressed("More information about data being sent back can be found here: https://docs.github.com/en/rest/orgs/orgs?apiVersion=2022-11-28#get-an-organization"), + }) + + df.logger.Info("Establishing github client and querying APIs") + client := github.NewClient(nil).WithAuthToken(df.config["api_key"]) + + ctx := context.Background() + + org, _, err := client.Organizations.Get(ctx, df.config["organization"]) + if err != nil { + // TODO handle error sensibly + df.logger.Error("Error getting organization information", "org", df.config["organization"], "error", err) + } + // + + // TODO: Rate limiting check and back off + return map[string]any{ - "hello": "world", + "organization": org, }, steps, nil } diff --git a/internal/eval.go b/internal/eval.go index 90a2663..2237400 100644 --- a/internal/eval.go +++ b/internal/eval.go @@ -5,13 +5,13 @@ import ( "errors" "fmt" "maps" - "os" "time" policyManager "github.com/compliance-framework/agent/policy-manager" "github.com/compliance-framework/agent/runner" "github.com/compliance-framework/agent/runner/proto" "github.com/compliance-framework/configuration-service/sdk" + "github.com/google/go-github/v71/github" "github.com/google/uuid" "github.com/hashicorp/go-hclog" "google.golang.org/protobuf/types/known/timestamppb" @@ -71,27 +71,25 @@ func (pe *PolicyEvaluator) Eval(data map[string]interface{}, policyPaths []strin continue } - // The plugin should pass in some parameters here that will uniquely identify the subject. - // This could be a hostname in the case it's a machine, the identifier of a cloud resource, etc. - hostname, err := os.Hostname() - if err != nil { - hostname = "fallback-val" - } + // Cast the interface{} back to a github Organization so we can use all the helper functions that exist underneath + org_data := data["organization"].(*github.Organization) + org_name := org_data.GetLogin() + subjectAttributeMap := map[string]string{ - "type": "machine-instance", - "hostname": hostname, + "type": "github-organization", + "name": org_name, } subjects := []*proto.SubjectReference{ { - Type: "machine-instance", + Type: "github-organization", Attributes: subjectAttributeMap, - Title: StringAddressed("Machine Instance"), - Remarks: StringAddressed("A machine instance where we've retrieved the installed packages."), + Title: StringAddressed("Github Organization "), + Remarks: StringAddressed("The Github organization that is being audited"), Props: []*proto.Property{ { - Name: "hostname", - Value: hostname, - Remarks: StringAddressed("The local hostname of the machine where the plugin has been executed"), + Name: "organization_name", + Value: org_name, + Remarks: StringAddressed("The name of the Github Organization"), }, }, }, @@ -110,13 +108,13 @@ func (pe *PolicyEvaluator) Eval(data map[string]interface{}, policyPaths []strin Props: nil, }, { - Title: "Continuous Compliance Framework - Local APT Installed Packages Plugin", + Title: "Continuous Compliance Framework - Github Settings plugin", Type: "tool", Links: []*proto.Link{ { - Href: "https://github.com/compliance-framework/plugin-apt-versions", + Href: "https://github.com/compliance-framework/plugin-github-settings", Rel: StringAddressed("reference"), - Text: StringAddressed("The Continuous Compliance Framework' Local APT Installed Packages Plugin"), + Text: StringAddressed("The Continuous Compliance Framework' Github Settings Plugin"), }, }, Props: nil, @@ -176,7 +174,7 @@ func (pe *PolicyEvaluator) Eval(data map[string]interface{}, policyPaths []strin Components: components, RelevantEvidence: []*proto.RelevantEvidence{ { - Description: fmt.Sprintf("Policy %v was executed against the Local SSH configuration, using the Local SSH Compliance Plugin", result.Policy.Package.PurePackage()), + Description: fmt.Sprintf("Policy %v was executed against the Github Settings, using the Github Setting Compliance Plugin", result.Policy.Package.PurePackage()), }, }, } @@ -187,10 +185,12 @@ func (pe *PolicyEvaluator) Eval(data map[string]interface{}, policyPaths []strin UUID: findingUUID.String(), Collected: timestamppb.New(time.Now()), Labels: map[string]string{ - "type": "ssh", - "host": hostname, - "_policy": result.Policy.Package.PurePackage(), - "_policy_path": result.Policy.File, + "provider": "github", + "type": "organization", + "service": "organization-settings", + "organization_name": org_name, + "_policy": result.Policy.Package.PurePackage(), + "_policy_path": result.Policy.File, }, Origins: []*proto.Origin{{Actors: actors}}, Subjects: subjects, diff --git a/internal/eval_test.go b/internal/eval_test.go new file mode 100644 index 0000000..bce79c1 --- /dev/null +++ b/internal/eval_test.go @@ -0,0 +1,104 @@ +package internal + +import ( + "context" + "encoding/json" + "testing" + + "github.com/compliance-framework/agent/runner/proto" + "github.com/google/go-github/v71/github" + "github.com/hashicorp/go-hclog" +) + +var test_org_data = ` +{ + "login": "test-org", + "id": 1234567, + "node_id": "O_abcdefg", + "url": "https://api.github.com/orgs/test-org", + "repos_url": "https://api.github.com/orgs/test-org/repos", + "events_url": "https://api.github.com/orgs/test-org/events", + "hooks_url": "https://api.github.com/orgs/test-org/hooks", + "issues_url": "https://api.github.com/orgs/test-org/issues", + "members_url": "https://api.github.com/orgs/test-org/members{/member}", + "public_members_url": "https://api.github.com/orgs/test-org/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/1234567?v=4", + "description": null, + "is_verified": false, + "has_organization_projects": true, + "has_repository_projects": true, + "public_repos": 0, + "public_gists": 0, + "followers": 0, + "following": 0, + "html_url": "https://github.com/test-org", + "created_at": "2025-04-09T15:36:21Z", + "updated_at": "2025-04-09T15:38:25Z", + "archived_at": null, + "type": "Organization", + "total_private_repos": 0, + "owned_private_repos": 0, + "private_gists": 0, + "disk_usage": 0, + "collaborators": 0, + "billing_email": "test@example.com", + "default_repository_permission": "read", + "members_can_create_repositories": true, + "two_factor_requirement_enabled": false, + "members_allowed_repository_creation_type": "all", + "members_can_create_public_repositories": true, + "members_can_create_private_repositories": true, + "members_can_create_internal_repositories": false, + "members_can_create_pages": true, + "members_can_fork_private_repositories": false, + "web_commit_signoff_required": false, + "deploy_keys_enabled_for_repositories": false, + "members_can_create_public_pages": true, + "members_can_create_private_pages": true, + "plan": { + "name": "free", + "space": 976562499, + "private_repos": 10000, + "filled_seats": 2, + "seats": 1 + }, + "advanced_security_enabled_for_new_repositories": false, + "dependabot_alerts_enabled_for_new_repositories": false, + "dependabot_security_updates_enabled_for_new_repositories": false, + "dependency_graph_enabled_for_new_repositories": false, + "secret_scanning_enabled_for_new_repositories": false, + "secret_scanning_push_protection_enabled_for_new_repositories": false, + "secret_scanning_push_protection_custom_link_enabled": false, + "secret_scanning_push_protection_custom_link": null, + "secret_scanning_validity_checks_enabled": false +} +` + +func TestGithubOrg_EvaluatePolicies(t *testing.T) { + logger := hclog.NewNullLogger() + steps := make([]*proto.Activity, 0) + + organization := &github.Organization{} + _ = json.Unmarshal([]byte(test_org_data), organization) + + data := map[string]interface{}{ + "organization": organization, + } + + ctx := context.TODO() + + evaluator := NewPolicyEvaluator(ctx, logger, steps) + status, err := evaluator.Eval(data, []string{"../examples/policies"}) + + if status != proto.ExecutionStatus_SUCCESS { + t.Fail() + } + + if err != nil { + t.Fail() + } + + if len(evaluator.GetFindings()) < 1 { + t.Fail() + } +} From 0936e8d0e1dbcc636b73428ba9219ffe25f7f230 Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Thu, 10 Apr 2025 16:11:25 +0100 Subject: [PATCH 05/12] Rewrite README.md - add context about the plugin - Update pre-reqs - describe expected configuration References BCH-868 --- README.md | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cb7b04d..6cd81c8 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@ -# Compliance Framework Plugin Template +# Compliance Framework Plugin For Github -This is a template for building a compliance framework plugin. +This is the individual plugin for polling github settings for organizations and repositories to test for configuration flags that are going to fail compliance checks. -Inspect main.go for a detailed description of how to build the plugin. +For the moment, it is solely limited to authenticated Github organizations with a Github PAT, but in the future it should query security plans & repositories for specific settings ## Prerequisites * GoReleaser https://goreleaser.com/install/ +* Github Fine Grain Personal Access Token with the following scopes: + * `read:org` for the organization to be queried. Note - you *might* need to be an administrator of the GH Org to work correctly + ## Building @@ -24,6 +27,20 @@ You can use this plugin by passing it to the compliiance agent agent --plugin=[PATH_TO_YOUR_BINARY] ``` +## Plugin Configuration + +The plugin configuration must be created and managed by the agent, but expects the following configuration keys to be set, otherwise it will fail +```yaml +... +plugins: + github: + config: + api_key: github_pat_1234.... # The configured Github PAT for the organization scopes + api_url: https://api.github.com # The URL for the API endpoint for GH installations on-premise + organization: test-org # The name of the organization +... +``` + ## Releasing This plugin is released using goreleaser to build binaries, and Docker to build OCI artifacts (WIP), which will ensure a binary is built for most OS and Architecture combinations. @@ -38,3 +55,10 @@ You can find the OCI implementations in the GitHub Packages page. concom agent --plugin=https://github.com/compliance-framework/plugin-template/releases/tag/0.0.1 ``` +## Todo + +- [X] Pull Organization settings as an authenticated user +- [ ] Pull repository information for the listed Organization +- [ ] Populate Security Plans and map them to the repositories to ensure that settings are enabled +- [ ] Sensible defaults for the configuration +- [ ] Better error handling for sending issues back to the agent \ No newline at end of file From 28bce5f32c47c368f96dcae1e027191e8886d471 Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Fri, 11 Apr 2025 15:16:27 +0100 Subject: [PATCH 06/12] Upgrade agent to latest API version, including refactor of eval --- examples/policies/policies.tar.gz | Bin 0 -> 483 bytes go.mod | 38 ++++- go.sum | 72 ++++++++ internal/data.go | 10 +- internal/eval.go | 273 ++++++++++-------------------- 5 files changed, 208 insertions(+), 185 deletions(-) create mode 100644 examples/policies/policies.tar.gz diff --git a/examples/policies/policies.tar.gz b/examples/policies/policies.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..eca002cde784b7b19db7df8e4b0656650229a9fa GIT binary patch literal 483 zcmV<90UZ7xiwFQ72>E9K1MO2iZ`&{s&Fo)s(9o&+avU2lkfBRD6a@$5@Cu| zj%19s$bauiiUS)#G6g6C_$}n&?jGNfk8M{uZmYh*iY)F7)frRkuHF+xQLI-h7}w4E zW?GBo9FHiM>ot_C&E{rvU0#<FW%~-GtZClhnP-9L z^@CtQwa1n~xqdJjt)i-7?CIcmpPjg3v3StVV9?I~{JQ`_5_B+>Y$5q^aBznzIEF7V zbYz28Qzd8*O!rYU)qnxef|w1h{xhcyJ&;L0&vZ3;#d;VMN77~{#dA{MxoB$G5j<%V z-dgsJVj4u z3JoenehNpz(^))t3PIb}PimM3=e6`|^6=?7cbt`}N8bB!&To$8_)&a6OKRBlN3BY3 zOy+D{6i%@xZJ`Tc@Y_7Eo$^^bm1XjHIobS7PrfG_3r4c`BkT)>ScdEKk3_@+P-W|7LUI`H!%B0+aZSRG@l7wHPcm3w&{iPXhFEW6-O9P Zi^u={Yc9Cpf(t%A{sD!s6zu>C003s}?7#p3 literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod index 640b286..429c623 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,8 @@ go 1.23.6 toolchain go1.24.1 require ( - github.com/compliance-framework/agent v0.1.2 - github.com/compliance-framework/configuration-service v0.1.1 + github.com/compliance-framework/agent v0.1.7 + github.com/compliance-framework/configuration-service v0.1.2-0.20250327060646-625c895cd99c github.com/google/go-github/v71 v71.0.0 github.com/google/uuid v1.6.0 github.com/hashicorp/go-hclog v1.6.3 @@ -18,28 +18,57 @@ require ( github.com/agnivade/levenshtein v1.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/compliance-framework/gooci v0.0.0-20250113172942-411c6f0468f0 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/docker/cli v27.1.1+incompatible // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/fatih/color v1.18.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-containerregistry v0.20.2 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/mux v1.8.1 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.2 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/klauspost/compress v1.17.11 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.1.0 // indirect github.com/open-policy-agent/opa v1.2.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.21.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.63.0 // indirect github.com/prometheus/procfs v0.16.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/robfig/cron/v3 v3.0.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/cobra v1.9.1 // indirect + github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/viper v1.19.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/tchap/go-patricia/v2 v2.3.2 // indirect + github.com/vbatts/tar-split v0.11.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/yashtewari/glob-intersection v0.2.0 // indirect @@ -48,11 +77,16 @@ require ( go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/otel/sdk v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/net v0.37.0 // indirect + golang.org/x/sync v0.12.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect google.golang.org/grpc v1.71.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index b4c1047..58d2d06 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,7 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -26,16 +27,28 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/compliance-framework/agent v0.1.2 h1:XIn6ccsSXh040boPKEcvObNAkCKHrN+krzfiPbTZuJ4= github.com/compliance-framework/agent v0.1.2/go.mod h1:jy/26xgTx9+at64ipTV1oo80pTVyhtlZaSMViQ3cVVQ= +github.com/compliance-framework/agent v0.1.7 h1:1UqJpNdrZrea9TCw9Z0bHN+I/L8Y67fl9teCGIqSU2g= +github.com/compliance-framework/agent v0.1.7/go.mod h1:dAjHJecMEMdKzylOatT54tXmbjgx5d2Wsq4mGnRksZk= github.com/compliance-framework/configuration-service v0.1.1 h1:p/r5vq1FLe0S8j/kLhth4Dvda8xajVPOBjnO9QauMjM= github.com/compliance-framework/configuration-service v0.1.1/go.mod h1:tLKJKXbQbY9Pg/e3BJtJVkqxaejXJMHoE8Yp0NW4lDE= +github.com/compliance-framework/configuration-service v0.1.2-0.20250327060646-625c895cd99c h1:7RIDZy+OcF/9O5EquFchd0W9TY+mlz2zSCVCsReG8Bw= +github.com/compliance-framework/configuration-service v0.1.2-0.20250327060646-625c895cd99c/go.mod h1:tLKJKXbQbY9Pg/e3BJtJVkqxaejXJMHoE8Yp0NW4lDE= +github.com/compliance-framework/gooci v0.0.0-20250113172942-411c6f0468f0 h1:GQMQcASZyfdkSFBiDcv5eOKfynShbb/z9sgiQHIdXVQ= +github.com/compliance-framework/gooci v0.0.0-20250113172942-411c6f0468f0/go.mod h1:UAxtWl/zNG1LxUYUxCbDAvJgJhY5KChnw+xZbXIquAY= github.com/containerd/containerd v1.7.26 h1:3cs8K2RHlMQaPifLqgRyI4VBkoldNdEw62cb7qQga7k= github.com/containerd/containerd v1.7.26/go.mod h1:m4JU0E+h0ebbo9yXD7Hyt+sWnc8tChm7MudCjj4jRvQ= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= +github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -50,8 +63,14 @@ github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7c github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= +github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -67,6 +86,8 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= @@ -98,6 +119,7 @@ github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIx github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -112,6 +134,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= +github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= github.com/google/go-github/v71 v71.0.0 h1:Zi16OymGKZZMm8ZliffVVJ/Q9YZreDKONCr+WUd0Z30= github.com/google/go-github/v71 v71.0.0/go.mod h1:URZXObp2BLlMjwu0O8g4y6VBneUj2bCHgnI8FfgZ51M= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -126,8 +150,12 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -160,6 +188,10 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= @@ -186,6 +218,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -203,19 +237,49 @@ github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2b github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/robfig/cron/v3 v3.0.0 h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E= +github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/swaggo/echo-swagger v1.4.1 h1:Yf0uPaJWp1uRtDloZALyLnvdBeoEL5Kc7DtnjzO/TUk= github.com/swaggo/echo-swagger v1.4.1/go.mod h1:C8bSi+9yH2FLZsnhqMZLIZddpUxZdBYuNHbtaS1Hljc= github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw= @@ -230,10 +294,13 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= +github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= @@ -282,6 +349,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= @@ -294,6 +363,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= @@ -315,6 +385,8 @@ google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/data.go b/internal/data.go index 982b1be..e94e6c2 100644 --- a/internal/data.go +++ b/internal/data.go @@ -8,6 +8,10 @@ import ( "github.com/hashicorp/go-hclog" ) +type GithubSettings struct { + Organization *github.Organization +} + type DataFetcher struct { logger hclog.Logger config map[string]string @@ -20,7 +24,7 @@ func NewDataFetcher(logger hclog.Logger, config map[string]string) *DataFetcher } } -func (df DataFetcher) FetchData() (map[string]any, []*proto.Step, error) { +func (df DataFetcher) FetchData() (GithubSettings, []*proto.Step, error) { steps := make([]*proto.Step, 0) steps = append(steps, &proto.Step{ @@ -48,7 +52,7 @@ func (df DataFetcher) FetchData() (map[string]any, []*proto.Step, error) { // TODO: Rate limiting check and back off - return map[string]any{ - "organization": org, + return GithubSettings{ + Organization: org, }, steps, nil } diff --git a/internal/eval.go b/internal/eval.go index 2237400..4bbac67 100644 --- a/internal/eval.go +++ b/internal/eval.go @@ -3,18 +3,11 @@ package internal import ( "context" "errors" - "fmt" - "maps" - "time" + "slices" policyManager "github.com/compliance-framework/agent/policy-manager" - "github.com/compliance-framework/agent/runner" "github.com/compliance-framework/agent/runner/proto" - "github.com/compliance-framework/configuration-service/sdk" - "github.com/google/go-github/v71/github" - "github.com/google/uuid" "github.com/hashicorp/go-hclog" - "google.golang.org/protobuf/types/known/timestamppb" ) type PolicyEvaluator struct { @@ -45,191 +38,111 @@ func (pe *PolicyEvaluator) GetFindings() []*proto.Finding { // Eval is used to run policies against the data you've collected. You could also consider an // `EvalAndSend` by passing in the `apiHelper` that sends the observations directly to the API. -func (pe *PolicyEvaluator) Eval(data map[string]interface{}, policyPaths []string) (proto.ExecutionStatus, error) { +func (pe *PolicyEvaluator) Eval(data GithubSettings, policyPaths []string) (proto.ExecutionStatus, error) { var accumulatedErrors error - activities := pe.stepActivities evalStatus := proto.ExecutionStatus_SUCCESS - startTime := time.Now() - for _, policyPath := range policyPaths { - steps := make([]*proto.Step, 0) - steps = append(steps, &proto.Step{ - Title: "Compile policy bundle", - Description: "Using a locally addressable policy path, compile the policy files to an in memory executable.", - }) - steps = append(steps, &proto.Step{ - Title: "Execute policy bundle", - Description: "Using previously collected JSON-formatted installed OS package data, execute the compiled policies", - }) - // The Policy Manager aggregates much of the policy execution and output structuring. - results, err := policyManager.New(pe.ctx, pe.logger, policyPath).Execute(pe.ctx, "compliance_plugin", data) - if err != nil { - pe.logger.Error("Failed to evaluate against policy bundle", "error", err) - evalStatus = proto.ExecutionStatus_FAILURE - accumulatedErrors = errors.Join(accumulatedErrors, err) - continue - } - - // Cast the interface{} back to a github Organization so we can use all the helper functions that exist underneath - org_data := data["organization"].(*github.Organization) - org_name := org_data.GetLogin() - - subjectAttributeMap := map[string]string{ - "type": "github-organization", - "name": org_name, - } - subjects := []*proto.SubjectReference{ - { - Type: "github-organization", - Attributes: subjectAttributeMap, - Title: StringAddressed("Github Organization "), - Remarks: StringAddressed("The Github organization that is being audited"), - Props: []*proto.Property{ - { - Name: "organization_name", - Value: org_name, - Remarks: StringAddressed("The name of the Github Organization"), - }, + // Cast the interface{} back to a github Organization so we can use all the helper functions that exist underneath + organization := data.Organization + org_name := organization.GetLogin() + + activities := make([]*proto.Activity, 0) + findings := make([]*proto.Finding, 0) + observations := make([]*proto.Observation, 0) + + steps := make([]*proto.Step, 0) + steps = append(steps, &proto.Step{ + Title: "Compile policy bundle", + Description: "Using a locally addressable policy path, compile the policy files to an in memory executable.", + }) + steps = append(steps, &proto.Step{ + Title: "Execute policy bundle", + Description: "Using previously collected JSON-formatted installed OS package data, execute the compiled policies", + }) + + subjectAttributeMap := map[string]string{ + "type": "github-organization", + "name": org_name, + } + subjects := []*proto.SubjectReference{ + { + Type: "github-organization", + Attributes: subjectAttributeMap, + Title: StringAddressed("Github Organization "), + Remarks: StringAddressed("The Github organization that is being audited"), + Props: []*proto.Property{ + { + Name: "organization_name", + Value: org_name, + Remarks: StringAddressed("The name of the Github Organization"), }, }, - } - actors := []*proto.OriginActor{ - { - Title: "The Continuous Compliance Framework", - Type: "assessment-platform", - Links: []*proto.Link{ - { - Href: "https://compliance-framework.github.io/docs/", - Rel: StringAddressed("reference"), - Text: StringAddressed("The Continuous Compliance Framework"), - }, + }, + } + actors := []*proto.OriginActor{ + { + Title: "The Continuous Compliance Framework", + Type: "assessment-platform", + Links: []*proto.Link{ + { + Href: "https://compliance-framework.github.io/docs/", + Rel: StringAddressed("reference"), + Text: StringAddressed("The Continuous Compliance Framework"), }, - Props: nil, }, - { - Title: "Continuous Compliance Framework - Github Settings plugin", - Type: "tool", - Links: []*proto.Link{ - { - Href: "https://github.com/compliance-framework/plugin-github-settings", - Rel: StringAddressed("reference"), - Text: StringAddressed("The Continuous Compliance Framework' Github Settings Plugin"), - }, + Props: nil, + }, + { + Title: "Continuous Compliance Framework - Github Settings plugin", + Type: "tool", + Links: []*proto.Link{ + { + Href: "https://github.com/compliance-framework/plugin-github-settings", + Rel: StringAddressed("reference"), + Text: StringAddressed("The Continuous Compliance Framework' Github Settings Plugin"), }, - Props: nil, - }, - } - components := []*proto.ComponentReference{ - { - Identifier: "common-components/template", }, - } + Props: nil, + }, + } + components := []*proto.ComponentReference{ + { + Identifier: "common-components/template", + }, + } - activities = append(activities, &proto.Activity{ - Title: "Compile Results", - Description: "Using the output from policy execution, compile the resulting output to Observations and Findings, marking any violations, risks, and other OSCAL-familiar data", - Steps: steps, - }) - - for _, result := range results { - // Observation UUID should differ for each individual subject, but remain consistent when validating the same policy for the same subject. - // This acts as an identifier to show the history of an observation. - observationUUIDMap := map[string]string{ - "policy": result.Policy.Package.PurePackage(), - "policy_file": result.Policy.File, - "policy_path": policyPath, - } - maps.Copy(subjectAttributeMap, observationUUIDMap) - observationUUID, err := sdk.SeededUUID(observationUUIDMap) - if err != nil { - accumulatedErrors = errors.Join(accumulatedErrors, err) - // We've been unable to do much here, but let's try the next one regardless. - continue - } - - // Finding UUID should differ for each individual subject, but remain consistent when validating the same policy for the same subject. - // This acts as an identifier to show the history of a finding. - findingUUIDMap := map[string]string{ - "policy": result.Policy.Package.PurePackage(), - "policy_file": result.Policy.File, - "policy_path": policyPath, - } - maps.Copy(subjectAttributeMap, findingUUIDMap) - findingUUID, err := sdk.SeededUUID(findingUUIDMap) - if err != nil { - accumulatedErrors = errors.Join(accumulatedErrors, err) - // We've been unable to do much here, but let's try the next one regardless. - continue - } - - observation := proto.Observation{ - ID: uuid.New().String(), - UUID: observationUUID.String(), - Collected: timestamppb.New(startTime), - Expires: timestamppb.New(startTime.Add(24 * time.Hour)), - Origins: []*proto.Origin{{Actors: actors}}, - Subjects: subjects, - Activities: activities, - Components: components, - RelevantEvidence: []*proto.RelevantEvidence{ - { - Description: fmt.Sprintf("Policy %v was executed against the Github Settings, using the Github Setting Compliance Plugin", result.Policy.Package.PurePackage()), - }, - }, - } - - newFinding := func() *proto.Finding { - return &proto.Finding{ - ID: uuid.New().String(), - UUID: findingUUID.String(), - Collected: timestamppb.New(time.Now()), - Labels: map[string]string{ - "provider": "github", - "type": "organization", - "service": "organization-settings", - "organization_name": org_name, - "_policy": result.Policy.Package.PurePackage(), - "_policy_path": result.Policy.File, - }, - Origins: []*proto.Origin{{Actors: actors}}, - Subjects: subjects, - Components: components, - RelatedObservations: []*proto.RelatedObservation{{ObservationUUID: observation.ID}}, - Controls: nil, - } - } - - if len(result.Violations) == 0 { - observation.Title = StringAddressed(fmt.Sprintf("Plugin validation on %s passed.", result.Policy.Package.PurePackage())) - observation.Description = fmt.Sprintf("Observed no violations on the %s policy within the Template Compliance Plugin.", result.Policy.Package.PurePackage()) - pe.observations = append(pe.observations, &observation) - - finding := newFinding() - finding.Title = fmt.Sprintf("No violations found on %s", result.Policy.Package.PurePackage()) - finding.Description = fmt.Sprintf("No violations found on the %s policy within the Template Compliance Plugin.", result.Policy.Package.PurePackage()) - finding.Status = &proto.FindingStatus{ - State: runner.FindingTargetStatusSatisfied, - } - pe.findings = append(pe.findings, finding) - } else { - observation.Title = StringAddressed(fmt.Sprintf("The plugin found violations for policy %s.", result.Policy.Package.PurePackage())) - observation.Description = fmt.Sprintf("Observed %d violation(s) on the %s policy within the Template Compliance Plugin.", len(result.Violations), result.Policy.Package.PurePackage()) - pe.observations = append(pe.observations, &observation) - - for _, violation := range result.Violations { - finding := newFinding() - finding.Title = violation.Title - finding.Description = violation.Description - finding.Remarks = StringAddressed(violation.Remarks) - finding.Status = &proto.FindingStatus{ - State: runner.FindingTargetStatusNotSatisfied, - } - pe.findings = append(pe.findings, finding) - } - } + activities = append(activities, &proto.Activity{ + Title: "Compile Results", + Description: "Using the output from policy execution, compile the resulting output to Observations and Findings, marking any violations, risks, and other OSCAL-familiar data", + Steps: steps, + }) + + for _, policyPath := range policyPaths { + // Explicitly reset steps to make things readable + processor := policyManager.NewPolicyProcessor( + pe.logger, + map[string]string{ + "provider": "github", + "type": "organization", + "organization-name": org_name, + "_policy_path": policyPath, + }, + subjects, + components, + actors, + activities, + ) + obs, finds, err := processor.GenerateResults(pe.ctx, policyPath, data) + observations = slices.Concat(observations, obs) + findings = slices.Concat(findings, finds) + if err != nil { + accumulatedErrors = errors.Join(accumulatedErrors, err) } } + pe.observations = observations + pe.findings = findings + return evalStatus, accumulatedErrors } From 301122c5bd62571ef27f52b8868f2b025b6ee545 Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Fri, 11 Apr 2025 15:17:31 +0100 Subject: [PATCH 07/12] Fix unit test for eval --- internal/eval_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/eval_test.go b/internal/eval_test.go index bce79c1..baa0702 100644 --- a/internal/eval_test.go +++ b/internal/eval_test.go @@ -81,8 +81,8 @@ func TestGithubOrg_EvaluatePolicies(t *testing.T) { organization := &github.Organization{} _ = json.Unmarshal([]byte(test_org_data), organization) - data := map[string]interface{}{ - "organization": organization, + data := GithubSettings{ + Organization: organization, } ctx := context.TODO() From 60c9b159ee65ceb202774ae3c14254f235ae31b4 Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Fri, 11 Apr 2025 15:46:18 +0100 Subject: [PATCH 08/12] Map subjects more generically --- internal/eval.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/internal/eval.go b/internal/eval.go index 4bbac67..fd174b4 100644 --- a/internal/eval.go +++ b/internal/eval.go @@ -62,18 +62,20 @@ func (pe *PolicyEvaluator) Eval(data GithubSettings, policyPaths []string) (prot }) subjectAttributeMap := map[string]string{ - "type": "github-organization", - "name": org_name, + "type": "software-organization", + "name": org_name, + "org-url": organization.GetURL(), + "billing-email": organization.GetBillingEmail(), } subjects := []*proto.SubjectReference{ { - Type: "github-organization", + Type: "software-organization", Attributes: subjectAttributeMap, Title: StringAddressed("Github Organization "), Remarks: StringAddressed("The Github organization that is being audited"), Props: []*proto.Property{ { - Name: "organization_name", + Name: "organization-name", Value: org_name, Remarks: StringAddressed("The name of the Github Organization"), }, From 07786d530eeae04549f8961ab3b34fd84640da4e Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Fri, 11 Apr 2025 15:46:34 +0100 Subject: [PATCH 09/12] Fix policy runs as the struct was not json encodable --- internal/data.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/data.go b/internal/data.go index e94e6c2..bdaa8c2 100644 --- a/internal/data.go +++ b/internal/data.go @@ -9,7 +9,7 @@ import ( ) type GithubSettings struct { - Organization *github.Organization + Organization *github.Organization `json:"organization"` } type DataFetcher struct { From 70878966b112f5b6fed2f2a729ad47d83be915f7 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 13 Apr 2025 10:02:46 +0200 Subject: [PATCH 10/12] Update composition of components, data structures, validations, and cleanup --- .gitignore | 2 + examples/data/organization.json | 58 +++++++++++++++++++ internal/data.go | 33 ++++------- internal/eval.go | 53 +++++++++-------- internal/eval_integration_test.go | 37 ++++++++++++ internal/eval_test.go | 6 +- internal/util.go | 5 -- main.go | 96 +++++++++++++------------------ 8 files changed, 176 insertions(+), 114 deletions(-) create mode 100644 examples/data/organization.json create mode 100644 internal/eval_integration_test.go delete mode 100644 internal/util.go diff --git a/.gitignore b/.gitignore index d6f94c4..8571042 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ dist/ .DS_Store # TODO: Change this to match the specific plugin name +/plugin /plugin-* +.envrc diff --git a/examples/data/organization.json b/examples/data/organization.json new file mode 100644 index 0000000..454dee8 --- /dev/null +++ b/examples/data/organization.json @@ -0,0 +1,58 @@ +{ + "login": "compliance-framework", + "id": 141143892, + "node_id": "O_kgDOCGmvVA", + "avatar_url": "https://avatars.githubusercontent.com/u/141143892?v=4", + "html_url": "https://github.com/compliance-framework", + "name": "Compliance Framework", + "description": "", + "public_repos": 53, + "public_gists": 0, + "followers": 35, + "following": 0, + "created_at": "2023-08-01T11:59:15Z", + "updated_at": "2024-11-22T13:28:00Z", + "total_private_repos": 4, + "owned_private_repos": 4, + "private_gists": 0, + "disk_usage": 175119, + "collaborators": 2, + "billing_email": "gustavo.carvalho@container-solutions.com", + "type": "Organization", + "plan": { + "name": "free", + "space": 976562499, + "private_repos": 10000, + "filled_seats": 19, + "seats": 2 + }, + "two_factor_requirement_enabled": false, + "is_verified": false, + "has_organization_projects": true, + "has_repository_projects": true, + "default_repository_permission": "write", + "members_can_create_repositories": true, + "members_can_create_public_repositories": true, + "members_can_create_private_repositories": true, + "members_can_create_internal_repositories": false, + "members_can_fork_private_repositories": false, + "members_allowed_repository_creation_type": "all", + "members_can_create_pages": true, + "members_can_create_public_pages": true, + "members_can_create_private_pages": true, + "web_commit_signoff_required": false, + "advanced_security_enabled_for_new_repositories": false, + "dependabot_alerts_enabled_for_new_repositories": false, + "dependabot_security_updates_enabled_for_new_repositories": false, + "dependency_graph_enabled_for_new_repositories": false, + "secret_scanning_enabled_for_new_repositories": false, + "secret_scanning_push_protection_enabled_for_new_repositories": false, + "secret_scanning_validity_checks_enabled": false, + "url": "https://api.github.com/orgs/compliance-framework", + "events_url": "https://api.github.com/orgs/compliance-framework/events", + "hooks_url": "https://api.github.com/orgs/compliance-framework/hooks", + "issues_url": "https://api.github.com/orgs/compliance-framework/issues", + "members_url": "https://api.github.com/orgs/compliance-framework/members{/member}", + "public_members_url": "https://api.github.com/orgs/compliance-framework/public_members{/member}", + "repos_url": "https://api.github.com/orgs/compliance-framework/repos" +} \ No newline at end of file diff --git a/internal/data.go b/internal/data.go index bdaa8c2..ce39e94 100644 --- a/internal/data.go +++ b/internal/data.go @@ -2,29 +2,26 @@ package internal import ( "context" + policy_manager "github.com/compliance-framework/agent/policy-manager" "github.com/compliance-framework/agent/runner/proto" "github.com/google/go-github/v71/github" "github.com/hashicorp/go-hclog" ) -type GithubSettings struct { - Organization *github.Organization `json:"organization"` -} - type DataFetcher struct { logger hclog.Logger - config map[string]string + client *github.Client } -func NewDataFetcher(logger hclog.Logger, config map[string]string) *DataFetcher { +func NewDataFetcher(logger hclog.Logger, client *github.Client) *DataFetcher { return &DataFetcher{ logger: logger, - config: config, + client: client, } } -func (df DataFetcher) FetchData() (GithubSettings, []*proto.Step, error) { +func (df DataFetcher) FetchData(ctx context.Context, organization string) (*github.Organization, []*proto.Step, error) { steps := make([]*proto.Step, 0) steps = append(steps, &proto.Step{ @@ -35,24 +32,14 @@ func (df DataFetcher) FetchData() (GithubSettings, []*proto.Step, error) { steps = append(steps, &proto.Step{ Title: "Query the organization endpoint", Description: "Using the client's native APIs, Get all the information from the organization endpoint", - Remarks: StringAddressed("More information about data being sent back can be found here: https://docs.github.com/en/rest/orgs/orgs?apiVersion=2022-11-28#get-an-organization"), + Remarks: policy_manager.Pointer("More information about data being sent back can be found here: https://docs.github.com/en/rest/orgs/orgs?apiVersion=2022-11-28#get-an-organization"), }) - df.logger.Info("Establishing github client and querying APIs") - client := github.NewClient(nil).WithAuthToken(df.config["api_key"]) - - ctx := context.Background() - - org, _, err := client.Organizations.Get(ctx, df.config["organization"]) + org, _, err := df.client.Organizations.Get(ctx, organization) if err != nil { - // TODO handle error sensibly - df.logger.Error("Error getting organization information", "org", df.config["organization"], "error", err) + df.logger.Error("Error getting organization information", "org", organization, "error", err) + return nil, nil, err } - // - - // TODO: Rate limiting check and back off - return GithubSettings{ - Organization: org, - }, steps, nil + return org, steps, nil } diff --git a/internal/eval.go b/internal/eval.go index fd174b4..55e61d4 100644 --- a/internal/eval.go +++ b/internal/eval.go @@ -3,6 +3,7 @@ package internal import ( "context" "errors" + "github.com/google/go-github/v71/github" "slices" policyManager "github.com/compliance-framework/agent/policy-manager" @@ -38,15 +39,11 @@ func (pe *PolicyEvaluator) GetFindings() []*proto.Finding { // Eval is used to run policies against the data you've collected. You could also consider an // `EvalAndSend` by passing in the `apiHelper` that sends the observations directly to the API. -func (pe *PolicyEvaluator) Eval(data GithubSettings, policyPaths []string) (proto.ExecutionStatus, error) { +func (pe *PolicyEvaluator) Eval(organization *github.Organization, policyPaths []string) (proto.ExecutionStatus, error) { var accumulatedErrors error evalStatus := proto.ExecutionStatus_SUCCESS - // Cast the interface{} back to a github Organization so we can use all the helper functions that exist underneath - organization := data.Organization - org_name := organization.GetLogin() - activities := make([]*proto.Activity, 0) findings := make([]*proto.Finding, 0) observations := make([]*proto.Observation, 0) @@ -61,23 +58,26 @@ func (pe *PolicyEvaluator) Eval(data GithubSettings, policyPaths []string) (prot Description: "Using previously collected JSON-formatted installed OS package data, execute the compiled policies", }) - subjectAttributeMap := map[string]string{ - "type": "software-organization", - "name": org_name, - "org-url": organization.GetURL(), - "billing-email": organization.GetBillingEmail(), - } subjects := []*proto.SubjectReference{ { - Type: "software-organization", - Attributes: subjectAttributeMap, - Title: StringAddressed("Github Organization "), - Remarks: StringAddressed("The Github organization that is being audited"), + Type: "software-organization", + Attributes: map[string]string{ + "provider": "github", + "type": "organization", + "organization-name": organization.GetName(), + "organization-path": organization.GetLogin(), + }, + Title: policyManager.Pointer("Software Organization"), Props: []*proto.Property{ { - Name: "organization-name", - Value: org_name, - Remarks: StringAddressed("The name of the Github Organization"), + Name: "organization", + Value: organization.GetName(), + }, + }, + Links: []*proto.Link{ + { + Href: organization.GetURL(), + Text: policyManager.Pointer("Organization URL"), }, }, }, @@ -89,8 +89,8 @@ func (pe *PolicyEvaluator) Eval(data GithubSettings, policyPaths []string) (prot Links: []*proto.Link{ { Href: "https://compliance-framework.github.io/docs/", - Rel: StringAddressed("reference"), - Text: StringAddressed("The Continuous Compliance Framework"), + Rel: policyManager.Pointer("reference"), + Text: policyManager.Pointer("The Continuous Compliance Framework"), }, }, Props: nil, @@ -101,8 +101,8 @@ func (pe *PolicyEvaluator) Eval(data GithubSettings, policyPaths []string) (prot Links: []*proto.Link{ { Href: "https://github.com/compliance-framework/plugin-github-settings", - Rel: StringAddressed("reference"), - Text: StringAddressed("The Continuous Compliance Framework' Github Settings Plugin"), + Rel: policyManager.Pointer("reference"), + Text: policyManager.Pointer("The Continuous Compliance Framework' Github Settings Plugin"), }, }, Props: nil, @@ -110,7 +110,10 @@ func (pe *PolicyEvaluator) Eval(data GithubSettings, policyPaths []string) (prot } components := []*proto.ComponentReference{ { - Identifier: "common-components/template", + Identifier: "common-components/github-organization", + }, + { + Identifier: "common-components/version-control", }, } @@ -127,7 +130,7 @@ func (pe *PolicyEvaluator) Eval(data GithubSettings, policyPaths []string) (prot map[string]string{ "provider": "github", "type": "organization", - "organization-name": org_name, + "organization-name": organization.GetName(), "_policy_path": policyPath, }, subjects, @@ -135,7 +138,7 @@ func (pe *PolicyEvaluator) Eval(data GithubSettings, policyPaths []string) (prot actors, activities, ) - obs, finds, err := processor.GenerateResults(pe.ctx, policyPath, data) + obs, finds, err := processor.GenerateResults(pe.ctx, policyPath, organization) observations = slices.Concat(observations, obs) findings = slices.Concat(findings, finds) if err != nil { diff --git a/internal/eval_integration_test.go b/internal/eval_integration_test.go new file mode 100644 index 0000000..4dc9c82 --- /dev/null +++ b/internal/eval_integration_test.go @@ -0,0 +1,37 @@ +//go:build integration + +package internal + +import ( + "context" + "encoding/json" + "github.com/google/go-github/v71/github" + "github.com/hashicorp/go-hclog" + "os" + "testing" +) + +func TestDataFetcher_FetchData(t *testing.T) { + t.Run("Fetch organization data and encode", func(t *testing.T) { + // Simple test to locally validate that data can be fetched correctly + ctx := context.Background() + + fetcher := DataFetcher{ + logger: hclog.NewNullLogger(), + client: github.NewClient(nil).WithAuthToken(os.Getenv("GITHUB_TOKEN")), + } + + org, _, err := fetcher.FetchData(ctx, "compliance-framework") + if err != nil { + t.Error(err) + } + t.Log(org) + + // Here I make sure that org can be encoded properly + data, err := json.Marshal(org) + if err != nil { + t.Error(err) + } + t.Log(string(data)) + }) +} diff --git a/internal/eval_test.go b/internal/eval_test.go index baa0702..651d27a 100644 --- a/internal/eval_test.go +++ b/internal/eval_test.go @@ -81,14 +81,10 @@ func TestGithubOrg_EvaluatePolicies(t *testing.T) { organization := &github.Organization{} _ = json.Unmarshal([]byte(test_org_data), organization) - data := GithubSettings{ - Organization: organization, - } - ctx := context.TODO() evaluator := NewPolicyEvaluator(ctx, logger, steps) - status, err := evaluator.Eval(data, []string{"../examples/policies"}) + status, err := evaluator.Eval(organization, []string{"../examples/policies"}) if status != proto.ExecutionStatus_SUCCESS { t.Fail() diff --git a/internal/util.go b/internal/util.go deleted file mode 100644 index f9d3492..0000000 --- a/internal/util.go +++ /dev/null @@ -1,5 +0,0 @@ -package internal - -func StringAddressed(str string) *string { - return &str -} diff --git a/main.go b/main.go index f25f970..3673d9d 100644 --- a/main.go +++ b/main.go @@ -2,51 +2,40 @@ package main import ( "context" + "errors" "fmt" - "net/url" - "regexp" - "github.com/compliance-framework/agent/runner" "github.com/compliance-framework/agent/runner/proto" "github.com/compliance-framework/plugin-github-settings/internal" + "github.com/google/go-github/v71/github" "github.com/hashicorp/go-hclog" goplugin "github.com/hashicorp/go-plugin" + "github.com/mitchellh/mapstructure" ) -type CompliancePlugin struct { - logger hclog.Logger - config map[string]string +type PluginConfig struct { + Token string `mapstructure:"token"` + Organization string `mapstructure:"organization"` } -type ConfigValidatorFn func(value string) error +type Validator interface { + Validate() error +} -var GithubConfigValidators = map[string]ConfigValidatorFn{ - "api_url": func(value string) error { - if len(value) == 0 { - return fmt.Errorf("api_url cannot be empty") - } - _, err := url.ParseRequestURI(value) - if err != nil { - return err - } - return nil - }, - "api_key": func(value string) error { - if len(value) == 0 { - return fmt.Errorf("api_key cannot be empty") - } - return nil - }, - "organization": func(value string) error { - if len(value) == 0 { - return fmt.Errorf("organization cannot be empty") - } - regex := regexp.MustCompile("^[A-Za-z0-9._-]+$") - if !regex.MatchString(value) { - return fmt.Errorf("organization formatted incorrectly, please check") - } - return nil - }, +func (c *PluginConfig) Validate() error { + if c.Token == "" { + return errors.New("token is required") + } + if c.Organization == "" { + return errors.New("organization is required") + } + return nil +} + +type CompliancePlugin struct { + logger hclog.Logger + config *PluginConfig + githubClient *github.Client } // Configure, and Eval are called at different times during the plugin execution lifecycle, @@ -81,29 +70,24 @@ func (l *CompliancePlugin) Configure(req *proto.ConfigureRequest) (*proto.Config // In this method, you should save any configuration values to your plugin struct, so you can later // re-use them in PrepareForEval and Eval. + config := &PluginConfig{} + err := mapstructure.Decode(req.GetConfig(), config) + if err != nil { + l.logger.Error("Configuration cannot be decoded. Ensure the correct data has been passed.") + return nil, err + } - passed_config := req.GetConfig() - - l.logger.Info("Validating configuration") - errored := false - for config_key, validator := range GithubConfigValidators { - value, ok := passed_config[config_key] - if !ok { - l.logger.Error("Config Validator failed", "key", config_key, "value", value, "not_set", true) - errored = true - continue - } - if err := validator(value); err != nil { - l.logger.Error("Config Validator failed", "key", config_key, "value", value, "error", err) - errored = true + // We could potentially move this interface to the shared agent SDK, so it can easily be used across plugins. + if v, ok := interface{}(config).(Validator); ok { + err = v.Validate() + if err != nil { + l.logger.Error("Configuration validation failed. Ensure the correct data has been passed.") + return nil, err } } - if errored { - l.logger.Error("Invalid configuration for the plugin. Check logs for the issues found") - } else { - l.logger.Info("Config Validator passed - continuing") - } - l.config = passed_config + + l.config = config + l.githubClient = github.NewClient(nil).WithAuthToken(l.config.Token) return &proto.ConfigureResponse{}, nil } @@ -119,9 +103,9 @@ func (l *CompliancePlugin) Eval(request *proto.EvalRequest, apiHelper runner.Api activities := make([]*proto.Activity, 0) - dataFetcher := internal.NewDataFetcher(l.logger, l.config) + dataFetcher := internal.NewDataFetcher(l.logger, l.githubClient) - data, collectSteps, err := dataFetcher.FetchData() + data, collectSteps, err := dataFetcher.FetchData(ctx, l.config.Organization) if err != nil { return &proto.EvalResponse{ Status: proto.ExecutionStatus_FAILURE, From cfca6f6dbf62909bfb8065445662545516cbe6a1 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 13 Apr 2025 10:04:56 +0200 Subject: [PATCH 11/12] Remove Gustavos email --- examples/data/organization.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/organization.json b/examples/data/organization.json index 454dee8..3d5ba40 100644 --- a/examples/data/organization.json +++ b/examples/data/organization.json @@ -17,7 +17,7 @@ "private_gists": 0, "disk_usage": 175119, "collaborators": 2, - "billing_email": "gustavo.carvalho@container-solutions.com", + "billing_email": "ccf@example.com", "type": "Organization", "plan": { "name": "free", From 6d9694f055c7eca17d3fcea21dbeac5b0720b727 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 13 Apr 2025 10:41:04 +0200 Subject: [PATCH 12/12] Update configuration in README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 6cd81c8..bf12341 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,7 @@ The plugin configuration must be created and managed by the agent, but expects t plugins: github: config: - api_key: github_pat_1234.... # The configured Github PAT for the organization scopes - api_url: https://api.github.com # The URL for the API endpoint for GH installations on-premise + token: github_pat_1234.... # The configured Github PAT for the organization scopes organization: test-org # The name of the organization ... ```