Support Alpine Linux #194 (#545)

* Support Alpine Linux #194

* Fix testcase

* Fix README

* Fix dep files

* Fix changelog

* Bump up version
This commit is contained in:
Kota Kanbe
2017-12-01 23:17:28 +09:00
committed by GitHub
parent d00e912934
commit e788e6a5ad
26 changed files with 502 additions and 120 deletions

View File

@@ -1,5 +1,7 @@
# Change Log
## v0.4.1 and later, see [GitHub release](https://github.com/future-architect/vuls/releases)
## [v0.4.0](https://github.com/future-architect/vuls/tree/v0.4.0) (2017-08-25)
[Full Changelog](https://github.com/future-architect/vuls/compare/v0.3.0...v0.4.0)
@@ -509,4 +511,4 @@
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*

48
Gopkg.lock generated
View File

@@ -4,14 +4,14 @@
[[projects]]
name = "github.com/Azure/azure-sdk-for-go"
packages = ["storage"]
revision = "df4dd90d076ebbf6e87d08d3f00bfac8ff4bde1a"
version = "v10.3.1-beta"
revision = "7692b0cef22674113fcf71cc17ac3ccc1a7fef48"
version = "v11.2.2-beta"
[[projects]]
name = "github.com/Azure/go-autorest"
packages = ["autorest","autorest/adal","autorest/azure","autorest/date"]
revision = "f6be1abbb5abd0517522f850dd785990d373da7e"
version = "v8.4.0"
revision = "c67b24a8e30d876542a85022ebbdecf0e5a935e8"
version = "v9.4.1"
[[projects]]
name = "github.com/BurntSushi/toml"
@@ -28,8 +28,8 @@
[[projects]]
name = "github.com/aws/aws-sdk-go"
packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","service/s3","service/sts"]
revision = "c652f9369083515c3ddf1fbaf6df68da2c101545"
version = "v1.12.1"
revision = "e4f7e38b704e3ed0acc4a7f8196b777696f6f1f3"
version = "v1.12.30"
[[projects]]
name = "github.com/boltdb/bolt"
@@ -52,20 +52,20 @@
[[projects]]
name = "github.com/dgrijalva/jwt-go"
packages = ["."]
revision = "d2709f9f1f31ebcda9651b03077758c1f3a0018c"
version = "v3.0.0"
revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29"
version = "v3.1.0"
[[projects]]
name = "github.com/go-ini/ini"
packages = ["."]
revision = "20b96f641a5ea98f2f8619ff4f3e061cff4833bd"
version = "v1.28.2"
revision = "32e4c1e6bc4e7d0d8451aa6b75200d19e37a536a"
version = "v1.32.0"
[[projects]]
name = "github.com/go-redis/redis"
packages = [".","internal","internal/consistenthash","internal/hashtag","internal/pool","internal/proto"]
revision = "975882d73d21759d45a4eb49652064083bc23e61"
version = "v6.7.0"
revision = "e5e021257bfc6d5fbf0beac33e30194311fb189f"
version = "v6.7.4"
[[projects]]
name = "github.com/go-sql-driver/mysql"
@@ -136,7 +136,7 @@
branch = "master"
name = "github.com/kotakanbe/go-cve-dictionary"
packages = ["config","db","jvn","log","models","nvd","util"]
revision = "f5406ffe8226f01f64544723339c6a17b2bd74af"
revision = "a64c5fc25cd9669b213986e1a02831c71a5c601d"
[[projects]]
name = "github.com/kotakanbe/go-pingscanner"
@@ -148,7 +148,7 @@
branch = "master"
name = "github.com/kotakanbe/goval-dictionary"
packages = ["config","db","db/rdb","log","models"]
revision = "fd8ff5a6343912117d1b7db16fbd5fa1f4116c3a"
revision = "dca4f21940cbf2245a50817177fed7eb6793e72c"
[[projects]]
branch = "master"
@@ -160,7 +160,7 @@
branch = "master"
name = "github.com/lib/pq"
packages = [".","hstore","oid"]
revision = "b77235e3890a962fe8a6f8c4c7198679ca7814e7"
revision = "8c6ee72f3e6bcb1542298dd5f76cb74af9742cec"
[[projects]]
name = "github.com/mattn/go-colorable"
@@ -183,8 +183,8 @@
[[projects]]
name = "github.com/mattn/go-sqlite3"
packages = ["."]
revision = "ca5e3819723d8eeaf170ad510e7da1d6d2e94a08"
version = "v1.2.0"
revision = "ed69081a91fd053f17672236b0dd52ba7485e1a3"
version = "v1.4.0"
[[projects]]
branch = "master"
@@ -208,7 +208,7 @@
branch = "master"
name = "github.com/nsf/termbox-go"
packages = ["."]
revision = "4ed959e0540971545eddb8c75514973d670cf739"
revision = "aa4a75b1c20a2b03751b1a9f7e41d58bd6f71c43"
[[projects]]
name = "github.com/parnurzeal/gorequest"
@@ -238,7 +238,7 @@
branch = "master"
name = "github.com/sirupsen/logrus"
packages = ["."]
revision = "89742aefa4b206dcf400792f3bd35b542998eb3b"
revision = "95cd2b9c79aa5e72ab0bc69b7ccc2be15bf850f6"
[[projects]]
branch = "master"
@@ -250,29 +250,29 @@
branch = "master"
name = "golang.org/x/crypto"
packages = ["curve25519","ed25519","ed25519/internal/edwards25519","ssh","ssh/agent","ssh/terminal"]
revision = "c84b36c635ad003a10f0c755dff5685ceef18c71"
revision = "9f005a07e0d31d45e6656d241bb5c0f2efd4bc94"
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = ["context","idna","publicsuffix","websocket"]
revision = "0a9397675ba34b2845f758fe3cd68828369c6517"
revision = "9dfe39835686865bff950a07b394c12a98ddc811"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["unix","windows"]
revision = "314a259e304ff91bd6985da2a7149bbf91237993"
revision = "0ac51a24ef1c37380f98ba8b98f56e3bffd59850"
[[projects]]
branch = "master"
name = "golang.org/x/text"
packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"]
revision = "1cbadb444a806fd9430d14ad08967ed91da4fa0a"
revision = "88f656faf3f37f690df1a32515b479415e1a6769"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "a0cf09ec0aec110a8743e9c6085f35052dcb9f1c5c9174efd89f179f5df64dfc"
inputs-digest = "58ae46498625e705c582d70591148e07dbac30bc4f75cadef3d2fda514cd5099"
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -88,3 +88,7 @@
[[constraint]]
branch = "master"
name = "github.com/kotakanbe/go-cve-dictionary"
[[constraint]]
branch = "master"
name = "github.com/kotakanbe/goval-dictionary"

View File

@@ -139,7 +139,7 @@ Vulsは上に挙げた手動運用での課題を解決するツールであり
# Main Features
- サーバに存在する脆弱性をスキャン
- FreeBSD, Ubuntu, Debian, CentOS, Amazon Linux, RHEL, Oracle Linux, SUSE Enterprise, Raspbianに対応
- Alpine, Ubuntu, Debian, CentOS, Amazon Linux, RHEL, Oracle Linux, SUSE Enterprise, Raspbian, FreeBSD に対応
- クラウド、オンプレミス、Docker
- 高精度なスキャン
- Vulsは複数の脆弱性データベース、複数の検知方法を組み合わせることで高精度なスキャンを実現している
@@ -324,6 +324,7 @@ $ goval-dictionary fetch-redhat 7
今回はスキャン対象がCentOS 7なので、RedHat 7のOVALを取得している。
他の種類のOSをスキャンする場合は以下を参照し、スキャン対象用のOVALを取得しておくこと
- [Alpine](https://github.com/kotakanbe/goval-dictionary#usage-fetch-alpine-secdb-as-oval-data-type)
- [RedHat, CentOS](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-redhat)
- [Debian](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-debian)
- [Ubuntu](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-ubuntu)
@@ -593,15 +594,16 @@ Vulsをスキャン対象サーバにデプロイする。Vulsはローカルホ
| Distribution| Scan Speed | Need Root Privilege | OVAL | Need Internet Access <br>on scan tareget|
|:------------|:--------------------------------------:|:-------------------:|:----------:|:---------------------------------------:|
| CentOS | Fast |  No | Supported | No |
| Alpine | Fast |  No | Supported | No |
| CentOS | Fast |  No | Supported | No |
| RHEL | Fast |  No | Supported | No |
| Oracle | Fast |  No | Supported | No |
| Ubuntu | Fast |  No | Supported | No |
| Debian | Fast |  No | Supported | No |
| Raspbian |1st time: Slow <br> From 2nd time: Fast | Need | No | Need |
| FreeBSD | Fast |  No | No | Need |
| Amazon | Fast |  No | No | Need |
| SUSE Enterprise | Fast |  No | Supported | No|
| Amazon | Fast |  No | No | Need |
| SUSE Enterprise | Fast |  No | Supported | No |
----
@@ -612,7 +614,8 @@ Vulsをスキャン対象サーバにデプロイする。Vulsはローカルホ
| Distribution| Scan Speed | Need Root Privilege | OVAL | Need Internet Access <br>on scan tareget|
|:------------|:-------------------------------------:|:-------------------------:|:---------:|:---------------------------------------:|
| CentOS | Slow |  No | Supported | Need |
| Alpine | Fast |  No | Supported | No |
| CentOS | Slow |  No | Supported | Need |
| RHEL | Slow |  Need | Supported | Need |
| Oracle | Slow |  Need | Supported | Need |
| Ubuntu |1st time: Slow <br> From 2nd time: Fast| Need | Supported | Need |
@@ -620,7 +623,7 @@ Vulsをスキャン対象サーバにデプロイする。Vulsはローカルホ
| Raspbian |1st time: Slow <br> From 2nd time: Fast| Need | No | Need |
| FreeBSD | Fast |  No | No | Need |
| Amazon | Slow |  No | No | Need |
| SUSE Enterprise | Fast |  No | Supported | No|
| SUSE Enterprise | Fast |  No | Supported | No |
- On Ubuntu, Debian and Raspbian
@@ -634,7 +637,7 @@ Vulsをスキャン対象サーバにデプロイする。Vulsはローカルホ
- On RHEL, Oracle, Amazon and FreeBSD
`yum changelog`でアップデート対象のパッケージのチェンジログを取得する(パースはしない)。
- On SUSE Enterprise Linux
- On SUSE Enterprise Linux and Alpine Linux
Same as fast scan mode for now.
----
@@ -657,6 +660,7 @@ web/app server in the same configuration under the load balancer
| Distribution| Release |
|:------------|-------------------:|
| Alpine | 3.2 and later |
| Ubuntu | 12, 14, 16|
| Debian | 7, 8, 9|
| RHEL | 5, 6, 7|
@@ -910,6 +914,7 @@ configtestサブコマンドは、config.tomlで定義されたサーバ/コン
| Distribution | Release | Requirements |
|:-------------|-------------------:|:-------------|
| Alpine | 3.2 and later | - |
| Ubuntu | 12, 14, 16| - |
| Debian | 7, 8, 9| reboot-notifier|
| CentOS | 6, 7| - |
@@ -933,6 +938,7 @@ Deep Scan Modeでスキャンするためには、下記のパッケージが必
| Distribution | Release | Requirements |
|:-------------|-------------------:|:-------------|
| Alpine | 3.2 and later | - |
| Ubuntu | 12, 14, 16| - |
| Debian | 7, 8, 9| aptitude, reboot-notifier |
| CentOS | 6, 7| yum-plugin-changelog, yum-utils |
@@ -1874,7 +1880,8 @@ Run with --debug, --sql-debug option.
[Riak docs](http://docs.basho.com/riak/latest/ops/tuning/open-files-limit/) is awesome.
- Does Vuls accept ssh connections with fish-shell or old zsh as the login shell?
No, Vuls needs a user on the server for bash login. see also [#8](/../../issues/8)
~~No, Vuls needs a user on the server for bash login. see also [#8](/../../issues/8)~~
Yes, fixed in [#545](https://github.com/future-architect/vuls/pull/545)
- Windows
Use Microsoft Baseline Security Analyzer. [MBSA](https://technet.microsoft.com/en-us/security/cc184924.aspx)

View File

@@ -144,7 +144,7 @@ Vuls is a tool created to solve the problems listed above. It has the following
# Main Features
- Scan for any vulnerabilities in Linux/FreeBSD Server
- Supports FreeBSD, Ubuntu, Debian, CentOS, Amazon Linux, RHEL, Oracle Linux, SUSE Enterprise Linux and Raspbian
- Supports Alpine, Ubuntu, Debian, CentOS, Amazon Linux, RHEL, Oracle Linux, SUSE Enterprise Linux and Raspbian, FreeBSD
- Cloud, on-premise, Docker
- High quality scan
- Vuls uses Multiple vulnerability databases
@@ -331,6 +331,7 @@ $ goval-dictionary fetch-redhat 7
```
If you want to scan other than CentOS 7, fetch OVAL data according to the OS type and version of scan target server in advance.
- [Alpine](https://github.com/kotakanbe/goval-dictionary#usage-fetch-alpine-secdb-as-oval-data-type)
- [RedHat, CentOS](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-redhat)
- [Debian](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-debian)
- [Ubuntu](https://github.com/kotakanbe/goval-dictionary#usage-fetch-oval-data-from-ubuntu)
@@ -600,16 +601,16 @@ On the aggregation server, you can refer to the scanning result of each scan tar
| Distribution| Scan Speed | Need Root Privilege | OVAL | Need Internet Access <br>on scan tareget|
|:------------|:--------------------------------------:|:-------------------:|:----------:|:---------------------------------------:|
| CentOS | Fast |  No | Supported | No |
| Alpine | Fast |  No | Supported | No |
| CentOS | Fast |  No | Supported | No |
| RHEL | Fast |  No | Supported | No |
| Oracle | Fast |  No | Supported | No |
| Ubuntu | Fast |  No | Supported | No |
| Debian | Fast |  No | Supported | No |
| Raspbian |1st time: Slow <br> From 2nd time: Fast | Need | No | Need |
| FreeBSD | Fast |  No | No | Need |
| Amazon | Fast |  No | No | Need |
| SUSE Enterprise | Fast |  No | Supported | No|
| Amazon | Fast |  No | No | Need |
| SUSE Enterprise | Fast |  No | Supported | No |
---------
@@ -618,7 +619,8 @@ On the aggregation server, you can refer to the scanning result of each scan tar
| Distribution| Scan Speed | Need Root Privilege | OVAL | Need Internet Access <br>on scan tareget|
|:------------|:-------------------------------------:|:-------------------------:|:---------:|:---------------------------------------:|
| CentOS | Slow |  No | Supported | Need |
| Alpine | Fast |  No | Supported | No |
| CentOS | Slow |  No | Supported | Need |
| RHEL | Slow |  Need | Supported | Need |
| Oracle | Slow |  Need | Supported | Need |
| Ubuntu |1st time: Slow <br> From 2nd time: Fast| Need | Supported | Need |
@@ -626,7 +628,7 @@ On the aggregation server, you can refer to the scanning result of each scan tar
| Raspbian |1st time: Slow <br> From 2nd time: Fast| Need | No | Need |
| FreeBSD | Fast |  No | No | Need |
| Amazon | Slow |  No | No | Need |
| SUSE Enterprise | Fast |  No | Supported | No|
| SUSE Enterprise | Fast |  No | Supported | No |
- On Ubuntu, Debian and Raspbian
@@ -641,7 +643,7 @@ Vuls issues `yum changelog` to get changelogs of upgradable packages at once and
- On RHEL, Oracle, Amazon and FreeBSD
Detect CVE IDs by using package manager.
- On SUSE Enterprise Linux
- On SUSE Enterprise Linux and Alpine Linux
Same as fast scan mode for now.
----
@@ -677,6 +679,7 @@ If there is a staging environment with the same configuration as the production
| FreeBSD | 10, 11|
| SUSE Enterprise | 11, 12|
| Raspbian | Jessie, Stretch |
| Alpine | 3.2 and later |
----
@@ -918,6 +921,7 @@ The configtest subcommand checks whether vuls is able to connect via SSH to serv
| Distribution | Release | Requirements |
|:-------------|-------------------:|:-------------|
| Alpine | 3.2 and later | - |
| Ubuntu | 12, 14, 16| - |
| Debian | 7, 8, 9| reboot-notifier|
| CentOS | 6, 7| - |
@@ -939,6 +943,7 @@ In order to scan with deep scan mode, the following dependencies are required, s
| Distribution | Release | Requirements |
|:-------------|-------------------:|:-------------|
| Alpine | 3.2 and later | - |
| Ubuntu | 12, 14, 16| - |
| Debian | 7, 8, 9| aptitude, reboot-notifier |
| CentOS | 6, 7| yum-plugin-changelog, yum-utils |
@@ -1855,7 +1860,8 @@ Run with --debug, --sql-debug option.
[Riak docs](http://docs.basho.com/riak/latest/ops/tuning/open-files-limit/) is awesome.
- Does Vuls accept SSH connections with fish-shell or old zsh as the login shell?
No, Vuls needs a user on the server for bash login. see also [#8](/../../issues/8)
~~No, Vuls needs a user on the server for bash login. see also [#8](/../../issues/8)~~
Yes, fixed in [#545](https://github.com/future-architect/vuls/pull/545)
- Windows
Use Microsoft Baseline Security Analyzer. [MBSA](https://technet.microsoft.com/en-us/security/cc184924.aspx)

View File

@@ -76,6 +76,9 @@ const (
// SUSEOpenstackCloud is
SUSEOpenstackCloud = "suse.openstack.cloud"
// Alpine is
Alpine = "alpine"
)
const (
@@ -466,7 +469,7 @@ func (s ServerInfo) GetServerName() string {
if len(s.Container.ContainerID) == 0 {
return s.ServerName
}
return fmt.Sprintf("%s@%s", s.Container.ContainerID, s.ServerName)
return fmt.Sprintf("%s@%s", s.Container.Name, s.ServerName)
}
// Distro has distribution info

View File

@@ -53,9 +53,11 @@
<y:Geometry height="90.44247787610618" width="268.0" x="309.6849206349206" y="86.0"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="60.53125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="170.763671875" x="48.61816406250006" y="14.95561393805309">Get installed packages
<y:NodeLabel alignment="right" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="88.796875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="170.763671875" x="48.61816406250006" y="0.8228014380530908">Get installed packages
Alpine: apk
Debian/Ubuntu: dpkg-query
Amazon/RHEL/CentOS: rpm
SUSE: zypper
FreeBSD: pkg<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
@@ -264,7 +266,7 @@ Debian/Ubuntu: aptitude changelog<y:LabelModel>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="51.806640625" x="183.35883739927397" y="2.000003510871693">Amazon
<y:EdgeLabel alignment="right" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="51.806640625" x="183.35883739927397" y="2.000003510871693">Amazon
FreeBSD<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
@@ -298,7 +300,6 @@ FreeBSD<y:LabelModel>
</data>
</edge>
<edge id="e4" source="n1" target="n3">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="-123.36984126984123" ty="0.0">
@@ -306,11 +307,13 @@ FreeBSD<y:LabelModel>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="74.6640625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="77.078125" x="-97.68364242524859" y="5.005267793098369">CentOS
<y:EdgeLabel alignment="right" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="102.9296875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="77.078125" x="-97.68364242524859" y="5.005267793098369">Alpine Linux
CentOS
RHEL
Ubuntu
Debian
Oracle Linux<y:LabelModel>
Oracle Linux
Suse<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
@@ -323,7 +326,6 @@ Oracle Linux<y:LabelModel>
</data>
</edge>
<edge id="e5" source="n4" target="n3">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
@@ -364,7 +366,6 @@ Oracle Linux<y:LabelModel>
</data>
</edge>
<edge id="e9" source="n3" target="n5">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
@@ -375,7 +376,6 @@ Oracle Linux<y:LabelModel>
</data>
</edge>
<edge id="e10" source="n1" target="n7">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
@@ -396,7 +396,6 @@ Oracle Linux<y:LabelModel>
</data>
</edge>
<edge id="e11" source="n10" target="n3">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="-125.78842258255952" ty="0.0">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

@@ -53,10 +53,12 @@
<y:Geometry height="90.44247787610618" width="268.0" x="309.6849206349206" y="86.0"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="60.53125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="170.763671875" x="48.61816406250006" y="14.95561393805309">Get installed packages
<y:NodeLabel alignment="right" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="88.796875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="170.763671875" x="48.61816406250006" y="0.8228014380530908">Get installed packages
Alpine Linux: apk
Debian/Ubuntu: dpkg-query
Amazon/RHEL/CentOS: rpm
FreeBSD: pkg<y:LabelModel>
FreeBSD: pkg
SUSE: zypper<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@@ -235,7 +237,6 @@ Amazon / RHEL: yum changelog<y:LabelModel>
</node>
<node id="n13" yfiles.foldertype="group">
<data key="d4"/>
<data key="d5"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
@@ -315,13 +316,13 @@ Amazon / RHEL: yum changelog<y:LabelModel>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="46.3984375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="56.98046875" x="-66.95987036992159" y="-48.39843398912808">Debian
<y:EdgeLabel alignment="right" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="46.3984375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="56.98046875" x="-257.65322875976574" y="2.0000035108718635">Debian
Ubuntu
Raspbian<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="1.9999999999998863" distanceToCenter="false" position="right" ratio="0.02215389573439544" segment="0"/>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="1.9999999999998863" distanceToCenter="false" position="left" ratio="0.8652035780364729" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
@@ -379,13 +380,13 @@ Raspbian<y:LabelModel>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="46.3984375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="51.806640625" x="10.125014629061297" y="-48.39843398912805">Amazon
<y:EdgeLabel alignment="right" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="46.3984375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="51.806640625" x="200.87829463898197" y="4.000003510871693">Amazon
RHEL
FreeBSD<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="1.9999999999998863" distanceToCenter="false" position="left" ratio="0.022401276994204813" segment="0"/>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="6.999999999999886" distanceToCenter="false" position="right" ratio="0.8192728556300707" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
@@ -442,7 +443,6 @@ FreeBSD<y:LabelModel>
</data>
</edge>
<edge id="e11" source="n11" target="n7">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="-24.34091537610618">
@@ -455,7 +455,6 @@ FreeBSD<y:LabelModel>
</data>
</edge>
<edge id="e12" source="n8" target="n12">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
@@ -466,7 +465,6 @@ FreeBSD<y:LabelModel>
</data>
</edge>
<edge id="e13" source="n12" target="n7">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
@@ -477,7 +475,6 @@ FreeBSD<y:LabelModel>
</data>
</edge>
<edge id="e14" source="n9" target="n13">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="10.8330078125"/>
@@ -487,6 +484,30 @@ FreeBSD<y:LabelModel>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e15" source="n1" target="n7">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="999.0" y="226.44247787610618"/>
<y:Point x="999.0" y="570.8409153761062"/>
<y:Point x="743.3698412698412" y="570.8409153761062"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:EdgeLabel alignment="right" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="76.8203125" x="422.923942251054" y="13.867191010871807">Alpine Linux
SUSE<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.8856709076027529" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d7">
<y:Resources/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View File

@@ -29,7 +29,7 @@ import (
)
// Version of Vuls
var version = "0.4.0"
var version = "0.4.2"
// Revision of Git
var revision string

82
oval/alpine.go Normal file
View File

@@ -0,0 +1,82 @@
/* Vuls - Vulnerability Scanner
Copyright (C) 2016 Future Architect, Inc. Japan.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package oval
import (
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
ovalmodels "github.com/kotakanbe/goval-dictionary/models"
)
// Alpine is the struct of Alpine Linux
type Alpine struct {
Base
}
// NewAlpine creates OVAL client for SUSE
func NewAlpine() Alpine {
return Alpine{
Base{
family: config.Alpine,
},
}
}
// FillWithOval returns scan result after updating CVE info by OVAL
func (o Alpine) FillWithOval(r *models.ScanResult) (err error) {
var relatedDefs ovalResult
if o.isFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
return err
}
} else {
if relatedDefs, err = getDefsByPackNameFromOvalDB(r); err != nil {
return err
}
}
for _, defPacks := range relatedDefs.entries {
o.update(r, defPacks)
}
return nil
}
func (o Alpine) update(r *models.ScanResult, defPacks defPacks) {
ovalContent := *o.convertToModel(&defPacks.def)
cveID := defPacks.def.Advisory.Cves[0].CveID
vinfo, ok := r.ScannedCves[cveID]
if !ok {
util.Log.Debugf("%s is newly detected by OVAL", cveID)
vinfo = models.VulnInfo{
CveID: cveID,
Confidence: models.OvalMatch,
CveContents: models.NewCveContents(ovalContent),
}
}
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family)
vinfo.AffectedPackages.Sort()
r.ScannedCves[cveID] = vinfo
}
func (o Alpine) convertToModel(def *ovalmodels.Definition) *models.CveContent {
return &models.CveContent{
CveID: def.Advisory.Cves[0].CveID,
}
}

View File

@@ -64,7 +64,7 @@ func (o DebianBase) update(r *models.ScanResult, defPacks defPacks) {
defPacks.actuallyAffectedPackNames[pack.Name] = notFixedYet
}
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages)
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family)
vinfo.AffectedPackages.Sort()
r.ScannedCves[defPacks.def.Debian.CveID] = vinfo
}

View File

@@ -21,7 +21,6 @@ import (
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"github.com/future-architect/vuls/config"
@@ -132,15 +131,14 @@ func (b Base) CheckIfOvalFresh(osFamily, release string) (ok bool, err error) {
}
}
major := strings.Split(release, ".")[0]
since := time.Now()
since = since.AddDate(0, 0, -3)
if lastModified.Before(since) {
util.Log.Warnf("OVAL for %s %s is old, last modified is %s. It's recommended to update OVAL to improve scanning accuracy. How to update OVAL database, see https://github.com/kotakanbe/goval-dictionary#usage",
osFamily, major, lastModified)
osFamily, release, lastModified)
return false, nil
}
util.Log.Infof("OVAL is fresh: %s %s ", osFamily, major)
util.Log.Infof("OVAL is fresh: %s %s ", osFamily, release)
return true, nil
}

View File

@@ -129,7 +129,7 @@ func (o RedHatBase) update(r *models.ScanResult, defPacks defPacks) {
notFixedYet, _ := defPacks.actuallyAffectedPackNames[pack.Name]
defPacks.actuallyAffectedPackNames[pack.Name] = notFixedYet
}
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages)
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family)
vinfo.AffectedPackages.Sort()
r.ScannedCves[cve.CveID] = vinfo
}

View File

@@ -96,7 +96,7 @@ func (o SUSE) update(r *models.ScanResult, defPacks defPacks) {
notFixedYet, _ := defPacks.actuallyAffectedPackNames[pack.Name]
defPacks.actuallyAffectedPackNames[pack.Name] = notFixedYet
}
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages)
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family)
vinfo.AffectedPackages.Sort()
r.ScannedCves[defPacks.def.Title] = vinfo
}

View File

@@ -48,7 +48,7 @@ type defPacks struct {
actuallyAffectedPackNames map[string]bool
}
func (e defPacks) toPackStatuses(family string, packs models.Packages) (ps models.PackageStatuses) {
func (e defPacks) toPackStatuses(family string) (ps models.PackageStatuses) {
for name, notFixedYet := range e.actuallyAffectedPackNames {
ps = append(ps, models.PackageStatus{
Name: name,
@@ -59,10 +59,13 @@ func (e defPacks) toPackStatuses(family string, packs models.Packages) (ps model
}
func (e *ovalResult) upsert(def ovalmodels.Definition, packName string, notFixedYet bool) (upserted bool) {
for i, entry := range e.entries {
if entry.def.DefinitionID == def.DefinitionID {
e.entries[i].actuallyAffectedPackNames[packName] = notFixedYet
return true
// alpine's entry is empty since Alpine secdb is not OVAL format
if def.DefinitionID != "" {
for i, entry := range e.entries {
if entry.def.DefinitionID == def.DefinitionID {
e.entries[i].actuallyAffectedPackNames[packName] = notFixedYet
return true
}
}
}
e.entries = append(e.entries, defPacks{
@@ -345,7 +348,7 @@ func lessThan(family, versionRelease string, packB ovalmodels.Package) (bool, er
return false, err
}
return vera.LessThan(verb), nil
case config.Oracle, config.SUSEEnterpriseServer:
case config.Oracle, config.SUSEEnterpriseServer, config.Alpine:
vera := rpmver.NewVersion(versionRelease)
verb := rpmver.NewVersion(packB.Version)
return vera.LessThan(verb), nil

View File

@@ -117,7 +117,6 @@ func TestDefpacksToPackStatuses(t *testing.T) {
{
in: in{
family: "ubuntu",
packs: models.Packages{},
dp: defPacks{
def: ovalmodels.Definition{
AffectedPacks: []ovalmodels.Package{
@@ -155,7 +154,7 @@ func TestDefpacksToPackStatuses(t *testing.T) {
},
}
for i, tt := range tests {
actual := tt.in.dp.toPackStatuses(tt.in.family, tt.in.packs)
actual := tt.in.dp.toPackStatuses(tt.in.family)
sort.Slice(actual, func(i, j int) bool {
return actual[i].Name < actual[j].Name
})

View File

@@ -142,21 +142,11 @@ func (api cvedictClient) FetchCveDetailsFromCveDB(cveIDs []string) (cveDetails [
cveconfig.Conf.DebugSQL = config.Conf.DebugSQL
var driver cvedb.DB
if driver, err = cvedb.NewDB(cveconfig.Conf.DBType); err != nil {
if driver, err = cvedb.NewDB(cveconfig.Conf.DBType, cveconfig.Conf.DBPath, cveconfig.Conf.DebugSQL); err != nil {
log.Error(err)
return []*cve.CveDetail{}, fmt.Errorf("Failed to New DB. err: %s", err)
}
util.Log.Debugf("Opening DB (%s).", driver.Name())
if err := driver.OpenDB(
cveconfig.Conf.DBType,
cveconfig.Conf.DBPath,
cveconfig.Conf.DebugSQL,
); err != nil {
return []*cve.CveDetail{},
fmt.Errorf("Failed to open DB. err: %s", err)
}
for _, cveID := range cveIDs {
cveDetail := driver.Get(cveID)
if len(cveDetail.CveID) == 0 {
@@ -276,19 +266,11 @@ func (api cvedictClient) FetchCveDetailsByCpeNameFromDB(cpeName string) (cveDeta
cveconfig.Conf.DebugSQL = config.Conf.DebugSQL
var driver cvedb.DB
if driver, err = cvedb.NewDB(cveconfig.Conf.DBType); err != nil {
if driver, err = cvedb.NewDB(cveconfig.Conf.DBType, cveconfig.Conf.DBPath, cveconfig.Conf.DebugSQL); err != nil {
log.Error(err)
return []*cve.CveDetail{}, fmt.Errorf("Failed to New DB. err: %s", err)
}
util.Log.Debugf("Opening DB (%s).", driver.Name())
if err = driver.OpenDB(
cveconfig.Conf.DBType,
cveconfig.Conf.DBPath,
cveconfig.Conf.DebugSQL,
); err != nil {
return []*cve.CveDetail{},
fmt.Errorf("Failed to open DB. err: %s", err)
}
return driver.GetByCpeName(cpeName), nil
}

View File

@@ -19,7 +19,6 @@ package report
import (
"fmt"
"strings"
"time"
c "github.com/future-architect/vuls/config"
@@ -181,6 +180,9 @@ func FillWithOval(r *models.ScanResult) (err error) {
// TODO other suse family
ovalClient = oval.NewSUSE()
ovalFamily = c.SUSEEnterpriseServer
case c.Alpine:
ovalClient = oval.NewAlpine()
ovalFamily = c.Alpine
case c.Amazon, c.Raspbian, c.FreeBSD, c.Windows:
return nil
case c.ServerTypePseudo:
@@ -189,13 +191,14 @@ func FillWithOval(r *models.ScanResult) (err error) {
return fmt.Errorf("OVAL for %s is not implemented yet", r.Family)
}
util.Log.Debugf("Check whether oval is already fetched: %s %s",
ovalFamily, r.Release)
ok, err := ovalClient.CheckIfOvalFetched(ovalFamily, r.Release)
if err != nil {
return err
}
if !ok {
major := strings.Split(r.Release, ".")[0]
util.Log.Warnf("OVAL entries of %s %s are not found. It's recommended to use OVAL to improve scanning accuracy. For details, see https://github.com/kotakanbe/goval-dictionary#usage , Then report with --ovaldb-path or --ovaldb-url flag", ovalFamily, major)
util.Log.Warnf("OVAL entries of %s %s are not found. It's recommended to use OVAL to improve scanning accuracy. For details, see https://github.com/kotakanbe/goval-dictionary#usage , Then report with --ovaldb-path or --ovaldb-url flag", ovalFamily, r.Release)
return nil
}

171
scan/alpine.go Normal file
View File

@@ -0,0 +1,171 @@
/* Vuls - Vulnerability Scanner
Copyright (C) 2016 Future Architect, Inc. Japan.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package scan
import (
"bufio"
"fmt"
"strings"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
)
// inherit OsTypeInterface
type alpine struct {
base
}
// NewAlpine is constructor
func newAlpine(c config.ServerInfo) *alpine {
d := &alpine{
base: base{
osPackages: osPackages{
Packages: models.Packages{},
VulnInfos: models.VulnInfos{},
},
},
}
d.log = util.NewCustomLogger(c)
d.setServerInfo(c)
return d
}
// Alpine
// https://github.com/mizzy/specinfra/blob/master/lib/specinfra/helper/detect_os/alpine.rb
func detectAlpine(c config.ServerInfo) (itsMe bool, os osTypeInterface) {
os = newAlpine(c)
if r := exec(c, "ls /etc/alpine-release", noSudo); !r.isSuccess() {
return false, os
}
if r := exec(c, "cat /etc/alpine-release", noSudo); r.isSuccess() {
os.setDistro(config.Alpine, strings.TrimSpace(r.Stdout))
return true, os
}
return false, os
}
func (o *alpine) checkDependencies() error {
o.log.Infof("Dependencies... No need")
return nil
}
func (o *alpine) checkIfSudoNoPasswd() error {
o.log.Infof("sudo ... No need")
return nil
}
func (o *alpine) apkUpdate() error {
r := o.exec("apk update", noSudo)
if !r.isSuccess() {
return fmt.Errorf("Failed to SSH: %s", r)
}
return nil
}
func (o *alpine) scanPackages() error {
if err := o.apkUpdate(); err != nil {
return err
}
// collect the running kernel information
release, version, err := o.runningKernel()
if err != nil {
o.log.Errorf("Failed to scan the running kernel version: %s", err)
return err
}
o.Kernel = models.Kernel{
Release: release,
Version: version,
}
installed, err := o.scanInstalledPackages()
if err != nil {
o.log.Errorf("Failed to scan installed packages: %s", err)
return err
}
updatable, err := o.scanUpdatablePackages()
if err != nil {
o.log.Errorf("Failed to scan installed packages: %s", err)
return err
}
installed.MergeNewVersion(updatable)
o.Packages = installed
return nil
}
func (o *alpine) scanInstalledPackages() (models.Packages, error) {
cmd := util.PrependProxyEnv("apk info -v")
r := o.exec(cmd, noSudo)
if !r.isSuccess() {
return nil, fmt.Errorf("Failed to SSH: %s", r)
}
return o.parseApkInfo(r.Stdout)
}
func (o *alpine) parseApkInfo(stdout string) (models.Packages, error) {
packs := models.Packages{}
scanner := bufio.NewScanner(strings.NewReader(stdout))
for scanner.Scan() {
line := scanner.Text()
ss := strings.Split(line, "-")
if len(ss) < 3 {
return nil, fmt.Errorf("Failed to parse apk info -v: %s", line)
}
name := strings.Join(ss[:len(ss)-2], "-")
packs[name] = models.Package{
Name: name,
Version: strings.Join(ss[len(ss)-2:], "-"),
}
}
return packs, nil
}
func (o *alpine) scanUpdatablePackages() (models.Packages, error) {
cmd := util.PrependProxyEnv("apk version")
r := o.exec(cmd, noSudo)
if !r.isSuccess() {
return nil, fmt.Errorf("Failed to SSH: %s", r)
}
return o.parseApkVersion(r.Stdout)
}
func (o *alpine) parseApkVersion(stdout string) (models.Packages, error) {
packs := models.Packages{}
scanner := bufio.NewScanner(strings.NewReader(stdout))
for scanner.Scan() {
line := scanner.Text()
if !strings.Contains(line, "<") {
continue
}
ss := strings.Split(line, "<")
namever := strings.TrimSpace(ss[0])
tt := strings.Split(namever, "-")
name := strings.Join(tt[:len(tt)-2], "-")
packs[name] = models.Package{
Name: name,
NewVersion: strings.TrimSpace(ss[1]),
}
}
return packs, nil
}

75
scan/alpine_test.go Normal file
View File

@@ -0,0 +1,75 @@
package scan
import (
"reflect"
"testing"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
)
func TestParseApkInfo(t *testing.T) {
var tests = []struct {
in string
packs models.Packages
}{
{
in: `musl-1.1.16-r14
busybox-1.26.2-r7
`,
packs: models.Packages{
"musl": {
Name: "musl",
Version: "1.1.16-r14",
},
"busybox": {
Name: "busybox",
Version: "1.26.2-r7",
},
},
},
}
d := newAlpine(config.ServerInfo{})
for i, tt := range tests {
pkgs, _ := d.parseApkInfo(tt.in)
if !reflect.DeepEqual(tt.packs, pkgs) {
t.Errorf("[%d] expected %v, actual %v", i, tt.packs, pkgs)
}
}
}
func TestParseApkVersion(t *testing.T) {
var tests = []struct {
in string
packs models.Packages
}{
{
in: `Installed: Available:
libcrypto1.0-1.0.1q-r0 < 1.0.2m-r0
libssl1.0-1.0.1q-r0 < 1.0.2m-r0
nrpe-2.14-r2 < 2.15-r5
`,
packs: models.Packages{
"libcrypto1.0": {
Name: "libcrypto1.0",
NewVersion: "1.0.2m-r0",
},
"libssl1.0": {
Name: "libssl1.0",
NewVersion: "1.0.2m-r0",
},
"nrpe": {
Name: "nrpe",
NewVersion: "2.15-r5",
},
},
},
}
d := newAlpine(config.ServerInfo{})
for i, tt := range tests {
pkgs, _ := d.parseApkVersion(tt.in)
if !reflect.DeepEqual(tt.packs, pkgs) {
t.Errorf("[%d] expected %v, actual %v", i, tt.packs, pkgs)
}
}
}

View File

@@ -29,8 +29,7 @@ import (
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
"github.com/knqyf263/go-deb-version"
version "github.com/knqyf263/go-deb-version"
)
// inherit OsTypeInterface

View File

@@ -41,6 +41,7 @@ import (
type execResult struct {
Servername string
Container conf.Container
Host string
Port string
Cmd string
@@ -51,9 +52,16 @@ type execResult struct {
}
func (s execResult) String() string {
sname := ""
if s.Container.ContainerID == "" {
sname = s.Servername
} else {
sname = s.Container.Name + "@" + s.Servername
}
return fmt.Sprintf(
"execResult: servername: %s\n cmd: %s\n exitstatus: %d\n stdout: %s\n stderr: %s\n err: %s",
s.Servername, s.Cmd, s.ExitStatus, s.Stdout, s.Stderr, s.Error)
sname, s.Cmd, s.ExitStatus, s.Stdout, s.Stderr, s.Error)
}
func (s execResult) isSuccess(expectedStatusCodes ...int) bool {
@@ -167,10 +175,11 @@ func exec(c conf.ServerInfo, cmd string, sudo bool, log ...*logrus.Entry) (resul
func localExec(c conf.ServerInfo, cmdstr string, sudo bool) (result execResult) {
cmdstr = decorateCmd(c, cmdstr, sudo)
var cmd *ex.Cmd
if c.Distro.Family == conf.FreeBSD {
switch c.Distro.Family {
// case conf.FreeBSD, conf.Alpine, conf.Debian:
// cmd = ex.Command("/bin/sh", "-c", cmdstr)
default:
cmd = ex.Command("/bin/sh", "-c", cmdstr)
} else {
cmd = ex.Command("/bin/bash", "-c", cmdstr)
}
var stdoutBuf, stderrBuf bytes.Buffer
cmd.Stdout = &stdoutBuf
@@ -196,6 +205,7 @@ func localExec(c conf.ServerInfo, cmdstr string, sudo bool) (result execResult)
func sshExecNative(c conf.ServerInfo, cmd string, sudo bool) (result execResult) {
result.Servername = c.ServerName
result.Container = c.Container
result.Host = c.Host
result.Port = c.Port
@@ -311,6 +321,7 @@ func sshExecExternal(c conf.ServerInfo, cmd string, sudo bool) (result execResul
result.Stdout = stdoutBuf.String()
result.Stderr = stderrBuf.String()
result.Servername = c.ServerName
result.Container = c.Container
result.Host = c.Host
result.Port = c.Port
result.Cmd = fmt.Sprintf("%s %s", sshBinaryPath, strings.Join(args, " "))
@@ -324,6 +335,16 @@ func getSSHLogger(log ...*logrus.Entry) *logrus.Entry {
return log[0]
}
func dockerShell(family string) string {
switch family {
// case conf.Alpine, conf.Debian:
// return "/bin/sh"
default:
// return "/bin/bash"
return "/bin/sh"
}
}
func decorateCmd(c conf.ServerInfo, cmd string, sudo bool) string {
if sudo && c.User != "root" && !c.IsContainer() {
cmd = fmt.Sprintf("sudo -S %s", cmd)
@@ -341,9 +362,11 @@ func decorateCmd(c conf.ServerInfo, cmd string, sudo bool) string {
if c.IsContainer() {
switch c.Containers.Type {
case "", "docker":
cmd = fmt.Sprintf(`docker exec --user 0 %s /bin/bash -c '%s'`, c.Container.ContainerID, cmd)
cmd = fmt.Sprintf(`docker exec --user 0 %s %s -c '%s'`,
c.Container.ContainerID, dockerShell(c.Distro.Family), cmd)
case "lxd":
cmd = fmt.Sprintf(`lxc exec %s -- /bin/bash -c '%s'`, c.Container.Name, cmd)
cmd = fmt.Sprintf(`lxc exec %s -- %s -c '%s'`,
c.Container.Name, dockerShell(c.Distro.Family), cmd)
}
}
// cmd = fmt.Sprintf("set -x; %s", cmd)

View File

@@ -75,7 +75,7 @@ func TestDecorateCmd(t *testing.T) {
},
cmd: "ls",
sudo: false,
expected: `docker exec --user 0 abc /bin/bash -c 'ls'`,
expected: `docker exec --user 0 abc /bin/sh -c 'ls'`,
},
// root sudo true docker
{
@@ -86,7 +86,7 @@ func TestDecorateCmd(t *testing.T) {
},
cmd: "ls",
sudo: true,
expected: `docker exec --user 0 abc /bin/bash -c 'ls'`,
expected: `docker exec --user 0 abc /bin/sh -c 'ls'`,
},
// non-root sudo false, docker
{
@@ -97,7 +97,7 @@ func TestDecorateCmd(t *testing.T) {
},
cmd: "ls",
sudo: false,
expected: `docker exec --user 0 abc /bin/bash -c 'ls'`,
expected: `docker exec --user 0 abc /bin/sh -c 'ls'`,
},
// non-root sudo true, docker
{
@@ -108,7 +108,7 @@ func TestDecorateCmd(t *testing.T) {
},
cmd: "ls",
sudo: true,
expected: `docker exec --user 0 abc /bin/bash -c 'ls'`,
expected: `docker exec --user 0 abc /bin/sh -c 'ls'`,
},
// non-root sudo true, docker
{
@@ -119,7 +119,7 @@ func TestDecorateCmd(t *testing.T) {
},
cmd: "ls | grep hoge",
sudo: true,
expected: `docker exec --user 0 abc /bin/bash -c 'ls | grep hoge'`,
expected: `docker exec --user 0 abc /bin/sh -c 'ls | grep hoge'`,
},
// -------------lxd-------------
// root sudo false lxd
@@ -131,7 +131,7 @@ func TestDecorateCmd(t *testing.T) {
},
cmd: "ls",
sudo: false,
expected: `lxc exec def -- /bin/bash -c 'ls'`,
expected: `lxc exec def -- /bin/sh -c 'ls'`,
},
// root sudo true lxd
{
@@ -142,7 +142,7 @@ func TestDecorateCmd(t *testing.T) {
},
cmd: "ls",
sudo: true,
expected: `lxc exec def -- /bin/bash -c 'ls'`,
expected: `lxc exec def -- /bin/sh -c 'ls'`,
},
// non-root sudo false, lxd
{
@@ -153,7 +153,7 @@ func TestDecorateCmd(t *testing.T) {
},
cmd: "ls",
sudo: false,
expected: `lxc exec def -- /bin/bash -c 'ls'`,
expected: `lxc exec def -- /bin/sh -c 'ls'`,
},
// non-root sudo true, lxd
{
@@ -164,7 +164,7 @@ func TestDecorateCmd(t *testing.T) {
},
cmd: "ls",
sudo: true,
expected: `lxc exec def -- /bin/bash -c 'ls'`,
expected: `lxc exec def -- /bin/sh -c 'ls'`,
},
// non-root sudo true lxd
{
@@ -175,7 +175,7 @@ func TestDecorateCmd(t *testing.T) {
},
cmd: "ls | grep hoge",
sudo: true,
expected: `lxc exec def -- /bin/bash -c 'ls | grep hoge'`,
expected: `lxc exec def -- /bin/sh -c 'ls | grep hoge'`,
},
}

View File

@@ -106,6 +106,11 @@ func detectOS(c config.ServerInfo) (osType osTypeInterface) {
return
}
if itsMe, osType = detectAlpine(c); itsMe {
util.Log.Debugf("Alpine. Host: %s:%s", c.Host, c.Port)
return
}
//TODO darwin https://github.com/mizzy/specinfra/blob/master/lib/specinfra/helper/detect_os/darwin.rb
osType.setErrs([]error{fmt.Errorf("Unknown OS Type")})
return