Merge pull request #8 from armosec/dev

Dev
This commit is contained in:
Benyamin Hirschberg
2021-09-13 17:07:58 +03:00
committed by GitHub
14 changed files with 81 additions and 42 deletions
+7 -1
View File
@@ -40,7 +40,13 @@ jobs:
- name: Build
env:
RELEASE: v1.0.${{ github.run_number }}
run: mkdir -p build/${{ matrix.os }} && go mod tidy && go build -ldflags "-w -s -X github.com/armosec/kubescape/cmd.BuildNumber=$RELEASE" -o build/${{ matrix.os }}/kubescape # && md5sum build/${{ matrix.os }}/kubescape > build/${{ matrix.os }}/kubescape.md5
ArmoBEServer: api.armo.cloud
ArmoERServer: report.euprod1.cyberarmorsoft.com
ArmoWebsite: portal.armo.cloud
BEServerConst: github.com/armosec/kubescape/cautils/getter.ArmoBEURL
ERServerConst: github.com/armosec/kubescape/cautils/getter.ArmoERURL
WebsiteConst: github.com/armosec/kubescape/cautils/getter.ArmoFEURL
run: mkdir -p build/${{ matrix.os }} && go mod tidy && go build -ldflags "-w -s -X github.com/armosec/kubescape/cmd.BuildNumber=$RELEASE -X $BEServerConst=$ArmoBEServer -X $ERServerConst=$ArmoERServer -X $WebsiteConst=$ArmoWebsite" -o build/${{ matrix.os }}/kubescape # && md5sum build/${{ matrix.os }}/kubescape > build/${{ matrix.os }}/kubescape.md5
- name: Upload Release binaries
id: upload-release-asset
+2 -2
View File
@@ -38,8 +38,8 @@ If you wish to scan all namespaces in your cluster, remove the `--exclude-namesp
| `-o`/`--output` | print to stdout | Save scan result in file |
| `--use-from` | | Load local framework object from specified path. If not used will download latest |
| `--use-default` | `false` | Load local framework object from default path. If not used will download latest | `true`/`false` |
| `--exceptions` | | Path to an [exceptions obj](examples/exceptions.json) |
| `--results-locally` | `false` | Kubescape sends scan results to its backend to allow users to control exceptions and maintain chronological scan results. Use results-locally if you do not wish to use these features | |
| `--exceptions` | | Path to an [exceptions obj](examples/exceptions.json). If not set will download exceptions from Armo management portal |
| `--results-locally` | `false` | Kubescape sends scan results to Armo management portal to allow users to control exceptions and maintain chronological scan results. Use this flag if you do not wish to use these features | `true`/`false`|
## Usage & Examples
+1 -1
View File
@@ -4,7 +4,7 @@ ENV GO111MODULE=on
WORKDIR /work
ADD . .
RUN go mod download
RUN go mod tidy
RUN GOOS=linux CGO_ENABLED=0 go build -ldflags="-s -w " -installsuffix cgo -o kubescape .
FROM alpine
+26 -9
View File
@@ -7,6 +7,7 @@ import (
"io/ioutil"
"net/url"
"os"
"strings"
"github.com/armosec/kubescape/cautils/getter"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -21,8 +22,9 @@ const (
)
type ConfigObj struct {
CustomerGUID string `json:"customerGUID"`
Token string `json:"token"`
CustomerGUID string `json:"customerGUID"`
Token string `json:"token"`
CustomerAdminEMail string `json:"adminMail"`
}
func (co *ConfigObj) Json() []byte {
@@ -79,6 +81,11 @@ func (c *ClusterConfig) GenerateURL() {
u := url.URL{}
u.Scheme = "https"
u.Host = getter.ArmoFEURL
if c.configObj.CustomerAdminEMail != "" {
msgStr := fmt.Sprintf("To view all controls and get remediations ask access permissions to %s from %s", u.String(), c.configObj.CustomerAdminEMail)
InfoTextDisplay(os.Stdout, msgStr+"\n")
return
}
u.Path = "account/sign-up"
q := u.Query()
q.Add("invitationToken", c.configObj.Token)
@@ -91,30 +98,40 @@ func (c *ClusterConfig) GenerateURL() {
}
func (c *ClusterConfig) GetCustomerGUID() string {
return c.configObj.CustomerGUID
if c.configObj != nil {
return c.configObj.CustomerGUID
}
return ""
}
func (c *ClusterConfig) SetCustomerGUID() error {
// get from configMap
if configObj, _ := c.loadConfigFromConfigMap(); configObj != nil {
c.update(configObj)
return nil
}
// get from file
if configObj, _ := c.loadConfigFromFile(); configObj != nil {
c.update(configObj)
c.updateConfigMap()
return nil
}
customerGUID := c.GetCustomerGUID()
// get from armoBE
if tenantResponse, err := c.armoAPI.GetCustomerGUID(); tenantResponse != nil {
c.update(&ConfigObj{CustomerGUID: tenantResponse.TenantID, Token: tenantResponse.Token})
return c.updateConfigMap()
tenantResponse, err := c.armoAPI.GetCustomerGUID(customerGUID)
if err == nil && tenantResponse != nil {
if tenantResponse.AdminMail != "" { // this customer already belongs to some user
c.update(&ConfigObj{CustomerGUID: customerGUID, CustomerAdminEMail: tenantResponse.AdminMail})
} else {
c.update(&ConfigObj{CustomerGUID: tenantResponse.TenantID, Token: tenantResponse.Token})
return c.updateConfigMap()
}
} else {
if err != nil && strings.Contains(err.Error(), "Invitation for tenant already exists") {
return nil
}
return err
}
return nil
}
func (c *ClusterConfig) loadConfigFromConfigMap() (*ConfigObj, error) {
+12 -6
View File
@@ -1,6 +1,7 @@
package getter
import (
"fmt"
"net/http"
"github.com/armosec/kubescape/cautils/armotypes"
@@ -11,7 +12,7 @@ import (
// =============================================== ArmoAPI ===============================================================
// =======================================================================================================================
const (
var (
ArmoBEURL = "eggdashbe.eudev3.cyberarmorsoft.com"
ArmoERURL = "report.eudev3.cyberarmorsoft.com"
ArmoFEURL = "armoui.eudev3.cyberarmorsoft.com"
@@ -60,8 +61,12 @@ func (armoAPI *ArmoAPI) GetExceptions(customerGUID, clusterName string) ([]armot
return exceptions, nil
}
func (armoAPI *ArmoAPI) GetCustomerGUID() (*TenantResponse, error) {
respStr, err := HttpGetter(armoAPI.httpClient, armoAPI.getCustomerURL())
func (armoAPI *ArmoAPI) GetCustomerGUID(customerGUID string) (*TenantResponse, error) {
url := armoAPI.getCustomerURL()
if customerGUID != "" {
url = fmt.Sprintf("%s?customerGUID=%s", url, customerGUID)
}
respStr, err := HttpGetter(armoAPI.httpClient, url)
if err != nil {
return nil, err
}
@@ -74,7 +79,8 @@ func (armoAPI *ArmoAPI) GetCustomerGUID() (*TenantResponse, error) {
}
type TenantResponse struct {
TenantID string `json:"tenantId"`
Token string `json:"token"`
Expires string `json:"expires"`
TenantID string `json:"tenantId"`
Token string `json:"token"`
Expires string `json:"expires"`
AdminMail string `json:"adminMail,omitempty"`
}
+3 -3
View File
@@ -27,9 +27,9 @@ func (armoAPI *ArmoAPI) getExceptionsURL(customerGUID, clusterName string) strin
q := u.Query()
q.Add("customerGUID", customerGUID)
if clusterName != "" {
q.Add("clusterName", clusterName)
}
// if clusterName != "" { // TODO - fix customer name support in Armo BE
// q.Add("clusterName", clusterName)
// }
u.RawQuery = q.Encode()
return u.String()
+5 -2
View File
@@ -27,7 +27,9 @@ func NewDownloadReleasedPolicy() *DownloadReleasedPolicy {
}
func (drp *DownloadReleasedPolicy) GetFramework(name string) (*opapolicy.Framework, error) {
drp.setURL(name)
if err := drp.setURL(name); err != nil {
return nil, err
}
respStr, err := HttpGetter(drp.httpClient, drp.hostURL)
if err != nil {
return nil, err
@@ -71,12 +73,13 @@ func (drp *DownloadReleasedPolicy) setURL(frameworkName string) error {
if name == frameworkName {
if url, ok := asset["browser_download_url"].(string); ok {
drp.hostURL = url
return nil
}
}
}
}
}
}
return nil
return fmt.Errorf("failed to download '%s' - not found", frameworkName)
}
+2 -2
View File
@@ -41,8 +41,8 @@ type FrameworkReport struct {
}
type ControlReport struct {
armotypes.PortalBase `json:",inline"`
ControlID string `json:"id"`
Name string `json:"name"`
ID string `json:"id"`
RuleReports []RuleReport `json:"ruleReports"`
Remediation string `json:"remediation"`
Description string `json:"description"`
@@ -101,7 +101,7 @@ type PolicyRule struct {
// Control represents a collection of rules which are combined together to single purpose
type Control struct {
armotypes.PortalBase `json:",inline"`
ID string `json:"id"`
ControlID string `json:"id"`
CreationTime string `json:"creationTime"`
Description string `json:"description"`
Remediation string `json:"remediation"`
+2 -1
View File
@@ -33,7 +33,8 @@ func MockFrameworkReportA() *FrameworkReport {
Name: AMockFrameworkName,
ControlReports: []ControlReport{
{
Name: AMockControlName,
ControlID: "C-0010",
Name: AMockControlName,
RuleReports: []RuleReport{
{
Name: AMockRuleName,
+1 -1
View File
@@ -94,7 +94,7 @@ func init() {
frameworkCmd.Flags().StringVarP(&scanInfo.Output, "output", "o", "", "Output file. print output to file and not stdout")
frameworkCmd.Flags().BoolVarP(&scanInfo.Silent, "silent", "s", false, "Silent progress messages")
frameworkCmd.Flags().Uint16VarP(&scanInfo.FailThreshold, "fail-threshold", "t", 0, "Failure threshold is the percent bellow which the command fails and returns exit code -1")
frameworkCmd.Flags().BoolVarP(&scanInfo.DoNotSendResults, "results-locally", "", false, "Kubescape sends scan results to its backend to allow users to control exceptions and maintain chronological scan results. Use results-locally if you do not wish to use these features")
frameworkCmd.Flags().BoolVarP(&scanInfo.DoNotSendResults, "results-locally", "", false, "Kubescape sends scan results to Armosec backend to allow users to control exceptions and maintain chronological scan results. Use this flag if you do not wish to use these features")
}
func CliSetup() error {
+12 -8
View File
@@ -1,7 +1,7 @@
#!/bin/bash
set -e
echo "Installing Kubescape..."
echo -e "\033[0;36mInstalling Kubescape..."
echo
BASE_DIR=~/.kubescape
@@ -27,18 +27,22 @@ mkdir -p $BASE_DIR
OUTPUT=$BASE_DIR/$KUBESCAPE_EXEC
curl --progress-bar -L $DOWNLOAD_URL -o $OUTPUT
echo -e "\033[32m[V] Downloaded Kubescape"
# Ping download counter
curl --silent https://us-central1-elated-pottery-310110.cloudfunctions.net/kubescape-download-counter -o /dev/null
chmod +x $OUTPUT || sudo chmod +x $OUTPUT
rm -f /usr/local/bin/$KUBESCAPE_EXEC || sudo rm -f /usr/local/bin/$KUBESCAPE_EXEC
cp $OUTPUT /usr/local/bin || sudo cp $OUTPUT /usr/local/bin
chmod +x $OUTPUT 2>/dev/null || sudo chmod +x $OUTPUT
rm -f /usr/local/bin/$KUBESCAPE_EXEC 2>/dev/null || sudo rm -f /usr/local/bin/$KUBESCAPE_EXEC
cp $OUTPUT /usr/local/bin 2>/dev/null || sudo cp $OUTPUT /usr/local/bin
rm -rf $OUTPUT
echo -e "[V] Finished Installation"
echo
echo -e "\033[32mFinished Installation."
echo -e "\033[0m"
$KUBESCAPE_EXEC version
echo
echo -e "\033[35m Usage: $ $KUBESCAPE_EXEC scan framework nsa --exclude-namespaces kube-system,kube-public"
echo
echo -e "\033[35mUsage: $ $KUBESCAPE_EXEC scan framework nsa --exclude-namespaces kube-system,kube-public"
echo -e "\033[0m"
+1 -1
View File
@@ -123,9 +123,9 @@ func (opap *OPAProcessor) processControl(control *opapolicy.Control) (*opapolicy
controlReport := opapolicy.ControlReport{}
controlReport.PortalBase = control.PortalBase
controlReport.ControlID = control.ControlID
controlReport.Name = control.Name
controlReport.ID = control.ID
controlReport.Description = control.Description
controlReport.Remediation = control.Remediation
+3 -2
View File
@@ -3,6 +3,7 @@ package policyhandler
import (
"fmt"
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/armotypes"
"github.com/armosec/kubescape/cautils/opapolicy"
)
@@ -18,7 +19,7 @@ func (policyHandler *PolicyHandler) GetPoliciesFromBackend(notification *opapoli
case opapolicy.KindFramework:
receivedFramework, recExceptionPolicies, err := policyHandler.getFrameworkPolicies(rule.Name)
if err != nil {
errs = fmt.Errorf("%v\nKind: %v, Name: %s, error: %s", errs, rule.Kind, rule.Name, err.Error())
return nil, nil, fmt.Errorf("kind: %v, name: %s, error: %s", rule.Kind, rule.Name, err.Error())
}
if receivedFramework != nil {
frameworks = append(frameworks, *receivedFramework)
@@ -41,7 +42,7 @@ func (policyHandler *PolicyHandler) getFrameworkPolicies(policyName string) (*op
return nil, nil, err
}
receivedException, err := policyHandler.getters.ExceptionsGetter.GetExceptions("", "")
receivedException, err := policyHandler.getters.ExceptionsGetter.GetExceptions(cautils.CustomerGUID, cautils.ClusterName)
if err != nil {
return receivedFramework, nil, err
}
+4 -3
View File
@@ -1,6 +1,7 @@
package exceptions
import (
"github.com/armosec/kubescape/cautils"
"github.com/armosec/kubescape/cautils/k8sinterface"
"github.com/armosec/kubescape/cautils/armotypes"
@@ -91,9 +92,9 @@ func hasException(designator *armotypes.PortalDesignator, workload k8sinterface.
return false // if designators are empty
}
// if cluster != "" && cluster != ClusterName { // TODO - where do we receive cluster name from?
// return false // cluster name does not match
// }
if cluster != "" && cautils.ClusterName != "" && cluster != cautils.ClusterName { // TODO - where do we receive cluster name from?
return false // cluster name does not match
}
if namespace != "" && !compareNamespace(workload, namespace) {
return false // namespaces do not match