rename hyperclair to clairctl
This commit is contained in:
parent
b45f471ccb
commit
fec01ae1ee
@ -1,42 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
# hyperclair
|
# clairctl
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/wemanity-belgium/hyperclair.svg?branch=develop)](https://travis-ci.org/wemanity-belgium/hyperclair) [![Join the chat at https://gitter.im/wemanity-belgium/hyperclair](https://badges.gitter.im/wemanity-belgium/hyperclair.svg)](https://gitter.im/wemanity-belgium/hyperclair?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
> Tracking container vulnerabilities with Clair Control
|
||||||
|
|
||||||
> Tracking container vulnerabilities, that's should be *Hyperclair*
|
Clairctl is a lightweight command-line tool doing the bridge between Registries as Docker Hub, Docker Registry or Quay.io, and the CoreOS vulnerability tracker, Clair.
|
||||||
|
Clairctl will play as reverse proxy for authentication.
|
||||||
Tracking vulnerabilities in your container images, it's easy with CoreOS Clair.
|
|
||||||
Integrate it inside your CI/CD pipeline is easier with Hyperclair.
|
|
||||||
|
|
||||||
Hyperclair is a lightweight command-line tool doing the bridge between Registries as Docker Hub, Docker Registry or Quay.io, and the CoreOS vulnerability tracker, Clair.
|
|
||||||
It's easily integrated in your CI/CD pipeline and Hyperclair will play as reverse proxy for authentication.
|
|
||||||
|
|
||||||
|
|
||||||
> The Registry is a stateless, highly scalable server side application that stores and lets you distribute Docker images. The Registry is open-source, under the permissive Apache license.
|
|
||||||
>
|
|
||||||
>*From https://docs.docker.com/registry/*
|
|
||||||
|
|
||||||
> Clair is a container vulnerability analysis service. It provides a list of vulnerabilities that threaten a container, and can notify users when new vulnerabilities that affect existing containers become known.
|
|
||||||
>
|
|
||||||
>*From https://github.com/coreos/clair*
|
|
||||||
|
|
||||||
hyperclair is tool to make the link between the Docker Registry and the CoreOS Clair tool.
|
|
||||||
|
|
||||||
![hyperclair](https://cloud.githubusercontent.com/assets/3304363/14174675/348bc190-f746-11e5-9edd-9e736ec38b0e.png)
|
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
[![asciicast](https://asciinema.org/a/41461.png)](https://asciinema.org/a/41461)
|
[![asciicast](https://asciinema.org/a/41461.png)](https://asciinema.org/a/41461)
|
||||||
|
|
||||||
# Notification
|
|
||||||
2. On-Demand: the CLI tool is used to pull image from Registry then push it to Clair
|
|
||||||
|
|
||||||
# Reporting
|
# Reporting
|
||||||
|
|
||||||
**hyperclair** get vulnerabilities report from Clair and generate HTML report
|
**clairctl** get vulnerabilities report from Clair and generate HTML report
|
||||||
|
|
||||||
hyperclair can be used for Docker Hub and self-hosted Registry
|
clairctl can be used for Docker Hub and self-hosted Registry
|
||||||
|
|
||||||
# Command
|
# Command
|
||||||
|
|
||||||
@ -44,23 +23,23 @@ hyperclair can be used for Docker Hub and self-hosted Registry
|
|||||||
Analyse your docker image with Clair, directly from your registry.
|
Analyse your docker image with Clair, directly from your registry.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
hyperclair [command]
|
clairctl [command]
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
analyse Analyse Docker image
|
analyse Analyse Docker image
|
||||||
health Get Health of Hyperclair and underlying services
|
health Get Health of clairctl and underlying services
|
||||||
login Log in to a Docker registry
|
login Log in to a Docker registry
|
||||||
logout Log out from a Docker registry
|
logout Log out from a Docker registry
|
||||||
pull Pull Docker image information
|
pull Pull Docker image information
|
||||||
push Push Docker image to Clair
|
push Push Docker image to Clair
|
||||||
report Generate Docker Image vulnerabilities report
|
report Generate Docker Image vulnerabilities report
|
||||||
version Get Versions of Hyperclair and underlying services
|
version Get Versions of clairctl and underlying services
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
--config string config file (default is ./.hyperclair.yml)
|
--config string config file (default is ./.hyperclair.yml)
|
||||||
--log-level string log level [Panic,Fatal,Error,Warn,Info,Debug]
|
--log-level string log level [Panic,Fatal,Error,Warn,Info,Debug]
|
||||||
|
|
||||||
Use "hyperclair [command] --help" for more information about a command.
|
Use "clairctl [command] --help" for more information about a command.
|
||||||
```
|
```
|
||||||
|
|
||||||
# Optional Configuration
|
# Optional Configuration
|
||||||
|
@ -2,11 +2,11 @@ package clair
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReportAsHtml(t *testing.T) {
|
func TestReportAsHtml(t *testing.T) {
|
||||||
@ -21,10 +21,10 @@ func TestReportAsHtml(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(os.TempDir()+"/hyperclair-html-report.html")
|
fmt.Println(os.TempDir() + "/clairctl-html-report.html")
|
||||||
|
|
||||||
err = ioutil.WriteFile(os.TempDir()+"/hyperclair-html-report.html", []byte(html), 0700)
|
err = ioutil.WriteFile(os.TempDir()+"/clairctl-html-report.html", []byte(html), 0700)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<title>Hyperclair Reports</title>
|
<title>Clair Control Reports</title>
|
||||||
<style>
|
<style>
|
||||||
*{
|
*{
|
||||||
font-family: "Lucida Console", Monaco, monospace;
|
font-family: "Lucida Console", Monaco, monospace;
|
||||||
@ -49,7 +49,7 @@
|
|||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>
|
<h1>
|
||||||
Hyperclair reports
|
Clair Control reports
|
||||||
</h1>
|
</h1>
|
||||||
<h2>
|
<h2>
|
||||||
Image: {{.ImageName}}
|
Image: {{.ImageName}}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>Hyperclair report : {{.ImageName}}</title>
|
<title>Clair Control report : {{.ImageName}}</title>
|
||||||
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,600italic,400italic,300italic,300' rel='stylesheet' type='text/css'>
|
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,600italic,400italic,300italic,300' rel='stylesheet' type='text/css'>
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
|
||||||
@ -314,7 +314,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<header class="app-header">
|
<header class="app-header">
|
||||||
<h1>Hyperclair report</h1>
|
<h1>Clair Control report</h1>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="app-intro clearfix">
|
<div class="app-intro clearfix">
|
||||||
|
@ -28,7 +28,7 @@ var analyseCmd = &cobra.Command{
|
|||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
fmt.Printf("hyperclair: \"analyse\" requires a minimum of 1 argument")
|
fmt.Printf("clairctl: \"analyse\" requires a minimum of 1 argument")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,8 +20,8 @@ type health struct {
|
|||||||
|
|
||||||
var healthCmd = &cobra.Command{
|
var healthCmd = &cobra.Command{
|
||||||
Use: "health",
|
Use: "health",
|
||||||
Short: "Get Health of Hyperclair and underlying services",
|
Short: "Get Health of clairctl and underlying services",
|
||||||
Long: `Get Health of Hyperclair and underlying services`,
|
Long: `Get Health of clairctl and underlying services`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
ok := clair.IsHealthy()
|
ok := clair.IsHealthy()
|
||||||
err := template.Must(template.New("health").Parse(healthTplt)).Execute(os.Stdout, ok)
|
err := template.Must(template.New("health").Parse(healthTplt)).Execute(os.Stdout, ok)
|
||||||
|
@ -10,10 +10,10 @@ import (
|
|||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/coreos/clair/cmd/clairctl/config"
|
"github.com/coreos/clair/cmd/clairctl/config"
|
||||||
"github.com/coreos/clair/cmd/clairctl/docker"
|
"github.com/coreos/clair/cmd/clairctl/docker"
|
||||||
"github.com/coreos/clair/cmd/clairctl/xstrings"
|
"github.com/coreos/clair/cmd/clairctl/xstrings"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
type user struct {
|
type user struct {
|
||||||
@ -38,7 +38,7 @@ var loginCmd = &cobra.Command{
|
|||||||
|
|
||||||
if err := readConfigFile(&users, config.HyperclairConfig()); err != nil {
|
if err := readConfigFile(&users, config.HyperclairConfig()); err != nil {
|
||||||
fmt.Println(errInternalError)
|
fmt.Println(errInternalError)
|
||||||
logrus.Fatalf("reading hyperclair file: %v", err)
|
logrus.Fatalf("reading clairctl file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var reg string = docker.DockerHub
|
var reg string = docker.DockerHub
|
||||||
|
@ -31,7 +31,7 @@ var logoutCmd = &cobra.Command{
|
|||||||
|
|
||||||
if err := readConfigFile(&users, config.HyperclairConfig()); err != nil {
|
if err := readConfigFile(&users, config.HyperclairConfig()); err != nil {
|
||||||
fmt.Println(errInternalError)
|
fmt.Println(errInternalError)
|
||||||
logrus.Fatalf("reading hyperclair file: %v", err)
|
logrus.Fatalf("reading clairctl file: %v", err)
|
||||||
}
|
}
|
||||||
if _, present := users[reg]; present {
|
if _, present := users[reg]; present {
|
||||||
delete(users, reg)
|
delete(users, reg)
|
||||||
|
@ -39,7 +39,7 @@ var pullCmd = &cobra.Command{
|
|||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
//TODO how to use args with viper
|
//TODO how to use args with viper
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
fmt.Printf("hyperclair: \"pull\" requires a minimum of 1 argument\n")
|
fmt.Printf("clairctl: \"pull\" requires a minimum of 1 argument\n")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
im := args[0]
|
im := args[0]
|
||||||
|
@ -18,7 +18,7 @@ var pushCmd = &cobra.Command{
|
|||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
fmt.Printf("hyperclair: \"push\" requires a minimum of 1 argument\n")
|
fmt.Printf("clairctl: \"push\" requires a minimum of 1 argument\n")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ func init() {
|
|||||||
pushCmd.Flags().BoolVarP(&docker.IsLocal, "local", "l", false, "Use local images")
|
pushCmd.Flags().BoolVarP(&docker.IsLocal, "local", "l", false, "Use local images")
|
||||||
}
|
}
|
||||||
|
|
||||||
//StartLocalServer start the hyperclair local server needed for reverse proxy and file server
|
//StartLocalServer start the clairctl local server needed for reverse proxy and file server
|
||||||
func startLocalServer() {
|
func startLocalServer() {
|
||||||
sURL, err := config.LocalServerIP()
|
sURL, err := config.LocalServerIP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -6,11 +6,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
"github.com/coreos/clair/cmd/clairctl/clair"
|
"github.com/coreos/clair/cmd/clairctl/clair"
|
||||||
"github.com/coreos/clair/cmd/clairctl/docker"
|
"github.com/coreos/clair/cmd/clairctl/docker"
|
||||||
"github.com/coreos/clair/cmd/clairctl/xstrings"
|
"github.com/coreos/clair/cmd/clairctl/xstrings"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
var reportCmd = &cobra.Command{
|
var reportCmd = &cobra.Command{
|
||||||
@ -19,7 +19,7 @@ var reportCmd = &cobra.Command{
|
|||||||
Long: `Generate Docker Image vulnerabilities report as HTML or JSON`,
|
Long: `Generate Docker Image vulnerabilities report as HTML or JSON`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
fmt.Printf("hyperclair: \"report\" requires a minimum of 1 argument")
|
fmt.Printf("clairctl: \"report\" requires a minimum of 1 argument")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ var logLevel string
|
|||||||
|
|
||||||
// RootCmd represents the base command when called without any subcommands
|
// RootCmd represents the base command when called without any subcommands
|
||||||
var RootCmd = &cobra.Command{
|
var RootCmd = &cobra.Command{
|
||||||
Use: "hyperclair",
|
Use: "clairctl",
|
||||||
Short: "Analyse your docker image with Clair, directly from your registry.",
|
Short: "Analyse your docker image with Clair, directly from your registry or local images.",
|
||||||
Long: ``,
|
Long: ``,
|
||||||
// Uncomment the following line if your bare application
|
// Uncomment the following line if your bare application
|
||||||
// has an action associated with it:
|
// has an action associated with it:
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const versionTplt = `
|
const versionTplt = `
|
||||||
Hyperclair version {{.}}
|
Clairctl version {{.}}
|
||||||
`
|
`
|
||||||
|
|
||||||
var version string
|
var version string
|
||||||
@ -19,8 +19,8 @@ var templ = template.Must(template.New("versions").Parse(versionTplt))
|
|||||||
|
|
||||||
var versionCmd = &cobra.Command{
|
var versionCmd = &cobra.Command{
|
||||||
Use: "version",
|
Use: "version",
|
||||||
Short: "Get Versions of Hyperclair and underlying services",
|
Short: "Get Versions of Clairctl and underlying services",
|
||||||
Long: `Get Versions of Hyperclair and underlying services`,
|
Long: `Get Versions of Clairctl and underlying services`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
err := templ.Execute(os.Stdout, version)
|
err := templ.Execute(os.Stdout, version)
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
FROM golang:latest
|
|
||||||
WORKDIR /go/src/github.com/wemanity-belgium/hyperclair
|
|
||||||
EXPOSE 9999
|
|
||||||
RUN mkdir -p /data
|
|
||||||
ENTRYPOINT bash
|
|
@ -4,12 +4,9 @@ CONTRIBUTION
|
|||||||
# Running full dev environnement
|
# Running full dev environnement
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Running Authentication server, Registry, Clair , Hyperclair-server and Hyperclair-DEV-BOX
|
# Running Authentication server, Registry, Clair
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
|
|
||||||
# Enter the hyperclair dev box
|
|
||||||
docker exec -ti hyperclair_dev bash
|
|
||||||
|
|
||||||
# Run Any command ex:
|
# Run Any command ex:
|
||||||
go run main.go help
|
go run main.go help
|
||||||
# Or
|
# Or
|
||||||
|
@ -27,14 +27,6 @@ services:
|
|||||||
- REGISTRY_AUTH_TOKEN_ISSUER="auth_service"
|
- REGISTRY_AUTH_TOKEN_ISSUER="auth_service"
|
||||||
- REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE=/ssl/server.pem
|
- REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE=/ssl/server.pem
|
||||||
|
|
||||||
# Uncomment to deploy an insecure registry
|
|
||||||
# registry_insecure:
|
|
||||||
# image: registry:2.2.1
|
|
||||||
# ports:
|
|
||||||
# - 5002:5000
|
|
||||||
# container_name: "registry_insecure"
|
|
||||||
|
|
||||||
|
|
||||||
clair:
|
clair:
|
||||||
image: quay.io/coreos/clair:v1.0.0-rc1
|
image: quay.io/coreos/clair:v1.0.0-rc1
|
||||||
volumes:
|
volumes:
|
||||||
@ -53,37 +45,8 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- POSTGRES_PASSWORD=root
|
- POSTGRES_PASSWORD=root
|
||||||
|
|
||||||
hyperclair:
|
|
||||||
build: .
|
|
||||||
volumes:
|
|
||||||
- $GOPATH:/go
|
|
||||||
- hyperclair-data:/data
|
|
||||||
ports:
|
|
||||||
- 9999:9999
|
|
||||||
tty: true
|
|
||||||
container_name: "hyperclair"
|
|
||||||
entrypoint: ["go","run","main.go","--log-level","debug","serve"]
|
|
||||||
|
|
||||||
ui:
|
|
||||||
image: jgsqware/registry-ui
|
|
||||||
ports:
|
|
||||||
- 5080:8080
|
|
||||||
environment:
|
|
||||||
- REGISTRYUI_HUB_URI=registry:5000
|
|
||||||
- REGISTRYUI_ACCOUNT_MGMT_ENABLED=true
|
|
||||||
- REGISTRYUI_ACCOUNT_MGMT_CONFIG=./config/auth_config.yml
|
|
||||||
- REGISTRYUI_HYPERCLAIR_REPORT_ENABLED=true
|
|
||||||
# hyperclair_dev:
|
|
||||||
# build: .
|
|
||||||
# volumes:
|
|
||||||
# - $GOPATH:/go
|
|
||||||
# tty: true
|
|
||||||
# container_name: "hyperclair_dev"
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
clair-data:
|
clair-data:
|
||||||
driver: local
|
driver: local
|
||||||
hyperclair-data:
|
|
||||||
driver: local
|
|
||||||
registry-data:
|
registry-data:
|
||||||
driver: local
|
driver: local
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user