Add docker container support
This commit is contained in:
@@ -26,6 +26,13 @@ type osTypeInterface interface {
|
||||
scanVulnByCpeName() error
|
||||
install() error
|
||||
convertToModel() (models.ScanResult, error)
|
||||
|
||||
runningContainers() ([]config.Container, error)
|
||||
exitedContainers() ([]config.Container, error)
|
||||
allContainers() ([]config.Container, error)
|
||||
|
||||
getErrs() []error
|
||||
setErrs([]error)
|
||||
}
|
||||
|
||||
// osPackages included by linux struct
|
||||
@@ -94,49 +101,68 @@ func (s CvePacksList) Less(i, j int) bool {
|
||||
return s[i].CveDetail.CvssScore("en") > s[j].CveDetail.CvssScore("en")
|
||||
}
|
||||
|
||||
func detectOs(c config.ServerInfo) (osType osTypeInterface) {
|
||||
func detectOS(c config.ServerInfo) (osType osTypeInterface) {
|
||||
var itsMe bool
|
||||
itsMe, osType = detectDebian(c)
|
||||
if itsMe {
|
||||
return
|
||||
}
|
||||
itsMe, osType = detectRedhat(c)
|
||||
if itsMe {
|
||||
return
|
||||
}
|
||||
|
||||
osType.setErrs([]error{fmt.Errorf("Unknown OS Type")})
|
||||
return
|
||||
}
|
||||
|
||||
// InitServers detect the kind of OS distribution of target servers
|
||||
func InitServers(localLogger *logrus.Entry) (err error) {
|
||||
func InitServers(localLogger *logrus.Entry) error {
|
||||
Log = localLogger
|
||||
if servers, err = detectServersOS(); err != nil {
|
||||
err = fmt.Errorf("Failed to detect the type of OS. err: %s", err)
|
||||
|
||||
hosts, err := detectServerOSes()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to detect server OSes. err: %s", err)
|
||||
}
|
||||
return
|
||||
servers = hosts
|
||||
|
||||
Log.Info("Detecting Container OS...")
|
||||
containers, err := detectContainerOSes()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to detect Container OSes. err: %s", err)
|
||||
}
|
||||
servers = append(servers, containers...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func detectServersOS() (osi []osTypeInterface, err error) {
|
||||
func detectServerOSes() (oses []osTypeInterface, err error) {
|
||||
osTypeChan := make(chan osTypeInterface, len(config.Conf.Servers))
|
||||
defer close(osTypeChan)
|
||||
for _, s := range config.Conf.Servers {
|
||||
go func(s config.ServerInfo) {
|
||||
osTypeChan <- detectOs(s)
|
||||
//TODO handling Unknown OS
|
||||
osTypeChan <- detectOS(s)
|
||||
}(s)
|
||||
}
|
||||
|
||||
timeout := time.After(60 * time.Second)
|
||||
timeout := time.After(300 * time.Second)
|
||||
for i := 0; i < len(config.Conf.Servers); i++ {
|
||||
select {
|
||||
case res := <-osTypeChan:
|
||||
Log.Infof("(%d/%d) Successfully detected. %s: %s",
|
||||
if 0 < len(res.getErrs()) {
|
||||
continue
|
||||
}
|
||||
Log.Infof("(%d/%d) Detected %s: %s",
|
||||
i+1, len(config.Conf.Servers),
|
||||
res.getServerInfo().ServerName,
|
||||
res.getDistributionInfo())
|
||||
osi = append(osi, res)
|
||||
oses = append(oses, res)
|
||||
case <-timeout:
|
||||
Log.Error("Timeout occured while detecting")
|
||||
err = fmt.Errorf("Timeout")
|
||||
msg := "Timeout occurred while detecting"
|
||||
Log.Error(msg)
|
||||
for servername := range config.Conf.Servers {
|
||||
found := false
|
||||
for _, o := range osi {
|
||||
for _, o := range oses {
|
||||
if servername == o.getServerInfo().ServerName {
|
||||
found = true
|
||||
break
|
||||
@@ -146,12 +172,158 @@ func detectServersOS() (osi []osTypeInterface, err error) {
|
||||
Log.Errorf("Failed to detect. servername: %s", servername)
|
||||
}
|
||||
}
|
||||
return
|
||||
return oses, fmt.Errorf(msg)
|
||||
}
|
||||
}
|
||||
|
||||
errorOccurred := false
|
||||
for _, osi := range oses {
|
||||
if errs := osi.getErrs(); 0 < len(errs) {
|
||||
errorOccurred = true
|
||||
Log.Errorf("Some errors occurred on %s",
|
||||
osi.getServerInfo().ServerName)
|
||||
for _, err := range errs {
|
||||
Log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if errorOccurred {
|
||||
return oses, fmt.Errorf("Some errors occurred")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func detectContainerOSes() (oses []osTypeInterface, err error) {
|
||||
osTypesChan := make(chan []osTypeInterface, len(servers))
|
||||
defer close(osTypesChan)
|
||||
for _, s := range servers {
|
||||
go func(s osTypeInterface) {
|
||||
osTypesChan <- detectContainerOSesOnServer(s)
|
||||
}(s)
|
||||
}
|
||||
|
||||
timeout := time.After(300 * time.Second)
|
||||
for i := 0; i < len(config.Conf.Servers); i++ {
|
||||
select {
|
||||
case res := <-osTypesChan:
|
||||
for _, osi := range res {
|
||||
if 0 < len(osi.getErrs()) {
|
||||
continue
|
||||
}
|
||||
sinfo := osi.getServerInfo()
|
||||
Log.Infof("Detected %s/%s on %s: %s",
|
||||
sinfo.Container.ContainerID, sinfo.Container.Name,
|
||||
sinfo.ServerName, osi.getDistributionInfo())
|
||||
}
|
||||
oses = append(oses, res...)
|
||||
case <-timeout:
|
||||
msg := "Timeout occurred while detecting"
|
||||
Log.Error(msg)
|
||||
for servername := range config.Conf.Servers {
|
||||
found := false
|
||||
for _, o := range oses {
|
||||
if servername == o.getServerInfo().ServerName {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
Log.Errorf("Failed to detect. servername: %s", servername)
|
||||
}
|
||||
}
|
||||
return oses, fmt.Errorf(msg)
|
||||
}
|
||||
}
|
||||
|
||||
errorOccurred := false
|
||||
for _, osi := range oses {
|
||||
if errs := osi.getErrs(); 0 < len(errs) {
|
||||
errorOccurred = true
|
||||
Log.Errorf("Some errors occurred on %s",
|
||||
osi.getServerInfo().ServerName)
|
||||
for _, err := range errs {
|
||||
Log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if errorOccurred {
|
||||
return oses, fmt.Errorf("Some errors occurred")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func detectContainerOSesOnServer(containerHost osTypeInterface) (oses []osTypeInterface) {
|
||||
containerHostInfo := containerHost.getServerInfo()
|
||||
if len(containerHostInfo.Containers) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
running, err := containerHost.runningContainers()
|
||||
if err != nil {
|
||||
containerHost.setErrs([]error{fmt.Errorf(
|
||||
"Failed to get running containers on %s. err: %s",
|
||||
containerHost.getServerInfo().ServerName, err)})
|
||||
return append(oses, containerHost)
|
||||
}
|
||||
|
||||
if containerHostInfo.Containers[0] == "${running}" {
|
||||
for _, containerInfo := range running {
|
||||
copied := containerHostInfo
|
||||
copied.SetContainer(config.Container{
|
||||
ContainerID: containerInfo.ContainerID,
|
||||
Name: containerInfo.Name,
|
||||
})
|
||||
os := detectOS(copied)
|
||||
oses = append(oses, os)
|
||||
}
|
||||
return oses
|
||||
}
|
||||
|
||||
exitedContainers, err := containerHost.exitedContainers()
|
||||
if err != nil {
|
||||
containerHost.setErrs([]error{fmt.Errorf(
|
||||
"Failed to get exited containers on %s. err: %s",
|
||||
containerHost.getServerInfo().ServerName, err)})
|
||||
return append(oses, containerHost)
|
||||
}
|
||||
|
||||
var exited, unknown []string
|
||||
for _, container := range containerHostInfo.Containers {
|
||||
found := false
|
||||
for _, c := range running {
|
||||
if c.ContainerID == container || c.Name == container {
|
||||
copied := containerHostInfo
|
||||
copied.SetContainer(c)
|
||||
os := detectOS(copied)
|
||||
oses = append(oses, os)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
foundInExitedContainers := false
|
||||
for _, c := range exitedContainers {
|
||||
if c.ContainerID == container || c.Name == container {
|
||||
exited = append(exited, container)
|
||||
foundInExitedContainers = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundInExitedContainers {
|
||||
unknown = append(unknown, container)
|
||||
}
|
||||
}
|
||||
}
|
||||
if 0 < len(exited) || 0 < len(unknown) {
|
||||
containerHost.setErrs([]error{fmt.Errorf(
|
||||
"Some containers on %s are exited or unknown. exited: %s, unknown: %s",
|
||||
containerHost.getServerInfo().ServerName, exited, unknown)})
|
||||
return append(oses, containerHost)
|
||||
}
|
||||
return oses
|
||||
}
|
||||
|
||||
// Prepare installs requred packages to scan vulnerabilities.
|
||||
func Prepare() []error {
|
||||
return parallelSSHExec(func(o osTypeInterface) error {
|
||||
|
||||
Reference in New Issue
Block a user