mirror of
https://github.com/kubescape/kubescape.git
synced 2026-02-14 18:09:55 +00:00
remove vendor
This commit is contained in:
@@ -41,7 +41,7 @@ func (flagHandler *FlagHandler) ParseFlag() {
|
||||
}
|
||||
|
||||
func (flagHandler *FlagHandler) Help() {
|
||||
fmt.Println("Run: ./kube-escape scan framework nsa")
|
||||
fmt.Println("Run: kube-escape scan framework nsa")
|
||||
}
|
||||
|
||||
func (flagHandler *FlagHandler) Version() {
|
||||
|
||||
34
vendor/github.com/armosec/capacketsgo/README.md
generated
vendored
34
vendor/github.com/armosec/capacketsgo/README.md
generated
vendored
@@ -1,34 +0,0 @@
|
||||
# ARMO Golang Utilities Repository
|
||||
|
||||
This is ARMO Golang repository for common data structures, functions and etc.
|
||||
|
||||
**Please keep everything organized**
|
||||
|
||||
Guideline: If you KNOW a datastructure/function will appear in two components or more this is where it belongs!
|
||||
|
||||
|
||||
Each subfolder contains it's own readme
|
||||
|
||||
### Clone `capacketsgo` to you repository
|
||||
|
||||
```
|
||||
git submodule add git@github.com:armosec/capacketsgo.git ./vendor/github.com/armosec/capacketsgo
|
||||
```
|
||||
|
||||
Update your project `go.mod`:
|
||||
```
|
||||
replace github.com/armosec/capacketsgo => ./vendor/github.com/armosec/capacketsgo
|
||||
|
||||
require (
|
||||
github.com/armosec/capacketsgo v0.0.0
|
||||
)
|
||||
```
|
||||
|
||||
When vendor is angry on u run build with the following command:
|
||||
```
|
||||
go build -mod=mod .
|
||||
```
|
||||
every project must do:
|
||||
|
||||
git config --global url."ssh://git@github.com/armosec/".insteadOf "https://github.com/armosec/"
|
||||
go env -w GOPRIVATE=github.com/armosec
|
||||
101
vendor/github.com/armosec/capacketsgo/apis/backendconnector.go
generated
vendored
101
vendor/github.com/armosec/capacketsgo/apis/backendconnector.go
generated
vendored
@@ -1,101 +0,0 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// HTTPReqFunc allows you to insert query params and more to aggregation message while using update aggregator
|
||||
type HTTPReqFunc func(req *http.Request, qryData interface{})
|
||||
|
||||
func BasicBEQuery(req *http.Request, qryData interface{}) {
|
||||
|
||||
q := req.URL.Query()
|
||||
|
||||
if notificationData, isok := qryData.(*LoginObject); isok {
|
||||
q.Add("customerGUID", notificationData.GUID)
|
||||
}
|
||||
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
func EmptyQuery(req *http.Request, qryData interface{}) {
|
||||
q := req.URL.Query()
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
func MapQuery(req *http.Request, qryData interface{}) {
|
||||
q := req.URL.Query()
|
||||
if qryMap, isok := qryData.(map[string]string); isok {
|
||||
for k, v := range qryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
func BEHttpRequest(loginobj *LoginObject, beURL,
|
||||
httpverb string,
|
||||
endpoint string,
|
||||
payload []byte,
|
||||
f HTTPReqFunc,
|
||||
qryData interface{}) ([]byte, error) {
|
||||
client := &http.Client{}
|
||||
|
||||
beURL = fmt.Sprintf("%v/%v", beURL, endpoint)
|
||||
req, err := http.NewRequest(httpverb, beURL, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", loginobj.Authorization)
|
||||
f(req, qryData)
|
||||
|
||||
for _, cookie := range loginobj.Cookies {
|
||||
req.AddCookie(cookie)
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
fmt.Printf("req:\n%v\nresp:%v\n", req, resp)
|
||||
return nil, fmt.Errorf("Error #%v Due to: %v", resp.StatusCode, resp.Status)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
type BELoginResponse struct {
|
||||
Name string `json:"name"`
|
||||
PreferredUsername string `json:"preferred_username"`
|
||||
Email string `json:"email"`
|
||||
CustomerGuid string `json:"customerGuid"`
|
||||
Expires string `json:"expires"`
|
||||
Authorization string `json:"authorization"`
|
||||
Cookies []*http.Cookie
|
||||
}
|
||||
|
||||
func (r *BELoginResponse) ToLoginObject() *LoginObject {
|
||||
l := &LoginObject{}
|
||||
l.Authorization = r.Authorization
|
||||
l.Cookies = r.Cookies
|
||||
l.Expires = r.Expires
|
||||
l.GUID = r.CustomerGuid
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
type BackendConnector struct {
|
||||
BaseURL string
|
||||
BELoginResponse *BELoginResponse
|
||||
Credentials *CustomerLoginDetails
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
128
vendor/github.com/armosec/capacketsgo/apis/backendconnectormethods.go
generated
vendored
128
vendor/github.com/armosec/capacketsgo/apis/backendconnectormethods.go
generated
vendored
@@ -1,128 +0,0 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func MakeBackendConnector(client *http.Client, baseURL string, loginDetails *CustomerLoginDetails) (*BackendConnector, error) {
|
||||
if err := ValidateBEConnectorMakerInput(client, baseURL, loginDetails); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn := &BackendConnector{BaseURL: baseURL, Credentials: loginDetails, HTTPClient: client}
|
||||
err := conn.Login()
|
||||
|
||||
return conn, err
|
||||
}
|
||||
|
||||
func ValidateBEConnectorMakerInput(client *http.Client, baseURL string, loginDetails *CustomerLoginDetails) error {
|
||||
if client == nil {
|
||||
fmt.Errorf("You must provide an initialized httpclient")
|
||||
}
|
||||
if len(baseURL) == 0 {
|
||||
return fmt.Errorf("you must provide a valid backend url")
|
||||
}
|
||||
|
||||
if loginDetails == nil || (len(loginDetails.Email) == 0 && len(loginDetails.Password) == 0) {
|
||||
return fmt.Errorf("you must provide valid login details")
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (r *BackendConnector) Login() error {
|
||||
if !r.IsExpired() {
|
||||
return nil
|
||||
}
|
||||
|
||||
loginInfoBytes, err := json.Marshal(r.Credentials)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to marshal credentials properly")
|
||||
}
|
||||
|
||||
beURL := fmt.Sprintf("%v/%v", r.BaseURL, "login")
|
||||
|
||||
req, err := http.NewRequest("POST", beURL, bytes.NewReader(loginInfoBytes))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Referer", strings.Replace(beURL, "dashbe", "cpanel", 1))
|
||||
resp, err := r.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read login response")
|
||||
}
|
||||
|
||||
loginS := &BELoginResponse{}
|
||||
json.Unmarshal(body, &loginS)
|
||||
|
||||
loginS.Cookies = resp.Cookies()
|
||||
r.BELoginResponse = loginS
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *BackendConnector) IsExpired() bool {
|
||||
return r.BELoginResponse == nil || r.BELoginResponse.ToLoginObject().IsExpired()
|
||||
}
|
||||
|
||||
func (r *BackendConnector) GetBaseURL() string {
|
||||
return r.BaseURL
|
||||
}
|
||||
func (r *BackendConnector) GetLoginObj() *LoginObject {
|
||||
return r.BELoginResponse.ToLoginObject()
|
||||
}
|
||||
func (r *BackendConnector) GetClient() *http.Client {
|
||||
return r.HTTPClient
|
||||
}
|
||||
|
||||
func (r *BackendConnector) HTTPSend(httpverb string,
|
||||
endpoint string,
|
||||
payload []byte,
|
||||
f HTTPReqFunc,
|
||||
qryData interface{}) ([]byte, error) {
|
||||
|
||||
beURL := fmt.Sprintf("%v/%v", r.GetBaseURL(), endpoint)
|
||||
req, err := http.NewRequest(httpverb, beURL, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if r.IsExpired() {
|
||||
r.Login()
|
||||
}
|
||||
|
||||
loginobj := r.GetLoginObj()
|
||||
req.Header.Set("Authorization", loginobj.Authorization)
|
||||
f(req, qryData)
|
||||
q := req.URL.Query()
|
||||
q.Set("customerGUID", loginobj.GUID)
|
||||
req.URL.RawQuery = q.Encode()
|
||||
|
||||
for _, cookie := range loginobj.Cookies {
|
||||
req.AddCookie(cookie)
|
||||
}
|
||||
resp, err := r.GetClient().Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
fmt.Printf("req:\n%v\nresp:%v\n", req, resp)
|
||||
return nil, fmt.Errorf("Error #%v Due to: %v", resp.StatusCode, resp.Status)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
25
vendor/github.com/armosec/capacketsgo/apis/clusterapis.go
generated
vendored
25
vendor/github.com/armosec/capacketsgo/apis/clusterapis.go
generated
vendored
@@ -1,25 +0,0 @@
|
||||
package apis
|
||||
|
||||
// WebsocketScanCommand api
|
||||
const (
|
||||
WebsocketScanCommandVersion string = "v1"
|
||||
WebsocketScanCommandPath string = "scanImage"
|
||||
)
|
||||
|
||||
// commands send via websocket
|
||||
const (
|
||||
UPDATE string = "update"
|
||||
ATTACH string = "Attach"
|
||||
REMOVE string = "remove"
|
||||
DETACH string = "Detach"
|
||||
INCOMPATIBLE string = "Incompatible"
|
||||
REPLACE_HEADERS string = "ReplaceHeaders"
|
||||
IMAGE_UNREACHABLE string = "ImageUnreachable"
|
||||
SIGN string = "sign"
|
||||
UNREGISTERED string = "unregistered"
|
||||
INJECT string = "inject"
|
||||
RESTART string = "restart"
|
||||
ENCRYPT string = "encryptSecret"
|
||||
DECRYPT string = "decryptSecret"
|
||||
SCAN string = "scan"
|
||||
)
|
||||
78
vendor/github.com/armosec/capacketsgo/apis/datastructures.go
generated
vendored
78
vendor/github.com/armosec/capacketsgo/apis/datastructures.go
generated
vendored
@@ -1,78 +0,0 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
)
|
||||
|
||||
// WebsocketScanCommand trigger scan thru the websocket
|
||||
type WebsocketScanCommand struct {
|
||||
// CustomerGUID string `json:"customerGUID"`
|
||||
ImageTag string `json:"imageTag"`
|
||||
Wlid string `json:"wlid"`
|
||||
IsScanned bool `json:"isScanned"`
|
||||
ContainerName string `json:"containerName"`
|
||||
JobID string `json:"jobID,omitempty"`
|
||||
LastAction int `json:"actionIDN"`
|
||||
// ImageHash string `json:"imageHash"`
|
||||
Credentials *types.AuthConfig `json:"credentials,omitempty"`
|
||||
}
|
||||
|
||||
//taken from BE
|
||||
// ElasticRespTotal holds the total struct in Elastic array response
|
||||
type ElasticRespTotal struct {
|
||||
Value int `json:"value"`
|
||||
Relation string `json:"relation"`
|
||||
}
|
||||
|
||||
// V2ListResponse holds the response of some list request with some metadata
|
||||
type V2ListResponse struct {
|
||||
Total ElasticRespTotal `json:"total"`
|
||||
Response interface{} `json:"response"`
|
||||
// Cursor for quick access to the next page. Not supported yet
|
||||
Cursor string `json:"cursor"`
|
||||
}
|
||||
|
||||
// Oauth2Customer returns inside the "ca_groups" field in claims section of
|
||||
// Oauth2 verification process
|
||||
type Oauth2Customer struct {
|
||||
CustomerName string `json:"customerName"`
|
||||
CustomerGUID string `json:"customerGUID"`
|
||||
}
|
||||
|
||||
type LoginObject struct {
|
||||
Authorization string `json:"authorization"`
|
||||
GUID string
|
||||
Cookies []*http.Cookie
|
||||
Expires string
|
||||
}
|
||||
|
||||
type SafeMode struct {
|
||||
Reporter string `json:"reporter"` // "Agent"
|
||||
Action string `json:"action,omitempty"` // "action"
|
||||
Wlid string `json:"wlid"` // CAA_WLID
|
||||
PodName string `json:"podName"` // CAA_POD_NAME
|
||||
InstanceID string `json:"instanceID"` // CAA_POD_NAME
|
||||
ContainerName string `json:"containerName,omitempty"` // CAA_CONTAINER_NAME
|
||||
ProcessName string `json:"processName,omitempty"`
|
||||
ProcessID int `json:"processID,omitempty"`
|
||||
ProcessCMD string `json:"processCMD,omitempty"`
|
||||
ComponentGUID string `json:"componentGUID,omitempty"` // CAA_GUID
|
||||
StatusCode int `json:"statusCode"` // 0/1/2
|
||||
ProcessExitCode int `json:"processExitCode"` // 0 +
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Message string `json:"message,omitempty"` // any string
|
||||
JobID string `json:"jobID,omitempty"` // any string
|
||||
Compatible *bool `json:"compatible,omitempty"`
|
||||
}
|
||||
|
||||
func (safeMode *SafeMode) Json() string {
|
||||
b, err := json.Marshal(*safeMode)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s", b)
|
||||
}
|
||||
26
vendor/github.com/armosec/capacketsgo/apis/datastructures_test.go
generated
vendored
26
vendor/github.com/armosec/capacketsgo/apis/datastructures_test.go
generated
vendored
@@ -1,26 +0,0 @@
|
||||
package apis
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "net/http"
|
||||
// "testing"
|
||||
// )
|
||||
|
||||
// func TestAuditStructure(t *testing.T) {
|
||||
// c := http.Client{}
|
||||
// be, err := MakeBackendConnector(&c, "https://dashbe.eudev3.cyberarmorsoft.com", &CustomerLoginDetails{Email: "lalafi@cyberarmor.io", Password: "*", CustomerName: "CyberArmorTests"})
|
||||
// if err != nil {
|
||||
// t.Errorf("sad1")
|
||||
|
||||
// }
|
||||
|
||||
// b, err := be.HTTPSend("GET", "v1/microservicesOverview", nil, MapQuery, map[string]string{"wlid": "wlid://cluster-childrenofbodom/namespace-default/deployment-pos"})
|
||||
// if err != nil {
|
||||
// t.Errorf("sad2")
|
||||
|
||||
// }
|
||||
// fmt.Printf("%v", string(b))
|
||||
|
||||
// t.Errorf("sad")
|
||||
|
||||
// }
|
||||
21
vendor/github.com/armosec/capacketsgo/apis/interfaces.go
generated
vendored
21
vendor/github.com/armosec/capacketsgo/apis/interfaces.go
generated
vendored
@@ -1,21 +0,0 @@
|
||||
package apis
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Connector - interface for any connector (BE/Portal and so on)
|
||||
type Connector interface {
|
||||
|
||||
//may used for a more generic httpsend interface based method
|
||||
GetBaseURL() string
|
||||
GetLoginObj() *LoginObject
|
||||
GetClient() *http.Client
|
||||
|
||||
Login() error
|
||||
IsExpired() bool
|
||||
|
||||
HTTPSend(httpverb string,
|
||||
endpoint string,
|
||||
payload []byte,
|
||||
f HTTPReqFunc,
|
||||
qryData interface{}) ([]byte, error)
|
||||
}
|
||||
256
vendor/github.com/armosec/capacketsgo/apis/login.go
generated
vendored
256
vendor/github.com/armosec/capacketsgo/apis/login.go
generated
vendored
@@ -1,256 +0,0 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"io/ioutil"
|
||||
|
||||
oidc "github.com/coreos/go-oidc"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
|
||||
// "go.uber.org/zap"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func GetOauth2TokenURL() string {
|
||||
return "https://idens.eudev3.cyberarmorsoft.com/auth/realms/CyberArmorSites"
|
||||
}
|
||||
|
||||
func GetLoginStruct() (LoginAux, error) {
|
||||
|
||||
return LoginAux{Referer: "https://cpanel.eudev3.cyberarmorsoft.com/login", Url: "https://cpanel.eudev3.cyberarmorsoft.com/login"}, nil
|
||||
}
|
||||
|
||||
func LoginWithKeycloak(loginDetails CustomerLoginDetails) ([]uuid.UUID, *oidc.IDToken, error) {
|
||||
// var custGUID uuid.UUID
|
||||
// config.Oauth2TokenURL
|
||||
if GetOauth2TokenURL() == "" {
|
||||
return nil, nil, fmt.Errorf("missing oauth2 token URL")
|
||||
}
|
||||
urlaux, _ := GetLoginStruct()
|
||||
conf, err := getOauth2Config(urlaux)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ctx := context.Background()
|
||||
provider, err := oidc.NewProvider(ctx, GetOauth2TokenURL())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// "Oauth2ClientID": "golang-client"
|
||||
oidcConfig := &oidc.Config{
|
||||
ClientID: "golang-client",
|
||||
SkipClientIDCheck: true,
|
||||
}
|
||||
|
||||
verifier := provider.Verifier(oidcConfig)
|
||||
ouToken, err := conf.PasswordCredentialsToken(ctx, loginDetails.Email, loginDetails.Password)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// "Authorization",
|
||||
authorization := fmt.Sprintf("%s %s", ouToken.Type(), ouToken.AccessToken)
|
||||
// oidc.IDTokenVerifier
|
||||
tkn, err := verifier.Verify(ctx, ouToken.AccessToken)
|
||||
if err != nil {
|
||||
return nil, tkn, err
|
||||
}
|
||||
tkn.Nonce = authorization
|
||||
if loginDetails.CustomerName == "" {
|
||||
customers, err := getCustomersNames(tkn)
|
||||
if err != nil {
|
||||
return nil, tkn, err
|
||||
}
|
||||
if len(customers) == 1 {
|
||||
loginDetails.CustomerName = customers[0]
|
||||
} else {
|
||||
return nil, tkn, fmt.Errorf("login with one of the following customers: %v", customers)
|
||||
}
|
||||
}
|
||||
custGUID, err := getCustomerGUID(tkn, &loginDetails)
|
||||
if err != nil {
|
||||
return nil, tkn, err
|
||||
}
|
||||
return []uuid.UUID{custGUID}, tkn, nil
|
||||
}
|
||||
|
||||
func getOauth2Config(urlaux LoginAux) (*oauth2.Config, error) {
|
||||
reURLSlices := strings.Split(urlaux.Referer, "/")
|
||||
if len(reURLSlices) == 0 {
|
||||
reURLSlices = strings.Split(urlaux.Url, "/")
|
||||
}
|
||||
// zapLogger.With(zap.Strings("referer", reURLSlices)).Info("Searching oauth2Config for")
|
||||
if len(reURLSlices) < 3 {
|
||||
reURLSlices = []string{reURLSlices[0], reURLSlices[0], reURLSlices[0]}
|
||||
}
|
||||
lg, _ := GetLoginStruct()
|
||||
provider, _ := oidc.NewProvider(context.Background(), GetOauth2TokenURL())
|
||||
//provider.Endpoint {"AuthURL":"https://idens.eudev3.cyberarmorsoft.com/auth/realms/CyberArmorSites/protocol/openid-connect/auth","TokenURL":"https://idens.eudev3.cyberarmorsoft.com/auth/realms/CyberArmorSites/protocol/openid-connect/token","AuthStyle":0}
|
||||
conf := oauth2.Config{
|
||||
ClientID: "golang-client",
|
||||
ClientSecret: "4e33bad2-3491-41a6-b486-93c492cfb4a2",
|
||||
RedirectURL: lg.Referer,
|
||||
// Discovery returns the OAuth2 endpoints.
|
||||
Endpoint: provider.Endpoint(),
|
||||
// "openid" is a required scope for OpenID Connect flows.
|
||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||
}
|
||||
return &conf, nil
|
||||
// return nil, fmt.Errorf("canno't find oauth2Config for referer '%+v'.\nPlease set referer or origin headers", reURLSlices)
|
||||
}
|
||||
|
||||
func getCustomersNames(oauth2Details *oidc.IDToken) ([]string, error) {
|
||||
var claimsJSON Oauth2Claims
|
||||
if err := oauth2Details.Claims(&claimsJSON); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
customersList := make([]string, 0, len(claimsJSON.CAGroups))
|
||||
for _, v := range claimsJSON.CAGroups {
|
||||
var caCustomer Oauth2Customer
|
||||
if err := json.Unmarshal([]byte(v), &caCustomer); err == nil {
|
||||
customersList = append(customersList, caCustomer.CustomerName)
|
||||
}
|
||||
}
|
||||
return customersList, nil
|
||||
}
|
||||
|
||||
func getCustomerGUID(tkn *oidc.IDToken, loginDetails *CustomerLoginDetails) (uuid.UUID, error) {
|
||||
|
||||
customers, err := getCustomersList(tkn)
|
||||
if err != nil {
|
||||
return uuid.UUID{}, err
|
||||
}
|
||||
|
||||
// if customer name not provided - use default customer
|
||||
if loginDetails.CustomerName == "" && len(customers) > 0 {
|
||||
return uuid.FromString(customers[0].CustomerGUID)
|
||||
}
|
||||
|
||||
for _, i := range customers {
|
||||
if i.CustomerName == loginDetails.CustomerName {
|
||||
return uuid.FromString(i.CustomerGUID)
|
||||
}
|
||||
}
|
||||
return uuid.UUID{}, fmt.Errorf("customer name not found in customer list")
|
||||
}
|
||||
|
||||
func getCustomersList(oauth2Details *oidc.IDToken) ([]Oauth2Customer, error) {
|
||||
var claimsJSON Oauth2Claims
|
||||
if err := oauth2Details.Claims(&claimsJSON); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
customersList := make([]Oauth2Customer, 0, len(claimsJSON.CAGroups))
|
||||
for _, v := range claimsJSON.CAGroups {
|
||||
var caCustomer Oauth2Customer
|
||||
if err := json.Unmarshal([]byte(v), &caCustomer); err == nil {
|
||||
customersList = append(customersList, caCustomer)
|
||||
}
|
||||
}
|
||||
return customersList, nil
|
||||
}
|
||||
|
||||
// func MakeAuthCookies(custGUID uuid.UUID, ouToken *oidc.IDToken) (*http.Cookie, error) {
|
||||
// var ccc http.Cookie
|
||||
// var responseData AuthenticationCookie
|
||||
// expireDate := time.Now().UTC().Add(time.Duration(config.CookieExpirationHours) * time.Hour)
|
||||
// if ouToken != nil {
|
||||
// expireDate = ouToken.Expiry
|
||||
// }
|
||||
// ccc.Expires = expireDate
|
||||
// responseData.CustomerGUID = custGUID
|
||||
// responseData.Expires = ccc.Expires
|
||||
// responseData.Version = 0
|
||||
// authorizationStr := ""
|
||||
// if ouToken != nil {
|
||||
// authorizationStr = ouToken.Nonce
|
||||
// if err := ouToken.Claims(&responseData.Oauth2Claims); err != nil {
|
||||
// errStr := fmt.Sprintf("failed to get claims from JWT")
|
||||
// return nil, fmt.Errorf("%v", errStr)
|
||||
// }
|
||||
// }
|
||||
// jsonBytes, err := json.Marshal(responseData)
|
||||
// if err != nil {
|
||||
// errStr := fmt.Sprintf("failed to get claims from JWT")
|
||||
// return nil, fmt.Errorf("%v", errStr)
|
||||
// }
|
||||
// ccc.Name = "auth"
|
||||
// ccc.Value = hex.EncodeToString(jsonBytes) + "." + cacheaccess.CalcHmac256(jsonBytes)
|
||||
// // TODO: HttpOnly for security...
|
||||
// ccc.HttpOnly = false
|
||||
// ccc.Path = "/"
|
||||
// ccc.Secure = true
|
||||
// ccc.SameSite = http.SameSiteNoneMode
|
||||
// http.SetCookie(w, &ccc)
|
||||
// responseData.Authorization = authorizationStr
|
||||
// jsonBytes, err = json.Marshal(responseData)
|
||||
// if err != nil {
|
||||
// w.WriteHeader(http.StatusInternalServerError)
|
||||
// fmt.Fprintf(w, "error while marshaling response(2) %s", err)
|
||||
// return
|
||||
// }
|
||||
// w.Write(jsonBytes)
|
||||
// }
|
||||
|
||||
func Login(loginDetails CustomerLoginDetails) (*LoginObject, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func GetBEInfo(cfgFile string) string {
|
||||
return "https://dashbe.eudev3.cyberarmorsoft.com"
|
||||
}
|
||||
|
||||
func BELogin(loginDetails *CustomerLoginDetails, login string, cfg string) (*BELoginResponse, error) {
|
||||
client := &http.Client{}
|
||||
|
||||
basebeURL := GetBEInfo(cfg)
|
||||
beURL := fmt.Sprintf("%v/%v", basebeURL, login)
|
||||
|
||||
loginInfoBytes, err := json.Marshal(loginDetails)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req, err := http.NewRequest("POST", beURL, bytes.NewReader(loginInfoBytes))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Referer", strings.Replace(beURL, "dashbe", "cpanel", 1))
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
loginS := &BELoginResponse{}
|
||||
json.Unmarshal(body, &loginS)
|
||||
|
||||
loginS.Cookies = resp.Cookies()
|
||||
return loginS, nil
|
||||
}
|
||||
|
||||
func (r *LoginObject) IsExpired() bool {
|
||||
if r == nil {
|
||||
return true
|
||||
}
|
||||
t, err := time.Parse(time.RFC3339, r.Expires)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return t.UTC().Before(time.Now().UTC())
|
||||
}
|
||||
41
vendor/github.com/armosec/capacketsgo/apis/login_test.go
generated
vendored
41
vendor/github.com/armosec/capacketsgo/apis/login_test.go
generated
vendored
@@ -1,41 +0,0 @@
|
||||
package apis
|
||||
|
||||
// func TestLogin2BE(t *testing.T) {
|
||||
|
||||
// loginDetails := CustomerLoginDetails{Email: "lalafi@cyberarmor.io", Password: "***", CustomerName: "CyberArmorTests"}
|
||||
// res, err := BELogin(loginDetails, "login")
|
||||
// if err != nil {
|
||||
// t.Errorf("failed to get raw audit is different ")
|
||||
// }
|
||||
// k := res.ToLoginObject()
|
||||
|
||||
// fmt.Printf("%v\n", k)
|
||||
|
||||
// }
|
||||
|
||||
// func TestGetMicroserviceOverview(t *testing.T) {
|
||||
// // client := &http.Client{}
|
||||
// loginDetails := CustomerLoginDetails{Email: "lalafi@cyberarmor.io", Password: "***", CustomerName: "CyberArmorTests"}
|
||||
// loginobj, err := BELogin(loginDetails, "login")
|
||||
// if err != nil {
|
||||
// t.Errorf("failed to get raw audit is different ")
|
||||
// }
|
||||
// k := loginobj.ToLoginObject()
|
||||
// beURL := GetBEInfo("")
|
||||
|
||||
// res, err := BEHttpRequest(k, beURL,
|
||||
// "GET",
|
||||
// "v1/microservicesOverview",
|
||||
// nil,
|
||||
// BasicBEQuery,
|
||||
// k)
|
||||
|
||||
// if err != nil {
|
||||
// t.Errorf("failed to get raw audit is different ")
|
||||
// }
|
||||
|
||||
// s := string(res)
|
||||
|
||||
// fmt.Printf("%v\n", s)
|
||||
|
||||
// }
|
||||
38
vendor/github.com/armosec/capacketsgo/apis/logindatastructures.go
generated
vendored
38
vendor/github.com/armosec/capacketsgo/apis/logindatastructures.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
)
|
||||
|
||||
// AuthenticationCookie is what it is
|
||||
type AuthenticationCookie struct {
|
||||
Oauth2Claims `json:",inline"`
|
||||
CustomerGUID uuid.UUID `json:"customerGuid"`
|
||||
Expires time.Time `json:"expires"`
|
||||
Version int `json:"version"`
|
||||
Authorization string `json:"authorization,omitempty"`
|
||||
}
|
||||
|
||||
type LoginAux struct {
|
||||
Referer string
|
||||
Url string
|
||||
}
|
||||
|
||||
// CustomerLoginDetails is what it is
|
||||
type CustomerLoginDetails struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
CustomerName string `json:"customer,omitempty"`
|
||||
CustomerGUID uuid.UUID `json:"customerGuid,omitempty"`
|
||||
}
|
||||
|
||||
// Oauth2Claims returns in claims section of Oauth2 verification process
|
||||
type Oauth2Claims struct {
|
||||
Sub string `json:"sub"`
|
||||
Name string `json:"name"`
|
||||
PreferredUserName string `json:"preferred_username"`
|
||||
CAGroups []string `json:"ca_groups"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
132
vendor/github.com/armosec/capacketsgo/apis/websocketdatastructures.go
generated
vendored
132
vendor/github.com/armosec/capacketsgo/apis/websocketdatastructures.go
generated
vendored
@@ -1,132 +0,0 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Commands list of commands received from websocket
|
||||
type Commands struct {
|
||||
Commands []Command `json:"commands"`
|
||||
}
|
||||
|
||||
// Command structure of command received from websocket
|
||||
type Command struct {
|
||||
CommandName string `json:"commandName"`
|
||||
ResponseID string `json:"responseID"`
|
||||
Wlid string `json:"wlid,omitempty"`
|
||||
WildWlid string `json:"wildWlid,omitempty"`
|
||||
Sid string `json:"sid,omitempty"`
|
||||
WildSid string `json:"wildSid,omitempty"`
|
||||
JobTracking JobTracking `json:"jobTracking"`
|
||||
Args map[string]interface{} `json:"args,omitempty"`
|
||||
}
|
||||
|
||||
type JobTracking struct {
|
||||
JobID string `json:"jobID,omitempty"`
|
||||
ParentID string `json:"parentAction,omitempty"`
|
||||
LastActionNumber int `json:"numSeq,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Command) DeepCopy() *Command {
|
||||
newCommand := &Command{}
|
||||
newCommand.CommandName = c.CommandName
|
||||
newCommand.ResponseID = c.ResponseID
|
||||
newCommand.Wlid = c.Wlid
|
||||
newCommand.WildWlid = c.WildWlid
|
||||
if c.Args != nil {
|
||||
newCommand.Args = make(map[string]interface{})
|
||||
for i, j := range c.Args {
|
||||
newCommand.Args[i] = j
|
||||
}
|
||||
}
|
||||
return newCommand
|
||||
}
|
||||
|
||||
func (c *Command) GetLabels() map[string]string {
|
||||
if c.Args != nil {
|
||||
if ilabels, ok := c.Args["labels"]; ok {
|
||||
labels := map[string]string{}
|
||||
if b, e := json.Marshal(ilabels); e == nil {
|
||||
if e = json.Unmarshal(b, &labels); e == nil {
|
||||
return labels
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (c *Command) SetLabels(labels map[string]string) {
|
||||
if c.Args == nil {
|
||||
c.Args = make(map[string]interface{})
|
||||
}
|
||||
c.Args["labels"] = labels
|
||||
}
|
||||
|
||||
func (c *Command) GetFieldSelector() map[string]string {
|
||||
if c.Args != nil {
|
||||
if ilabels, ok := c.Args["fieldSelector"]; ok {
|
||||
labels := map[string]string{}
|
||||
if b, e := json.Marshal(ilabels); e == nil {
|
||||
if e = json.Unmarshal(b, &labels); e == nil {
|
||||
return labels
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (c *Command) SetFieldSelector(labels map[string]string) {
|
||||
if c.Args == nil {
|
||||
c.Args = make(map[string]interface{})
|
||||
}
|
||||
c.Args["fieldSelector"] = labels
|
||||
}
|
||||
|
||||
func (c *Command) GetID() string {
|
||||
if c.WildWlid != "" {
|
||||
return c.WildWlid
|
||||
}
|
||||
if c.WildSid != "" {
|
||||
return c.WildSid
|
||||
}
|
||||
if c.Wlid != "" {
|
||||
return c.Wlid
|
||||
}
|
||||
if c.Sid != "" {
|
||||
return c.Sid
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *Command) Json() string {
|
||||
b, _ := json.Marshal(*c)
|
||||
return fmt.Sprintf("%s", b)
|
||||
}
|
||||
|
||||
func SIDFallback(c *Command) {
|
||||
if c.GetID() == "" {
|
||||
sid, err := getSIDFromArgs(c.Args)
|
||||
if err != nil || sid == "" {
|
||||
return
|
||||
}
|
||||
c.Sid = sid
|
||||
}
|
||||
}
|
||||
|
||||
func getSIDFromArgs(args map[string]interface{}) (string, error) {
|
||||
sidInterface, ok := args["sid"]
|
||||
if !ok {
|
||||
return "", nil
|
||||
}
|
||||
sid, ok := sidInterface.(string)
|
||||
if !ok || sid == "" {
|
||||
return "", fmt.Errorf("sid found in args but empty")
|
||||
}
|
||||
// if _, err := secrethandling.SplitSecretID(sid); err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
return sid, nil
|
||||
}
|
||||
16
vendor/github.com/armosec/capacketsgo/armotypes/executionpolicytypes.go
generated
vendored
16
vendor/github.com/armosec/capacketsgo/armotypes/executionpolicytypes.go
generated
vendored
@@ -1,16 +0,0 @@
|
||||
package armotypes
|
||||
|
||||
type EnforcmentsRule struct {
|
||||
MonitoredObject []string `json:"monitoredObject"`
|
||||
MonitoredObjectExistence []string `json:"objectExistence"`
|
||||
MonitoredObjectEvent []string `json:"event"`
|
||||
Action []string `json:"action"`
|
||||
}
|
||||
|
||||
type ExecutionPolicy struct {
|
||||
PortalBase `json:",inline"`
|
||||
Designators []PortalDesignator `json:"designators"`
|
||||
PolicyType string `json:"policyType"`
|
||||
CreationTime string `json:"creation_time"`
|
||||
ExecutionEnforcmentsRules []EnforcmentsRule `json:"enforcementRules"`
|
||||
}
|
||||
57
vendor/github.com/armosec/capacketsgo/armotypes/portaltypes.go
generated
vendored
57
vendor/github.com/armosec/capacketsgo/armotypes/portaltypes.go
generated
vendored
@@ -1,57 +0,0 @@
|
||||
package armotypes
|
||||
|
||||
const (
|
||||
CostumerGuidQuery = "costumerGUID"
|
||||
ClusterNameQuery = "cluster"
|
||||
DatacenterNameQuery = "datacenter"
|
||||
NamespaceQuery = "namespace"
|
||||
ProjectQuery = "project"
|
||||
WlidQuery = "wlid"
|
||||
SidQuery = "sid"
|
||||
)
|
||||
|
||||
// PortalBase holds basic items data from portal BE
|
||||
type PortalBase struct {
|
||||
GUID string `json:"guid"`
|
||||
Name string `json:"name"`
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"` // could be string
|
||||
}
|
||||
|
||||
type DesignatorType string
|
||||
|
||||
// Supported designators
|
||||
const (
|
||||
DesignatorAttributes DesignatorType = "Attributes"
|
||||
/*
|
||||
WorkloadID format.
|
||||
k8s format: wlid://cluster-<cluster>/namespace-<namespace>/<kind>-<name>
|
||||
native format: wlid://datacenter-<datacenter>/project-<project>/native-<name>
|
||||
*/
|
||||
DesignatorWlid DesignatorType = "Wlid"
|
||||
/*
|
||||
Wild card - subset of wlid. e.g.
|
||||
1. Include cluster:
|
||||
wlid://cluster-<cluster>/
|
||||
2. Include cluster and namespace (filter out all other namespaces):
|
||||
wlid://cluster-<cluster>/namespace-<namespace>/
|
||||
*/
|
||||
DesignatorWildWlid DesignatorType = "WildWlid"
|
||||
DesignatorWlidContainer DesignatorType = "WlidContainer"
|
||||
DesignatorWlidProcess DesignatorType = "WlidProcess"
|
||||
DesignatorSid DesignatorType = "Sid" // secret id
|
||||
)
|
||||
|
||||
// attributes
|
||||
const (
|
||||
AttributeCluster = "cluster"
|
||||
AttributeNamespace = "namespace"
|
||||
)
|
||||
|
||||
// PortalDesignator represented single designation options
|
||||
type PortalDesignator struct {
|
||||
DesignatorType DesignatorType `json:"designatorType"`
|
||||
WLID string `json:"wlid"`
|
||||
WildWLID string `json:"wildwlid"`
|
||||
SID string `json:"sid"`
|
||||
Attributes map[string]string `json:"attributes"`
|
||||
}
|
||||
18
vendor/github.com/armosec/capacketsgo/armotypes/portaltypes_mock.go
generated
vendored
18
vendor/github.com/armosec/capacketsgo/armotypes/portaltypes_mock.go
generated
vendored
@@ -1,18 +0,0 @@
|
||||
package armotypes
|
||||
|
||||
func MockPortalBase(customerGUID, name string, attributes map[string]interface{}) *PortalBase {
|
||||
if customerGUID == "" {
|
||||
customerGUID = "36b6f9e1-3b63-4628-994d-cbe16f81e9c7"
|
||||
}
|
||||
if name == "" {
|
||||
name = "portalbase-a"
|
||||
}
|
||||
if attributes == nil {
|
||||
attributes = make(map[string]interface{})
|
||||
}
|
||||
return &PortalBase{
|
||||
GUID: customerGUID,
|
||||
Name: name,
|
||||
Attributes: attributes,
|
||||
}
|
||||
}
|
||||
39
vendor/github.com/armosec/capacketsgo/armotypes/portaltypesutils.go
generated
vendored
39
vendor/github.com/armosec/capacketsgo/armotypes/portaltypesutils.go
generated
vendored
@@ -1,39 +0,0 @@
|
||||
package armotypes
|
||||
|
||||
import "github.com/golang/glog"
|
||||
|
||||
var IgnoreLabels = []string{AttributeCluster, AttributeNamespace}
|
||||
|
||||
// DigestPortalDesignator - get cluster namespace and labels from designator
|
||||
func DigestPortalDesignator(designator *PortalDesignator) (string, string, map[string]string) {
|
||||
switch designator.DesignatorType {
|
||||
case DesignatorAttributes:
|
||||
return DigestAttributesDesignator(designator.Attributes)
|
||||
// case DesignatorWlid: TODO
|
||||
// case DesignatorWildWlid: TODO
|
||||
default:
|
||||
glog.Warningf("in 'digestPortalDesignator' designator type: '%v' not yet supported. please contact Armo team", designator.DesignatorType)
|
||||
}
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
func DigestAttributesDesignator(attributes map[string]string) (string, string, map[string]string) {
|
||||
cluster := ""
|
||||
namespace := ""
|
||||
labels := map[string]string{}
|
||||
if attributes == nil || len(attributes) == 0 {
|
||||
return cluster, namespace, labels
|
||||
}
|
||||
for k, v := range attributes {
|
||||
labels[k] = v
|
||||
}
|
||||
if v, ok := attributes[AttributeNamespace]; ok {
|
||||
namespace = v
|
||||
delete(labels, AttributeNamespace)
|
||||
}
|
||||
if v, ok := attributes[AttributeCluster]; ok {
|
||||
cluster = v
|
||||
delete(labels, AttributeCluster)
|
||||
}
|
||||
return cluster, namespace, labels
|
||||
}
|
||||
16
vendor/github.com/armosec/capacketsgo/audit-connector/README.md
generated
vendored
16
vendor/github.com/armosec/capacketsgo/audit-connector/README.md
generated
vendored
@@ -1,16 +0,0 @@
|
||||
# Audit-logs connector
|
||||
## Example
|
||||
===
|
||||
Define this *ELASTICSEARCH_URL*
|
||||
Or use pre-defined elastic client by calling ReinitElastic function
|
||||
|
||||
```
|
||||
AuditReportAction(&AuditReport{
|
||||
Source: AuditSourceTest,
|
||||
Details: "here is some test detail",
|
||||
Subject: "the go compiler",
|
||||
Action: "ran in test mode",
|
||||
User: "ben",
|
||||
Customer: "35d5509a-e81a-492b-a4c6-55264de33e0b",
|
||||
})
|
||||
```
|
||||
69
vendor/github.com/armosec/capacketsgo/audit-connector/auditlog.go
generated
vendored
69
vendor/github.com/armosec/capacketsgo/audit-connector/auditlog.go
generated
vendored
@@ -1,69 +0,0 @@
|
||||
package auditconnector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/elastic/go-elasticsearch/v7/esapi"
|
||||
"github.com/elastic/go-elasticsearch/v7/esutil"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (audit *AuditReport) getIndexName() string {
|
||||
return "v1-audit-" + audit.CustomerGUID
|
||||
}
|
||||
|
||||
func (audit *AuditReport) doReportAuditReport() error {
|
||||
indexName := audit.getIndexName()
|
||||
esRequest := esapi.IndexRequest{
|
||||
Index: indexName,
|
||||
Body: esutil.NewJSONReader(*audit),
|
||||
}
|
||||
err := validateResponse(esRequest.Do(context.Background(), elasticClient))
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "index_not_found_exception") {
|
||||
if err = validateResponse(elasticClient.Indices.Create(indexName, elasticClient.API.Indices.Create.WithBody(strings.NewReader(indexMapping)))); err == nil {
|
||||
esRequest := esapi.IndexRequest{
|
||||
Index: indexName,
|
||||
Body: esutil.NewJSONReader(*audit),
|
||||
}
|
||||
err = validateResponse(esRequest.Do(context.Background(), elasticClient))
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func validateResponse(res *esapi.Response, err error) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("In validateRespons. Primary error. Error: '%v', ", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
dec := json.NewDecoder(res.Body)
|
||||
elErr := make(map[string]interface{})
|
||||
if err := dec.Decode(&elErr); err != nil {
|
||||
return fmt.Errorf("In validateResponse failed to decode error body: %v", err)
|
||||
}
|
||||
if res.IsError() {
|
||||
return fmt.Errorf("In validateResponse error returned (%s): %v, ", res.Status(), elErr)
|
||||
}
|
||||
zap.L().Info("In validateResponse", zap.Any("result", elErr))
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuditReportAction stores the audit report in elastic
|
||||
func AuditReportAction(action *AuditReport) {
|
||||
action.TimeStamp = time.Now()
|
||||
if elasticClient != nil {
|
||||
go func() {
|
||||
if err := action.doReportAuditReport(); err != nil {
|
||||
zap.L().Error("In AuditReportAction, failed to doReportAuditReport",
|
||||
zap.Any("report", action), zap.Error(err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
48
vendor/github.com/armosec/capacketsgo/audit-connector/auditlog_test.go
generated
vendored
48
vendor/github.com/armosec/capacketsgo/audit-connector/auditlog_test.go
generated
vendored
@@ -1,48 +0,0 @@
|
||||
package auditconnector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAuditReportBasic(t *testing.T) {
|
||||
report := AuditReport{
|
||||
Source: AuditSourceTest,
|
||||
Details: "here is some test detail",
|
||||
Subject: "the go compiler",
|
||||
Action: "ran in test mode",
|
||||
User: "ben",
|
||||
CustomerGUID: "35d5509a-e81a-492b-a4c6-55264de33e0b",
|
||||
}
|
||||
err := report.doReportAuditReport()
|
||||
if err != nil {
|
||||
t.Errorf("error reporting %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := elasticClient.Search(elasticClient.Search.WithIndex(report.getIndexName()))
|
||||
if err != nil {
|
||||
t.Errorf("error retrieving results %s", err)
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.IsError() {
|
||||
t.Errorf("error retrieving results at ES level %s", res.Status())
|
||||
return
|
||||
}
|
||||
if b, err := ioutil.ReadAll(res.Body); err == nil {
|
||||
fmt.Print(string(b))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuditReportGoRutined(t *testing.T) {
|
||||
AuditReportAction(&AuditReport{
|
||||
Source: AuditSourceTest,
|
||||
Details: "here is some test detail",
|
||||
Subject: "the go compiler",
|
||||
Action: "ran in test mode",
|
||||
User: "ben",
|
||||
CustomerGUID: "35d5509a-e81a-492b-a4c6-55264de33e0b",
|
||||
})
|
||||
}
|
||||
26
vendor/github.com/armosec/capacketsgo/audit-connector/init.go
generated
vendored
26
vendor/github.com/armosec/capacketsgo/audit-connector/init.go
generated
vendored
@@ -1,26 +0,0 @@
|
||||
package auditconnector
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
elasticsearch "github.com/elastic/go-elasticsearch/v7"
|
||||
)
|
||||
|
||||
var elasticClient *elasticsearch.Client = nil
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
elasticClient, err = elasticsearch.NewDefaultClient()
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
log.Print("Error: audit elasticsearch client could not be created")
|
||||
elasticClient = nil
|
||||
}
|
||||
}
|
||||
|
||||
// ReinitElastic inits the underlying elastic client with well-configured one instead of the default one
|
||||
func ReinitElastic(client *elasticsearch.Client) {
|
||||
if client != nil {
|
||||
elasticClient = client
|
||||
}
|
||||
}
|
||||
83
vendor/github.com/armosec/capacketsgo/audit-connector/types.go
generated
vendored
83
vendor/github.com/armosec/capacketsgo/audit-connector/types.go
generated
vendored
@@ -1,83 +0,0 @@
|
||||
package auditconnector
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// available sources for audit logs
|
||||
const (
|
||||
AuditSourceControlPanel = "ControlPanel"
|
||||
AuditSourceAggregator = "Aggregator"
|
||||
AuditSourceEventReceiver = "EventReceiver"
|
||||
AuditSourceTest = "Test"
|
||||
)
|
||||
|
||||
// type Marshaler interface {
|
||||
// MarshalJSON() ([]byte, error)
|
||||
// }
|
||||
|
||||
// AuditTime wraps the golang time object
|
||||
type AuditTime time.Time
|
||||
|
||||
// AuditReport represents single audit log entry
|
||||
type AuditReport struct {
|
||||
Source string `json:"source"`
|
||||
TimeStamp time.Time `json:"time"`
|
||||
Action string `json:"action"`
|
||||
Subject string `json:"subject"`
|
||||
Details string `json:"details"`
|
||||
User string `json:"user"`
|
||||
CustomerGUID string `json:"-"`
|
||||
}
|
||||
|
||||
// func (t AuditTime) MarshalJSON() ([]byte, error) {
|
||||
// stamp := fmt.Sprintf("\"%s\"", time.Time(t).String())
|
||||
// return []byte(stamp), nil
|
||||
// }
|
||||
|
||||
const indexMapping = `
|
||||
{
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"source": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
},
|
||||
"time": {
|
||||
"type": "date",
|
||||
"ignore_malformed": true,
|
||||
"format": "strict_date_optional_time_nanos"
|
||||
},
|
||||
"action": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
},
|
||||
"subject": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 8000
|
||||
}
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"type": "text"
|
||||
},
|
||||
"user": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"customerGUID": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 64
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
83
vendor/github.com/armosec/capacketsgo/cacli/cacliinterface.go
generated
vendored
83
vendor/github.com/armosec/capacketsgo/cacli/cacliinterface.go
generated
vendored
@@ -1,83 +0,0 @@
|
||||
package cacli
|
||||
|
||||
import (
|
||||
"github.com/armosec/capacketsgo/opapolicy"
|
||||
"github.com/armosec/capacketsgo/secrethandling"
|
||||
)
|
||||
|
||||
/*
|
||||
Please follow the convention:
|
||||
cacli <group1> <group2> <command>
|
||||
The function name should look like:
|
||||
GROUP1GROUP2Command (groups should be upper-case. command - first leeter upper case)
|
||||
|
||||
Examples:
|
||||
cacli wt get -> WTGet
|
||||
cacli wt Triplet -> WTTriplet
|
||||
cacli secp list -> SECPList
|
||||
cacli secp encrypt -> SECPEncrypt
|
||||
cacli k8s attach -> K8SAttach
|
||||
cacli opa framework get -> OPAFRAMEWORKGet
|
||||
*/
|
||||
type ICacli interface {
|
||||
// basic commands
|
||||
Login() error
|
||||
Status() (*Status, error)
|
||||
Sign(wlid, user, password, ociImageURL string) error
|
||||
|
||||
// wt
|
||||
WTCreate(*WorkloadTemplate, string) (string, error)
|
||||
WTApply(*WorkloadTemplate, string) (string, error)
|
||||
WTUpdate(*WorkloadTemplate, string) (string, error)
|
||||
WTDelete(string) error
|
||||
WTTriplet(string) (*GUIDTriplet, error)
|
||||
WTGet(string) (*WorkloadTemplate, error)
|
||||
WTDownload(wlid, containerName, output string) error
|
||||
WTSign(wlid, user, password, ociImageURL string) error
|
||||
|
||||
// sp
|
||||
// SPGet(name string) (*SigningProfile, error)
|
||||
// SPCreate(sp *SigningProfile) (string, error)
|
||||
// SPDelete(name string) error
|
||||
// SPGenarate(name string) (*SigningProfile, error)
|
||||
|
||||
// k8s
|
||||
K8SAttach(_, _, _ string, injectLabel bool) error
|
||||
|
||||
// OPA FRAMEWORK
|
||||
OPAFRAMEWORKCreate(*opapolicy.Framework, string) (*opapolicy.Framework, error)
|
||||
OPAFRAMEWORKUpdate(*opapolicy.Framework, string) (*opapolicy.Framework, error)
|
||||
OPAFRAMEWORKGet(string, bool) ([]opapolicy.Framework, error)
|
||||
OPAFRAMEWORKList(bool) ([]string, error)
|
||||
OPAFRAMEWORKDelete(string) error
|
||||
|
||||
// OPA CONTROL
|
||||
OPACONTROLCreate(*opapolicy.Control, string) (*opapolicy.Control, error)
|
||||
OPACONTROLUpdate(*opapolicy.Control, string) (*opapolicy.Control, error)
|
||||
OPACONTROLGet(string) ([]opapolicy.Control, error)
|
||||
OPACONTROLList() ([]string, error)
|
||||
OPACONTROLDelete(string) error
|
||||
|
||||
// OPA RULE
|
||||
OPARULECreate(*opapolicy.PolicyRule, string) (*opapolicy.PolicyRule, error)
|
||||
OPARULEUpdate(*opapolicy.PolicyRule, string) (*opapolicy.PolicyRule, error)
|
||||
OPARULEGet(string) ([]opapolicy.PolicyRule, error)
|
||||
OPARULEList() ([]string, error)
|
||||
OPARULEDelete(string) error
|
||||
|
||||
// // key
|
||||
// KEYGet(string) (*Key, error)
|
||||
|
||||
// secret policy
|
||||
|
||||
SECPGet(sid, name, cluster, namespace string) ([]secrethandling.SecretAccessPolicy, error)
|
||||
SECPEncrypt(message, inputFile, outputFile, keyID string, base64Enc bool) ([]byte, error)
|
||||
SECPDecrypt(message, inputFile, outputFile string, base64Enc bool) ([]byte, error)
|
||||
// SECPMetadata(string, bool) (*SecretMetadata, error)
|
||||
// SECPCreate(*secrethandling.SecretAccessPolicy) (*secrethandling.SecretAccessPolicy, error)
|
||||
// SECPUpdate(*secrethandling.SecretAccessPolicy) (*secrethandling.SecretAccessPolicy, error)
|
||||
// SECPList() ([]string, error)
|
||||
|
||||
// Utils
|
||||
UTILSCleanup(string, bool) error
|
||||
}
|
||||
183
vendor/github.com/armosec/capacketsgo/cacli/datastructures.go
generated
vendored
183
vendor/github.com/armosec/capacketsgo/cacli/datastructures.go
generated
vendored
@@ -1,183 +0,0 @@
|
||||
package cacli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultCredentialsPath = "/etc/credentials"
|
||||
DefaultCredentialsPathEnv = "CACLI_CREDENTAILS"
|
||||
)
|
||||
|
||||
//WorkloadTemplate sent
|
||||
type WorkloadTemplate struct {
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
Cluster string `json:"cluster,omitempty"`
|
||||
Datacenter string `json:"datacenter,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Project string `json:"project,omitempty"`
|
||||
GroupingLevel0 string `json:"groupingLevel0"`
|
||||
GroupingLevel1 string `json:"groupingLevel1"`
|
||||
Wlid string `json:"wlid"`
|
||||
MetaInfo WorkloadTemplateMetaInfo `json:"metainfo,omitempty"`
|
||||
AutoAccessTokenUpdate bool `json:"autoAccessTokenUpdate"`
|
||||
Containers []DockerContainers `json:"containers"`
|
||||
WorkloadTemplateAttributes map[string]string `json:"attributes,omitempty"`
|
||||
}
|
||||
|
||||
// WorkloadTemplateMetaInfo attributes in workload
|
||||
type WorkloadTemplateMetaInfo struct {
|
||||
CreationDate string `json:"creationDate"`
|
||||
LastEdited string `json:"lastEdited"`
|
||||
WorkloadKind string `json:"workloadKind"`
|
||||
Instances WorkloadTemplateInstances `json:"instances"`
|
||||
Categories []string `json:"categories"`
|
||||
}
|
||||
|
||||
//WorkloadTemplateInstances list of active and inactive
|
||||
type WorkloadTemplateInstances struct {
|
||||
Active []string `json:"active"`
|
||||
Inactive []string `json:"inactive"`
|
||||
}
|
||||
|
||||
// DockerContainers -
|
||||
type DockerContainers struct {
|
||||
Name string `json:"name"`
|
||||
Os string `json:"os,omitempty"`
|
||||
Architecture string `json:"architecture,omitempty"`
|
||||
ImageHash string `json:"imageHash,omitempty"`
|
||||
ImageTag string `json:"imageTag,omitempty"`
|
||||
EnableVisiblity []map[string]bool `json:"enableVisiblity,omitempty"`
|
||||
SigningProfileName string `json:"signingProfileName,omitempty"`
|
||||
}
|
||||
|
||||
// ModulesInformation holds data of specific module in signing profile
|
||||
type ModulesInformation struct {
|
||||
FullPath string `json:"fullPath"`
|
||||
Name string `json:"name"`
|
||||
Mandatory int `json:"mandatory"`
|
||||
Version string `json:"version,omitempty"`
|
||||
SignatureMismatchAction int `json:"signatureMismatchAction,omitempty"`
|
||||
Type int `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// GUIDTriplet CyberArmor IDs of given microservice
|
||||
type GUIDTriplet struct {
|
||||
CustomerGUID string `json:"customerGUID"`
|
||||
SolutionGUID string `json:"solutionGUID"`
|
||||
ComponentGUID string `json:"componentGUID"`
|
||||
ContainersComponentGUIDs []ContainerCAGUIDs `json:"containers"`
|
||||
}
|
||||
|
||||
// ContainerCAGUIDs CyberArmor component IDs of given container
|
||||
type ContainerCAGUIDs struct {
|
||||
ContainerName string `json:"containerName"`
|
||||
ComponentGUID string `json:"componentGUID"`
|
||||
ProcessesComponentGUIDs []ProcessGUIDs `json:"processes"`
|
||||
}
|
||||
|
||||
// ProcessGUIDs CyberArmor component ID of single process
|
||||
type ProcessGUIDs struct {
|
||||
ProcessName string `json:"name"`
|
||||
ComponentGUID string `json:"componentGUID"`
|
||||
}
|
||||
|
||||
// CredStruct holds the various credentials needed to do login into CA BE
|
||||
type CredStruct struct {
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
Customer string `json:"customer"`
|
||||
}
|
||||
|
||||
// Key portal key structure
|
||||
type Key struct {
|
||||
GUID string `json:"guid"`
|
||||
Name string `json:"name"`
|
||||
CustomID string `json:"custom_id"`
|
||||
Key string `json:"key"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
Description string `json:"description"`
|
||||
DliveryFlags string `json:"delivery_flags"`
|
||||
BackupInDB bool `json:"backup_in_ca_db"`
|
||||
BusinessRulePackage interface{} `json:"business_rule_package"`
|
||||
Attributes map[string]string `json:"attributes"`
|
||||
}
|
||||
|
||||
// SecretPolicy portal SecretPolicy structure
|
||||
type SecretPolicy struct {
|
||||
AccessPolicy int `json:"guid"`
|
||||
AccessSet string `json:"name"`
|
||||
EncryptionStatus string `json:"custom_id"`
|
||||
KeyID string `json:"key"`
|
||||
Type string `json:"algorithm"`
|
||||
}
|
||||
|
||||
// SecretAccessSetPolicy portal SecretPolicy structure
|
||||
type SecretAccessSetPolicy struct {
|
||||
Wlids []string `json:"wlids"`
|
||||
Attributes map[string]string `json:"attributes"`
|
||||
}
|
||||
|
||||
// Status cacli status
|
||||
type Status struct {
|
||||
CacliVersion string `json:"cacli-version"`
|
||||
CacsignerVersion string `json:"casigner-version"`
|
||||
Server string `json:"server"`
|
||||
Customer string `json:"customer"`
|
||||
UserName string `json:"user-name"`
|
||||
LoggedIn bool `json:"logged-in"`
|
||||
}
|
||||
|
||||
// SecretMetadata cacli secret metadata
|
||||
type SecretMetadata struct {
|
||||
Version int `json:"version"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
KeyID string `json:"keyID"`
|
||||
}
|
||||
|
||||
// SigningProfile signingProfile configuration
|
||||
type SigningProfile struct {
|
||||
Name string `json:"name"`
|
||||
GUID string `json:"guid"`
|
||||
Platform int64 `json:"platform"`
|
||||
Architecture int64 `json:"architecture"`
|
||||
CreationTime string `json:"creation_time"`
|
||||
LastEditTime string `json:"last_edit_time"`
|
||||
Attributes SignigProfileAttributes `json:"attributes"`
|
||||
ExecutableList []ExecutablesList `json:"executablesList"` // Use structs from catypes
|
||||
FullPathMap map[string]bool `json:"-"`
|
||||
}
|
||||
|
||||
// SignigProfileAttributes -
|
||||
type SignigProfileAttributes struct {
|
||||
IsStockProfile bool `json:"isStockProfile,omitempty"`
|
||||
ContainerName string `json:"containerName,omitempty"`
|
||||
DockerImageTag string `json:"dockerImageTag,omitempty"`
|
||||
DockerImageSHA256 string `json:"dockerImageSHA256,omitempty"`
|
||||
GeneratedFor string `json:"generatedFor,omitempty"`
|
||||
GeneratedFrom string `json:"generatedFrom,omitempty"`
|
||||
}
|
||||
|
||||
// ExecutablesList holds the list of executables in this signing profile
|
||||
type ExecutablesList struct {
|
||||
MainProcess string `json:"mainProcess"`
|
||||
FullProcessCommandLine string `json:"fullProcessCommandLine,omitempty"`
|
||||
FullProcessEnvironmentVariables map[string]string `json:"fullProcessEnvironmentVariables,omitempty"`
|
||||
ModulesInfo []ModulesInformation `json:"modulesInfo"`
|
||||
Filters FiltersSection `json:"filter,omitempty"`
|
||||
}
|
||||
|
||||
// FiltersSection holds the filter section of ExecutablesList
|
||||
type FiltersSection struct {
|
||||
IncludePaths []string `json:"includePaths,omitempty"`
|
||||
IncludeExtensions []string `json:"includeExtensions,omitempty"`
|
||||
}
|
||||
|
||||
func (wt *WorkloadTemplate) Json() string {
|
||||
if b, err := json.Marshal(*wt); err == nil {
|
||||
return fmt.Sprintf("%s", b)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
171
vendor/github.com/armosec/capacketsgo/cacli/execute.go
generated
vendored
171
vendor/github.com/armosec/capacketsgo/cacli/execute.go
generated
vendored
@@ -1,171 +0,0 @@
|
||||
package cacli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// RunCommand -
|
||||
func runCacliCommand(arg []string, display bool) ([]byte, error) {
|
||||
cmd := &exec.Cmd{}
|
||||
command := "cacli"
|
||||
displayCommand := ""
|
||||
if display {
|
||||
displayCommand = fmt.Sprintf("command: %s %v", command, arg)
|
||||
}
|
||||
if display {
|
||||
glog.Infof("Running: %s", displayCommand)
|
||||
}
|
||||
var outb, errb bytes.Buffer
|
||||
cmd = exec.Command(command, arg...)
|
||||
cmd.Stdout = &outb
|
||||
cmd.Stderr = &errb
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
e := fmt.Sprintf("error: %v, exit code: %s. %s", cmd.Stdout, err.Error(), displayCommand)
|
||||
glog.Errorf(e)
|
||||
return nil, fmt.Errorf(e)
|
||||
}
|
||||
glog.Infof("command executed successfully. %s", displayCommand)
|
||||
return cmd.Stdout.(*bytes.Buffer).Bytes(), err
|
||||
}
|
||||
|
||||
// runCacliCommandWithTimeout -
|
||||
func runCacliCommandWithTimeout(arg []string, display bool, timeout time.Duration) ([]byte, error) {
|
||||
var outb, errb bytes.Buffer
|
||||
var cancel context.CancelFunc
|
||||
|
||||
// adding timeout
|
||||
ctx := context.Background()
|
||||
ctx, cancel = context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
command := "cacli"
|
||||
if display {
|
||||
glog.Infof("Running: %s %v", command, arg)
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, command, arg...)
|
||||
|
||||
cmd.Stdout = &outb
|
||||
cmd.Stderr = &errb
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
err = fmt.Errorf(fmt.Sprintf("stdout: %v. stderr:%v. err: %v", cmd.Stdout, cmd.Stderr, err))
|
||||
glog.Errorf("error running command, reason: %v", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return cmd.Stdout.(*bytes.Buffer).Bytes(), err
|
||||
}
|
||||
|
||||
// RunCommand -
|
||||
func RunCommand(command string, arg []string, display bool, timeout time.Duration) ([]byte, error) {
|
||||
var outb, errb bytes.Buffer
|
||||
var cancel context.CancelFunc
|
||||
|
||||
// adding timeout
|
||||
ctx := context.Background()
|
||||
ctx, cancel = context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
if display {
|
||||
glog.Infof("Running: %s %v", command, arg)
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, command, arg...)
|
||||
|
||||
cmd.Stdout = &outb
|
||||
cmd.Stderr = &errb
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
err = fmt.Errorf(fmt.Sprintf("stdout: %v. stderr:%v. err: %v", cmd.Stdout, cmd.Stderr, err))
|
||||
glog.Errorf("error running command, reason: %v", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return cmd.Stdout.(*bytes.Buffer).Bytes(), err
|
||||
}
|
||||
|
||||
func (cacli *Cacli) runCacliCommandRepeat(arg []string, display bool, timeout time.Duration) ([]byte, error) {
|
||||
rep, err := runCacliCommandWithTimeout(arg, display, timeout)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Name or service not known") {
|
||||
return nil, fmt.Errorf("failed to connect to Armo backend, please restart network. error: %s", err.Error())
|
||||
}
|
||||
status, _ := cacli.Status()
|
||||
if !status.LoggedIn {
|
||||
glog.Infof("logging in again and retrying %d times", 3)
|
||||
if err := cacli.cacliLogin(0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
i := 0
|
||||
for i < 3 { // retry
|
||||
rep, err = runCacliCommandWithTimeout(arg, display, timeout)
|
||||
if err == nil {
|
||||
return rep, nil
|
||||
}
|
||||
i++
|
||||
time.Sleep(3 * time.Second)
|
||||
}
|
||||
// glog.Errorf("stdout: %v. stderr:%v. err: %v", cmd.Stdout, cmd.Stderr, err)
|
||||
return nil, err
|
||||
}
|
||||
return rep, nil
|
||||
}
|
||||
|
||||
// LoginCacli -
|
||||
func (cacli *Cacli) cacliLogin(retries int) error {
|
||||
if cacli.credentials.User == "" || cacli.credentials.Password == "" {
|
||||
return fmt.Errorf("Missing cacli username or password")
|
||||
}
|
||||
if err := cacli.cacliLoginRetry(retries); err != nil {
|
||||
return fmt.Errorf("failed to login, url: '%s', reason: %s", cacli.backendURL, err.Error())
|
||||
}
|
||||
|
||||
status, err := cacli.Status()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s, err := json.Marshal(status)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !status.LoggedIn {
|
||||
return fmt.Errorf("Status logged-in is false, please check your credentials")
|
||||
}
|
||||
glog.Infof("%s", string(s))
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoginCacli -
|
||||
func (cacli *Cacli) cacliLoginRetry(retries int) error {
|
||||
if retries == 0 {
|
||||
retries = 1
|
||||
}
|
||||
|
||||
var err error
|
||||
for i := 0; i < retries; i++ {
|
||||
if err = cacli.Login(); err == nil {
|
||||
return nil
|
||||
}
|
||||
if i != retries-1 {
|
||||
time.Sleep(3 * time.Second)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// IsLoggedIn -
|
||||
func (cacli *Cacli) IsLoggedIn() (bool, error) {
|
||||
status, err := cacli.Status()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return status.LoggedIn, nil
|
||||
}
|
||||
769
vendor/github.com/armosec/capacketsgo/cacli/mothods.go
generated
vendored
769
vendor/github.com/armosec/capacketsgo/cacli/mothods.go
generated
vendored
@@ -1,769 +0,0 @@
|
||||
package cacli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/armosec/capacketsgo/opapolicy"
|
||||
"github.com/armosec/capacketsgo/secrethandling"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// Cacli commands
|
||||
type Cacli struct {
|
||||
backendURL string
|
||||
credentials CredStruct
|
||||
}
|
||||
|
||||
// NewCacli -
|
||||
func NewCacli(backendURL string, setCredInEnv bool) *Cacli {
|
||||
// Load credentials from mounted secret
|
||||
credentials, err := LoadCredentials()
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cacliObj := &Cacli{
|
||||
backendURL: backendURL,
|
||||
credentials: *credentials,
|
||||
}
|
||||
|
||||
// login cacli
|
||||
if err := cacliObj.cacliLogin(3); err != nil {
|
||||
glog.Error(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if setCredInEnv {
|
||||
if err := cacliObj.setCredentialsInEnv(); err != nil {
|
||||
glog.Error(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
return cacliObj
|
||||
}
|
||||
|
||||
// NewCacliWithoutLogin -
|
||||
func NewCacliWithoutLogin() *Cacli {
|
||||
|
||||
cacliObj := &Cacli{}
|
||||
// loggedin, err := cacliObj.IsLoggedIn()
|
||||
// if err != nil || !loggedin {
|
||||
// glog.Errorf("Please run `cacli login`\n")
|
||||
// os.Exit(1)
|
||||
// }
|
||||
return cacliObj
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================ BASIC =========================================================
|
||||
// ================================================================================================
|
||||
|
||||
// Login command
|
||||
func (cacli *Cacli) Login() error {
|
||||
args := []string{}
|
||||
args = append(args, "login")
|
||||
args = append(args, "-u")
|
||||
args = append(args, cacli.credentials.User)
|
||||
if cacli.credentials.Customer != "" {
|
||||
args = append(args, "-c")
|
||||
args = append(args, cacli.credentials.Customer)
|
||||
}
|
||||
args = append(args, "--dashboard")
|
||||
args = append(args, cacli.backendURL)
|
||||
|
||||
// must be last argument
|
||||
args = append(args, "-p")
|
||||
args = append(args, cacli.credentials.Password)
|
||||
|
||||
glog.Infof("Running: cacli %v", args[:len(args)-1])
|
||||
|
||||
_, err := runCacliCommandWithTimeout(args, false, time.Duration(2)*time.Minute)
|
||||
return err
|
||||
}
|
||||
|
||||
// Status -
|
||||
func (cacli *Cacli) Status() (*Status, error) {
|
||||
status := &Status{}
|
||||
args := []string{}
|
||||
args = append(args, "--status")
|
||||
statusReceive, err := runCacliCommand(args, true)
|
||||
if err == nil {
|
||||
err = json.Unmarshal(statusReceive, status)
|
||||
}
|
||||
return status, err
|
||||
}
|
||||
|
||||
// Sign command
|
||||
func (cacli *Cacli) Sign(wlid, user, password, ociImageURL string) error {
|
||||
args := []string{}
|
||||
display := true
|
||||
args = append(args, "--debug")
|
||||
args = append(args, "sign")
|
||||
args = append(args, "-wlid")
|
||||
args = append(args, wlid)
|
||||
|
||||
if ociImageURL != "" {
|
||||
args = append(args, "--dockerless-service-url")
|
||||
args = append(args, ociImageURL)
|
||||
}
|
||||
|
||||
if user != "" && password != "" {
|
||||
display = false
|
||||
args = append(args, "--docker-registry-user")
|
||||
args = append(args, user)
|
||||
args = append(args, "--docker-registry-password")
|
||||
args = append(args, password)
|
||||
}
|
||||
|
||||
_, err := runCacliCommandWithTimeout(args, display, time.Duration(8)*time.Minute)
|
||||
return err
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================== vulnscan ==========================================================
|
||||
// ================================================================================================
|
||||
func (cacli *Cacli) VulnerabilityScan(cluster, namespace, wlid string, attributes map[string]interface{}) error {
|
||||
|
||||
args := []string{}
|
||||
args = append(args, "k8s")
|
||||
args = append(args, "scan")
|
||||
if wlid != "" {
|
||||
args = append(args, "-wlid")
|
||||
args = append(args, wlid)
|
||||
} else if attributes == nil {
|
||||
if cluster == "" {
|
||||
return fmt.Errorf("invalid vulnerability scan request- missing cluster")
|
||||
}
|
||||
args = append(args, "--cluster")
|
||||
args = append(args, cluster)
|
||||
if namespace != "" {
|
||||
args = append(args, "--namespace")
|
||||
args = append(args, namespace)
|
||||
}
|
||||
}
|
||||
|
||||
b, err := cacli.runCacliCommandRepeat(args, true, time.Duration(5)*time.Minute)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
glog.Infof("%v", string(b))
|
||||
return nil
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================== WT ==========================================================
|
||||
// ================================================================================================
|
||||
|
||||
// Create command
|
||||
func (cacli *Cacli) WTCreate(wt *WorkloadTemplate, fileName string) (string, error) {
|
||||
if fileName == "" {
|
||||
var err error
|
||||
if fileName, err = ConvertObjectTOFile(*wt); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
args := []string{}
|
||||
args = append(args, "wt")
|
||||
args = append(args, "create")
|
||||
args = append(args, "-i")
|
||||
args = append(args, fileName)
|
||||
wlid, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
DeleteObjTmpFile(fileName)
|
||||
wlidMap := make(map[string]string)
|
||||
json.Unmarshal(wlid, &wlidMap)
|
||||
return wlidMap["wlid"], err
|
||||
}
|
||||
|
||||
// Apply command
|
||||
func (cacli *Cacli) WTApply(wt *WorkloadTemplate, fileName string) (string, error) {
|
||||
if fileName == "" {
|
||||
if wt == nil {
|
||||
return "", fmt.Errorf("missing wt and fileName, you must provide one of them")
|
||||
}
|
||||
f, err := StoreObjTmpFile(wt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fileName = f
|
||||
}
|
||||
args := []string{}
|
||||
args = append(args, "wt")
|
||||
args = append(args, "apply")
|
||||
args = append(args, "-i")
|
||||
args = append(args, fileName)
|
||||
wlid, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
DeleteObjTmpFile(fileName)
|
||||
wlidMap := make(map[string]string)
|
||||
json.Unmarshal(wlid, &wlidMap)
|
||||
return wlidMap["wlid"], err
|
||||
}
|
||||
|
||||
// Update command
|
||||
func (cacli *Cacli) WTUpdate(wt *WorkloadTemplate, fileName string) (string, error) {
|
||||
if fileName == "" {
|
||||
if wt == nil {
|
||||
return "", fmt.Errorf("missing wt and fileName, you must provide one of them")
|
||||
}
|
||||
f, err := StoreObjTmpFile(wt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fileName = f
|
||||
}
|
||||
args := []string{}
|
||||
args = append(args, "wt")
|
||||
args = append(args, "update")
|
||||
args = append(args, "-i")
|
||||
args = append(args, fileName)
|
||||
wlid, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
DeleteObjTmpFile(fileName)
|
||||
wlidMap := make(map[string]string)
|
||||
json.Unmarshal(wlid, &wlidMap)
|
||||
return wlidMap["wlid"], err
|
||||
}
|
||||
|
||||
// Triplet command
|
||||
func (cacli *Cacli) WTTriplet(wlid string) (*GUIDTriplet, error) {
|
||||
triplet := GUIDTriplet{}
|
||||
args := []string{}
|
||||
args = append(args, "wt")
|
||||
args = append(args, "triplet")
|
||||
args = append(args, "-wlid")
|
||||
args = append(args, wlid)
|
||||
tripletReceive, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err == nil {
|
||||
json.Unmarshal(tripletReceive, &triplet)
|
||||
}
|
||||
return &triplet, err
|
||||
}
|
||||
|
||||
// Get command
|
||||
// func (cacli *Cacli) Get(wlid string) error {
|
||||
func (cacli *Cacli) WTGet(wlid string) (*WorkloadTemplate, error) {
|
||||
wt := WorkloadTemplate{}
|
||||
args := []string{}
|
||||
args = append(args, "wt")
|
||||
args = append(args, "get")
|
||||
args = append(args, "-wlid")
|
||||
args = append(args, wlid)
|
||||
wtReceive, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err == nil {
|
||||
json.Unmarshal(wtReceive, &wt)
|
||||
}
|
||||
return &wt, err
|
||||
}
|
||||
|
||||
// Get command
|
||||
func (cacli *Cacli) WTDelete(wlid string) error {
|
||||
args := []string{}
|
||||
args = append(args, "wt")
|
||||
args = append(args, "delete")
|
||||
args = append(args, "-wlid")
|
||||
args = append(args, wlid)
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
return err
|
||||
}
|
||||
|
||||
// Download command
|
||||
func (cacli *Cacli) WTDownload(wlid, containerName, output string) error {
|
||||
args := []string{}
|
||||
args = append(args, "wt")
|
||||
args = append(args, "download")
|
||||
args = append(args, "-wlid")
|
||||
args = append(args, wlid)
|
||||
args = append(args, "-o")
|
||||
args = append(args, output)
|
||||
|
||||
if containerName != "" {
|
||||
args = append(args, "-n")
|
||||
args = append(args, containerName)
|
||||
}
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(6)*time.Minute)
|
||||
return err
|
||||
}
|
||||
|
||||
// Sign command
|
||||
func (cacli *Cacli) WTSign(wlid, user, password, ociImageURL string) error {
|
||||
args := []string{}
|
||||
display := true
|
||||
args = append(args, "--debug")
|
||||
args = append(args, "wt")
|
||||
args = append(args, "sign")
|
||||
args = append(args, "-wlid")
|
||||
args = append(args, wlid)
|
||||
|
||||
if ociImageURL != "" {
|
||||
args = append(args, "--dockerless-service-url")
|
||||
args = append(args, ociImageURL)
|
||||
}
|
||||
|
||||
if user != "" && password != "" {
|
||||
display = false
|
||||
args = append(args, "--docker-registry-user")
|
||||
args = append(args, user)
|
||||
args = append(args, "--docker-registry-password")
|
||||
args = append(args, password)
|
||||
}
|
||||
|
||||
_, err := runCacliCommandWithTimeout(args, display, time.Duration(8)*time.Minute)
|
||||
return err
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================= K8S ==========================================================
|
||||
// ================================================================================================
|
||||
|
||||
// AttachNameSpace command attach workloads
|
||||
func (cacli *Cacli) K8SAttach(cluster, ns, wlid string, injectLabel bool) error {
|
||||
args := []string{}
|
||||
args = append(args, "attach")
|
||||
args = append(args, SetArgs(cluster, ns, wlid, nil)...)
|
||||
if injectLabel {
|
||||
args = append(args, "--attach-future")
|
||||
}
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
return err
|
||||
}
|
||||
|
||||
func (cacli *Cacli) RunPostureScan(framework, cluster string) error {
|
||||
args := []string{}
|
||||
// cacli k8s posture create --framework "MITRE" --cluster childrenofbodom
|
||||
|
||||
args = append(args, "k8s")
|
||||
args = append(args, "posture")
|
||||
args = append(args, "create")
|
||||
args = append(args, "--cluster")
|
||||
args = append(args, cluster)
|
||||
args = append(args, "--framework")
|
||||
args = append(args, framework)
|
||||
res, err := cacli.runCacliCommandRepeat(args, false, time.Duration(3)*time.Minute)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
glog.Infof("%v", string(res))
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ============================ OPA FRAMEWORK =====================================================
|
||||
// ================================================================================================
|
||||
|
||||
// OPAFRAMEWORKGet cacli opa get
|
||||
func (cacli *Cacli) OPAFRAMEWORKGet(name string, public bool) ([]opapolicy.Framework, error) {
|
||||
args := []string{}
|
||||
opaList := []opapolicy.Framework{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "framework")
|
||||
args = append(args, "get")
|
||||
if name != "" {
|
||||
args = append(args, "--name")
|
||||
args = append(args, name)
|
||||
}
|
||||
if public {
|
||||
args = append(args, "--public")
|
||||
}
|
||||
args = append(args, "--expand")
|
||||
|
||||
opaReceive, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err == nil {
|
||||
if name == "" {
|
||||
err = json.Unmarshal(opaReceive, &opaList)
|
||||
} else {
|
||||
opaSingle := opapolicy.Framework{}
|
||||
err = json.Unmarshal(opaReceive, &opaSingle)
|
||||
opaList = append(opaList, opaSingle)
|
||||
}
|
||||
}
|
||||
return opaList, err
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKList - cacli opa list
|
||||
func (cacli *Cacli) OPAFRAMEWORKList(public bool) ([]string, error) {
|
||||
args := []string{}
|
||||
opaList := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "framework")
|
||||
args = append(args, "list")
|
||||
if public {
|
||||
args = append(args, "--public")
|
||||
}
|
||||
opaReceive, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err == nil {
|
||||
json.Unmarshal(opaReceive, &opaList)
|
||||
}
|
||||
return opaList, err
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKCreate - cacli opa create
|
||||
func (cacli *Cacli) OPAFRAMEWORKCreate(framework *opapolicy.Framework, fileName string) (*opapolicy.Framework, error) {
|
||||
if fileName == "" {
|
||||
var err error
|
||||
if fileName, err = ConvertObjectTOFile(*framework); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "framework")
|
||||
args = append(args, "create")
|
||||
args = append(args, "--input")
|
||||
args = append(args, fileName)
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
// if err == nil {
|
||||
// json.Unmarshal(opaReceive, &opaList)
|
||||
// }
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKUpdate - cacli opa update
|
||||
func (cacli *Cacli) OPAFRAMEWORKUpdate(framework *opapolicy.Framework, fileName string) (*opapolicy.Framework, error) {
|
||||
if fileName == "" {
|
||||
var err error
|
||||
if fileName, err = ConvertObjectTOFile(*framework); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "framework")
|
||||
args = append(args, "update")
|
||||
args = append(args, "--input")
|
||||
args = append(args, fileName)
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
// if err == nil {
|
||||
// json.Unmarshal(opaReceive, &opaList)
|
||||
// }
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKDelete cacli opa delete
|
||||
func (cacli *Cacli) OPAFRAMEWORKDelete(name string) error {
|
||||
args := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "framework")
|
||||
args = append(args, "delete")
|
||||
args = append(args, "--name")
|
||||
args = append(args, name)
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
return err
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ============================ OPA CONTROL =======================================================
|
||||
// ================================================================================================
|
||||
|
||||
// OPACONTROLGet cacli opa get
|
||||
func (cacli *Cacli) OPACONTROLGet(name string) ([]opapolicy.Control, error) {
|
||||
args := []string{}
|
||||
opaList := []opapolicy.Control{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "control")
|
||||
args = append(args, "get")
|
||||
if name != "" {
|
||||
args = append(args, "--name")
|
||||
args = append(args, name)
|
||||
}
|
||||
args = append(args, "--expand")
|
||||
|
||||
opaReceive, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err == nil {
|
||||
if name == "" {
|
||||
err = json.Unmarshal(opaReceive, &opaList)
|
||||
} else {
|
||||
opaSingle := opapolicy.Control{}
|
||||
err = json.Unmarshal(opaReceive, &opaSingle)
|
||||
opaList = append(opaList, opaSingle)
|
||||
}
|
||||
}
|
||||
return opaList, err
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKList - cacli opa list
|
||||
func (cacli *Cacli) OPACONTROLList() ([]string, error) {
|
||||
args := []string{}
|
||||
opaList := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "control")
|
||||
args = append(args, "list")
|
||||
opaReceive, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err == nil {
|
||||
json.Unmarshal(opaReceive, &opaList)
|
||||
}
|
||||
return opaList, err
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKCreate - cacli opa create
|
||||
func (cacli *Cacli) OPACONTROLCreate(control *opapolicy.Control, fileName string) (*opapolicy.Control, error) {
|
||||
if fileName == "" {
|
||||
var err error
|
||||
if fileName, err = ConvertObjectTOFile(*control); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "control")
|
||||
args = append(args, "create")
|
||||
args = append(args, "--input")
|
||||
args = append(args, fileName)
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
// if err == nil {
|
||||
// json.Unmarshal(opaReceive, &opaList)
|
||||
// }
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKUpdate - cacli opa update
|
||||
func (cacli *Cacli) OPACONTROLUpdate(control *opapolicy.Control, fileName string) (*opapolicy.Control, error) {
|
||||
if fileName == "" {
|
||||
var err error
|
||||
if fileName, err = ConvertObjectTOFile(*control); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "control")
|
||||
args = append(args, "update")
|
||||
args = append(args, "--input")
|
||||
args = append(args, fileName)
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
// if err == nil {
|
||||
// json.Unmarshal(opaReceive, &opaList)
|
||||
// }
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// OPACONTROLDelete cacli opa delete
|
||||
func (cacli *Cacli) OPACONTROLDelete(name string) error {
|
||||
args := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "control")
|
||||
args = append(args, "delete")
|
||||
args = append(args, "--name")
|
||||
args = append(args, name)
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
return err
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ============================== OPA RULE ========================================================
|
||||
// ================================================================================================
|
||||
|
||||
// OPARULEGet cacli opa get
|
||||
func (cacli *Cacli) OPARULEGet(name string) ([]opapolicy.PolicyRule, error) {
|
||||
args := []string{}
|
||||
opaList := []opapolicy.PolicyRule{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "rule")
|
||||
args = append(args, "get")
|
||||
if name != "" {
|
||||
args = append(args, "--name")
|
||||
args = append(args, name)
|
||||
}
|
||||
opaReceive, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err == nil {
|
||||
if name == "" {
|
||||
err = json.Unmarshal(opaReceive, &opaList)
|
||||
} else {
|
||||
opaSingle := opapolicy.PolicyRule{}
|
||||
err = json.Unmarshal(opaReceive, &opaSingle)
|
||||
opaList = append(opaList, opaSingle)
|
||||
}
|
||||
}
|
||||
return opaList, err
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKList - cacli opa list
|
||||
func (cacli *Cacli) OPARULEList() ([]string, error) {
|
||||
args := []string{}
|
||||
opaList := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "rule")
|
||||
args = append(args, "list")
|
||||
opaReceive, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
if err == nil {
|
||||
json.Unmarshal(opaReceive, &opaList)
|
||||
}
|
||||
return opaList, err
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKCreate - cacli opa create
|
||||
func (cacli *Cacli) OPARULECreate(rule *opapolicy.PolicyRule, fileName string) (*opapolicy.PolicyRule, error) {
|
||||
if fileName == "" {
|
||||
var err error
|
||||
if fileName, err = ConvertObjectTOFile(*rule); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "rule")
|
||||
args = append(args, "create")
|
||||
args = append(args, "--input")
|
||||
args = append(args, fileName)
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
// if err == nil {
|
||||
// json.Unmarshal(opaReceive, &opaList)
|
||||
// }
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKUpdate - cacli opa update
|
||||
func (cacli *Cacli) OPARULEUpdate(rule *opapolicy.PolicyRule, fileName string) (*opapolicy.PolicyRule, error) {
|
||||
if fileName == "" {
|
||||
var err error
|
||||
if fileName, err = ConvertObjectTOFile(*rule); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "rule")
|
||||
args = append(args, "update")
|
||||
args = append(args, "--input")
|
||||
args = append(args, fileName)
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
// if err == nil {
|
||||
// json.Unmarshal(opaReceive, &opaList)
|
||||
// }
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// OPARULEDelete cacli opa delete
|
||||
func (cacli *Cacli) OPARULEDelete(name string) error {
|
||||
args := []string{}
|
||||
args = append(args, "opa")
|
||||
args = append(args, "rule")
|
||||
args = append(args, "delete")
|
||||
args = append(args, "--name")
|
||||
args = append(args, name)
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(2)*time.Minute)
|
||||
return err
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================ SECP ==========================================================
|
||||
// ================================================================================================
|
||||
|
||||
// SecretEncrypt -
|
||||
func (cacli *Cacli) SECPEncrypt(message, inputFile, outputFile, keyID string, base64Enc bool) ([]byte, error) {
|
||||
args := []string{}
|
||||
args = append(args, "secret-policy")
|
||||
args = append(args, "encrypt")
|
||||
if message != "" {
|
||||
args = append(args, "--message")
|
||||
args = append(args, message)
|
||||
}
|
||||
if inputFile != "" {
|
||||
args = append(args, "--input")
|
||||
args = append(args, inputFile)
|
||||
}
|
||||
if keyID != "" {
|
||||
args = append(args, "-kid")
|
||||
args = append(args, keyID)
|
||||
}
|
||||
if outputFile != "" {
|
||||
args = append(args, "--output")
|
||||
args = append(args, outputFile)
|
||||
}
|
||||
if base64Enc {
|
||||
args = append(args, "--base64")
|
||||
}
|
||||
|
||||
messageByte, err := runCacliCommand(args, false)
|
||||
return messageByte, err
|
||||
}
|
||||
|
||||
// SecretDecrypt -
|
||||
func (cacli *Cacli) SECPDecrypt(message, inputFile, outputFile string, base64Enc bool) ([]byte, error) {
|
||||
args := []string{}
|
||||
args = append(args, "secret-policy")
|
||||
args = append(args, "decrypt")
|
||||
if message != "" {
|
||||
args = append(args, "--message")
|
||||
args = append(args, message)
|
||||
}
|
||||
if inputFile != "" {
|
||||
args = append(args, "--input")
|
||||
args = append(args, inputFile)
|
||||
}
|
||||
if outputFile != "" {
|
||||
args = append(args, "--output")
|
||||
args = append(args, outputFile)
|
||||
}
|
||||
if base64Enc {
|
||||
args = append(args, "--base64")
|
||||
}
|
||||
|
||||
messageByte, err := runCacliCommand(args, true)
|
||||
|
||||
return messageByte, err
|
||||
}
|
||||
|
||||
// GetSecretAccessPolicy -
|
||||
func (cacli *Cacli) SECPGet(sid, name, cluster, namespace string) ([]secrethandling.SecretAccessPolicy, error) {
|
||||
secretAccessPolicy := []secrethandling.SecretAccessPolicy{}
|
||||
args := []string{}
|
||||
args = append(args, "secret-policy")
|
||||
args = append(args, "get")
|
||||
if sid != "" {
|
||||
args = append(args, "-sid")
|
||||
args = append(args, sid)
|
||||
} else if name != "" {
|
||||
args = append(args, "--name")
|
||||
args = append(args, name)
|
||||
} else {
|
||||
if cluster != "" {
|
||||
args = append(args, "--cluster")
|
||||
args = append(args, cluster)
|
||||
if namespace != "" {
|
||||
args = append(args, "--namespace")
|
||||
args = append(args, namespace)
|
||||
}
|
||||
}
|
||||
}
|
||||
sReceive, err := cacli.runCacliCommandRepeat(args, true, time.Duration(3)*time.Minute)
|
||||
if err == nil {
|
||||
if err = json.Unmarshal(sReceive, &secretAccessPolicy); err != nil {
|
||||
tmpSecretAccessPolicy := secrethandling.SecretAccessPolicy{}
|
||||
if err = json.Unmarshal(sReceive, &tmpSecretAccessPolicy); err == nil {
|
||||
secretAccessPolicy = []secrethandling.SecretAccessPolicy{tmpSecretAccessPolicy}
|
||||
}
|
||||
}
|
||||
err = nil // if received and empty list
|
||||
}
|
||||
return secretAccessPolicy, err
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================ UTILS =========================================================
|
||||
// ================================================================================================
|
||||
|
||||
func (cacli *Cacli) UTILSCleanup(wlid string, discoveryOnly bool) error {
|
||||
args := []string{}
|
||||
args = append(args, "utils")
|
||||
args = append(args, "cleanup")
|
||||
args = append(args, "--workload-id")
|
||||
args = append(args, wlid)
|
||||
if discoveryOnly {
|
||||
args = append(args, "--discovery")
|
||||
}
|
||||
_, err := cacli.runCacliCommandRepeat(args, true, time.Duration(3)*time.Minute)
|
||||
return err
|
||||
}
|
||||
211
vendor/github.com/armosec/capacketsgo/cacli/mothods_mock.go
generated
vendored
211
vendor/github.com/armosec/capacketsgo/cacli/mothods_mock.go
generated
vendored
@@ -1,211 +0,0 @@
|
||||
package cacli
|
||||
|
||||
import (
|
||||
"github.com/armosec/capacketsgo/opapolicy"
|
||||
"github.com/armosec/capacketsgo/secrethandling"
|
||||
)
|
||||
|
||||
// Cacli commands
|
||||
type CacliMock struct {
|
||||
backendURL string
|
||||
credentials CredStruct
|
||||
}
|
||||
|
||||
// NewCacli -
|
||||
func NewCacliMock(backendURL string) *CacliMock {
|
||||
// Load credentials from mounted secret
|
||||
return &CacliMock{
|
||||
backendURL: backendURL,
|
||||
credentials: CredStruct{},
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================ BASIC =========================================================
|
||||
// ================================================================================================
|
||||
|
||||
// Login cacli login
|
||||
func (cacli *CacliMock) Login() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Status cacli --status
|
||||
func (caclim *CacliMock) Status() (*Status, error) {
|
||||
return &Status{}, nil
|
||||
}
|
||||
|
||||
// Sign command
|
||||
func (caclim *CacliMock) Sign(wlid, user, password, ociImageURL string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================== WT ==========================================================
|
||||
// ================================================================================================
|
||||
|
||||
// Create command
|
||||
func (caclim *CacliMock) WTCreate(wt *WorkloadTemplate, fileName string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Apply command
|
||||
func (caclim *CacliMock) WTApply(wt *WorkloadTemplate, fileName string) (string, error) {
|
||||
return "", nil
|
||||
|
||||
}
|
||||
|
||||
// Update command
|
||||
func (caclim *CacliMock) WTUpdate(wt *WorkloadTemplate, fileName string) (string, error) {
|
||||
return "", nil
|
||||
|
||||
}
|
||||
|
||||
// Triplet command
|
||||
func (caclim *CacliMock) WTTriplet(wlid string) (*GUIDTriplet, error) {
|
||||
return &GUIDTriplet{}, nil
|
||||
}
|
||||
|
||||
// Get command
|
||||
// func (caclim *CacliMock) Get(wlid string) error {
|
||||
func (caclim *CacliMock) WTGet(wlid string) (*WorkloadTemplate, error) {
|
||||
return &WorkloadTemplate{}, nil
|
||||
}
|
||||
|
||||
// Get command
|
||||
func (caclim *CacliMock) WTDelete(wlid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Download command
|
||||
func (caclim *CacliMock) WTDownload(wlid, containerName, output string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sign command
|
||||
func (caclim *CacliMock) WTSign(wlid, user, password, ociImageURL string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================= K8S ==========================================================
|
||||
// ================================================================================================
|
||||
|
||||
// AttachNameSpace command attach all workloads in namespace
|
||||
func (caclim *CacliMock) K8SAttach(cluster, ns, wlid string, _ bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ============================ OPA FRAMEWORK =====================================================
|
||||
// ================================================================================================
|
||||
|
||||
// OPAFRAMEWORKGet cacli opa get
|
||||
func (caclim *CacliMock) OPAFRAMEWORKGet(name string) ([]opapolicy.Framework, error) {
|
||||
return []opapolicy.Framework{}, nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKDelete cacli opa delete
|
||||
func (caclim *CacliMock) OPAFRAMEWORKDelete(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKList - cacli opa list
|
||||
func (caclim *CacliMock) OPAFRAMEWORKList() ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKCreate - cacli opa create
|
||||
func (caclim *CacliMock) OPAFRAMEWORKCreate(framework *opapolicy.Framework, fileName string) (*opapolicy.Framework, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKUpdate - cacli opa update
|
||||
func (caclim *CacliMock) OPAFRAMEWORKUpdate(framework *opapolicy.Framework, fileName string) (*opapolicy.Framework, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ============================ OPA CONTROL =======================================================
|
||||
// ================================================================================================
|
||||
|
||||
// OPAFRAMEWORKGet cacli opa get
|
||||
func (caclim *CacliMock) OPACONTROLGet(name string) ([]opapolicy.Control, error) {
|
||||
return []opapolicy.Control{}, nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKGet cacli opa get
|
||||
func (caclim *CacliMock) OPACONTROLDelete(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKList - cacli opa list
|
||||
func (caclim *CacliMock) OPACONTROLList() ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKCreate - cacli opa create
|
||||
func (caclim *CacliMock) OPACONTROLCreate(control *opapolicy.Control, fileName string) (*opapolicy.Control, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKUpdate - cacli opa update
|
||||
func (caclim *CacliMock) OPACONTROLUpdate(control *opapolicy.Control, fileName string) (*opapolicy.Control, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ============================== OPA RULE ========================================================
|
||||
// ================================================================================================
|
||||
|
||||
// OPAFRAMEWORKGet cacli opa get
|
||||
func (caclim *CacliMock) OPARULEGet(name string) ([]opapolicy.PolicyRule, error) {
|
||||
return []opapolicy.PolicyRule{}, nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKGet cacli opa get
|
||||
func (caclim *CacliMock) OPARULEDelete(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKList - cacli opa list
|
||||
func (caclim *CacliMock) OPARULEList() ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKCreate - cacli opa create
|
||||
func (caclim *CacliMock) OPARULECreate(rule *opapolicy.PolicyRule, fileName string) (*opapolicy.PolicyRule, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// OPAFRAMEWORKUpdate - cacli opa update
|
||||
func (caclim *CacliMock) OPARULEUpdate(rule *opapolicy.PolicyRule, fileName string) (*opapolicy.PolicyRule, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================ SECP ==========================================================
|
||||
// ================================================================================================
|
||||
|
||||
// SecretEncrypt -
|
||||
func (caclim *CacliMock) SECPEncrypt(message, inputFile, outputFile, keyID string, base64Enc bool) ([]byte, error) {
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
// SecretDecrypt -
|
||||
func (caclim *CacliMock) SECPDecrypt(message, inputFile, outputFile string, base64Enc bool) ([]byte, error) {
|
||||
return []byte{}, nil
|
||||
|
||||
}
|
||||
|
||||
// GetSecretAccessPolicy -
|
||||
func (caclim *CacliMock) SECPGet(sid, name, cluster, namespace string) ([]secrethandling.SecretAccessPolicy, error) {
|
||||
return []secrethandling.SecretAccessPolicy{}, nil
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================================ UTILS =========================================================
|
||||
// ================================================================================================
|
||||
|
||||
func (caclim *CacliMock) UTILSCleanup(wlid string, _ bool) error {
|
||||
return nil
|
||||
}
|
||||
106
vendor/github.com/armosec/capacketsgo/cacli/utils.go
generated
vendored
106
vendor/github.com/armosec/capacketsgo/cacli/utils.go
generated
vendored
@@ -1,106 +0,0 @@
|
||||
package cacli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func StoreObjTmpFile(obj interface{}) (string, error) {
|
||||
|
||||
bet, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
file := fmt.Sprintf("/tmp/%d.json", rand.Int())
|
||||
if err := ioutil.WriteFile(file, bet, 0644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func DeleteObjTmpFile(path string) {
|
||||
// delete file
|
||||
var err = os.Remove(path)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func SetArgs(wlid, cluster, namespace string, attributes map[string]string) []string {
|
||||
args := []string{}
|
||||
if wlid != "" {
|
||||
args = append(args, "--workload-id")
|
||||
args = append(args, wlid)
|
||||
}
|
||||
if cluster != "" {
|
||||
args = append(args, "--cluster")
|
||||
args = append(args, cluster)
|
||||
}
|
||||
if namespace != "" {
|
||||
args = append(args, "--namespace")
|
||||
args = append(args, namespace)
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func ConvertObjectTOFile(obj interface{}) (string, error) {
|
||||
if obj == nil {
|
||||
return "", fmt.Errorf("missing wt and fileName, you must provide one of them")
|
||||
}
|
||||
f, err := StoreObjTmpFile(obj)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func LoadCredentials() (*CredStruct, error) {
|
||||
credentials := CredStruct{}
|
||||
credentialsPath := getCredentialsPath()
|
||||
customer, err := ioutil.ReadFile(filepath.Join(credentialsPath, "customer"))
|
||||
if err != nil || len(customer) == 0 {
|
||||
glog.Warningf("'customer' not found in credentials secret. path: %s", filepath.Join(credentialsPath, "customer"))
|
||||
}
|
||||
credentials.Customer = string(customer)
|
||||
|
||||
username, err := ioutil.ReadFile(filepath.Join(credentialsPath, "username"))
|
||||
if err != nil || len(username) == 0 {
|
||||
return nil, fmt.Errorf("'username' not found in credentials secret. path: %s", filepath.Join(credentialsPath, "username"))
|
||||
}
|
||||
credentials.User = string(username)
|
||||
|
||||
password, err := ioutil.ReadFile(filepath.Join(credentialsPath, "password"))
|
||||
if err != nil || len(password) == 0 {
|
||||
return nil, fmt.Errorf("'password' not found in credentials secret. path: %s", filepath.Join(credentialsPath, "password"))
|
||||
}
|
||||
credentials.Password = string(password)
|
||||
|
||||
return &credentials, nil
|
||||
}
|
||||
func getCredentialsPath() string {
|
||||
if credentialsPath := os.Getenv(DefaultCredentialsPathEnv); credentialsPath != "" {
|
||||
return credentialsPath
|
||||
}
|
||||
return DefaultCredentialsPath
|
||||
}
|
||||
|
||||
func (cacli *Cacli) setCredentialsInEnv() error {
|
||||
if err := os.Setenv("CA_USERNAME", cacli.credentials.User); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Setenv("CA_PASSWORD", cacli.credentials.Password); err != nil {
|
||||
return err
|
||||
}
|
||||
if cacli.credentials.Customer != "" {
|
||||
if err := os.Setenv("CA_CUSTOMER", cacli.credentials.Customer); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
197
vendor/github.com/armosec/capacketsgo/cautils/armometadata.go
generated
vendored
197
vendor/github.com/armosec/capacketsgo/cautils/armometadata.go
generated
vendored
@@ -1,197 +0,0 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// labels added to the workload
|
||||
const (
|
||||
ArmoPrefix string = "armo"
|
||||
ArmoAttach string = ArmoPrefix + ".attach"
|
||||
ArmoInitialSecret string = ArmoPrefix + ".initial"
|
||||
ArmoSecretStatus string = ArmoPrefix + ".secret"
|
||||
ArmoCompatibleLabel string = ArmoPrefix + ".compatible"
|
||||
|
||||
ArmoSecretProtectStatus string = "protect"
|
||||
ArmoSecretClearStatus string = "clear"
|
||||
)
|
||||
|
||||
// annotations added to the workload
|
||||
const (
|
||||
ArmoUpdate string = ArmoPrefix + ".last-update"
|
||||
ArmoWlid string = ArmoPrefix + ".wlid"
|
||||
ArmoSid string = ArmoPrefix + ".sid"
|
||||
ArmoJobID string = ArmoPrefix + ".job"
|
||||
ArmoJobIDPath string = ArmoJobID + "/id"
|
||||
ArmoJobParentPath string = ArmoJobID + "/parent"
|
||||
ArmoJobActionPath string = ArmoJobID + "/action"
|
||||
ArmoCompatibleAnnotation string = ArmoAttach + "/compatible"
|
||||
ArmoReplaceheaders string = ArmoAttach + "/replaceheaders"
|
||||
)
|
||||
|
||||
const ( // DEPRECATED
|
||||
|
||||
CAAttachLabel string = "cyberarmor"
|
||||
Patched string = "Patched"
|
||||
Done string = "Done"
|
||||
Encrypted string = "Protected"
|
||||
|
||||
CAInjectOld = "injectCyberArmor"
|
||||
|
||||
CAPrefix string = "cyberarmor"
|
||||
CAProtectedSecret string = CAPrefix + ".secret"
|
||||
CAInitialSecret string = CAPrefix + ".initial"
|
||||
CAInject string = CAPrefix + ".inject"
|
||||
CAIgnore string = CAPrefix + ".ignore"
|
||||
CAReplaceHeaders string = CAPrefix + ".removeSecurityHeaders"
|
||||
)
|
||||
|
||||
const ( // DEPRECATED
|
||||
CAUpdate string = CAPrefix + ".last-update"
|
||||
CAStatus string = CAPrefix + ".status"
|
||||
CAWlid string = CAPrefix + ".wlid"
|
||||
)
|
||||
|
||||
type ClusterConfig struct {
|
||||
EventReceiverREST string `json:"eventReceiverREST"`
|
||||
EventReceiverWS string `json:"eventReceiverWS"`
|
||||
MaserNotificationServer string `json:"maserNotificationServer"`
|
||||
Postman string `json:"postman"`
|
||||
Dashboard string `json:"dashboard"`
|
||||
Portal string `json:"portal"`
|
||||
CustomerGUID string `json:"customerGUID"`
|
||||
ClusterGUID string `json:"clusterGUID"`
|
||||
ClusterName string `json:"clusterName"`
|
||||
OciImageURL string `json:"ociImageURL"`
|
||||
NotificationWSURL string `json:"notificationWSURL"`
|
||||
NotificationRestURL string `json:"notificationRestURL"`
|
||||
VulnScanURL string `json:"vulnScanURL"`
|
||||
OracleURL string `json:"oracleURL"`
|
||||
ClairURL string `json:"clairURL"`
|
||||
}
|
||||
|
||||
// represents workload basic info
|
||||
type SpiffeBasicInfo struct {
|
||||
//cluster/datacenter
|
||||
Level0 string `json:"level0"`
|
||||
Level0Type string `json:"level0Type"`
|
||||
|
||||
//namespace/project
|
||||
Level1 string `json:"level0"`
|
||||
Level1Type string `json:"level0Type"`
|
||||
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ImageInfo struct {
|
||||
Registry string `json:"registry"`
|
||||
VersionImage string `json:"versionImage"`
|
||||
}
|
||||
|
||||
func IsAttached(labels map[string]string) *bool {
|
||||
attach := false
|
||||
if labels == nil {
|
||||
return nil
|
||||
}
|
||||
if attached, ok := labels[ArmoAttach]; ok {
|
||||
if strings.ToLower(attached) == "true" {
|
||||
attach = true
|
||||
return &attach
|
||||
} else {
|
||||
return &attach
|
||||
}
|
||||
}
|
||||
|
||||
// deprecated
|
||||
if _, ok := labels[CAAttachLabel]; ok {
|
||||
attach = true
|
||||
return &attach
|
||||
}
|
||||
|
||||
// deprecated
|
||||
if inject, ok := labels[CAInject]; ok {
|
||||
if strings.ToLower(inject) == "true" {
|
||||
attach = true
|
||||
return &attach
|
||||
}
|
||||
}
|
||||
|
||||
// deprecated
|
||||
if ignore, ok := labels[CAIgnore]; ok {
|
||||
if strings.ToLower(ignore) == "true" {
|
||||
return &attach
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsSecretProtected(labels map[string]string) *bool {
|
||||
protect := false
|
||||
if labels == nil {
|
||||
return nil
|
||||
}
|
||||
if protected, ok := labels[ArmoSecretStatus]; ok {
|
||||
if strings.ToLower(protected) == ArmoSecretProtectStatus {
|
||||
protect = true
|
||||
return &protect
|
||||
} else {
|
||||
return &protect
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoadConfig(configPath string, loadToEnv bool) (*ClusterConfig, error) {
|
||||
if configPath == "" {
|
||||
configPath = "/etc/config/clusterData.json"
|
||||
}
|
||||
|
||||
dat, err := ioutil.ReadFile(configPath)
|
||||
if err != nil || len(dat) == 0 {
|
||||
return nil, fmt.Errorf("Config empty or not found. path: %s", configPath)
|
||||
}
|
||||
componentConfig := &ClusterConfig{}
|
||||
if err := json.Unmarshal(dat, componentConfig); err != nil {
|
||||
return componentConfig, fmt.Errorf("Failed to read component config, path: %s, reason: %s", configPath, err.Error())
|
||||
}
|
||||
if loadToEnv {
|
||||
componentConfig.LoadConfigToEnv()
|
||||
}
|
||||
return componentConfig, nil
|
||||
}
|
||||
|
||||
func (clusterConfig *ClusterConfig) LoadConfigToEnv() {
|
||||
|
||||
SetEnv("CA_CLUSTER_NAME", clusterConfig.ClusterName)
|
||||
SetEnv("CA_CLUSTER_GUID", clusterConfig.ClusterGUID)
|
||||
SetEnv("CA_ORACLE_SERVER", clusterConfig.OracleURL)
|
||||
SetEnv("CA_CUSTOMER_GUID", clusterConfig.CustomerGUID)
|
||||
SetEnv("CA_DASHBOARD_BACKEND", clusterConfig.Dashboard)
|
||||
SetEnv("CA_NOTIFICATION_SERVER_REST", clusterConfig.NotificationWSURL)
|
||||
SetEnv("CA_NOTIFICATION_SERVER_WS", clusterConfig.NotificationWSURL)
|
||||
SetEnv("CA_NOTIFICATION_SERVER_REST", clusterConfig.NotificationRestURL)
|
||||
SetEnv("CA_OCIMAGE_URL", clusterConfig.OciImageURL)
|
||||
SetEnv("CA_K8S_REPORT_URL", clusterConfig.EventReceiverWS)
|
||||
SetEnv("CA_EVENT_RECEIVER_HTTP", clusterConfig.EventReceiverREST)
|
||||
SetEnv("CA_VULNSCAN", clusterConfig.VulnScanURL)
|
||||
SetEnv("CA_POSTMAN", clusterConfig.Postman)
|
||||
SetEnv("MASTER_NOTIFICATION_SERVER_HOST", clusterConfig.MaserNotificationServer)
|
||||
SetEnv("CLAIR_URL", clusterConfig.ClairURL)
|
||||
|
||||
}
|
||||
|
||||
func SetEnv(key, value string) {
|
||||
if e := os.Getenv(key); e == "" {
|
||||
if err := os.Setenv(key, value); err != nil {
|
||||
glog.Warning("%s: %s", key, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
29
vendor/github.com/armosec/capacketsgo/cautils/cautils_test.go
generated
vendored
29
vendor/github.com/armosec/capacketsgo/cautils/cautils_test.go
generated
vendored
@@ -1,29 +0,0 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// tests wlid parse
|
||||
|
||||
func TestSpiffeWLIDToInfoSuccess(t *testing.T) {
|
||||
|
||||
WLID := "wlid://cluster-HipsterShopCluster2/namespace-prod/deployment-cartservice"
|
||||
ms, er := SpiffeToSpiffeInfo(WLID)
|
||||
|
||||
if er != nil || ms.Level0 != "HipsterShopCluster2" || ms.Level0Type != "cluster" || ms.Level1 != "prod" || ms.Level1Type != "namespace" ||
|
||||
ms.Kind != "deployment" || ms.Name != "cartservice" {
|
||||
t.Errorf("TestSpiffeWLIDToInfoSuccess failed to parse %v", WLID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpiffeSIDInfoSuccess(t *testing.T) {
|
||||
|
||||
SID := "sid://cluster-HipsterShopCluster2/namespace-dev/secret-caregcred"
|
||||
ms, er := SpiffeToSpiffeInfo(SID)
|
||||
|
||||
if er != nil || ms.Level0 != "HipsterShopCluster2" || ms.Level0Type != "cluster" || ms.Level1 != "dev" || ms.Level1Type != "namespace" ||
|
||||
ms.Kind != "secret" || ms.Name != "caregcred" {
|
||||
t.Errorf("TestSpiffeSIDInfoSuccess failed to parse %v", SID)
|
||||
}
|
||||
}
|
||||
118
vendor/github.com/armosec/capacketsgo/cautils/genericutils.go
generated
vendored
118
vendor/github.com/armosec/capacketsgo/cautils/genericutils.go
generated
vendored
@@ -1,118 +0,0 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// wlid/ sid utils
|
||||
const (
|
||||
SpiffePrefix = "://"
|
||||
)
|
||||
|
||||
// wlid/ sid utils
|
||||
const (
|
||||
PackagePath = "vendor/github.com/armosec/capacketsgo"
|
||||
)
|
||||
|
||||
//AsSHA256 takes anything turns it into string :) https://blog.8bitzen.com/posts/22-08-2019-how-to-hash-a-struct-in-go
|
||||
func AsSHA256(v interface{}) string {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(fmt.Sprintf("%v", v)))
|
||||
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
|
||||
func SpiffeToSpiffeInfo(spiffe string) (*SpiffeBasicInfo, error) {
|
||||
basicInfo := &SpiffeBasicInfo{}
|
||||
|
||||
pos := strings.Index(spiffe, SpiffePrefix)
|
||||
if pos < 0 {
|
||||
return nil, fmt.Errorf("invalid spiffe %s", spiffe)
|
||||
}
|
||||
|
||||
pos += len(SpiffePrefix)
|
||||
spiffeNoPrefix := spiffe[pos:]
|
||||
splits := strings.Split(spiffeNoPrefix, "/")
|
||||
if len(splits) < 3 {
|
||||
return nil, fmt.Errorf("invalid spiffe %s", spiffe)
|
||||
}
|
||||
|
||||
p0 := strings.Index(splits[0], "-")
|
||||
p1 := strings.Index(splits[1], "-")
|
||||
p2 := strings.Index(splits[2], "-")
|
||||
if p0 == -1 || p1 == -1 || p2 == -1 {
|
||||
return nil, fmt.Errorf("invalid spiffe %s", spiffe)
|
||||
}
|
||||
basicInfo.Level0Type = splits[0][:p0]
|
||||
basicInfo.Level0 = splits[0][p0+1:]
|
||||
basicInfo.Level1Type = splits[1][:p1]
|
||||
basicInfo.Level1 = splits[1][p1+1:]
|
||||
basicInfo.Kind = splits[2][:p2]
|
||||
basicInfo.Name = splits[2][p2+1:]
|
||||
|
||||
return basicInfo, nil
|
||||
}
|
||||
|
||||
func ImageTagToImageInfo(imageTag string) (*ImageInfo, error) {
|
||||
ImageInfo := &ImageInfo{}
|
||||
spDelimiter := "/"
|
||||
pos := strings.Index(imageTag, spDelimiter)
|
||||
if pos < 0 {
|
||||
ImageInfo.Registry = ""
|
||||
ImageInfo.VersionImage = imageTag
|
||||
return ImageInfo, nil
|
||||
}
|
||||
|
||||
splits := strings.Split(imageTag, spDelimiter)
|
||||
if len(splits) == 0 {
|
||||
|
||||
return nil, fmt.Errorf("Invalid image info %s", imageTag)
|
||||
}
|
||||
|
||||
ImageInfo.Registry = splits[0]
|
||||
if len(splits) > 1 {
|
||||
ImageInfo.VersionImage = splits[len(splits)-1]
|
||||
} else {
|
||||
ImageInfo.VersionImage = ""
|
||||
}
|
||||
|
||||
return ImageInfo, nil
|
||||
}
|
||||
|
||||
func BoolPointer(b bool) *bool { return &b }
|
||||
|
||||
func BoolToString(b bool) string {
|
||||
if b {
|
||||
return "true"
|
||||
}
|
||||
return "false"
|
||||
}
|
||||
|
||||
func BoolPointerToString(b *bool) string {
|
||||
if b == nil {
|
||||
return ""
|
||||
}
|
||||
if *b {
|
||||
return "true"
|
||||
}
|
||||
return "false"
|
||||
}
|
||||
|
||||
func StringToBool(s string) bool {
|
||||
if strings.ToLower(s) == "true" || strings.ToLower(s) == "1" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func StringToBoolPointer(s string) *bool {
|
||||
if strings.ToLower(s) == "true" || strings.ToLower(s) == "1" {
|
||||
return BoolPointer(true)
|
||||
}
|
||||
if strings.ToLower(s) == "false" || strings.ToLower(s) == "0" {
|
||||
return BoolPointer(false)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
52
vendor/github.com/armosec/capacketsgo/cautils/k8sutils.go
generated
vendored
52
vendor/github.com/armosec/capacketsgo/cautils/k8sutils.go
generated
vendored
@@ -1,52 +0,0 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
"strings"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
var NamespacesListToIgnore = make([]string, 0)
|
||||
var KubeNamespaces = []string{metav1.NamespaceSystem, metav1.NamespacePublic}
|
||||
|
||||
// NamespacesListToIgnore namespaces to ignore if a pod
|
||||
func InitNamespacesListToIgnore(caNamespace string) {
|
||||
if len(NamespacesListToIgnore) > 0 {
|
||||
return
|
||||
}
|
||||
NamespacesListToIgnore = append(NamespacesListToIgnore, KubeNamespaces...)
|
||||
NamespacesListToIgnore = append(NamespacesListToIgnore, caNamespace)
|
||||
}
|
||||
|
||||
func IfIgnoreNamespace(ns string) bool {
|
||||
for i := range NamespacesListToIgnore {
|
||||
if NamespacesListToIgnore[i] == ns {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IfKubeNamespace(ns string) bool {
|
||||
for i := range KubeNamespaces {
|
||||
if NamespacesListToIgnore[i] == ns {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hash(s string) string {
|
||||
h := fnv.New32a()
|
||||
h.Write([]byte(s))
|
||||
return fmt.Sprintf("%d", h.Sum32())
|
||||
}
|
||||
func GenarateConfigMapName(wlid string) string {
|
||||
name := strings.ToLower(fmt.Sprintf("ca-%s-%s-%s", GetNamespaceFromWlid(wlid), GetKindFromWlid(wlid), GetNameFromWlid(wlid)))
|
||||
if len(name) >= 63 {
|
||||
name = hash(name)
|
||||
}
|
||||
return name
|
||||
}
|
||||
238
vendor/github.com/armosec/capacketsgo/cautils/wlid.go
generated
vendored
238
vendor/github.com/armosec/capacketsgo/cautils/wlid.go
generated
vendored
@@ -1,238 +0,0 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// API fields
|
||||
var (
|
||||
WlidPrefix = "wlid://"
|
||||
SidPrefix = "sid://"
|
||||
ClusterWlidPrefix = "cluster-"
|
||||
NamespaceWlidPrefix = "namespace-"
|
||||
DataCenterWlidPrefix = "datacenter-"
|
||||
ProjectWlidPrefix = "project-"
|
||||
SecretSIDPrefix = "secret-"
|
||||
SubSecretSIDPrefix = "subsecret-"
|
||||
K8SKindsList = []string{"ComponentStatus", "ConfigMap", "ControllerRevision", "CronJob",
|
||||
"CustomResourceDefinition", "DaemonSet", "Deployment", "Endpoints", "Event", "HorizontalPodAutoscaler",
|
||||
"Ingress", "Job", "Lease", "LimitRange", "LocalSubjectAccessReview", "MutatingWebhookConfiguration",
|
||||
"Namespace", "NetworkPolicy", "Node", "PersistentVolume", "PersistentVolumeClaim", "Pod",
|
||||
"PodDisruptionBudget", "PodSecurityPolicy", "PodTemplate", "PriorityClass", "ReplicaSet",
|
||||
"ReplicationController", "ResourceQuota", "Role", "RoleBinding", "Secret", "SelfSubjectAccessReview",
|
||||
"SelfSubjectRulesReview", "Service", "ServiceAccount", "StatefulSet", "StorageClass",
|
||||
"SubjectAccessReview", "TokenReview", "ValidatingWebhookConfiguration", "VolumeAttachment"}
|
||||
NativeKindsList = []string{"Dockerized", "Native"}
|
||||
KindReverseMap = map[string]string{}
|
||||
dataImagesList = []string{}
|
||||
)
|
||||
|
||||
func IsWlid(id string) bool {
|
||||
return strings.HasPrefix(id, WlidPrefix)
|
||||
}
|
||||
|
||||
func IsSid(id string) bool {
|
||||
return strings.HasPrefix(id, SidPrefix)
|
||||
}
|
||||
|
||||
// GetK8SKindFronList get the calculated wlid
|
||||
func GetK8SKindFronList(kind string) string { // TODO GetK8SKindFromList
|
||||
for i := range K8SKindsList {
|
||||
if strings.ToLower(kind) == strings.ToLower(K8SKindsList[i]) {
|
||||
return K8SKindsList[i]
|
||||
}
|
||||
}
|
||||
return kind
|
||||
}
|
||||
|
||||
// IsK8SKindInList Check if the kind is a known kind
|
||||
func IsK8SKindInList(kind string) bool {
|
||||
for i := range K8SKindsList {
|
||||
if strings.ToLower(kind) == strings.ToLower(K8SKindsList[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// generateWLID
|
||||
func generateWLID(pLevel0, level0, pLevel1, level1, k, name string) string {
|
||||
kind := strings.ToLower(k)
|
||||
kind = strings.Replace(kind, "-", "", -1)
|
||||
|
||||
wlid := WlidPrefix
|
||||
wlid += fmt.Sprintf("%s%s", pLevel0, level0)
|
||||
if level1 == "" {
|
||||
return wlid
|
||||
}
|
||||
wlid += fmt.Sprintf("/%s%s", pLevel1, level1)
|
||||
|
||||
if kind == "" {
|
||||
return wlid
|
||||
}
|
||||
wlid += fmt.Sprintf("/%s", kind)
|
||||
|
||||
if name == "" {
|
||||
return wlid
|
||||
}
|
||||
wlid += fmt.Sprintf("-%s", name)
|
||||
|
||||
return wlid
|
||||
}
|
||||
|
||||
// GetWLID get the calculated wlid
|
||||
func GetWLID(level0, level1, k, name string) string {
|
||||
return generateWLID(ClusterWlidPrefix, level0, NamespaceWlidPrefix, level1, k, name)
|
||||
}
|
||||
|
||||
// GetK8sWLID get the k8s calculated wlid
|
||||
func GetK8sWLID(level0, level1, k, name string) string {
|
||||
return generateWLID(ClusterWlidPrefix, level0, NamespaceWlidPrefix, level1, k, name)
|
||||
}
|
||||
|
||||
// GetNativeWLID get the native calculated wlid
|
||||
func GetNativeWLID(level0, level1, k, name string) string {
|
||||
return generateWLID(DataCenterWlidPrefix, level0, ProjectWlidPrefix, level1, k, name)
|
||||
}
|
||||
|
||||
// WildWlidContainsWlid does WildWlid contains Wlid
|
||||
func WildWlidContainsWlid(wildWlid, wlid string) bool { // TODO- test
|
||||
if wildWlid == wlid {
|
||||
return true
|
||||
}
|
||||
wildWlidR, _ := RestoreMicroserviceIDsFromSpiffe(wildWlid)
|
||||
wlidR, _ := RestoreMicroserviceIDsFromSpiffe(wlid)
|
||||
if len(wildWlidR) > len(wildWlidR) {
|
||||
// invalid wlid
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range wildWlidR {
|
||||
if wildWlidR[i] != wlidR[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func restoreInnerIdentifiersFromID(spiffeSlices []string) []string {
|
||||
if len(spiffeSlices) >= 1 && strings.HasPrefix(spiffeSlices[0], ClusterWlidPrefix) {
|
||||
spiffeSlices[0] = spiffeSlices[0][len(ClusterWlidPrefix):]
|
||||
}
|
||||
if len(spiffeSlices) >= 2 && strings.HasPrefix(spiffeSlices[1], NamespaceWlidPrefix) {
|
||||
spiffeSlices[1] = spiffeSlices[1][len(NamespaceWlidPrefix):]
|
||||
}
|
||||
if len(spiffeSlices) >= 3 && strings.Contains(spiffeSlices[2], "-") {
|
||||
dashIdx := strings.Index(spiffeSlices[2], "-")
|
||||
spiffeSlices = append(spiffeSlices, spiffeSlices[2][dashIdx+1:])
|
||||
spiffeSlices[2] = spiffeSlices[2][:dashIdx]
|
||||
if val, ok := KindReverseMap[spiffeSlices[2]]; ok {
|
||||
spiffeSlices[2] = val
|
||||
}
|
||||
}
|
||||
return spiffeSlices
|
||||
}
|
||||
|
||||
// RestoreMicroserviceIDsFromSpiffe -
|
||||
func RestoreMicroserviceIDsFromSpiffe(spiffe string) ([]string, error) {
|
||||
if spiffe == "" {
|
||||
return nil, fmt.Errorf("in RestoreMicroserviceIDsFromSpiffe, expecting valid wlid recieved empty string")
|
||||
}
|
||||
|
||||
if StringHasWhitespace(spiffe) {
|
||||
return nil, fmt.Errorf("wlid %s invalid. whitespace found", spiffe)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(spiffe, WlidPrefix) {
|
||||
spiffe = spiffe[len(WlidPrefix):]
|
||||
} else if strings.HasPrefix(spiffe, SidPrefix) {
|
||||
spiffe = spiffe[len(SidPrefix):]
|
||||
}
|
||||
spiffeSlices := strings.Split(spiffe, "/")
|
||||
// The documented WLID format (https://cyberarmorio.sharepoint.com/sites/development2/Shared%20Documents/kubernetes_design1.docx?web=1)
|
||||
if len(spiffeSlices) <= 3 {
|
||||
spiffeSlices = restoreInnerIdentifiersFromID(spiffeSlices)
|
||||
}
|
||||
if len(spiffeSlices) != 4 { // first used WLID, deprecated since 24.10.2019
|
||||
return spiffeSlices, fmt.Errorf("invalid WLID format. format received: %v", spiffeSlices)
|
||||
}
|
||||
|
||||
for i := range spiffeSlices {
|
||||
if spiffeSlices[i] == "" {
|
||||
return spiffeSlices, fmt.Errorf("one or more entities are empty, spiffeSlices: %v", spiffeSlices)
|
||||
}
|
||||
}
|
||||
|
||||
return spiffeSlices, nil
|
||||
}
|
||||
|
||||
// RestoreMicroserviceIDsFromSpiffe -
|
||||
func RestoreMicroserviceIDs(spiffe string) []string {
|
||||
if spiffe == "" {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
if StringHasWhitespace(spiffe) {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(spiffe, WlidPrefix) {
|
||||
spiffe = spiffe[len(WlidPrefix):]
|
||||
} else if strings.HasPrefix(spiffe, SidPrefix) {
|
||||
spiffe = spiffe[len(SidPrefix):]
|
||||
}
|
||||
spiffeSlices := strings.Split(spiffe, "/")
|
||||
|
||||
return restoreInnerIdentifiersFromID(spiffeSlices)
|
||||
}
|
||||
|
||||
// GetClusterFromWlid parse wlid and get cluster
|
||||
func GetClusterFromWlid(wlid string) string {
|
||||
r := RestoreMicroserviceIDs(wlid)
|
||||
if len(r) >= 1 {
|
||||
return r[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetNamespaceFromWlid parse wlid and get Namespace
|
||||
func GetNamespaceFromWlid(wlid string) string {
|
||||
r := RestoreMicroserviceIDs(wlid)
|
||||
if len(r) >= 2 {
|
||||
return r[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetKindFromWlid parse wlid and get kind
|
||||
func GetKindFromWlid(wlid string) string {
|
||||
r := RestoreMicroserviceIDs(wlid)
|
||||
if len(r) >= 3 {
|
||||
return GetK8SKindFronList(r[2])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetNameFromWlid parse wlid and get name
|
||||
func GetNameFromWlid(wlid string) string {
|
||||
r := RestoreMicroserviceIDs(wlid)
|
||||
if len(r) >= 4 {
|
||||
return GetK8SKindFronList(r[3])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsWlidValid test if wlid is a valid wlid
|
||||
func IsWlidValid(wlid string) error {
|
||||
_, err := RestoreMicroserviceIDsFromSpiffe(wlid)
|
||||
return err
|
||||
}
|
||||
|
||||
// StringHasWhitespace check if a string has whitespace
|
||||
func StringHasWhitespace(str string) bool {
|
||||
if whitespace := strings.Index(str, " "); whitespace != -1 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
90
vendor/github.com/armosec/capacketsgo/containerscan/containerscan_mock.go
generated
vendored
90
vendor/github.com/armosec/capacketsgo/containerscan/containerscan_mock.go
generated
vendored
@@ -1,90 +0,0 @@
|
||||
package containerscan
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/francoispqt/gojay"
|
||||
)
|
||||
|
||||
// GenerateContainerScanReportMock - generate a scan result
|
||||
func GenerateContainerScanReportMock() ScanResultReport {
|
||||
ds := ScanResultReport{
|
||||
WLID: "wlid://cluster-k8s-geriatrix-k8s-demo3/namespace-whisky-app/deployment-whisky4all-shipping",
|
||||
CustomerGUID: "1231bcb1-49ce-4a67-bdd3-5da7a393ae08",
|
||||
ImgTag: "dreg.armo.cloud:443/demoservice:v16",
|
||||
ImgHash: "docker-pullable://dreg.armo.cloud:443/demoservice@sha256:754f3cfca915a07ed10655a301dd7a8dc5526a06f9bd06e7c932f4d4108a8296",
|
||||
Timestamp: time.Now().UnixNano(),
|
||||
}
|
||||
|
||||
ds.Layers = make(LayersList, 0)
|
||||
layer := ScanResultLayer{}
|
||||
GenerateContainerScanLayer(&layer)
|
||||
ds.Layers = append(ds.Layers, layer)
|
||||
return ds
|
||||
}
|
||||
|
||||
// GenerateContainerScanReportMock - generate a scan result
|
||||
func GenerateContainerScanReportNoVulMock() ScanResultReport {
|
||||
ds := ScanResultReport{
|
||||
WLID: "wlid://cluster-k8s-geriatrix-k8s-demo3/namespace-whisky-app/deployment-whisky4all-shipping",
|
||||
CustomerGUID: "1231bcb1-49ce-4a67-bdd3-5da7a393ae08",
|
||||
ImgTag: "dreg.armo.cloud:443/demoservice:v16",
|
||||
ImgHash: "docker-pullable://dreg.armo.cloud:443/demoservice@sha256:754f3cfca915a07ed10655a301dd7a8dc5526a06f9bd06e7c932f4d4108a8296",
|
||||
Timestamp: time.Now().UnixNano(),
|
||||
ContainerName: "shipping",
|
||||
}
|
||||
|
||||
ds.Layers = make(LayersList, 0)
|
||||
layer := ScanResultLayer{LayerHash: "aaa"}
|
||||
ds.Layers = append(ds.Layers, layer)
|
||||
return ds
|
||||
}
|
||||
|
||||
var hash = []rune("abcdef0123456789")
|
||||
var nums = []rune("0123456789")
|
||||
|
||||
func randSeq(n int, bank []rune) string {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
b := make([]rune, n)
|
||||
for i := range b {
|
||||
b[i] = bank[rand.Intn(len(bank))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// GenerateContainerScanLayer - generate a layer with random vuls
|
||||
func GenerateContainerScanLayer(layer *ScanResultLayer) {
|
||||
layer.LayerHash = randSeq(32, hash)
|
||||
layer.Vulnerabilities = make(VulnerabilitiesList, 0)
|
||||
layer.Packages = make(LinuxPkgs, 0)
|
||||
vuls := rand.Intn(10) + 1
|
||||
|
||||
for i := 0; i < vuls; i++ {
|
||||
v := Vulnerability{}
|
||||
GenerateVulnerability(&v)
|
||||
layer.Vulnerabilities = append(layer.Vulnerabilities, v)
|
||||
}
|
||||
|
||||
pkg := LinuxPackage{PackageName: "coreutils"}
|
||||
pkg.Files = make(PkgFiles, 0)
|
||||
pf := PackageFile{Filename: "aa"}
|
||||
pkg.Files = append(pkg.Files, pf)
|
||||
layer.Packages = append(layer.Packages, pkg)
|
||||
}
|
||||
|
||||
// GenerateVulnerability - generate a vul (just diff "cve"'s)
|
||||
func GenerateVulnerability(v *Vulnerability) error {
|
||||
baseVul := " { \"name\": \"CVE-2014-9471\", \"imageTag\": \"debian:8\", \"link\": \"https://security-tracker.debian.org/tracker/CVE-2014-9471\", \"description\": \"The parse_datetime function in GNU coreutils allows remote attackers to cause a denial of service (crash) or possibly execute arbitrary code via a crafted date string, as demonstrated by the sdf\", \"severity\": \"Low\", \"metadata\": { \"NVD\": { \"CVSSv2\": { \"Score\": 7.5, \"Vectors\": \"AV:N/AC:L/Au:N/C:P/I:P\" } } }, \"fixedIn\": [ { \"name\": \"coreutils\", \"imageTag\": \"debian:8\", \"version\": \"8.23-1\" } ] }"
|
||||
b := []byte(baseVul)
|
||||
r := bytes.NewReader(b)
|
||||
er := gojay.NewDecoder(r).DecodeObject(v)
|
||||
v.RelatedPackageName = "coreutils"
|
||||
v.Severity = HighSeverity
|
||||
v.Relevancy = Irelevant
|
||||
v.Name = "CVE-" + randSeq(4, nums) + "-" + randSeq(4, nums)
|
||||
return er
|
||||
|
||||
}
|
||||
80
vendor/github.com/armosec/capacketsgo/containerscan/containerscan_test.go
generated
vendored
80
vendor/github.com/armosec/capacketsgo/containerscan/containerscan_test.go
generated
vendored
@@ -1,80 +0,0 @@
|
||||
package containerscan
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/francoispqt/gojay"
|
||||
)
|
||||
|
||||
func TestUnmarshalScanReport(t *testing.T) {
|
||||
ds := GenerateContainerScanReportMock()
|
||||
str1 := ds.AsSha256()
|
||||
rhs := &ScanResultReport{}
|
||||
|
||||
bolB, _ := json.Marshal(ds)
|
||||
r := bytes.NewReader(bolB)
|
||||
|
||||
er := gojay.NewDecoder(r).DecodeObject(rhs)
|
||||
if er != nil {
|
||||
t.Errorf("marshalling failed due to: %v", er.Error())
|
||||
}
|
||||
|
||||
if rhs.AsSha256() != str1 {
|
||||
t.Errorf("marshalling failed different values after marshal:\nOriginal:\n%v\nParsed:\n%v\n\n===\n", string(bolB), rhs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvScanReport2ESvul(t *testing.T) {
|
||||
// ds := GenerateContainerScanReportMock()
|
||||
// res := ds.ToFlatVulnerabilities()
|
||||
// vulsBytes, _ := json.Marshal(res)
|
||||
|
||||
// summary := ds.Summerize()
|
||||
// summaryBytes, _ := json.Marshal(summary)
|
||||
|
||||
// fmt.Printf("summary:\n%v\n\nvulnerabilities:\n%v\n\n", string(summaryBytes), string(vulsBytes))
|
||||
// t.Errorf("%v\n", string(vulsBytes))
|
||||
|
||||
}
|
||||
|
||||
func TestConvScanReport2ESWithNoVul(t *testing.T) {
|
||||
// ds := GenerateContainerScanReportNoVulMock()
|
||||
// res := ds.ToFlatVulnerabilities()
|
||||
// vulsBytes, _ := json.Marshal(res)
|
||||
|
||||
// summary := ds.Summerize()
|
||||
// summaryBytes, _ := json.Marshal(summary)
|
||||
|
||||
// fmt.Printf("summary:\n%v\n\nvulnerabilities:\n%v\n\n", string(summaryBytes), string(vulsBytes))
|
||||
// t.Errorf("%v\n", string(vulsBytes))
|
||||
|
||||
}
|
||||
func TestUnmarshalScanReport1(t *testing.T) {
|
||||
ds := Vulnerability{}
|
||||
if err := GenerateVulnerability(&ds); err != nil {
|
||||
t.Errorf("%v\n%v\n", ds, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetByPkgNameSuccess(t *testing.T) {
|
||||
ds := GenerateContainerScanReportMock()
|
||||
a := ds.Layers[0].GetFilesByPackage("coreutils")
|
||||
if a != nil {
|
||||
|
||||
fmt.Printf("%+v\n", *a)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetByPkgNameMissing(t *testing.T) {
|
||||
ds := GenerateContainerScanReportMock()
|
||||
a := ds.Layers[0].GetFilesByPackage("s")
|
||||
if a != nil {
|
||||
|
||||
t.Errorf("expected - no such package should be in that layer %v\n\n", ds)
|
||||
}
|
||||
|
||||
}
|
||||
113
vendor/github.com/armosec/capacketsgo/containerscan/datastructures.go
generated
vendored
113
vendor/github.com/armosec/capacketsgo/containerscan/datastructures.go
generated
vendored
@@ -1,113 +0,0 @@
|
||||
package containerscan
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
//!!!!!!!!!!!!EVERY CHANGE IN THESE STRUCTURES => CHANGE gojayunmarshaller ASWELL!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
// ScanResultReport - the report given from scanner to event receiver
|
||||
type ScanResultReport struct {
|
||||
CustomerGUID string `json:"customerGUID"`
|
||||
ImgTag string `json:"imageTag",omitempty`
|
||||
ImgHash string `json:"imageHash"`
|
||||
WLID string `json:"wlid"`
|
||||
ContainerName string `json:"containerName"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Layers LayersList `json:"layers"`
|
||||
ListOfDangerousArtifcats []string `json:"listOfDangerousArtifcats"`
|
||||
}
|
||||
|
||||
// ScanResultLayer - represents a single layer from container scan result
|
||||
type ScanResultLayer struct {
|
||||
LayerHash string `json:"layerHash"`
|
||||
ParentLayerHash string `json:"parentLayerHash"`
|
||||
Vulnerabilities VulnerabilitiesList `json:"vulnerabilities"`
|
||||
Packages LinuxPkgs `json:"packageToFile"`
|
||||
}
|
||||
|
||||
// Vulnerability - a vul object
|
||||
type Vulnerability struct {
|
||||
Name string `json:"name"`
|
||||
ImgHash string `json:"imageHash"`
|
||||
ImgTag string `json:"imageTag",omitempty`
|
||||
RelatedPackageName string `json:"packageName"`
|
||||
PackageVersion string `json:"packageVersion"`
|
||||
Link string `json:"link"`
|
||||
Description string `json:"description"`
|
||||
Severity string `json:"severity"`
|
||||
Metadata interface{} `json:"metadata",omitempty`
|
||||
Fixes VulFixes `json:"fixedIn",omitempty`
|
||||
Relevancy string `json:"relevant"` // use the related enum
|
||||
}
|
||||
|
||||
// FixedIn when and which pkg was fixed (which version as well)
|
||||
type FixedIn struct {
|
||||
Name string `json:"name"`
|
||||
ImgTag string `json:"imageTag"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// LinuxPackage- Linux package representation
|
||||
type LinuxPackage struct {
|
||||
PackageName string `json:"packageName"`
|
||||
Files PkgFiles `json:"files"`
|
||||
PackageVersion string `json:"version"`
|
||||
}
|
||||
|
||||
// PackageFile - s.e
|
||||
type PackageFile struct {
|
||||
Filename string `json:"name"`
|
||||
}
|
||||
|
||||
// types to provide unmarshalling:
|
||||
|
||||
//VulnerabilitiesList -s.e
|
||||
type LayersList []ScanResultLayer
|
||||
|
||||
//VulnerabilitiesList -s.e
|
||||
type VulnerabilitiesList []Vulnerability
|
||||
|
||||
//LinuxPkgs - slice of linux pkgs
|
||||
type LinuxPkgs []LinuxPackage
|
||||
|
||||
//VulFixes - information bout when/how this vul was fixed
|
||||
type VulFixes []FixedIn
|
||||
|
||||
//PkgFiles - slice of files belong to specific pkg
|
||||
type PkgFiles []PackageFile
|
||||
|
||||
func (v *ScanResultReport) AsSha256() string {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(fmt.Sprintf("%v", *v)))
|
||||
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
|
||||
const (
|
||||
//defines Relevancy as enum-like
|
||||
Unknown = "Unknown"
|
||||
Relevant = "Relevant"
|
||||
Irelevant = "Irelevant"
|
||||
NoSP = "No signature profile to compare"
|
||||
|
||||
//Clair Severities
|
||||
UnknownSeverity = "Unknown"
|
||||
NegligibleSeverity = "Negligible"
|
||||
LowSeverity = "Low"
|
||||
MediumSeverity = "Medium"
|
||||
HighSeverity = "High"
|
||||
CriticalSeverity = "Critical"
|
||||
|
||||
ContainerScanRedisPrefix = "_containerscan"
|
||||
)
|
||||
|
||||
func CalculateFixed(Fixes []FixedIn) int {
|
||||
for _, fix := range Fixes {
|
||||
if fix.Version != "None" {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
39
vendor/github.com/armosec/capacketsgo/containerscan/datastructuresmethods.go
generated
vendored
39
vendor/github.com/armosec/capacketsgo/containerscan/datastructuresmethods.go
generated
vendored
@@ -1,39 +0,0 @@
|
||||
package containerscan
|
||||
|
||||
import "strings"
|
||||
|
||||
func (layer *ScanResultLayer) GetFilesByPackage(pkgname string) (files *PkgFiles) {
|
||||
for _, pkg := range layer.Packages {
|
||||
if pkg.PackageName == pkgname {
|
||||
return &pkg.Files
|
||||
}
|
||||
}
|
||||
|
||||
return &PkgFiles{}
|
||||
}
|
||||
|
||||
func (layer *ScanResultLayer) GetPackagesNames() []string {
|
||||
pkgsNames := []string{}
|
||||
for _, pkg := range layer.Packages {
|
||||
pkgsNames = append(pkgsNames, pkg.PackageName)
|
||||
}
|
||||
return pkgsNames
|
||||
}
|
||||
|
||||
func (scanresult *ScanResultReport) Validate() bool {
|
||||
if scanresult.CustomerGUID == "" || (scanresult.ImgHash == "" && scanresult.ImgTag == "") || scanresult.Timestamp <= 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
//TODO validate layers & vuls
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (v *Vulnerability) IsRCE() bool {
|
||||
desc := strings.ToLower(v.Description)
|
||||
|
||||
isRCE := strings.Contains(v.Description, "RCE")
|
||||
|
||||
return isRCE || strings.Contains(desc, "remote code execution") || strings.Contains(desc, "remote command execution") || strings.Contains(desc, "arbitrary code") || strings.Contains(desc, "code execution") || strings.Contains(desc, "code injection") || strings.Contains(desc, "command injection") || strings.Contains(desc, "inject arbitrary commands")
|
||||
}
|
||||
265
vendor/github.com/armosec/capacketsgo/containerscan/elasticadapters.go
generated
vendored
265
vendor/github.com/armosec/capacketsgo/containerscan/elasticadapters.go
generated
vendored
@@ -1,265 +0,0 @@
|
||||
package containerscan
|
||||
|
||||
import "github.com/armosec/capacketsgo/cautils"
|
||||
|
||||
// ToFlatVulnerabilities - returnsgit p
|
||||
func (scanresult *ScanResultReport) ToFlatVulnerabilities() []*ElasticContainerVulnerabilityResult {
|
||||
vuls := make([]*ElasticContainerVulnerabilityResult, 0)
|
||||
vul2indx := make(map[string]int, 0)
|
||||
for _, layer := range scanresult.Layers {
|
||||
for _, vul := range layer.Vulnerabilities {
|
||||
esLayer := ESLayer{LayerHash: layer.LayerHash, ParentLayerHash: layer.ParentLayerHash}
|
||||
if indx, isOk := vul2indx[vul.Name]; isOk {
|
||||
vuls[indx].Layers = append(vuls[indx].Layers, esLayer)
|
||||
continue
|
||||
}
|
||||
result := &ElasticContainerVulnerabilityResult{WLID: scanresult.WLID, Timestamp: scanresult.Timestamp}
|
||||
result.Vulnerability = vul
|
||||
result.Layers = make([]ESLayer, 0)
|
||||
result.Layers = append(result.Layers, esLayer)
|
||||
result.ContainerScanID = scanresult.AsSha256()
|
||||
|
||||
result.IsFixed = CalculateFixed(vul.Fixes)
|
||||
result.RelevantLinks = append(result.RelevantLinks, "https://nvd.nist.gov/vuln/detail/"+vul.Name)
|
||||
result.RelevantLinks = append(result.RelevantLinks, vul.Link)
|
||||
result.Vulnerability.Link = "https://nvd.nist.gov/vuln/detail/" + vul.Name
|
||||
vuls = append(vuls, result)
|
||||
vul2indx[vul.Name] = len(vuls) - 1
|
||||
}
|
||||
}
|
||||
// find first introduced
|
||||
for i, v := range vuls {
|
||||
earlyLayer := ""
|
||||
for _, layer := range v.Layers {
|
||||
if layer.ParentLayerHash == earlyLayer {
|
||||
earlyLayer = layer.LayerHash
|
||||
}
|
||||
}
|
||||
vuls[i].IntroducedInLayer = earlyLayer
|
||||
|
||||
}
|
||||
|
||||
return vuls
|
||||
}
|
||||
|
||||
func (scanresult *ScanResultReport) Summerize() *ElasticContainerScanSummaryResult {
|
||||
summary := &ElasticContainerScanSummaryResult{
|
||||
CustomerGUID: scanresult.CustomerGUID,
|
||||
ImgTag: scanresult.ImgTag,
|
||||
ImgHash: scanresult.ImgHash,
|
||||
WLID: scanresult.WLID,
|
||||
Timestamp: scanresult.Timestamp,
|
||||
ContainerName: scanresult.ContainerName,
|
||||
ContainerScanID: scanresult.AsSha256(),
|
||||
ListOfDangerousArtifcats: scanresult.ListOfDangerousArtifcats,
|
||||
RCESummary: make(map[string]int64),
|
||||
}
|
||||
|
||||
obj, e := cautils.SpiffeToSpiffeInfo(scanresult.WLID)
|
||||
|
||||
if e == nil {
|
||||
summary.Cluster = obj.Level0
|
||||
summary.Namespace = obj.Level1
|
||||
}
|
||||
|
||||
imageInfo, e2 := cautils.ImageTagToImageInfo(scanresult.ImgTag)
|
||||
if e2 == nil {
|
||||
summary.Registry = imageInfo.Registry
|
||||
summary.VersionImage = imageInfo.VersionImage
|
||||
}
|
||||
|
||||
summary.PackagesName = make([]string, 0)
|
||||
|
||||
summary.Severity = make([]string, 0)
|
||||
summary.Relevancy = make([]string, 0)
|
||||
summary.FixAvailble = make([]string, 0)
|
||||
|
||||
summary.SeveritiesSum = make([]RelevanciesSum, 0)
|
||||
summary.RelevanciesSum = make([]RelevanciesSum, 0)
|
||||
summary.FixAvailbleSum = make([]RelevanciesSum, 0)
|
||||
|
||||
uniqueVulsMap := make(map[string]bool, 0)
|
||||
for _, layer := range scanresult.Layers {
|
||||
summary.PackagesName = append(summary.PackagesName, (layer.GetPackagesNames())...)
|
||||
for _, vul := range layer.Vulnerabilities {
|
||||
|
||||
if _, isOk := uniqueVulsMap[vul.Name]; isOk {
|
||||
continue
|
||||
}
|
||||
uniqueVulsMap[vul.Name] = true
|
||||
|
||||
if vul.IsRCE() {
|
||||
summary.RCESummary[vul.Severity]++
|
||||
}
|
||||
|
||||
switch vul.Relevancy {
|
||||
case Relevant:
|
||||
summary.NumOfRelevantIssues++
|
||||
case Irelevant:
|
||||
summary.NumOfIrelevantIssues++
|
||||
default: //includes unknown as well
|
||||
summary.NumOfUnknownIssues++
|
||||
}
|
||||
|
||||
switch vul.Severity {
|
||||
case NegligibleSeverity:
|
||||
summary.NumOfNegligibleSeverity++
|
||||
if vul.Relevancy == Relevant {
|
||||
summary.NumOfRelevantNegligibleSeverity++
|
||||
}
|
||||
|
||||
if CalculateFixed(vul.Fixes) > 0 {
|
||||
summary.NumOfFixAvailableNegligibleSeverity++
|
||||
}
|
||||
case LowSeverity:
|
||||
summary.NumOfLowSeverity++
|
||||
|
||||
if vul.Relevancy == Relevant {
|
||||
summary.NumOfRelevantLowSeverity++
|
||||
}
|
||||
|
||||
if CalculateFixed(vul.Fixes) > 0 {
|
||||
summary.NumOfFixAvailableLowSeverity++
|
||||
}
|
||||
case MediumSeverity:
|
||||
summary.NumOfMediumSeverity++
|
||||
|
||||
if vul.Relevancy == Relevant {
|
||||
summary.NumOfRelevantMediumSeverity++
|
||||
}
|
||||
|
||||
if CalculateFixed(vul.Fixes) > 0 {
|
||||
summary.NumOfFixAvailableMediumSeverity++
|
||||
}
|
||||
case HighSeverity:
|
||||
summary.NumOfHighSeverity++
|
||||
|
||||
if vul.Relevancy == Relevant {
|
||||
summary.NumOfRelevantHighSeverity++
|
||||
}
|
||||
|
||||
if CalculateFixed(vul.Fixes) > 0 {
|
||||
summary.NumOfFixAvailableHighSeverity++
|
||||
}
|
||||
case CriticalSeverity:
|
||||
summary.NumOfCriticalSeverity++
|
||||
|
||||
if vul.Relevancy == Relevant {
|
||||
summary.NumOfRelevantCriticalSeverity++
|
||||
}
|
||||
|
||||
if CalculateFixed(vul.Fixes) > 0 {
|
||||
summary.NumOfFixAvailableCriticalSeverity++
|
||||
}
|
||||
default: //includes unknown as well
|
||||
summary.NumOfUnknownSeverity++
|
||||
if vul.Relevancy == Relevant {
|
||||
summary.NumOfRelevantUnknownSeverity++
|
||||
}
|
||||
|
||||
if CalculateFixed(vul.Fixes) > 0 {
|
||||
summary.NumOfFixAvailableUnknownSeverity++
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if summary.NumOfCriticalSeverity > 0 || summary.NumOfRelevantHighSeverity > 3 {
|
||||
summary.Status = "Fail"
|
||||
} else {
|
||||
summary.Status = "Success"
|
||||
}
|
||||
|
||||
//Negligible
|
||||
if summary.NumOfNegligibleSeverity > 0 {
|
||||
summary.Severity = append(summary.Severity, "Negligible")
|
||||
summary.SeveritiesSum = append(summary.SeveritiesSum, RelevanciesSum{Relevancy: "Negligible", Sum: summary.NumOfNegligibleSeverity})
|
||||
|
||||
if summary.NumOfRelevantNegligibleSeverity > 0 {
|
||||
summary.Relevancy = append(summary.Relevancy, "Negligible")
|
||||
summary.RelevanciesSum = append(summary.RelevanciesSum, RelevanciesSum{Relevancy: "Negligible", Sum: summary.NumOfRelevantNegligibleSeverity})
|
||||
}
|
||||
|
||||
if summary.NumOfFixAvailableNegligibleSeverity > 0 {
|
||||
summary.FixAvailble = append(summary.FixAvailble, "Negligible")
|
||||
summary.FixAvailbleSum = append(summary.FixAvailbleSum, RelevanciesSum{Relevancy: "Negligible", Sum: summary.NumOfFixAvailableNegligibleSeverity})
|
||||
}
|
||||
}
|
||||
|
||||
if summary.NumOfLowSeverity > 0 {
|
||||
summary.Severity = append(summary.Severity, "Low")
|
||||
summary.SeveritiesSum = append(summary.SeveritiesSum, RelevanciesSum{Relevancy: "Low", Sum: summary.NumOfLowSeverity})
|
||||
|
||||
if summary.NumOfRelevantLowSeverity > 0 {
|
||||
summary.Relevancy = append(summary.Relevancy, "Low")
|
||||
summary.RelevanciesSum = append(summary.RelevanciesSum, RelevanciesSum{Relevancy: "Low", Sum: summary.NumOfRelevantLowSeverity})
|
||||
}
|
||||
|
||||
if summary.NumOfFixAvailableLowSeverity > 0 {
|
||||
summary.FixAvailble = append(summary.FixAvailble, "Low")
|
||||
summary.FixAvailbleSum = append(summary.FixAvailbleSum, RelevanciesSum{Relevancy: "Low", Sum: summary.NumOfFixAvailableLowSeverity})
|
||||
}
|
||||
}
|
||||
|
||||
if summary.NumOfMediumSeverity > 0 {
|
||||
summary.Severity = append(summary.Severity, "Medium")
|
||||
summary.SeveritiesSum = append(summary.SeveritiesSum, RelevanciesSum{Relevancy: "Medium", Sum: summary.NumOfMediumSeverity})
|
||||
|
||||
if summary.NumOfRelevantMediumSeverity > 0 {
|
||||
summary.Relevancy = append(summary.Relevancy, "Medium")
|
||||
summary.RelevanciesSum = append(summary.RelevanciesSum, RelevanciesSum{Relevancy: "Medium", Sum: summary.NumOfRelevantMediumSeverity})
|
||||
}
|
||||
|
||||
if summary.NumOfFixAvailableMediumSeverity > 0 {
|
||||
summary.FixAvailble = append(summary.FixAvailble, "Medium")
|
||||
summary.FixAvailbleSum = append(summary.FixAvailbleSum, RelevanciesSum{Relevancy: "Medium", Sum: summary.NumOfFixAvailableMediumSeverity})
|
||||
}
|
||||
}
|
||||
|
||||
if summary.NumOfHighSeverity > 0 {
|
||||
summary.Severity = append(summary.Severity, "High")
|
||||
summary.SeveritiesSum = append(summary.SeveritiesSum, RelevanciesSum{Relevancy: "High", Sum: summary.NumOfHighSeverity})
|
||||
|
||||
if summary.NumOfRelevantHighSeverity > 0 {
|
||||
summary.Relevancy = append(summary.Relevancy, "High")
|
||||
summary.RelevanciesSum = append(summary.RelevanciesSum, RelevanciesSum{Relevancy: "High", Sum: summary.NumOfRelevantHighSeverity})
|
||||
}
|
||||
|
||||
if summary.NumOfFixAvailableHighSeverity > 0 {
|
||||
summary.FixAvailble = append(summary.FixAvailble, "High")
|
||||
summary.FixAvailbleSum = append(summary.FixAvailbleSum, RelevanciesSum{Relevancy: "High", Sum: summary.NumOfFixAvailableHighSeverity})
|
||||
}
|
||||
}
|
||||
|
||||
if summary.NumOfCriticalSeverity > 0 {
|
||||
summary.Severity = append(summary.Severity, "Critical")
|
||||
summary.SeveritiesSum = append(summary.SeveritiesSum, RelevanciesSum{Relevancy: "Critical", Sum: summary.NumOfCriticalSeverity})
|
||||
|
||||
if summary.NumOfRelevantCriticalSeverity > 0 {
|
||||
summary.Relevancy = append(summary.Relevancy, "Critical")
|
||||
summary.RelevanciesSum = append(summary.RelevanciesSum, RelevanciesSum{Relevancy: "Critical", Sum: summary.NumOfRelevantCriticalSeverity})
|
||||
}
|
||||
|
||||
if summary.NumOfFixAvailableCriticalSeverity > 0 {
|
||||
summary.FixAvailble = append(summary.FixAvailble, "Critical")
|
||||
summary.FixAvailbleSum = append(summary.FixAvailbleSum, RelevanciesSum{Relevancy: "Critical", Sum: summary.NumOfFixAvailableCriticalSeverity})
|
||||
}
|
||||
}
|
||||
|
||||
if summary.NumOfUnknownSeverity > 0 {
|
||||
summary.Severity = append(summary.Severity, "Unknown")
|
||||
summary.SeveritiesSum = append(summary.SeveritiesSum, RelevanciesSum{Relevancy: "Unknown", Sum: summary.NumOfUnknownSeverity})
|
||||
|
||||
if summary.NumOfRelevantUnknownSeverity > 0 {
|
||||
summary.Relevancy = append(summary.Relevancy, "Unknown")
|
||||
summary.RelevanciesSum = append(summary.RelevanciesSum, RelevanciesSum{Relevancy: "Unknown", Sum: summary.NumOfRelevantUnknownSeverity})
|
||||
}
|
||||
|
||||
if summary.NumOfFixAvailableUnknownSeverity > 0 {
|
||||
summary.FixAvailble = append(summary.FixAvailble, "Unknown")
|
||||
summary.FixAvailbleSum = append(summary.FixAvailbleSum, RelevanciesSum{Relevancy: "Unknown", Sum: summary.NumOfFixAvailableUnknownSeverity})
|
||||
}
|
||||
}
|
||||
|
||||
return summary
|
||||
}
|
||||
91
vendor/github.com/armosec/capacketsgo/containerscan/elasticdatastructures.go
generated
vendored
91
vendor/github.com/armosec/capacketsgo/containerscan/elasticdatastructures.go
generated
vendored
@@ -1,91 +0,0 @@
|
||||
package containerscan
|
||||
|
||||
type ElasticContainerVulnerabilityResult struct {
|
||||
WLID string `json:"wlid"`
|
||||
ContainerScanID string `json:"containersScanID"`
|
||||
Layers []ESLayer `json:"layers"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
IsFixed int `json:"isFixed"`
|
||||
IntroducedInLayer string `json:LayerHash`
|
||||
RelevantLinks []string `json:"links"` // shitty SE practice
|
||||
//
|
||||
|
||||
Vulnerability `json:",inline"`
|
||||
}
|
||||
|
||||
type ESLayer struct {
|
||||
LayerHash string `json:"layerHash"`
|
||||
ParentLayerHash string `json:"parentLayerHash"`
|
||||
}
|
||||
type ElasticContainerScanSummaryResult struct {
|
||||
CustomerGUID string `json:"customerGUID"`
|
||||
ContainerScanID string `json:"containersScanID"`
|
||||
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
WLID string `json:"wlid"`
|
||||
ImgTag string `json:"imageTag",omitempty`
|
||||
ImgHash string `json:"imageHash"`
|
||||
Cluster string `json:"cluster"`
|
||||
Namespace string `json:"namespace"`
|
||||
ContainerName string `json:"containerName"`
|
||||
PackagesName []string `json:"packages"`
|
||||
|
||||
Severity []string `json:"severities"`
|
||||
Relevancy []string `json:"relevancies"`
|
||||
FixAvailble []string `json:"fixes"`
|
||||
ListOfDangerousArtifcats []string `json:"listOfDangerousArtifcats"`
|
||||
|
||||
SeveritiesSum []RelevanciesSum `json:"severitiesSum"`
|
||||
RelevanciesSum []RelevanciesSum `json:"relevanciesSum"`
|
||||
FixAvailbleSum []RelevanciesSum `json:"fixAvailbleSum"`
|
||||
|
||||
Status string `json:"status"`
|
||||
|
||||
Registry string `json:"registry"`
|
||||
VersionImage string `json:"versionImage"`
|
||||
|
||||
RCESummary map[string]int64 `json:"RCE,omitempty"`
|
||||
NumOfUnknownSeverity int64 `json:"numOfUnknownSeverity"`
|
||||
NumOfNegligibleSeverity int64 `json:"numOfNegligibleSeverity"`
|
||||
NumOfLowSeverity int64 `json:"numOfLowSeverity"`
|
||||
NumOfMediumSeverity int64 `json:"numOfMeduiumSeverity"`
|
||||
NumOfHighSeverity int64 `json:"numOfHighSeverity"`
|
||||
NumOfCriticalSeverity int64 `json:"numOfCriticalSeverity"`
|
||||
|
||||
NumOfRelevantUnknownSeverity int64 `json:"numOfRelevantUnknownSeverity"`
|
||||
NumOfRelevantNegligibleSeverity int64 `json:"numOfRelevantNegligibleSeverity"`
|
||||
NumOfRelevantLowSeverity int64 `json:"numOfRelevantLowSeverity"`
|
||||
NumOfRelevantMediumSeverity int64 `json:"numOfRelevantMediumSeverity"`
|
||||
NumOfRelevantHighSeverity int64 `json:"numOfHighRelevantSeverity"`
|
||||
NumOfRelevantCriticalSeverity int64 `json:"numOfRelevantCriticalSeverity"`
|
||||
|
||||
NumOfFixAvailableUnknownSeverity int64 `json:"numOfFixAvailableUnknownSeverity"`
|
||||
NumOfFixAvailableNegligibleSeverity int64 `json:"numOfFixAvailableNegligibleSeverity"`
|
||||
NumOfFixAvailableLowSeverity int64 `json:"numOfFixAvailableLowSeverity"`
|
||||
NumOfFixAvailableMediumSeverity int64 `json:"numOfFixAvailableMediumSeverity"`
|
||||
NumOfFixAvailableHighSeverity int64 `json:"numOfFixAvailableHighSeverity"`
|
||||
NumOfFixAvailableCriticalSeverity int64 `json:"numOfFixAvailableCriticalSeverity"`
|
||||
|
||||
NumOfRelevantIssues int64 `json:"numOfRelevantIssues"`
|
||||
NumOfIrelevantIssues int64 `json:"numOfIrelevantIssues"`
|
||||
NumOfUnknownIssues int64 `json:"numOfUnknownIssues"`
|
||||
|
||||
NumOfLeakedSecrets int64 `json:"numOfLeakedSecrets"`
|
||||
Version string `json:"version"`
|
||||
|
||||
History []ContainerScanHistoryEntry `json:"history",omitempty`
|
||||
}
|
||||
|
||||
type RelevanciesSum struct {
|
||||
Relevancy string `json:"relevancy"`
|
||||
Sum int64 `json:"sum"`
|
||||
}
|
||||
|
||||
type ContainerScanHistoryEntry struct {
|
||||
ContainerScanID string `json:"containerScanID"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
func (summary *ElasticContainerScanSummaryResult) Validate() bool {
|
||||
return summary.CustomerGUID != "" && summary.ContainerScanID != "" && (summary.ImgTag != "" || summary.ImgHash != "") && summary.Timestamp > 0
|
||||
}
|
||||
271
vendor/github.com/armosec/capacketsgo/containerscan/gojayunmarshaller.go
generated
vendored
271
vendor/github.com/armosec/capacketsgo/containerscan/gojayunmarshaller.go
generated
vendored
@@ -1,271 +0,0 @@
|
||||
package containerscan
|
||||
|
||||
import (
|
||||
"github.com/francoispqt/gojay"
|
||||
)
|
||||
|
||||
/*
|
||||
responsible on fast unmarshaling of various COMMON containerscan structures and substructures
|
||||
|
||||
*/
|
||||
|
||||
// //VulnerabilitiesList -s.e
|
||||
// type LayersList []ScanResultLayer
|
||||
|
||||
// //VulnerabilitiesList -s.e
|
||||
// type VulnerabilitiesList []Vulnerability
|
||||
|
||||
// //LinuxPkgs - slice of linux pkgs
|
||||
// type LinuxPkgs []LinuxPackage
|
||||
|
||||
// //VulFixes - information bout when/how this vul was fixed
|
||||
// type VulFixes []FixedIn
|
||||
|
||||
// //PkgFiles - slice of files belong to specific pkg
|
||||
// type PkgFiles []PackageFile
|
||||
|
||||
// UnmarshalJSONObject - File inside a pkg
|
||||
func (file *PackageFile) UnmarshalJSONObject(dec *gojay.Decoder, key string) (err error) {
|
||||
|
||||
switch key {
|
||||
case "name":
|
||||
err = dec.String(&(file.Filename))
|
||||
}
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func (files *PkgFiles) UnmarshalJSONArray(dec *gojay.Decoder) error {
|
||||
lae := PackageFile{}
|
||||
if err := dec.Object(&lae); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*files = append(*files, lae)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (file *PackageFile) NKeys() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// UnmarshalJSONObject--- Package
|
||||
func (pkgnx *LinuxPackage) UnmarshalJSONObject(dec *gojay.Decoder, key string) (err error) {
|
||||
|
||||
switch key {
|
||||
case "packageName":
|
||||
err = dec.String(&(pkgnx.PackageName))
|
||||
|
||||
case "version":
|
||||
err = dec.String(&(pkgnx.PackageVersion))
|
||||
|
||||
case "files":
|
||||
err = dec.Array(&(pkgnx.Files))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (file *LinuxPackage) NKeys() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (pkgs *LinuxPkgs) UnmarshalJSONArray(dec *gojay.Decoder) error {
|
||||
lae := LinuxPackage{}
|
||||
if err := dec.Object(&lae); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*pkgs = append(*pkgs, lae)
|
||||
return nil
|
||||
}
|
||||
|
||||
//--------Vul fixed in----------------------------------
|
||||
func (fx *FixedIn) UnmarshalJSONObject(dec *gojay.Decoder, key string) (err error) {
|
||||
|
||||
switch key {
|
||||
case "name":
|
||||
err = dec.String(&(fx.Name))
|
||||
|
||||
case "imageTag":
|
||||
err = dec.String(&(fx.ImgTag))
|
||||
case "version":
|
||||
err = dec.String(&(fx.Version))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *VulFixes) UnmarshalJSONArray(dec *gojay.Decoder) error {
|
||||
lae := FixedIn{}
|
||||
if err := dec.Object(&lae); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*t = append(*t, lae)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (file *FixedIn) NKeys() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
//------ VULNERABIlITy ---------------------
|
||||
|
||||
// Name string `json:"name"`
|
||||
// ImgHash string `json:"imageHash"`
|
||||
// ImgTag string `json:"imageTag",omitempty`
|
||||
// RelatedPackageName string `json:"packageName"`
|
||||
// PackageVersion string `json:"packageVersion"`
|
||||
// Link string `json:"link"`
|
||||
// Description string `json:"description"`
|
||||
// Severity string `json:"severity"`
|
||||
// Metadata interface{} `json:"metadata",omitempty`
|
||||
// Fixes VulFixes `json:"fixedIn",omitempty`
|
||||
// Relevancy string `json:"relevant"` // use the related enum
|
||||
|
||||
func (v *Vulnerability) UnmarshalJSONObject(dec *gojay.Decoder, key string) (err error) {
|
||||
|
||||
switch key {
|
||||
case "name":
|
||||
err = dec.String(&(v.Name))
|
||||
|
||||
case "imageTag":
|
||||
err = dec.String(&(v.ImgTag))
|
||||
case "imageHash":
|
||||
err = dec.String(&(v.ImgHash))
|
||||
|
||||
case "packageName":
|
||||
err = dec.String(&(v.RelatedPackageName))
|
||||
|
||||
case "packageVersion":
|
||||
err = dec.String(&(v.PackageVersion))
|
||||
|
||||
case "link":
|
||||
err = dec.String(&(v.Link))
|
||||
|
||||
case "description":
|
||||
err = dec.String(&(v.Description))
|
||||
|
||||
case "severity":
|
||||
err = dec.String(&(v.Severity))
|
||||
|
||||
case "relevant":
|
||||
err = dec.String(&(v.Relevancy))
|
||||
|
||||
case "fixedIn":
|
||||
err = dec.Array(&(v.Fixes))
|
||||
|
||||
case "metadata":
|
||||
err = dec.Interface(&(v.Metadata))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *VulnerabilitiesList) UnmarshalJSONArray(dec *gojay.Decoder) error {
|
||||
lae := Vulnerability{}
|
||||
if err := dec.Object(&lae); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*t = append(*t, lae)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Vulnerability) NKeys() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
//---------Layer Object----------------------------------
|
||||
// type ScanResultLayer struct {
|
||||
// LayerHash string `json:layerHash`
|
||||
// Vulnerabilities []Vulnerability `json:vulnerabilities`
|
||||
// Packages []LinuxPackage `json:packageToFile`
|
||||
// }
|
||||
|
||||
func (scan *ScanResultLayer) UnmarshalJSONObject(dec *gojay.Decoder, key string) (err error) {
|
||||
|
||||
switch key {
|
||||
// case "timestamp":
|
||||
// err = dec.Time(&(reporter.Timestamp), time.RFC3339)
|
||||
// reporter.Timestamp = reporter.Timestamp.Local()
|
||||
case "layerHash":
|
||||
err = dec.String(&(scan.LayerHash))
|
||||
|
||||
case "parentLayerHash":
|
||||
err = dec.String(&(scan.ParentLayerHash))
|
||||
|
||||
case "vulnerabilities":
|
||||
err = dec.Array(&(scan.Vulnerabilities))
|
||||
case "packageToFile":
|
||||
err = dec.Array(&(scan.Packages))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *LayersList) UnmarshalJSONArray(dec *gojay.Decoder) error {
|
||||
lae := ScanResultLayer{}
|
||||
if err := dec.Object(&lae); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*t = append(*t, lae)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (scan *ScanResultLayer) NKeys() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
//---------------------SCAN RESULT--------------------------------------------------------------------------
|
||||
|
||||
// type ScanResultReport struct {
|
||||
// CustomerGUID string `json:customerGuid`
|
||||
// ImgTag string `json:imageTag,omitempty`
|
||||
// ImgHash string `json:imageHash`
|
||||
// WLID string `json:wlid`
|
||||
// Timestamp int `json:customerGuid`
|
||||
// Layers []ScanResultLayer `json:layers`
|
||||
// ContainerName
|
||||
// }
|
||||
|
||||
func (scan *ScanResultReport) UnmarshalJSONObject(dec *gojay.Decoder, key string) (err error) {
|
||||
|
||||
switch key {
|
||||
// case "timestamp":
|
||||
// err = dec.Time(&(reporter.Timestamp), time.RFC3339)
|
||||
// reporter.Timestamp = reporter.Timestamp.Local()
|
||||
case "customerGUID":
|
||||
err = dec.String(&(scan.CustomerGUID))
|
||||
case "imageTag":
|
||||
err = dec.String(&(scan.ImgTag))
|
||||
case "imageHash":
|
||||
err = dec.String(&(scan.ImgHash))
|
||||
case "wlid":
|
||||
err = dec.String(&(scan.WLID))
|
||||
case "containerName":
|
||||
err = dec.String(&(scan.ContainerName))
|
||||
case "timestamp":
|
||||
err = dec.Int64(&(scan.Timestamp))
|
||||
case "layers":
|
||||
err = dec.Array(&(scan.Layers))
|
||||
|
||||
case "listOfDangerousArtifcats":
|
||||
err = dec.SliceString(&(scan.ListOfDangerousArtifcats))
|
||||
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// func (errors *[]string) UnmarshalJSONArray(dec *gojay.Decoder) error {
|
||||
// lae := ""
|
||||
// if err := dec.String(&lae); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// *t = append(*t, lae)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (scan *ScanResultReport) NKeys() int {
|
||||
return 0
|
||||
}
|
||||
29
vendor/github.com/armosec/capacketsgo/go.mod
generated
vendored
29
vendor/github.com/armosec/capacketsgo/go.mod
generated
vendored
@@ -1,29 +0,0 @@
|
||||
module github.com/armosec/capacketsgo
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/armosec/armopa v0.0.4
|
||||
github.com/aws/aws-sdk-go v1.40.18
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible
|
||||
github.com/docker/docker v20.10.8+incompatible
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
// github.com/elastic/go-elasticsearch v0.0.0
|
||||
github.com/elastic/go-elasticsearch/v7 v7.14.0
|
||||
github.com/francoispqt/gojay v1.2.13
|
||||
github.com/gofrs/uuid v4.0.0+incompatible
|
||||
github.com/golang/glog v0.0.0-20210429001901-424d2337a529
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||
//github.com/open-policy-agent/opa v0.27.1
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
go.uber.org/zap v1.19.0
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a
|
||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
|
||||
k8s.io/api v0.22.0
|
||||
k8s.io/apimachinery v0.22.0
|
||||
k8s.io/apiserver v0.22.0
|
||||
k8s.io/client-go v0.22.0
|
||||
)
|
||||
1142
vendor/github.com/armosec/capacketsgo/go.sum
generated
vendored
1142
vendor/github.com/armosec/capacketsgo/go.sum
generated
vendored
File diff suppressed because it is too large
Load Diff
265
vendor/github.com/armosec/capacketsgo/k8sinterface/cloudvendorregistrycreds.go
generated
vendored
265
vendor/github.com/armosec/capacketsgo/k8sinterface/cloudvendorregistrycreds.go
generated
vendored
@@ -1,265 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/ecr"
|
||||
"github.com/docker/docker/api/types"
|
||||
)
|
||||
|
||||
// For GCR there are some permissions one need to assign in order to allow ARMO to pull images:
|
||||
// https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
|
||||
// gcloud iam service-accounts create armo-controller-sa
|
||||
// gcloud projects add-iam-policy-binding <PROJECT_NAME> --role roles/storage.objectViewer --member "serviceAccount:armo-controller-sa@<PROJECT_NAME>.iam.gserviceaccount.com"
|
||||
// gcloud iam service-accounts add-iam-policy-binding --role roles/iam.workloadIdentityUser --member "serviceAccount:<PROJECT_NAME>.svc.id.goog[cyberarmor-system/ca-controller-service-account]" armo-controller-sa@<PROJECT_NAME>.iam.gserviceaccount.com
|
||||
// kubectl annotate serviceaccount --overwrite --namespace cyberarmor-system ca-controller-service-account iam.gke.io/gcp-service-account=armo-controller-sa@<PROJECT_NAME>.iam.gserviceaccount.com
|
||||
|
||||
const (
|
||||
gcrDefaultServiceAccountName = "default"
|
||||
// armoServiceAccountName = "ca-controller-service-account"
|
||||
)
|
||||
|
||||
var (
|
||||
httpClient = http.Client{Timeout: 5 * time.Second}
|
||||
)
|
||||
|
||||
// CheckIsECRImage check if this image is suspected as ECR hosted image
|
||||
func CheckIsECRImage(imageTag string) bool {
|
||||
return strings.Contains(imageTag, "dkr.ecr")
|
||||
}
|
||||
|
||||
// GetLoginDetailsForECR return user name + password using the default iam-role OR ~/.aws/config of the machine
|
||||
func GetLoginDetailsForECR(imageTag string) (string, string, error) {
|
||||
// imageTag := "015253967648.dkr.ecr.eu-central-1.amazonaws.com/armo:1"
|
||||
imageTagSlices := strings.Split(imageTag, ".")
|
||||
repo := imageTagSlices[0]
|
||||
region := imageTagSlices[3]
|
||||
mySession := session.Must(session.NewSession())
|
||||
ecrClient := ecr.New(mySession, aws.NewConfig().WithRegion(region))
|
||||
input := &ecr.GetAuthorizationTokenInput{
|
||||
RegistryIds: []*string{&repo},
|
||||
}
|
||||
res, err := ecrClient.GetAuthorizationToken(input)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("in PullFromECR, failed to GetAuthorizationToken: %v", err)
|
||||
}
|
||||
res64 := (*res.AuthorizationData[0].AuthorizationToken)
|
||||
resB, err := base64.StdEncoding.DecodeString(res64)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("in PullFromECR, failed to DecodeString: %v", err)
|
||||
}
|
||||
delimiterIdx := bytes.IndexByte(resB, ':')
|
||||
// userName := resB[:delimiterIdx]
|
||||
// resB = resB[delimiterIdx+1:]
|
||||
// resB, err = base64.StdEncoding.DecodeString(string(resB))
|
||||
// if err != nil {
|
||||
// t.Errorf("failed to DecodeString #2: %v\n\n", err)
|
||||
// }
|
||||
return string(resB[:delimiterIdx]), string(resB[delimiterIdx+1:]), nil
|
||||
}
|
||||
|
||||
func CheckIsACRImage(imageTag string) bool {
|
||||
// atest1.azurecr.io/go-inf:1
|
||||
return strings.Contains(imageTag, ".azurecr.io/")
|
||||
}
|
||||
|
||||
type azureADDResponseJson struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn string `json:"expires_in"`
|
||||
ExpiresOn string `json:"expires_on"`
|
||||
NotBefore string `json:"not_before"`
|
||||
Resource string `json:"resource"`
|
||||
TokenType string `json:"token_type"`
|
||||
}
|
||||
|
||||
func getAzureAADAccessToken() (string, error) {
|
||||
msi_endpoint, err := url.Parse("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("creating URL : %v", err)
|
||||
}
|
||||
msi_parameters := url.Values{}
|
||||
msi_parameters.Add("resource", "https://management.azure.com/")
|
||||
msi_parameters.Add("api-version", "2018-02-01")
|
||||
msi_endpoint.RawQuery = msi_parameters.Encode()
|
||||
req, err := http.NewRequest("GET", msi_endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("creating HTTP request : %v", err)
|
||||
}
|
||||
req.Header.Add("Metadata", "true")
|
||||
|
||||
// Call managed services for Azure resources token endpoint
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("calling token endpoint : %v", err)
|
||||
}
|
||||
|
||||
// Pull out response body
|
||||
responseBytes, err := ioutil.ReadAll(resp.Body)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("reading response body : %v", err)
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return "", fmt.Errorf("azure ActiveDirectory AT resp: %v, %v", resp.Status, string(responseBytes))
|
||||
}
|
||||
|
||||
// Unmarshall response body into struct
|
||||
var r azureADDResponseJson
|
||||
err = json.Unmarshal(responseBytes, &r)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unmarshalling the response: %v", err)
|
||||
}
|
||||
return r.AccessToken, nil
|
||||
}
|
||||
|
||||
// GetLoginDetailsForAzurCR return user name + password to use
|
||||
func GetLoginDetailsForAzurCR(imageTag string) (string, string, error) {
|
||||
// imageTag := "atest1.azurecr.io/go-inf:1"
|
||||
imageTagSlices := strings.Split(imageTag, "/")
|
||||
azureIdensAT, err := getAzureAADAccessToken()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
atMap := make(map[string]interface{})
|
||||
azureIdensATSlices := strings.Split(azureIdensAT, ".")
|
||||
if len(azureIdensATSlices) < 2 {
|
||||
return "", "", fmt.Errorf("len(azureIdensATSlices) < 2")
|
||||
}
|
||||
resB, err := base64.RawStdEncoding.DecodeString(azureIdensATSlices[1])
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("in GetLoginDetailsForAzurCR, failed to DecodeString: %v, %s", err, azureIdensATSlices[1])
|
||||
}
|
||||
if err := json.Unmarshal(resB, &atMap); err != nil {
|
||||
return "", "", fmt.Errorf("failed to unmarshal azureIdensAT: %v, %s", err, string(resB))
|
||||
}
|
||||
// excahnging AAD for ACR refresh token
|
||||
refreshToken, err := excahngeAzureAADAccessTokenForACRRefreshToken(imageTagSlices[0], fmt.Sprintf("%v", atMap["tid"]), azureIdensAT)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("failed to excahngeAzureAADAccessTokenForACRRefreshToken: %v, registry: %s, tenantID: %s, azureAADAT: %s", err, imageTagSlices[0], fmt.Sprintf("%v", atMap["tid"]), azureIdensAT)
|
||||
}
|
||||
|
||||
return "00000000-0000-0000-0000-000000000000", refreshToken, nil
|
||||
}
|
||||
|
||||
func excahngeAzureAADAccessTokenForACRRefreshToken(registry, tenantID, azureAADAT string) (string, error) {
|
||||
msi_parameters := url.Values{}
|
||||
msi_parameters.Add("service", registry)
|
||||
msi_parameters.Add("grant_type", "access_token")
|
||||
msi_parameters.Add("tenant", tenantID)
|
||||
msi_parameters.Add("access_token", azureAADAT)
|
||||
postBodyStr := msi_parameters.Encode()
|
||||
req, err := http.NewRequest("POST", fmt.Sprintf("https://%v/oauth2/exchange", registry), strings.NewReader(postBodyStr))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("creating HTTP request : %v", err)
|
||||
}
|
||||
req.Header.Add("Metadata", "true")
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
// Call managed services for Azure resources token endpoint
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("calling token endpoint : %v", err)
|
||||
}
|
||||
|
||||
// Pull out response body
|
||||
responseBytes, err := ioutil.ReadAll(resp.Body)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("reading response body : %v", err)
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return "", fmt.Errorf("azure exchange AT resp: %v, %v", resp.Status, string(responseBytes))
|
||||
}
|
||||
resultMap := make(map[string]string)
|
||||
err = json.Unmarshal(responseBytes, &resultMap)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unmarshalling the response: %v", err)
|
||||
}
|
||||
return resultMap["refresh_token"], nil
|
||||
}
|
||||
|
||||
func CheckIsGCRImage(imageTag string) bool {
|
||||
// gcr.io/elated-pottery-310110/golang-inf:2
|
||||
return strings.Contains(imageTag, "gcr.io/")
|
||||
}
|
||||
|
||||
// GetLoginDetailsForGCR return user name + password to use
|
||||
func GetLoginDetailsForGCR(imageTag string) (string, string, error) {
|
||||
msi_endpoint, err := url.Parse(fmt.Sprintf("http://169.254.169.254/computeMetadata/v1/instance/service-accounts/%s/token", gcrDefaultServiceAccountName))
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("creating URL : %v", err)
|
||||
}
|
||||
req, err := http.NewRequest("GET", msi_endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("creating HTTP request : %v", err)
|
||||
}
|
||||
req.Header.Add("Metadata-Flavor", "Google")
|
||||
|
||||
// Call managed services for Azure resources token endpoint
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("calling token endpoint : %v", err)
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return "", "", fmt.Errorf("HTTP Status : %v, make sure the '%s' service account is configured for ARMO pod", resp.Status, gcrDefaultServiceAccountName)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
respMap := make(map[string]interface{})
|
||||
if err := json.NewDecoder(resp.Body).Decode(&respMap); err != nil {
|
||||
return "", "", fmt.Errorf("json Decode : %v", err)
|
||||
}
|
||||
return "oauth2accesstoken", fmt.Sprintf("%v", respMap["access_token"]), nil
|
||||
}
|
||||
|
||||
func GetCloudVendorRegistryCredentials(imageTag string) (map[string]types.AuthConfig, error) {
|
||||
secrets := map[string]types.AuthConfig{}
|
||||
var errRes error
|
||||
if CheckIsACRImage(imageTag) {
|
||||
userName, password, err := GetLoginDetailsForAzurCR(imageTag)
|
||||
if err != nil {
|
||||
errRes = fmt.Errorf("failed to GetLoginDetailsForACR(%s): %v", imageTag, err)
|
||||
} else {
|
||||
secrets[imageTag] = types.AuthConfig{
|
||||
Username: userName,
|
||||
Password: password,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if CheckIsECRImage(imageTag) {
|
||||
userName, password, err := GetLoginDetailsForECR(imageTag)
|
||||
if err != nil {
|
||||
errRes = fmt.Errorf("failed to GetLoginDetailsForECR(%s): %v", imageTag, err)
|
||||
} else {
|
||||
secrets[imageTag] = types.AuthConfig{
|
||||
Username: userName,
|
||||
Password: password,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if CheckIsGCRImage(imageTag) {
|
||||
userName, password, err := GetLoginDetailsForGCR(imageTag)
|
||||
if err != nil {
|
||||
errRes = fmt.Errorf("failed to GetLoginDetailsForGCR(%s): %v", imageTag, err)
|
||||
} else {
|
||||
secrets[imageTag] = types.AuthConfig{
|
||||
Username: userName,
|
||||
Password: password,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return secrets, errRes
|
||||
}
|
||||
109
vendor/github.com/armosec/capacketsgo/k8sinterface/dockerregistrycredsutils.go
generated
vendored
109
vendor/github.com/armosec/capacketsgo/k8sinterface/dockerregistrycredsutils.go
generated
vendored
@@ -1,109 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/armosec/capacketsgo/secrethandling"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/golang/glog"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func listPodImagePullSecrets(pod *corev1.Pod) ([]string, error) {
|
||||
if pod == nil {
|
||||
return []string{}, fmt.Errorf("in listPodImagePullSecrets pod is nil")
|
||||
}
|
||||
secrets := []string{}
|
||||
for _, i := range pod.Spec.ImagePullSecrets {
|
||||
secrets = append(secrets, i.Name)
|
||||
}
|
||||
return secrets, nil
|
||||
}
|
||||
|
||||
func listServiceAccountImagePullSecrets(k8sAPI *KubernetesApi, pod *corev1.Pod) ([]string, error) {
|
||||
if pod == nil {
|
||||
return []string{}, fmt.Errorf("in listServiceAccountImagePullSecrets pod is nil")
|
||||
}
|
||||
secrets := []string{}
|
||||
serviceAccountName := pod.Spec.ServiceAccountName
|
||||
if serviceAccountName == "" {
|
||||
return secrets, nil
|
||||
}
|
||||
|
||||
serviceAccount, err := k8sAPI.KubernetesClient.CoreV1().ServiceAccounts(pod.ObjectMeta.Namespace).Get(k8sAPI.Context, serviceAccountName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return secrets, fmt.Errorf("in listServiceAccountImagePullSecrets failed to get ServiceAccounts: %v", err)
|
||||
}
|
||||
for i := range serviceAccount.ImagePullSecrets {
|
||||
secrets = append(secrets, serviceAccount.ImagePullSecrets[i].Name)
|
||||
}
|
||||
return secrets, nil
|
||||
}
|
||||
|
||||
func getImagePullSecret(k8sAPI *KubernetesApi, secrets []string, namespace string) map[string]types.AuthConfig {
|
||||
|
||||
secretsAuthConfig := make(map[string]types.AuthConfig)
|
||||
|
||||
for i := range secrets {
|
||||
res, err := k8sAPI.KubernetesClient.CoreV1().Secrets(namespace).Get(context.Background(), secrets[i], metav1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Errorf("%s", err.Error())
|
||||
continue
|
||||
}
|
||||
sec, err := secrethandling.ParseSecret(res, secrets[i])
|
||||
if err == nil {
|
||||
secretsAuthConfig[secrets[i]] = *sec
|
||||
} else {
|
||||
glog.Errorf("unable to get secret: %s", err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// glog.Infof("secrets array: %v", secretsAuthConfig)
|
||||
return secretsAuthConfig
|
||||
}
|
||||
|
||||
// GetImageRegistryCredentials returns various credentials for images in the pod
|
||||
// imageTag empty means returns all of the credentials for all images in pod spec containers
|
||||
// pod.ObjectMeta.Namespace must be well setted
|
||||
func GetImageRegistryCredentials(imageTag string, pod *corev1.Pod) (map[string]types.AuthConfig, error) {
|
||||
k8sAPI := NewKubernetesApi()
|
||||
listSecret, _ := listPodImagePullSecrets(pod)
|
||||
listServiceSecret, _ := listServiceAccountImagePullSecrets(k8sAPI, pod)
|
||||
listSecret = append(listSecret, listServiceSecret...)
|
||||
secrets := getImagePullSecret(k8sAPI, listSecret, pod.ObjectMeta.Namespace)
|
||||
|
||||
if len(secrets) == 0 {
|
||||
secrets = make(map[string]types.AuthConfig)
|
||||
}
|
||||
|
||||
if imageTag != "" {
|
||||
cloudVendorSecrets, err := GetCloudVendorRegistryCredentials(imageTag)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to GetCloudVendorRegistryCredentials(%s): %v", imageTag, err)
|
||||
|
||||
} else if len(cloudVendorSecrets) > 0 {
|
||||
for secName := range cloudVendorSecrets {
|
||||
secrets[secName] = cloudVendorSecrets[secName]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for contIdx := range pod.Spec.Containers {
|
||||
imageTag := pod.Spec.Containers[contIdx].Image
|
||||
glog.Infof("GetCloudVendorRegistryCredentials for image: %v", imageTag)
|
||||
cloudVendorSecrets, err := GetCloudVendorRegistryCredentials(imageTag)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to GetCloudVendorRegistryCredentials(%s): %v", imageTag, err)
|
||||
|
||||
} else if len(cloudVendorSecrets) > 0 {
|
||||
for secName := range cloudVendorSecrets {
|
||||
secrets[secName] = cloudVendorSecrets[secName]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return secrets, nil
|
||||
}
|
||||
73
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sconfig.go
generated
vendored
73
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sconfig.go
generated
vendored
@@ -1,73 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
// DO NOT REMOVE - load cloud providers auth
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||
)
|
||||
|
||||
// K8SConfig pointer to k8s config
|
||||
var K8SConfig *restclient.Config
|
||||
|
||||
// KubernetesApi -
|
||||
type KubernetesApi struct {
|
||||
KubernetesClient kubernetes.Interface
|
||||
DynamicClient dynamic.Interface
|
||||
Context context.Context
|
||||
}
|
||||
|
||||
// NewKubernetesApi -
|
||||
func NewKubernetesApi() *KubernetesApi {
|
||||
kubernetesClient, err := kubernetes.NewForConfig(GetK8sConfig())
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("kubernetes.NewForConfig - Failed to load config file, reason: %s", err.Error()))
|
||||
}
|
||||
dynamicClient, err := dynamic.NewForConfig(GetK8sConfig())
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("dynamic.NewForConfig - Failed to load config file, reason: %s", err.Error()))
|
||||
}
|
||||
|
||||
return &KubernetesApi{
|
||||
KubernetesClient: kubernetesClient,
|
||||
DynamicClient: dynamicClient,
|
||||
Context: context.Background(),
|
||||
}
|
||||
}
|
||||
|
||||
var ConfigPath = filepath.Join(os.Getenv("HOME"), ".kube", "config")
|
||||
var RunningIncluster bool
|
||||
|
||||
// LoadK8sConfig load config from local file or from cluster
|
||||
func LoadK8sConfig() error {
|
||||
kubeconfig, err := clientcmd.BuildConfigFromFlags("", ConfigPath)
|
||||
if err != nil {
|
||||
kubeconfig, err = restclient.InClusterConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to load kubernetes config from file: '%s', err: %v", ConfigPath, err)
|
||||
}
|
||||
RunningIncluster = true
|
||||
} else {
|
||||
RunningIncluster = false
|
||||
}
|
||||
K8SConfig = kubeconfig
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetK8sConfig get config. load if not loaded yer
|
||||
func GetK8sConfig() *restclient.Config {
|
||||
if K8SConfig == nil {
|
||||
if err := LoadK8sConfig(); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return K8SConfig
|
||||
}
|
||||
26
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sconfig_test.go
generated
vendored
26
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sconfig_test.go
generated
vendored
@@ -1,26 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/armosec/capacketsgo/cautils"
|
||||
)
|
||||
|
||||
func TestGetGroupVersionResource(t *testing.T) {
|
||||
wlid := "wlid://cluster-david-v1/namespace-default/deployment-nginx-deployment"
|
||||
r, err := GetGroupVersionResource(cautils.GetKindFromWlid(wlid))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if r.Group != "apps" {
|
||||
t.Errorf("wrong group")
|
||||
}
|
||||
if r.Version != "v1" {
|
||||
t.Errorf("wrong Version")
|
||||
}
|
||||
if r.Resource != "deployments" {
|
||||
t.Errorf("wrong Resource")
|
||||
}
|
||||
|
||||
}
|
||||
144
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sdynamic.go
generated
vendored
144
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sdynamic.go
generated
vendored
@@ -1,144 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/capacketsgo/cautils"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
//
|
||||
// Uncomment to load all auth plugins
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth
|
||||
//
|
||||
// Or uncomment to load specific auth plugins
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/azure"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/openstack"
|
||||
)
|
||||
|
||||
func (k8sAPI *KubernetesApi) GetWorkloadByWlid(wlid string) (*Workload, error) {
|
||||
return k8sAPI.GetWorkload(cautils.GetNamespaceFromWlid(wlid), cautils.GetKindFromWlid(wlid), cautils.GetNameFromWlid(wlid))
|
||||
}
|
||||
|
||||
func (k8sAPI *KubernetesApi) GetWorkload(namespace, kind, name string) (*Workload, error) {
|
||||
groupVersionResource, err := GetGroupVersionResource(kind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
w, err := k8sAPI.ResourceInterface(&groupVersionResource, namespace).Get(k8sAPI.Context, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to GET resource, kind: '%s', namespace: '%s', name: '%s', reason: %s", kind, namespace, name, err.Error())
|
||||
}
|
||||
return NewWorkloadObj(w.Object), nil
|
||||
}
|
||||
|
||||
func (k8sAPI *KubernetesApi) ListWorkloads(groupVersionResource *schema.GroupVersionResource, namespace string, podLabels, fieldSelector map[string]string) ([]Workload, error) {
|
||||
listOptions := metav1.ListOptions{}
|
||||
if podLabels != nil && len(podLabels) > 0 {
|
||||
set := labels.Set(podLabels)
|
||||
listOptions.LabelSelector = SelectorToString(set)
|
||||
}
|
||||
if fieldSelector != nil && len(fieldSelector) > 0 {
|
||||
set := labels.Set(fieldSelector)
|
||||
listOptions.FieldSelector = SelectorToString(set)
|
||||
}
|
||||
uList, err := k8sAPI.ResourceInterface(groupVersionResource, namespace).List(k8sAPI.Context, listOptions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to LIST resources, reason: %s", err.Error())
|
||||
}
|
||||
workloads := make([]Workload, len(uList.Items))
|
||||
for i := range uList.Items {
|
||||
workloads[i] = *NewWorkloadObj(uList.Items[i].Object)
|
||||
}
|
||||
return workloads, nil
|
||||
}
|
||||
|
||||
func (k8sAPI *KubernetesApi) DeleteWorkloadByWlid(wlid string) error {
|
||||
groupVersionResource, err := GetGroupVersionResource(cautils.GetKindFromWlid(wlid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = k8sAPI.ResourceInterface(&groupVersionResource, cautils.GetNamespaceFromWlid(wlid)).Delete(k8sAPI.Context, cautils.GetNameFromWlid(wlid), metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to DELETE resource, workloadID: '%s', reason: %s", wlid, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k8sAPI *KubernetesApi) CreateWorkload(workload *Workload) (*Workload, error) {
|
||||
groupVersionResource, err := GetGroupVersionResource(workload.GetKind())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obj, err := workload.ToUnstructured()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w, err := k8sAPI.ResourceInterface(&groupVersionResource, workload.GetNamespace()).Create(k8sAPI.Context, obj, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to CREATE resource, workload: '%s', reason: %s", workload.Json(), err.Error())
|
||||
}
|
||||
return NewWorkloadObj(w.Object), nil
|
||||
}
|
||||
|
||||
func (k8sAPI *KubernetesApi) UpdateWorkload(workload *Workload) (*Workload, error) {
|
||||
groupVersionResource, err := GetGroupVersionResource(workload.GetKind())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj, err := workload.ToUnstructured()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
w, err := k8sAPI.ResourceInterface(&groupVersionResource, workload.GetNamespace()).Update(k8sAPI.Context, obj, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to UPDATE resource, workload: '%s', reason: %s", workload.Json(), err.Error())
|
||||
}
|
||||
return NewWorkloadObj(w.Object), nil
|
||||
}
|
||||
|
||||
func (k8sAPI *KubernetesApi) GetNamespace(ns string) (*Workload, error) {
|
||||
groupVersionResource, err := GetGroupVersionResource("namespace")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w, err := k8sAPI.DynamicClient.Resource(groupVersionResource).Get(k8sAPI.Context, ns, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get namespace: '%s', reason: %s", ns, err.Error())
|
||||
}
|
||||
return NewWorkloadObj(w.Object), nil
|
||||
}
|
||||
|
||||
func (k8sAPI *KubernetesApi) ResourceInterface(resource *schema.GroupVersionResource, namespace string) dynamic.ResourceInterface {
|
||||
if IsNamespaceScope(resource.Group, resource.Resource) {
|
||||
return k8sAPI.DynamicClient.Resource(*resource).Namespace(namespace)
|
||||
}
|
||||
return k8sAPI.DynamicClient.Resource(*resource)
|
||||
}
|
||||
|
||||
func (k8sAPI *KubernetesApi) CalculateWorkloadParentRecursive(workload *Workload) (string, string, error) {
|
||||
ownerReferences, err := workload.GetOwnerReferences() // OwnerReferences in workload
|
||||
if err != nil {
|
||||
return workload.GetKind(), workload.GetName(), err
|
||||
}
|
||||
if len(ownerReferences) == 0 {
|
||||
return workload.GetKind(), workload.GetName(), nil // parent found
|
||||
}
|
||||
ownerReference := ownerReferences[0]
|
||||
|
||||
parentWorkload, err := k8sAPI.GetWorkload(workload.GetNamespace(), ownerReference.Kind, ownerReference.Name)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not found in resourceMap") { // if parent is RCD
|
||||
return workload.GetKind(), workload.GetName(), nil // parent found
|
||||
}
|
||||
return workload.GetKind(), workload.GetName(), err
|
||||
}
|
||||
return k8sAPI.CalculateWorkloadParentRecursive(parentWorkload)
|
||||
}
|
||||
43
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sdynamic_test.go
generated
vendored
43
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sdynamic_test.go
generated
vendored
@@ -1,43 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
dynamicfake "k8s.io/client-go/dynamic/fake"
|
||||
kubernetesfake "k8s.io/client-go/kubernetes/fake"
|
||||
//
|
||||
// metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
// Uncomment to load all auth plugins
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth
|
||||
//
|
||||
// Or uncomment to load specific auth plugins
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/azure"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/openstack"
|
||||
)
|
||||
|
||||
// NewKubernetesApi -
|
||||
func NewKubernetesApiMock() *KubernetesApi {
|
||||
|
||||
return &KubernetesApi{
|
||||
KubernetesClient: kubernetesfake.NewSimpleClientset(),
|
||||
DynamicClient: dynamicfake.NewSimpleDynamicClient(&runtime.Scheme{}),
|
||||
Context: context.Background(),
|
||||
}
|
||||
}
|
||||
|
||||
// func TestListDynamic(t *testing.T) {
|
||||
// k8s := NewKubernetesApi()
|
||||
// resource := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
|
||||
// clientResource, err := k8s.DynamicClient.Resource(resource).Namespace("default").List(k8s.Context, metav1.ListOptions{})
|
||||
// if err != nil {
|
||||
// t.Errorf("err: %v", err)
|
||||
// } else {
|
||||
// bla, _ := json.Marshal(clientResource)
|
||||
// // t.Errorf("BearerToken: %v", *K8SConfig)
|
||||
// // ioutil.WriteFile("bla.json", bla, 777)
|
||||
// t.Errorf("clientResource: %s", string(bla))
|
||||
// }
|
||||
// }
|
||||
66
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sdynamicutils.go
generated
vendored
66
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sdynamicutils.go
generated
vendored
@@ -1,66 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
//
|
||||
// Uncomment to load all auth plugins
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth
|
||||
//
|
||||
// Or uncomment to load specific auth plugins
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/azure"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/openstack"
|
||||
|
||||
func ConvertUnstructuredSliceToMap(unstructuredSlice []unstructured.Unstructured) []map[string]interface{} {
|
||||
converted := make([]map[string]interface{}, len(unstructuredSlice))
|
||||
for i := range unstructuredSlice {
|
||||
converted[i] = unstructuredSlice[i].Object
|
||||
}
|
||||
return converted
|
||||
}
|
||||
|
||||
func FilterOutOwneredResources(result []unstructured.Unstructured) []unstructured.Unstructured {
|
||||
response := []unstructured.Unstructured{}
|
||||
recognizedOwners := []string{"Deployment", "ReplicaSet", "DaemonSet", "StatefulSet", "Job", "CronJob"}
|
||||
for i := range result {
|
||||
ownerReferences := result[i].GetOwnerReferences()
|
||||
if len(ownerReferences) == 0 {
|
||||
response = append(response, result[i])
|
||||
} else if !IsStringInSlice(recognizedOwners, ownerReferences[0].Kind) {
|
||||
response = append(response, result[i])
|
||||
}
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
func IsStringInSlice(slice []string, val string) bool {
|
||||
for _, item := range slice {
|
||||
if item == val {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// String returns all labels listed as a human readable string.
|
||||
// Conveniently, exactly the format that ParseSelector takes.
|
||||
func SelectorToString(ls labels.Set) string {
|
||||
selector := make([]string, 0, len(ls))
|
||||
for key, value := range ls {
|
||||
if value != "" {
|
||||
selector = append(selector, key+"="+value)
|
||||
} else {
|
||||
selector = append(selector, key)
|
||||
}
|
||||
}
|
||||
// Sort for determinism.
|
||||
sort.StringSlice(selector).Sort()
|
||||
return strings.Join(selector, ",")
|
||||
}
|
||||
10
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sdynamicutils_test.go
generated
vendored
10
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sdynamicutils_test.go
generated
vendored
@@ -1,10 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestConvertUnstructuredSliceToMap(t *testing.T) {
|
||||
converted := ConvertUnstructuredSliceToMap(V1KubeSystemNamespaceMock().Items)
|
||||
if len(converted) == 0 { // != 7
|
||||
t.Errorf("len(converted) == 0")
|
||||
}
|
||||
}
|
||||
70
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sstatic.go
generated
vendored
70
vendor/github.com/armosec/capacketsgo/k8sinterface/k8sstatic.go
generated
vendored
@@ -1,70 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/armosec/capacketsgo/cautils"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
func IsAttached(labels map[string]string) *bool {
|
||||
return IsLabel(labels, cautils.ArmoAttach)
|
||||
}
|
||||
|
||||
func IsAgentCompatibleLabel(labels map[string]string) *bool {
|
||||
return IsLabel(labels, cautils.ArmoCompatibleLabel)
|
||||
}
|
||||
func IsAgentCompatibleAnnotation(annotations map[string]string) *bool {
|
||||
return IsLabel(annotations, cautils.ArmoCompatibleAnnotation)
|
||||
}
|
||||
func SetAgentCompatibleLabel(labels map[string]string, val bool) {
|
||||
SetLabel(labels, cautils.ArmoCompatibleLabel, val)
|
||||
}
|
||||
func SetAgentCompatibleAnnotation(annotations map[string]string, val bool) {
|
||||
SetLabel(annotations, cautils.ArmoCompatibleAnnotation, val)
|
||||
}
|
||||
func IsLabel(labels map[string]string, key string) *bool {
|
||||
if labels == nil || len(labels) == 0 {
|
||||
return nil
|
||||
}
|
||||
var k bool
|
||||
if l, ok := labels[key]; ok {
|
||||
if l == "true" {
|
||||
k = true
|
||||
} else if l == "false" {
|
||||
k = false
|
||||
}
|
||||
return &k
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func SetLabel(labels map[string]string, key string, val bool) {
|
||||
if labels == nil {
|
||||
return
|
||||
}
|
||||
v := ""
|
||||
if val {
|
||||
v = "true"
|
||||
} else {
|
||||
v = "false"
|
||||
}
|
||||
labels[key] = v
|
||||
}
|
||||
func (k8sAPI *KubernetesApi) ListAttachedPods(namespace string) ([]corev1.Pod, error) {
|
||||
return k8sAPI.ListPods(namespace, map[string]string{cautils.ArmoAttach: cautils.BoolToString(true)})
|
||||
}
|
||||
|
||||
func (k8sAPI *KubernetesApi) ListPods(namespace string, podLabels map[string]string) ([]corev1.Pod, error) {
|
||||
listOptions := metav1.ListOptions{}
|
||||
if podLabels != nil && len(podLabels) > 0 {
|
||||
set := labels.Set(podLabels)
|
||||
listOptions.LabelSelector = set.AsSelector().String()
|
||||
}
|
||||
pods, err := k8sAPI.KubernetesClient.CoreV1().Pods(namespace).List(context.Background(), listOptions)
|
||||
if err != nil {
|
||||
return []corev1.Pod{}, err
|
||||
}
|
||||
return pods.Items, nil
|
||||
}
|
||||
1963
vendor/github.com/armosec/capacketsgo/k8sinterface/mockdynamicobjects.go
generated
vendored
1963
vendor/github.com/armosec/capacketsgo/k8sinterface/mockdynamicobjects.go
generated
vendored
File diff suppressed because one or more lines are too long
132
vendor/github.com/armosec/capacketsgo/k8sinterface/resourcegroupmapping.go
generated
vendored
132
vendor/github.com/armosec/capacketsgo/k8sinterface/resourcegroupmapping.go
generated
vendored
@@ -1,132 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
const ValueNotFound = -1
|
||||
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#-strong-api-groups-strong-
|
||||
var ResourceGroupMapping = map[string]string{
|
||||
"services": "/v1",
|
||||
"pods": "/v1",
|
||||
"replicationcontrollers": "/v1",
|
||||
"podtemplates": "/v1",
|
||||
"namespaces": "/v1",
|
||||
"nodes": "/v1",
|
||||
"configmaps": "/v1",
|
||||
"secrets": "/v1",
|
||||
"serviceaccounts": "/v1",
|
||||
"persistentvolumeclaims": "/v1",
|
||||
"daemonsets": "apps/v1",
|
||||
"deployments": "apps/v1",
|
||||
"replicasets": "apps/v1",
|
||||
"statefulsets": "apps/v1",
|
||||
"controllerrevisions": "apps/v1",
|
||||
"jobs": "batch/v1",
|
||||
"cronjobs": "batch/v1beta1",
|
||||
"horizontalpodautoscalers": "autoscaling/v1",
|
||||
"ingresses": "extensions/v1beta1",
|
||||
"networkpolicies": "networking.k8s.io/v1",
|
||||
"clusterroles": "rbac.authorization.k8s.io/v1",
|
||||
"clusterrolebindings": "rbac.authorization.k8s.io/v1",
|
||||
"roles": "rbac.authorization.k8s.io/v1",
|
||||
"rolebindings": "rbac.authorization.k8s.io/v1",
|
||||
"mutatingwebhookconfigurations": "admissionregistration.k8s.io/v1",
|
||||
"validatingwebhookconfigurations": "admissionregistration.k8s.io/v1",
|
||||
}
|
||||
|
||||
var GroupsClusterScope = []string{}
|
||||
var ResourceClusterScope = []string{"nodes", "namespaces", "clusterroles", "clusterrolebindings"}
|
||||
|
||||
func GetGroupVersionResource(resource string) (schema.GroupVersionResource, error) {
|
||||
resource = strings.ToLower(resource)
|
||||
if resource != "" && !strings.HasSuffix(resource, "s") {
|
||||
resource = fmt.Sprintf("%ss", resource) // add 's' at the end of a resource
|
||||
}
|
||||
if r, ok := ResourceGroupMapping[resource]; ok {
|
||||
gv := strings.Split(r, "/")
|
||||
return schema.GroupVersionResource{Group: gv[0], Version: gv[1], Resource: resource}, nil
|
||||
}
|
||||
return schema.GroupVersionResource{}, fmt.Errorf("resource '%s' not found in resourceMap", resource)
|
||||
}
|
||||
|
||||
func IsNamespaceScope(apiGroup, resource string) bool {
|
||||
return StringInSlice(GroupsClusterScope, apiGroup) == ValueNotFound &&
|
||||
StringInSlice(ResourceClusterScope, resource) == ValueNotFound
|
||||
}
|
||||
|
||||
func StringInSlice(strSlice []string, str string) int {
|
||||
for i := range strSlice {
|
||||
if strSlice[i] == str {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return ValueNotFound
|
||||
}
|
||||
|
||||
func JoinResourceTriplets(group, version, resource string) string {
|
||||
return fmt.Sprintf("%s/%s/%s", group, version, resource)
|
||||
}
|
||||
func GetResourceTriplets(group, version, resource string) []string {
|
||||
resourceTriplets := []string{}
|
||||
if resource == "" {
|
||||
// load full map
|
||||
for k, v := range ResourceGroupMapping {
|
||||
g := strings.Split(v, "/")
|
||||
resourceTriplets = append(resourceTriplets, JoinResourceTriplets(g[0], g[1], k))
|
||||
}
|
||||
} else if version == "" {
|
||||
// load by resource
|
||||
if v, ok := ResourceGroupMapping[resource]; ok {
|
||||
g := strings.Split(v, "/")
|
||||
if group == "" {
|
||||
group = g[0]
|
||||
}
|
||||
resourceTriplets = append(resourceTriplets, JoinResourceTriplets(group, g[1], resource))
|
||||
} else {
|
||||
glog.Errorf("Resource '%s' unknown", resource)
|
||||
}
|
||||
} else if group == "" {
|
||||
// load by resource and version
|
||||
if v, ok := ResourceGroupMapping[resource]; ok {
|
||||
g := strings.Split(v, "/")
|
||||
resourceTriplets = append(resourceTriplets, JoinResourceTriplets(g[0], version, resource))
|
||||
} else {
|
||||
glog.Errorf("Resource '%s' unknown", resource)
|
||||
}
|
||||
} else {
|
||||
resourceTriplets = append(resourceTriplets, JoinResourceTriplets(group, version, resource))
|
||||
}
|
||||
return resourceTriplets
|
||||
}
|
||||
func ResourceGroupToString(group, version, resource string) []string {
|
||||
if group == "*" {
|
||||
group = ""
|
||||
}
|
||||
if version == "*" {
|
||||
version = ""
|
||||
}
|
||||
if resource == "*" {
|
||||
resource = ""
|
||||
}
|
||||
resource = strings.ToLower(resource)
|
||||
if resource != "" && !strings.HasSuffix(resource, "s") {
|
||||
resource = fmt.Sprintf("%ss", resource) // add 's' at the end of a resource
|
||||
}
|
||||
return GetResourceTriplets(group, version, resource)
|
||||
}
|
||||
|
||||
func StringToResourceGroup(str string) (string, string, string) {
|
||||
splitted := strings.Split(str, "/")
|
||||
for i := range splitted {
|
||||
if splitted[i] == "*" {
|
||||
splitted[i] = ""
|
||||
}
|
||||
}
|
||||
return splitted[0], splitted[1], splitted[2]
|
||||
}
|
||||
22
vendor/github.com/armosec/capacketsgo/k8sinterface/resourcegroupmapping_test.go
generated
vendored
22
vendor/github.com/armosec/capacketsgo/k8sinterface/resourcegroupmapping_test.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestResourceGroupToString(t *testing.T) {
|
||||
allResources := ResourceGroupToString("*", "*", "*")
|
||||
if len(allResources) != len(ResourceGroupMapping) {
|
||||
t.Errorf("Expected len: %d, received: %d", len(ResourceGroupMapping), len(allResources))
|
||||
}
|
||||
pod := ResourceGroupToString("*", "*", "Pod")
|
||||
if len(pod) == 0 || pod[0] != "/v1/pods" {
|
||||
t.Errorf("pod: %v", pod)
|
||||
}
|
||||
deployments := ResourceGroupToString("*", "*", "Deployment")
|
||||
if len(deployments) == 0 || deployments[0] != "apps/v1/deployments" {
|
||||
t.Errorf("deployments: %v", deployments)
|
||||
}
|
||||
cronjobs := ResourceGroupToString("*", "*", "cronjobs")
|
||||
if len(cronjobs) == 0 || cronjobs[0] != "batch/v1beta1/cronjobs" {
|
||||
t.Errorf("cronjobs: %v", cronjobs)
|
||||
}
|
||||
}
|
||||
147
vendor/github.com/armosec/capacketsgo/k8sinterface/workload.go
generated
vendored
147
vendor/github.com/armosec/capacketsgo/k8sinterface/workload.go
generated
vendored
@@ -1,147 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/armosec/capacketsgo/apis"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
type IWorkload interface {
|
||||
IBasicWorkload
|
||||
|
||||
// GET
|
||||
GetWlid() string
|
||||
GetJobID() *apis.JobTracking
|
||||
|
||||
// SET
|
||||
SetWlid(string)
|
||||
SetInject()
|
||||
SetIgnore()
|
||||
SetUpdateTime()
|
||||
SetJobID(apis.JobTracking)
|
||||
SetCompatible()
|
||||
SetIncompatible()
|
||||
|
||||
// EXIST
|
||||
IsIgnore() bool
|
||||
IsInject() bool
|
||||
IsAttached() bool
|
||||
IsCompatible() bool
|
||||
IsIncompatible() bool
|
||||
|
||||
// REMOVE
|
||||
RemoveWlid()
|
||||
RemoveInject()
|
||||
RemoveIgnore()
|
||||
RemoveUpdateTime()
|
||||
RemoveJobID()
|
||||
RemoveCompatible()
|
||||
RemoveArmoMetadata()
|
||||
RemoveArmoLabels()
|
||||
RemoveArmoAnnotations()
|
||||
}
|
||||
type IBasicWorkload interface {
|
||||
|
||||
// Set
|
||||
SetKind(string)
|
||||
SetWorkload(map[string]interface{})
|
||||
SetLabel(key, value string)
|
||||
SetAnnotation(key, value string)
|
||||
SetNamespace(string)
|
||||
SetName(string)
|
||||
|
||||
// Get
|
||||
GetNamespace() string
|
||||
GetName() string
|
||||
GetGenerateName() string
|
||||
GetKind() string
|
||||
GetInnerAnnotation() (string, bool)
|
||||
GetPodAnnotation() (string, bool)
|
||||
GetAnnotation(string) (string, bool)
|
||||
GetLabel(string) (string, bool)
|
||||
GetAnnotations() map[string]string
|
||||
GetInnerAnnotations() map[string]string
|
||||
GetPodAnnotations() map[string]string
|
||||
GetLabels() map[string]string
|
||||
GetInnerLabels() map[string]string
|
||||
GetPodLabels() map[string]string
|
||||
GetJobLabels() map[string]string
|
||||
GetVolumes() []corev1.Volume
|
||||
GetContainers() []corev1.Container
|
||||
GetInitContainers() []corev1.Container
|
||||
GetOwnerReferences() ([]metav1.OwnerReference, error)
|
||||
GetImagePullSecret() ([]corev1.LocalObjectReference, error)
|
||||
GetServiceAccountName() string
|
||||
GetSelector() (*metav1.LabelSelector, error)
|
||||
GetResourceVersion() string
|
||||
GetUID() string
|
||||
|
||||
GetWorkload() map[string]interface{}
|
||||
|
||||
// REMOVE
|
||||
RemoveLabel(string)
|
||||
RemoveAnnotation(string)
|
||||
RemovePodStatus()
|
||||
RemoveResourceVersion()
|
||||
}
|
||||
|
||||
type Workload struct {
|
||||
workload map[string]interface{}
|
||||
}
|
||||
|
||||
func NewWorkload(bWorkload []byte) (*Workload, error) {
|
||||
workload := make(map[string]interface{})
|
||||
if bWorkload != nil {
|
||||
if err := json.Unmarshal(bWorkload, &workload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &Workload{
|
||||
workload: workload,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewWorkloadObj(workload map[string]interface{}) *Workload {
|
||||
return &Workload{
|
||||
workload: workload,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Workload) Json() string {
|
||||
if w.workload == nil {
|
||||
return ""
|
||||
}
|
||||
bWorkload, err := json.Marshal(w.workload)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return fmt.Sprintf("%s", bWorkload)
|
||||
}
|
||||
|
||||
func (workload *Workload) DeepCopy(w map[string]interface{}) {
|
||||
workload.workload = make(map[string]interface{})
|
||||
byt, _ := json.Marshal(w)
|
||||
json.Unmarshal(byt, &workload.workload)
|
||||
}
|
||||
|
||||
func (w *Workload) ToUnstructured() (*unstructured.Unstructured, error) {
|
||||
obj := &unstructured.Unstructured{}
|
||||
if w.workload == nil {
|
||||
return obj, nil
|
||||
}
|
||||
bWorkload, err := json.Marshal(w.workload)
|
||||
if err != nil {
|
||||
return obj, err
|
||||
}
|
||||
if err := json.Unmarshal(bWorkload, obj); err != nil {
|
||||
return obj, err
|
||||
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
649
vendor/github.com/armosec/capacketsgo/k8sinterface/workloadmethods.go
generated
vendored
649
vendor/github.com/armosec/capacketsgo/k8sinterface/workloadmethods.go
generated
vendored
@@ -1,649 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/armosec/capacketsgo/apis"
|
||||
"github.com/armosec/capacketsgo/cautils"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// ======================================= DELETE ========================================
|
||||
|
||||
func (w *Workload) RemoveInject() {
|
||||
w.RemovePodLabel(cautils.CAInject) // DEPRECATED
|
||||
w.RemovePodLabel(cautils.CAAttachLabel) // DEPRECATED
|
||||
w.RemovePodLabel(cautils.ArmoAttach)
|
||||
|
||||
w.RemoveLabel(cautils.CAInject) // DEPRECATED
|
||||
w.RemoveLabel(cautils.CAAttachLabel) // DEPRECATED
|
||||
w.RemoveLabel(cautils.ArmoAttach)
|
||||
}
|
||||
|
||||
func (w *Workload) RemoveIgnore() {
|
||||
w.RemovePodLabel(cautils.CAIgnore) // DEPRECATED
|
||||
w.RemovePodLabel(cautils.ArmoAttach)
|
||||
|
||||
w.RemoveLabel(cautils.CAIgnore) // DEPRECATED
|
||||
w.RemoveLabel(cautils.ArmoAttach)
|
||||
}
|
||||
|
||||
func (w *Workload) RemoveWlid() {
|
||||
w.RemovePodAnnotation(cautils.CAWlid) // DEPRECATED
|
||||
w.RemovePodAnnotation(cautils.ArmoWlid)
|
||||
|
||||
w.RemoveAnnotation(cautils.CAWlid) // DEPRECATED
|
||||
w.RemoveAnnotation(cautils.ArmoWlid)
|
||||
}
|
||||
|
||||
func (w *Workload) RemoveCompatible() {
|
||||
w.RemovePodAnnotation(cautils.ArmoCompatibleAnnotation)
|
||||
}
|
||||
func (w *Workload) RemoveJobID() {
|
||||
w.RemovePodAnnotation(cautils.ArmoJobIDPath)
|
||||
w.RemovePodAnnotation(cautils.ArmoJobParentPath)
|
||||
w.RemovePodAnnotation(cautils.ArmoJobActionPath)
|
||||
|
||||
w.RemoveAnnotation(cautils.ArmoJobIDPath)
|
||||
w.RemoveAnnotation(cautils.ArmoJobParentPath)
|
||||
w.RemoveAnnotation(cautils.ArmoJobActionPath)
|
||||
}
|
||||
func (w *Workload) RemoveArmoMetadata() {
|
||||
w.RemoveArmoLabels()
|
||||
w.RemoveArmoAnnotations()
|
||||
}
|
||||
|
||||
func (w *Workload) RemoveArmoAnnotations() {
|
||||
l := w.GetAnnotations()
|
||||
if l != nil {
|
||||
for k := range l {
|
||||
if strings.HasPrefix(k, cautils.ArmoPrefix) {
|
||||
w.RemoveAnnotation(k)
|
||||
}
|
||||
if strings.HasPrefix(k, cautils.CAPrefix) { // DEPRECATED
|
||||
w.RemoveAnnotation(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
lp := w.GetPodAnnotations()
|
||||
if lp != nil {
|
||||
for k := range lp {
|
||||
if strings.HasPrefix(k, cautils.ArmoPrefix) {
|
||||
w.RemovePodAnnotation(k)
|
||||
}
|
||||
if strings.HasPrefix(k, cautils.CAPrefix) { // DEPRECATED
|
||||
w.RemovePodAnnotation(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func (w *Workload) RemoveArmoLabels() {
|
||||
l := w.GetLabels()
|
||||
if l != nil {
|
||||
for k := range l {
|
||||
if strings.HasPrefix(k, cautils.ArmoPrefix) {
|
||||
w.RemoveLabel(k)
|
||||
}
|
||||
if strings.HasPrefix(k, cautils.CAPrefix) { // DEPRECATED
|
||||
w.RemoveLabel(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
lp := w.GetPodLabels()
|
||||
if lp != nil {
|
||||
for k := range lp {
|
||||
if strings.HasPrefix(k, cautils.ArmoPrefix) {
|
||||
w.RemovePodLabel(k)
|
||||
}
|
||||
if strings.HasPrefix(k, cautils.CAPrefix) { // DEPRECATED
|
||||
w.RemovePodLabel(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func (w *Workload) RemoveUpdateTime() {
|
||||
|
||||
// remove from pod
|
||||
w.RemovePodAnnotation(cautils.CAUpdate) // DEPRECATED
|
||||
w.RemovePodAnnotation(cautils.ArmoUpdate)
|
||||
|
||||
// remove from workload
|
||||
w.RemoveAnnotation(cautils.CAUpdate) // DEPRECATED
|
||||
w.RemoveAnnotation(cautils.ArmoUpdate)
|
||||
}
|
||||
|
||||
func (w *Workload) RemovePodStatus() {
|
||||
delete(w.workload, "status")
|
||||
}
|
||||
|
||||
func (w *Workload) RemoveResourceVersion() {
|
||||
if _, ok := w.workload["metadata"]; !ok {
|
||||
return
|
||||
}
|
||||
meta, _ := w.workload["metadata"].(map[string]interface{})
|
||||
delete(meta, "resourceVersion")
|
||||
}
|
||||
|
||||
func (w *Workload) RemoveLabel(key string) {
|
||||
w.RemoveMetadata([]string{"metadata"}, "labels", key)
|
||||
}
|
||||
|
||||
func (w *Workload) RemoveAnnotation(key string) {
|
||||
w.RemoveMetadata([]string{"metadata"}, "annotations", key)
|
||||
}
|
||||
|
||||
func (w *Workload) RemovePodAnnotation(key string) {
|
||||
w.RemoveMetadata(PodMetadata(w.GetKind()), "annotations", key)
|
||||
}
|
||||
|
||||
func (w *Workload) RemovePodLabel(key string) {
|
||||
w.RemoveMetadata(PodMetadata(w.GetKind()), "labels", key)
|
||||
}
|
||||
|
||||
func (w *Workload) RemoveMetadata(scope []string, metadata, key string) {
|
||||
|
||||
workload := w.workload
|
||||
for i := range scope {
|
||||
if _, ok := workload[scope[i]]; !ok {
|
||||
return
|
||||
}
|
||||
workload, _ = workload[scope[i]].(map[string]interface{})
|
||||
}
|
||||
|
||||
if _, ok := workload[metadata]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
labels, _ := workload[metadata].(map[string]interface{})
|
||||
delete(labels, key)
|
||||
|
||||
}
|
||||
|
||||
// ========================================= SET =========================================
|
||||
|
||||
func (w *Workload) SetWorkload(workload map[string]interface{}) {
|
||||
w.workload = workload
|
||||
}
|
||||
|
||||
func (w *Workload) SetKind(kind string) {
|
||||
w.workload["kind"] = kind
|
||||
}
|
||||
|
||||
func (w *Workload) SetInject() {
|
||||
w.SetPodLabel(cautils.ArmoAttach, cautils.BoolToString(true))
|
||||
}
|
||||
|
||||
func (w *Workload) SetJobID(jobTracking apis.JobTracking) {
|
||||
w.SetPodAnnotation(cautils.ArmoJobIDPath, jobTracking.JobID)
|
||||
w.SetPodAnnotation(cautils.ArmoJobParentPath, jobTracking.ParentID)
|
||||
w.SetPodAnnotation(cautils.ArmoJobActionPath, fmt.Sprintf("%d", jobTracking.LastActionNumber))
|
||||
}
|
||||
|
||||
func (w *Workload) SetIgnore() {
|
||||
w.SetPodLabel(cautils.ArmoAttach, cautils.BoolToString(false))
|
||||
}
|
||||
|
||||
func (w *Workload) SetCompatible() {
|
||||
w.SetPodAnnotation(cautils.ArmoCompatibleAnnotation, cautils.BoolToString(true))
|
||||
}
|
||||
|
||||
func (w *Workload) SetIncompatible() {
|
||||
w.SetPodAnnotation(cautils.ArmoCompatibleAnnotation, cautils.BoolToString(false))
|
||||
}
|
||||
|
||||
func (w *Workload) SetReplaceheaders() {
|
||||
w.SetPodAnnotation(cautils.ArmoReplaceheaders, cautils.BoolToString(true))
|
||||
}
|
||||
|
||||
func (w *Workload) SetWlid(wlid string) {
|
||||
w.SetPodAnnotation(cautils.ArmoWlid, wlid)
|
||||
}
|
||||
|
||||
func (w *Workload) SetUpdateTime() {
|
||||
w.SetPodAnnotation(cautils.ArmoUpdate, string(time.Now().UTC().Format("02-01-2006 15:04:05")))
|
||||
}
|
||||
|
||||
func (w *Workload) SetNamespace(namespace string) {
|
||||
w.SetMetadata([]string{"metadata"}, "namespace", namespace)
|
||||
}
|
||||
|
||||
func (w *Workload) SetName(name string) {
|
||||
w.SetMetadata([]string{"metadata"}, "name", name)
|
||||
}
|
||||
|
||||
func (w *Workload) SetLabel(key, value string) {
|
||||
w.SetMetadata([]string{"metadata", "labels"}, key, value)
|
||||
}
|
||||
|
||||
func (w *Workload) SetPodLabel(key, value string) {
|
||||
w.SetMetadata(append(PodMetadata(w.GetKind()), "labels"), key, value)
|
||||
}
|
||||
func (w *Workload) SetAnnotation(key, value string) {
|
||||
w.SetMetadata([]string{"metadata", "annotations"}, key, value)
|
||||
}
|
||||
func (w *Workload) SetPodAnnotation(key, value string) {
|
||||
w.SetMetadata(append(PodMetadata(w.GetKind()), "annotations"), key, value)
|
||||
}
|
||||
|
||||
func (w *Workload) SetMetadata(scope []string, key string, val interface{}) {
|
||||
workload := w.workload
|
||||
for i := range scope {
|
||||
if _, ok := workload[scope[i]]; !ok {
|
||||
workload[scope[i]] = make(map[string]interface{})
|
||||
}
|
||||
workload, _ = workload[scope[i]].(map[string]interface{})
|
||||
}
|
||||
|
||||
workload[key] = val
|
||||
}
|
||||
|
||||
// ========================================= GET =========================================
|
||||
func (w *Workload) GetWorkload() map[string]interface{} {
|
||||
return w.workload
|
||||
}
|
||||
func (w *Workload) GetNamespace() string {
|
||||
if v, ok := InspectWorkload(w.workload, "metadata", "namespace"); ok {
|
||||
return v.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (w *Workload) GetName() string {
|
||||
if v, ok := InspectWorkload(w.workload, "metadata", "name"); ok {
|
||||
return v.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (w *Workload) GetGenerateName() string {
|
||||
if v, ok := InspectWorkload(w.workload, "metadata", "generateName"); ok {
|
||||
return v.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (w *Workload) GetKind() string {
|
||||
if v, ok := InspectWorkload(w.workload, "kind"); ok {
|
||||
return v.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func (w *Workload) GetSelector() (*metav1.LabelSelector, error) {
|
||||
selector := &metav1.LabelSelector{}
|
||||
if v, ok := InspectWorkload(w.workload, "spec", "selector", "matchLabels"); ok && v != nil {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return selector, err
|
||||
}
|
||||
if err := json.Unmarshal(b, selector); err != nil {
|
||||
return selector, err
|
||||
}
|
||||
return selector, nil
|
||||
}
|
||||
return selector, nil
|
||||
}
|
||||
|
||||
func (w *Workload) GetAnnotation(annotation string) (string, bool) {
|
||||
if v, ok := InspectWorkload(w.workload, "metadata", "annotations", annotation); ok {
|
||||
return v.(string), ok
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
func (w *Workload) GetLabel(label string) (string, bool) {
|
||||
if v, ok := InspectWorkload(w.workload, "metadata", "labels", label); ok {
|
||||
return v.(string), ok
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (w *Workload) GetPodLabel(label string) (string, bool) {
|
||||
if v, ok := InspectWorkload(w.workload, append(PodMetadata(w.GetKind()), "labels", label)...); ok && v != nil {
|
||||
return v.(string), ok
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (w *Workload) GetLabels() map[string]string {
|
||||
if v, ok := InspectWorkload(w.workload, "metadata", "labels"); ok && v != nil {
|
||||
labels := make(map[string]string)
|
||||
for k, i := range v.(map[string]interface{}) {
|
||||
labels[k] = i.(string)
|
||||
}
|
||||
return labels
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInnerLabels - DEPRECATED
|
||||
func (w *Workload) GetInnerLabels() map[string]string {
|
||||
return w.GetPodLabels()
|
||||
}
|
||||
|
||||
func (w *Workload) GetPodLabels() map[string]string {
|
||||
if v, ok := InspectWorkload(w.workload, append(PodMetadata(w.GetKind()), "labels")...); ok && v != nil {
|
||||
labels := make(map[string]string)
|
||||
for k, i := range v.(map[string]interface{}) {
|
||||
labels[k] = i.(string)
|
||||
}
|
||||
return labels
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInnerAnnotations - DEPRECATED
|
||||
func (w *Workload) GetInnerAnnotations() map[string]string {
|
||||
return w.GetPodAnnotations()
|
||||
}
|
||||
|
||||
// GetPodAnnotations
|
||||
func (w *Workload) GetPodAnnotations() map[string]string {
|
||||
if v, ok := InspectWorkload(w.workload, append(PodMetadata(w.GetKind()), "annotations")...); ok && v != nil {
|
||||
annotations := make(map[string]string)
|
||||
for k, i := range v.(map[string]interface{}) {
|
||||
annotations[k] = fmt.Sprintf("%v", i)
|
||||
}
|
||||
return annotations
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInnerAnnotation DEPRECATED
|
||||
func (w *Workload) GetInnerAnnotation(annotation string) (string, bool) {
|
||||
return w.GetPodAnnotation(annotation)
|
||||
}
|
||||
|
||||
func (w *Workload) GetPodAnnotation(annotation string) (string, bool) {
|
||||
if v, ok := InspectWorkload(w.workload, append(PodMetadata(w.GetKind()), "annotations", annotation)...); ok && v != nil {
|
||||
return v.(string), ok
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (w *Workload) GetAnnotations() map[string]string {
|
||||
if v, ok := InspectWorkload(w.workload, "metadata", "annotations"); ok && v != nil {
|
||||
annotations := make(map[string]string)
|
||||
for k, i := range v.(map[string]interface{}) {
|
||||
annotations[k] = fmt.Sprintf("%v", i)
|
||||
}
|
||||
return annotations
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetVolumes -
|
||||
func (w *Workload) GetVolumes() ([]corev1.Volume, error) {
|
||||
volumes := []corev1.Volume{}
|
||||
|
||||
interVolumes, _ := InspectWorkload(w.workload, append(PodSpec(w.GetKind()), "volumes")...)
|
||||
if interVolumes == nil {
|
||||
return volumes, nil
|
||||
}
|
||||
volumesBytes, err := json.Marshal(interVolumes)
|
||||
if err != nil {
|
||||
return volumes, err
|
||||
}
|
||||
err = json.Unmarshal(volumesBytes, &volumes)
|
||||
|
||||
return volumes, err
|
||||
}
|
||||
|
||||
func (w *Workload) GetServiceAccountName() string {
|
||||
|
||||
if v, ok := InspectWorkload(w.workload, append(PodSpec(w.GetKind()), "serviceAccountName")...); ok && v != nil {
|
||||
return v.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (w *Workload) GetPodSpec() (*corev1.PodSpec, error) {
|
||||
podSpec := &corev1.PodSpec{}
|
||||
podSepcRaw, _ := InspectWorkload(w.workload, PodSpec(w.GetKind())...)
|
||||
if podSepcRaw == nil {
|
||||
return podSpec, fmt.Errorf("no PodSpec for workload: %v", w)
|
||||
}
|
||||
b, err := json.Marshal(podSepcRaw)
|
||||
if err != nil {
|
||||
return podSpec, err
|
||||
}
|
||||
err = json.Unmarshal(b, podSpec)
|
||||
|
||||
return podSpec, err
|
||||
}
|
||||
|
||||
func (w *Workload) GetImagePullSecret() ([]corev1.LocalObjectReference, error) {
|
||||
imgPullSecrets := []corev1.LocalObjectReference{}
|
||||
|
||||
iImgPullSecrets, _ := InspectWorkload(w.workload, append(PodSpec(w.GetKind()), "imagePullSecrets")...)
|
||||
b, err := json.Marshal(iImgPullSecrets)
|
||||
if err != nil {
|
||||
return imgPullSecrets, err
|
||||
}
|
||||
err = json.Unmarshal(b, &imgPullSecrets)
|
||||
|
||||
return imgPullSecrets, err
|
||||
}
|
||||
|
||||
// GetContainers -
|
||||
func (w *Workload) GetContainers() ([]corev1.Container, error) {
|
||||
containers := []corev1.Container{}
|
||||
|
||||
interContainers, _ := InspectWorkload(w.workload, append(PodSpec(w.GetKind()), "containers")...)
|
||||
if interContainers == nil {
|
||||
return containers, nil
|
||||
}
|
||||
containersBytes, err := json.Marshal(interContainers)
|
||||
if err != nil {
|
||||
return containers, err
|
||||
}
|
||||
err = json.Unmarshal(containersBytes, &containers)
|
||||
|
||||
return containers, err
|
||||
}
|
||||
|
||||
// GetContainers -
|
||||
func (w *Workload) GetInitContainers() ([]corev1.Container, error) {
|
||||
containers := []corev1.Container{}
|
||||
|
||||
interContainers, _ := InspectWorkload(w.workload, append(PodSpec(w.GetKind()), "initContainers")...)
|
||||
if interContainers == nil {
|
||||
return containers, nil
|
||||
}
|
||||
containersBytes, err := json.Marshal(interContainers)
|
||||
if err != nil {
|
||||
return containers, err
|
||||
}
|
||||
err = json.Unmarshal(containersBytes, &containers)
|
||||
|
||||
return containers, err
|
||||
}
|
||||
|
||||
// GetOwnerReferences -
|
||||
func (w *Workload) GetOwnerReferences() ([]metav1.OwnerReference, error) {
|
||||
ownerReferences := []metav1.OwnerReference{}
|
||||
interOwnerReferences, ok := InspectWorkload(w.workload, "metadata", "ownerReferences")
|
||||
if !ok {
|
||||
return ownerReferences, nil
|
||||
}
|
||||
|
||||
ownerReferencesBytes, err := json.Marshal(interOwnerReferences)
|
||||
if err != nil {
|
||||
return ownerReferences, err
|
||||
}
|
||||
err = json.Unmarshal(ownerReferencesBytes, &ownerReferences)
|
||||
if err != nil {
|
||||
return ownerReferences, err
|
||||
|
||||
}
|
||||
return ownerReferences, nil
|
||||
}
|
||||
func (w *Workload) GetResourceVersion() string {
|
||||
if v, ok := InspectWorkload(w.workload, "metadata", "resourceVersion"); ok {
|
||||
return v.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func (w *Workload) GetUID() string {
|
||||
if v, ok := InspectWorkload(w.workload, "metadata", "uid"); ok {
|
||||
return v.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func (w *Workload) GetWlid() string {
|
||||
if wlid, ok := w.GetAnnotation(cautils.ArmoWlid); ok {
|
||||
return wlid
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (w *Workload) GetJobID() *apis.JobTracking {
|
||||
jobTracking := apis.JobTracking{}
|
||||
if job, ok := w.GetPodAnnotation(cautils.ArmoJobIDPath); ok {
|
||||
jobTracking.JobID = job
|
||||
}
|
||||
if parent, ok := w.GetPodAnnotation(cautils.ArmoJobParentPath); ok {
|
||||
jobTracking.ParentID = parent
|
||||
}
|
||||
if action, ok := w.GetPodAnnotation(cautils.ArmoJobActionPath); ok {
|
||||
if i, err := strconv.Atoi(action); err == nil {
|
||||
jobTracking.LastActionNumber = i
|
||||
}
|
||||
}
|
||||
if jobTracking.LastActionNumber == 0 { // start the counter at 1
|
||||
jobTracking.LastActionNumber = 1
|
||||
}
|
||||
return &jobTracking
|
||||
}
|
||||
|
||||
// func (w *Workload) GetJobID() string {
|
||||
// if status, ok := w.GetAnnotation(cautils.ArmoJobID); ok {
|
||||
// return status
|
||||
// }
|
||||
// return ""
|
||||
// }
|
||||
|
||||
// ========================================= IS =========================================
|
||||
|
||||
func (w *Workload) IsInject() bool {
|
||||
return w.IsAttached()
|
||||
}
|
||||
|
||||
func (w *Workload) IsIgnore() bool {
|
||||
if attach := cautils.IsAttached(w.GetPodLabels()); attach != nil {
|
||||
return !(*attach)
|
||||
}
|
||||
if attach := cautils.IsAttached(w.GetLabels()); attach != nil {
|
||||
return !(*attach)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *Workload) IsCompatible() bool {
|
||||
if c, ok := w.GetPodAnnotation(cautils.ArmoCompatibleAnnotation); ok {
|
||||
return cautils.StringToBool(c)
|
||||
|
||||
}
|
||||
if c, ok := w.GetAnnotation(cautils.ArmoCompatibleAnnotation); ok {
|
||||
return cautils.StringToBool(c)
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *Workload) IsIncompatible() bool {
|
||||
if c, ok := w.GetPodAnnotation(cautils.ArmoCompatibleAnnotation); ok {
|
||||
return !cautils.StringToBool(c)
|
||||
}
|
||||
if c, ok := w.GetAnnotation(cautils.ArmoCompatibleAnnotation); ok {
|
||||
return !cautils.StringToBool(c)
|
||||
}
|
||||
return false
|
||||
}
|
||||
func (w *Workload) IsAttached() bool {
|
||||
if attach := cautils.IsAttached(w.GetPodLabels()); attach != nil {
|
||||
return *attach
|
||||
}
|
||||
if attach := cautils.IsAttached(w.GetLabels()); attach != nil {
|
||||
return *attach
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *Workload) IsReplaceheaders() bool {
|
||||
if c, ok := w.GetPodAnnotation(cautils.ArmoReplaceheaders); ok {
|
||||
return cautils.StringToBool(c)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ======================================= UTILS =========================================
|
||||
|
||||
// InspectWorkload -
|
||||
func InspectWorkload(workload interface{}, scopes ...string) (val interface{}, k bool) {
|
||||
|
||||
val, k = nil, false
|
||||
if len(scopes) == 0 {
|
||||
if workload != nil {
|
||||
return workload, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
if data, ok := workload.(map[string]interface{}); ok {
|
||||
val, k = InspectWorkload(data[scopes[0]], scopes[1:]...)
|
||||
}
|
||||
return val, k
|
||||
|
||||
}
|
||||
|
||||
// // InspectWorkload -
|
||||
// func InjectWorkload(workload interface{}, scopes []string, val string) {
|
||||
|
||||
// if len(scopes) == 0 {
|
||||
|
||||
// }
|
||||
// if data, ok := workload.(map[string]interface{}); ok {
|
||||
// InjectWorkload(data[scopes[0]], scopes[1:], val)
|
||||
// } else {
|
||||
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// InjectWorkload -
|
||||
// func InjectWorkload(workload interface{}, scopes []string, val string) {
|
||||
|
||||
// if len(scopes) == 0 {
|
||||
// workload = ""
|
||||
// }
|
||||
// if data, ok := workload.(map[string]interface{}); ok {
|
||||
// d := InjectWorkload(data[scopes[0]], scopes[1:], val)
|
||||
// data[scopes[0]] = d
|
||||
// return data
|
||||
// } else {
|
||||
|
||||
// }
|
||||
|
||||
// }
|
||||
// func (w *Workload) SetNamespace(ns string) {
|
||||
|
||||
// if v, k := w.workload["metadata"]; k {
|
||||
// if vv, kk := v.(map[string]interface{}); kk {
|
||||
// vv["namespace"] = ""
|
||||
// // if v3, k3 := w.workload["namespace"]; k3 {
|
||||
// // if v4, k4 := v.(map[string]interface{}); kk {
|
||||
|
||||
// // }
|
||||
// // }
|
||||
// v = vv
|
||||
// }
|
||||
// w.workload = v
|
||||
// }
|
||||
// // if data, ok := w.workload.(map[string]interface{}); ok {
|
||||
// // val, k = InspectWorkload(data[scopes[0]], scopes[1:]...)
|
||||
// // }
|
||||
|
||||
// }
|
||||
155
vendor/github.com/armosec/capacketsgo/k8sinterface/workloadmethods_test.go
generated
vendored
155
vendor/github.com/armosec/capacketsgo/k8sinterface/workloadmethods_test.go
generated
vendored
@@ -1,155 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// ========================================= IS =========================================
|
||||
|
||||
func TestLabels(t *testing.T) {
|
||||
w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"deployment.kubernetes.io/revision":"1"},"creationTimestamp":"2021-05-03T13:10:32Z","generation":1,"labels":{"app":"demoservice-server","cyberarmor.inject":"true"},"managedFields":[{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{".":{},"f:app":{},"f:cyberarmor.inject":{}}},"f:spec":{"f:progressDeadlineSeconds":{},"f:replicas":{},"f:revisionHistoryLimit":{},"f:selector":{},"f:strategy":{"f:rollingUpdate":{".":{},"f:maxSurge":{},"f:maxUnavailable":{}},"f:type":{}},"f:template":{"f:metadata":{"f:labels":{".":{},"f:app":{}}},"f:spec":{"f:containers":{"k:{\"name\":\"demoservice\"}":{".":{},"f:env":{".":{},"k:{\"name\":\"ARMO_TEST_NAME\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"CAA_ENABLE_CRASH_REPORTER\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"DEMO_FOLDERS\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SERVER_PORT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SLEEP_DURATION\"}":{".":{},"f:name":{},"f:value":{}}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":8089,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}},"manager":"OpenAPI-Generator","operation":"Update","time":"2021-05-03T13:10:32Z"},{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:deployment.kubernetes.io/revision":{}}},"f:status":{"f:availableReplicas":{},"f:conditions":{".":{},"k:{\"type\":\"Available\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Progressing\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:observedGeneration":{},"f:readyReplicas":{},"f:replicas":{},"f:updatedReplicas":{}}},"manager":"kube-controller-manager","operation":"Update","time":"2021-05-03T13:52:58Z"}],"name":"demoservice-server","namespace":"default","resourceVersion":"1016043","uid":"e9e8a3e9-6cb4-4301-ace1-2c0cef3bd61e"},"spec":{"progressDeadlineSeconds":600,"replicas":1,"revisionHistoryLimit":10,"selector":{"matchLabels":{"app":"demoservice-server"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"demoservice-server"}},"spec":{"containers":[{"env":[{"name":"SERVER_PORT","value":"8089"},{"name":"SLEEP_DURATION","value":"1"},{"name":"DEMO_FOLDERS","value":"/app"},{"name":"ARMO_TEST_NAME","value":"auto_attach_deployment"},{"name":"CAA_ENABLE_CRASH_REPORTER","value":"1"}],"image":"quay.io/armosec/demoservice:v25","imagePullPolicy":"IfNotPresent","name":"demoservice","ports":[{"containerPort":8089,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}},"status":{"availableReplicas":1,"conditions":[{"lastTransitionTime":"2021-05-03T13:10:32Z","lastUpdateTime":"2021-05-03T13:10:37Z","message":"ReplicaSet \"demoservice-server-7d478b6998\" has successfully progressed.","reason":"NewReplicaSetAvailable","status":"True","type":"Progressing"},{"lastTransitionTime":"2021-05-03T13:52:58Z","lastUpdateTime":"2021-05-03T13:52:58Z","message":"Deployment has minimum availability.","reason":"MinimumReplicasAvailable","status":"True","type":"Available"}],"observedGeneration":1,"readyReplicas":1,"replicas":1,"updatedReplicas":1}}`
|
||||
workload, err := NewWorkload([]byte(w))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
if workload.GetKind() != "Deployment" {
|
||||
t.Errorf("wrong kind")
|
||||
}
|
||||
if workload.GetNamespace() != "default" {
|
||||
t.Errorf("wrong namespace")
|
||||
}
|
||||
if workload.GetName() != "demoservice-server" {
|
||||
t.Errorf("wrong name")
|
||||
}
|
||||
if !workload.IsInject() {
|
||||
t.Errorf("expect to find inject label")
|
||||
}
|
||||
if workload.IsIgnore() {
|
||||
t.Errorf("expect to find ignore label")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetNamespace(t *testing.T) {
|
||||
w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"demoservice-server"},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"demoservice-server"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"demoservice-server"}},"spec":{"containers":[{"env":[{"name":"SERVER_PORT","value":"8089"},{"name":"SLEEP_DURATION","value":"1"},{"name":"DEMO_FOLDERS","value":"/app"},{"name":"ARMO_TEST_NAME","value":"auto_attach_deployment"},{"name":"CAA_ENABLE_CRASH_REPORTER","value":"1"}],"image":"quay.io/armosec/demoservice:v25","imagePullPolicy":"IfNotPresent","name":"demoservice","ports":[{"containerPort":8089,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}}}`
|
||||
workload, err := NewWorkload([]byte(w))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
workload.SetNamespace("default")
|
||||
if workload.GetNamespace() != "default" {
|
||||
t.Errorf("wrong namespace")
|
||||
}
|
||||
}
|
||||
func TestSetLabels(t *testing.T) {
|
||||
w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"deployment.kubernetes.io/revision":"1"},"creationTimestamp":"2021-05-03T13:10:32Z","generation":1,"managedFields":[{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{".":{},"f:app":{},"f:cyberarmor.inject":{}}},"f:spec":{"f:progressDeadlineSeconds":{},"f:replicas":{},"f:revisionHistoryLimit":{},"f:selector":{},"f:strategy":{"f:rollingUpdate":{".":{},"f:maxSurge":{},"f:maxUnavailable":{}},"f:type":{}},"f:template":{"f:metadata":{"f:labels":{".":{},"f:app":{}}},"f:spec":{"f:containers":{"k:{\"name\":\"demoservice\"}":{".":{},"f:env":{".":{},"k:{\"name\":\"ARMO_TEST_NAME\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"CAA_ENABLE_CRASH_REPORTER\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"DEMO_FOLDERS\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SERVER_PORT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SLEEP_DURATION\"}":{".":{},"f:name":{},"f:value":{}}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":8089,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}},"manager":"OpenAPI-Generator","operation":"Update","time":"2021-05-03T13:10:32Z"},{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:deployment.kubernetes.io/revision":{}}},"f:status":{"f:availableReplicas":{},"f:conditions":{".":{},"k:{\"type\":\"Available\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Progressing\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:observedGeneration":{},"f:readyReplicas":{},"f:replicas":{},"f:updatedReplicas":{}}},"manager":"kube-controller-manager","operation":"Update","time":"2021-05-03T13:52:58Z"}],"name":"demoservice-server","namespace":"default","resourceVersion":"1016043","uid":"e9e8a3e9-6cb4-4301-ace1-2c0cef3bd61e"},"spec":{"progressDeadlineSeconds":600,"replicas":1,"revisionHistoryLimit":10,"selector":{"matchLabels":{"app":"demoservice-server"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"demoservice-server"}},"spec":{"containers":[{"env":[{"name":"SERVER_PORT","value":"8089"},{"name":"SLEEP_DURATION","value":"1"},{"name":"DEMO_FOLDERS","value":"/app"},{"name":"ARMO_TEST_NAME","value":"auto_attach_deployment"},{"name":"CAA_ENABLE_CRASH_REPORTER","value":"1"}],"image":"quay.io/armosec/demoservice:v25","imagePullPolicy":"IfNotPresent","name":"demoservice","ports":[{"containerPort":8089,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}},"status":{"availableReplicas":1,"conditions":[{"lastTransitionTime":"2021-05-03T13:10:32Z","lastUpdateTime":"2021-05-03T13:10:37Z","message":"ReplicaSet \"demoservice-server-7d478b6998\" has successfully progressed.","reason":"NewReplicaSetAvailable","status":"True","type":"Progressing"},{"lastTransitionTime":"2021-05-03T13:52:58Z","lastUpdateTime":"2021-05-03T13:52:58Z","message":"Deployment has minimum availability.","reason":"MinimumReplicasAvailable","status":"True","type":"Available"}],"observedGeneration":1,"readyReplicas":1,"replicas":1,"updatedReplicas":1}}`
|
||||
workload, err := NewWorkload([]byte(w))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
workload.SetLabel("bla", "daa")
|
||||
v, ok := workload.GetLabel("bla")
|
||||
if !ok || v != "daa" {
|
||||
t.Errorf("expect to find label")
|
||||
}
|
||||
workload.RemoveLabel("bla")
|
||||
v2, ok2 := workload.GetLabel("bla")
|
||||
if ok2 || v2 == "daa" {
|
||||
t.Errorf("label not deleted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetAnnotations(t *testing.T) {
|
||||
w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"deployment.kubernetes.io/revision":"1"},"creationTimestamp":"2021-05-03T13:10:32Z","generation":1,"managedFields":[{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{".":{},"f:app":{},"f:cyberarmor.inject":{}}},"f:spec":{"f:progressDeadlineSeconds":{},"f:replicas":{},"f:revisionHistoryLimit":{},"f:selector":{},"f:strategy":{"f:rollingUpdate":{".":{},"f:maxSurge":{},"f:maxUnavailable":{}},"f:type":{}},"f:template":{"f:metadata":{"f:labels":{".":{},"f:app":{}}},"f:spec":{"f:containers":{"k:{\"name\":\"demoservice\"}":{".":{},"f:env":{".":{},"k:{\"name\":\"ARMO_TEST_NAME\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"CAA_ENABLE_CRASH_REPORTER\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"DEMO_FOLDERS\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SERVER_PORT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SLEEP_DURATION\"}":{".":{},"f:name":{},"f:value":{}}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":8089,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}},"manager":"OpenAPI-Generator","operation":"Update","time":"2021-05-03T13:10:32Z"},{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:deployment.kubernetes.io/revision":{}}},"f:status":{"f:availableReplicas":{},"f:conditions":{".":{},"k:{\"type\":\"Available\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Progressing\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:observedGeneration":{},"f:readyReplicas":{},"f:replicas":{},"f:updatedReplicas":{}}},"manager":"kube-controller-manager","operation":"Update","time":"2021-05-03T13:52:58Z"}],"name":"demoservice-server","namespace":"default","resourceVersion":"1016043","uid":"e9e8a3e9-6cb4-4301-ace1-2c0cef3bd61e"},"spec":{"progressDeadlineSeconds":600,"replicas":1,"revisionHistoryLimit":10,"selector":{"matchLabels":{"app":"demoservice-server"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"demoservice-server"}},"spec":{"containers":[{"env":[{"name":"SERVER_PORT","value":"8089"},{"name":"SLEEP_DURATION","value":"1"},{"name":"DEMO_FOLDERS","value":"/app"},{"name":"ARMO_TEST_NAME","value":"auto_attach_deployment"},{"name":"CAA_ENABLE_CRASH_REPORTER","value":"1"}],"image":"quay.io/armosec/demoservice:v25","imagePullPolicy":"IfNotPresent","name":"demoservice","ports":[{"containerPort":8089,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}},"status":{"availableReplicas":1,"conditions":[{"lastTransitionTime":"2021-05-03T13:10:32Z","lastUpdateTime":"2021-05-03T13:10:37Z","message":"ReplicaSet \"demoservice-server-7d478b6998\" has successfully progressed.","reason":"NewReplicaSetAvailable","status":"True","type":"Progressing"},{"lastTransitionTime":"2021-05-03T13:52:58Z","lastUpdateTime":"2021-05-03T13:52:58Z","message":"Deployment has minimum availability.","reason":"MinimumReplicasAvailable","status":"True","type":"Available"}],"observedGeneration":1,"readyReplicas":1,"replicas":1,"updatedReplicas":1}}`
|
||||
workload, err := NewWorkload([]byte(w))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
workload.SetAnnotation("bla", "daa")
|
||||
v, ok := workload.GetAnnotation("bla")
|
||||
if !ok || v != "daa" {
|
||||
t.Errorf("expect to find annotation")
|
||||
}
|
||||
workload.RemoveAnnotation("bla")
|
||||
v2, ok2 := workload.GetAnnotation("bla")
|
||||
if ok2 || v2 == "daa" {
|
||||
t.Errorf("annotation not deleted")
|
||||
}
|
||||
}
|
||||
func TestSetPodLabels(t *testing.T) {
|
||||
w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"deployment.kubernetes.io/revision":"1"},"creationTimestamp":"2021-05-03T13:10:32Z","generation":1,"managedFields":[{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{".":{},"f:app":{},"f:cyberarmor.inject":{}}},"f:spec":{"f:progressDeadlineSeconds":{},"f:replicas":{},"f:revisionHistoryLimit":{},"f:selector":{},"f:strategy":{"f:rollingUpdate":{".":{},"f:maxSurge":{},"f:maxUnavailable":{}},"f:type":{}},"f:template":{"f:metadata":{"f:labels":{".":{},"f:app":{}}},"f:spec":{"f:containers":{"k:{\"name\":\"demoservice\"}":{".":{},"f:env":{".":{},"k:{\"name\":\"ARMO_TEST_NAME\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"CAA_ENABLE_CRASH_REPORTER\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"DEMO_FOLDERS\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SERVER_PORT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SLEEP_DURATION\"}":{".":{},"f:name":{},"f:value":{}}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":8089,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}},"manager":"OpenAPI-Generator","operation":"Update","time":"2021-05-03T13:10:32Z"},{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:deployment.kubernetes.io/revision":{}}},"f:status":{"f:availableReplicas":{},"f:conditions":{".":{},"k:{\"type\":\"Available\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Progressing\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:observedGeneration":{},"f:readyReplicas":{},"f:replicas":{},"f:updatedReplicas":{}}},"manager":"kube-controller-manager","operation":"Update","time":"2021-05-03T13:52:58Z"}],"name":"demoservice-server","namespace":"default","resourceVersion":"1016043","uid":"e9e8a3e9-6cb4-4301-ace1-2c0cef3bd61e"},"spec":{"progressDeadlineSeconds":600,"replicas":1,"revisionHistoryLimit":10,"selector":{"matchLabels":{"app":"demoservice-server"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"demoservice-server"}},"spec":{"containers":[{"env":[{"name":"SERVER_PORT","value":"8089"},{"name":"SLEEP_DURATION","value":"1"},{"name":"DEMO_FOLDERS","value":"/app"},{"name":"ARMO_TEST_NAME","value":"auto_attach_deployment"},{"name":"CAA_ENABLE_CRASH_REPORTER","value":"1"}],"image":"quay.io/armosec/demoservice:v25","imagePullPolicy":"IfNotPresent","name":"demoservice","ports":[{"containerPort":8089,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}},"status":{"availableReplicas":1,"conditions":[{"lastTransitionTime":"2021-05-03T13:10:32Z","lastUpdateTime":"2021-05-03T13:10:37Z","message":"ReplicaSet \"demoservice-server-7d478b6998\" has successfully progressed.","reason":"NewReplicaSetAvailable","status":"True","type":"Progressing"},{"lastTransitionTime":"2021-05-03T13:52:58Z","lastUpdateTime":"2021-05-03T13:52:58Z","message":"Deployment has minimum availability.","reason":"MinimumReplicasAvailable","status":"True","type":"Available"}],"observedGeneration":1,"readyReplicas":1,"replicas":1,"updatedReplicas":1}}`
|
||||
workload, err := NewWorkload([]byte(w))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
workload.SetPodLabel("bla", "daa")
|
||||
v, ok := workload.GetPodLabel("bla")
|
||||
if !ok || v != "daa" {
|
||||
t.Errorf("expect to find label")
|
||||
}
|
||||
workload.RemovePodLabel("bla")
|
||||
v2, ok2 := workload.GetPodLabel("bla")
|
||||
if ok2 || v2 == "daa" {
|
||||
t.Errorf("label not deleted")
|
||||
}
|
||||
}
|
||||
func TestRemoveArmo(t *testing.T) {
|
||||
w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"deployment.kubernetes.io/revision":"1"},"creationTimestamp":"2021-05-03T13:10:32Z","generation":1,"managedFields":[{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{".":{},"f:app":{},"f:cyberarmor.inject":{}}},"f:spec":{"f:progressDeadlineSeconds":{},"f:replicas":{},"f:revisionHistoryLimit":{},"f:selector":{},"f:strategy":{"f:rollingUpdate":{".":{},"f:maxSurge":{},"f:maxUnavailable":{}},"f:type":{}},"f:template":{"f:metadata":{"f:labels":{".":{},"f:app":{}}},"f:spec":{"f:containers":{"k:{\"name\":\"demoservice\"}":{".":{},"f:env":{".":{},"k:{\"name\":\"ARMO_TEST_NAME\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"CAA_ENABLE_CRASH_REPORTER\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"DEMO_FOLDERS\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SERVER_PORT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SLEEP_DURATION\"}":{".":{},"f:name":{},"f:value":{}}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":8089,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}},"manager":"OpenAPI-Generator","operation":"Update","time":"2021-05-03T13:10:32Z"},{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:deployment.kubernetes.io/revision":{}}},"f:status":{"f:availableReplicas":{},"f:conditions":{".":{},"k:{\"type\":\"Available\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Progressing\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:observedGeneration":{},"f:readyReplicas":{},"f:replicas":{},"f:updatedReplicas":{}}},"manager":"kube-controller-manager","operation":"Update","time":"2021-05-03T13:52:58Z"}],"name":"demoservice-server","namespace":"default","resourceVersion":"1016043","uid":"e9e8a3e9-6cb4-4301-ace1-2c0cef3bd61e"},"spec":{"progressDeadlineSeconds":600,"replicas":1,"revisionHistoryLimit":10,"selector":{"matchLabels":{"app":"demoservice-server"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"demoservice-server", "armo.attach": "true"}},"spec":{"containers":[{"env":[{"name":"SERVER_PORT","value":"8089"},{"name":"SLEEP_DURATION","value":"1"},{"name":"DEMO_FOLDERS","value":"/app"},{"name":"ARMO_TEST_NAME","value":"auto_attach_deployment"},{"name":"CAA_ENABLE_CRASH_REPORTER","value":"1"}],"image":"quay.io/armosec/demoservice:v25","imagePullPolicy":"IfNotPresent","name":"demoservice","ports":[{"containerPort":8089,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}},"status":{"availableReplicas":1,"conditions":[{"lastTransitionTime":"2021-05-03T13:10:32Z","lastUpdateTime":"2021-05-03T13:10:37Z","message":"ReplicaSet \"demoservice-server-7d478b6998\" has successfully progressed.","reason":"NewReplicaSetAvailable","status":"True","type":"Progressing"},{"lastTransitionTime":"2021-05-03T13:52:58Z","lastUpdateTime":"2021-05-03T13:52:58Z","message":"Deployment has minimum availability.","reason":"MinimumReplicasAvailable","status":"True","type":"Available"}],"observedGeneration":1,"readyReplicas":1,"replicas":1,"updatedReplicas":1}}`
|
||||
workload, err := NewWorkload([]byte(w))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
if !workload.IsAttached() {
|
||||
t.Errorf("expect to be attached")
|
||||
}
|
||||
workload.RemoveArmoMetadata()
|
||||
if workload.IsAttached() {
|
||||
t.Errorf("expect to be clear")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSetWlid(t *testing.T) {
|
||||
w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"deployment.kubernetes.io/revision":"1"},"creationTimestamp":"2021-05-03T13:10:32Z","generation":1,"managedFields":[{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{".":{},"f:app":{},"f:cyberarmor.inject":{}}},"f:spec":{"f:progressDeadlineSeconds":{},"f:replicas":{},"f:revisionHistoryLimit":{},"f:selector":{},"f:strategy":{"f:rollingUpdate":{".":{},"f:maxSurge":{},"f:maxUnavailable":{}},"f:type":{}},"f:template":{"f:metadata":{"f:labels":{".":{},"f:app":{}}},"f:spec":{"f:containers":{"k:{\"name\":\"demoservice\"}":{".":{},"f:env":{".":{},"k:{\"name\":\"ARMO_TEST_NAME\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"CAA_ENABLE_CRASH_REPORTER\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"DEMO_FOLDERS\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SERVER_PORT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SLEEP_DURATION\"}":{".":{},"f:name":{},"f:value":{}}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":8089,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}},"manager":"OpenAPI-Generator","operation":"Update","time":"2021-05-03T13:10:32Z"},{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:deployment.kubernetes.io/revision":{}}},"f:status":{"f:availableReplicas":{},"f:conditions":{".":{},"k:{\"type\":\"Available\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Progressing\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:observedGeneration":{},"f:readyReplicas":{},"f:replicas":{},"f:updatedReplicas":{}}},"manager":"kube-controller-manager","operation":"Update","time":"2021-05-03T13:52:58Z"}],"name":"demoservice-server","namespace":"default","resourceVersion":"1016043","uid":"e9e8a3e9-6cb4-4301-ace1-2c0cef3bd61e"},"spec":{"progressDeadlineSeconds":600,"replicas":1,"revisionHistoryLimit":10,"selector":{"matchLabels":{"app":"demoservice-server"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"demoservice-server"}},"spec":{"containers":[{"env":[{"name":"SERVER_PORT","value":"8089"},{"name":"SLEEP_DURATION","value":"1"},{"name":"DEMO_FOLDERS","value":"/app"},{"name":"ARMO_TEST_NAME","value":"auto_attach_deployment"},{"name":"CAA_ENABLE_CRASH_REPORTER","value":"1"}],"image":"quay.io/armosec/demoservice:v25","imagePullPolicy":"IfNotPresent","name":"demoservice","ports":[{"containerPort":8089,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}},"status":{"availableReplicas":1,"conditions":[{"lastTransitionTime":"2021-05-03T13:10:32Z","lastUpdateTime":"2021-05-03T13:10:37Z","message":"ReplicaSet \"demoservice-server-7d478b6998\" has successfully progressed.","reason":"NewReplicaSetAvailable","status":"True","type":"Progressing"},{"lastTransitionTime":"2021-05-03T13:52:58Z","lastUpdateTime":"2021-05-03T13:52:58Z","message":"Deployment has minimum availability.","reason":"MinimumReplicasAvailable","status":"True","type":"Available"}],"observedGeneration":1,"readyReplicas":1,"replicas":1,"updatedReplicas":1}}`
|
||||
workload, err := NewWorkload([]byte(w))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
workload.SetWlid("wlid://bla")
|
||||
// t.Errorf(workload.Json())
|
||||
|
||||
}
|
||||
|
||||
func TestGetResourceVersion(t *testing.T) {
|
||||
w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"deployment.kubernetes.io/revision":"1"},"creationTimestamp":"2021-05-03T13:10:32Z","generation":1,"managedFields":[{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{".":{},"f:app":{},"f:cyberarmor.inject":{}}},"f:spec":{"f:progressDeadlineSeconds":{},"f:replicas":{},"f:revisionHistoryLimit":{},"f:selector":{},"f:strategy":{"f:rollingUpdate":{".":{},"f:maxSurge":{},"f:maxUnavailable":{}},"f:type":{}},"f:template":{"f:metadata":{"f:labels":{".":{},"f:app":{}}},"f:spec":{"f:containers":{"k:{\"name\":\"demoservice\"}":{".":{},"f:env":{".":{},"k:{\"name\":\"ARMO_TEST_NAME\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"CAA_ENABLE_CRASH_REPORTER\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"DEMO_FOLDERS\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SERVER_PORT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SLEEP_DURATION\"}":{".":{},"f:name":{},"f:value":{}}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":8089,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}},"manager":"OpenAPI-Generator","operation":"Update","time":"2021-05-03T13:10:32Z"},{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:deployment.kubernetes.io/revision":{}}},"f:status":{"f:availableReplicas":{},"f:conditions":{".":{},"k:{\"type\":\"Available\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Progressing\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:observedGeneration":{},"f:readyReplicas":{},"f:replicas":{},"f:updatedReplicas":{}}},"manager":"kube-controller-manager","operation":"Update","time":"2021-05-03T13:52:58Z"}],"name":"demoservice-server","namespace":"default","resourceVersion":"1016043","uid":"e9e8a3e9-6cb4-4301-ace1-2c0cef3bd61e"},"spec":{"progressDeadlineSeconds":600,"replicas":1,"revisionHistoryLimit":10,"selector":{"matchLabels":{"app":"demoservice-server"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"demoservice-server"}},"spec":{"containers":[{"env":[{"name":"SERVER_PORT","value":"8089"},{"name":"SLEEP_DURATION","value":"1"},{"name":"DEMO_FOLDERS","value":"/app"},{"name":"ARMO_TEST_NAME","value":"auto_attach_deployment"},{"name":"CAA_ENABLE_CRASH_REPORTER","value":"1"}],"image":"quay.io/armosec/demoservice:v25","imagePullPolicy":"IfNotPresent","name":"demoservice","ports":[{"containerPort":8089,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}},"status":{"availableReplicas":1,"conditions":[{"lastTransitionTime":"2021-05-03T13:10:32Z","lastUpdateTime":"2021-05-03T13:10:37Z","message":"ReplicaSet \"demoservice-server-7d478b6998\" has successfully progressed.","reason":"NewReplicaSetAvailable","status":"True","type":"Progressing"},{"lastTransitionTime":"2021-05-03T13:52:58Z","lastUpdateTime":"2021-05-03T13:52:58Z","message":"Deployment has minimum availability.","reason":"MinimumReplicasAvailable","status":"True","type":"Available"}],"observedGeneration":1,"readyReplicas":1,"replicas":1,"updatedReplicas":1}}`
|
||||
workload, err := NewWorkload([]byte(w))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
if workload.GetResourceVersion() != "1016043" {
|
||||
t.Errorf("wrong resourceVersion")
|
||||
}
|
||||
|
||||
}
|
||||
func TestGetUID(t *testing.T) {
|
||||
w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"deployment.kubernetes.io/revision":"1"},"creationTimestamp":"2021-05-03T13:10:32Z","generation":1,"managedFields":[{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{".":{},"f:app":{},"f:cyberarmor.inject":{}}},"f:spec":{"f:progressDeadlineSeconds":{},"f:replicas":{},"f:revisionHistoryLimit":{},"f:selector":{},"f:strategy":{"f:rollingUpdate":{".":{},"f:maxSurge":{},"f:maxUnavailable":{}},"f:type":{}},"f:template":{"f:metadata":{"f:labels":{".":{},"f:app":{}}},"f:spec":{"f:containers":{"k:{\"name\":\"demoservice\"}":{".":{},"f:env":{".":{},"k:{\"name\":\"ARMO_TEST_NAME\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"CAA_ENABLE_CRASH_REPORTER\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"DEMO_FOLDERS\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SERVER_PORT\"}":{".":{},"f:name":{},"f:value":{}},"k:{\"name\":\"SLEEP_DURATION\"}":{".":{},"f:name":{},"f:value":{}}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":8089,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}},"manager":"OpenAPI-Generator","operation":"Update","time":"2021-05-03T13:10:32Z"},{"apiVersion":"apps/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:deployment.kubernetes.io/revision":{}}},"f:status":{"f:availableReplicas":{},"f:conditions":{".":{},"k:{\"type\":\"Available\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}},"k:{\"type\":\"Progressing\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:reason":{},"f:status":{},"f:type":{}}},"f:observedGeneration":{},"f:readyReplicas":{},"f:replicas":{},"f:updatedReplicas":{}}},"manager":"kube-controller-manager","operation":"Update","time":"2021-05-03T13:52:58Z"}],"name":"demoservice-server","namespace":"default","resourceVersion":"1016043","uid":"e9e8a3e9-6cb4-4301-ace1-2c0cef3bd61e"},"spec":{"progressDeadlineSeconds":600,"replicas":1,"revisionHistoryLimit":10,"selector":{"matchLabels":{"app":"demoservice-server"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"demoservice-server"}},"spec":{"containers":[{"env":[{"name":"SERVER_PORT","value":"8089"},{"name":"SLEEP_DURATION","value":"1"},{"name":"DEMO_FOLDERS","value":"/app"},{"name":"ARMO_TEST_NAME","value":"auto_attach_deployment"},{"name":"CAA_ENABLE_CRASH_REPORTER","value":"1"}],"image":"quay.io/armosec/demoservice:v25","imagePullPolicy":"IfNotPresent","name":"demoservice","ports":[{"containerPort":8089,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}},"status":{"availableReplicas":1,"conditions":[{"lastTransitionTime":"2021-05-03T13:10:32Z","lastUpdateTime":"2021-05-03T13:10:37Z","message":"ReplicaSet \"demoservice-server-7d478b6998\" has successfully progressed.","reason":"NewReplicaSetAvailable","status":"True","type":"Progressing"},{"lastTransitionTime":"2021-05-03T13:52:58Z","lastUpdateTime":"2021-05-03T13:52:58Z","message":"Deployment has minimum availability.","reason":"MinimumReplicasAvailable","status":"True","type":"Available"}],"observedGeneration":1,"readyReplicas":1,"replicas":1,"updatedReplicas":1}}`
|
||||
workload, err := NewWorkload([]byte(w))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
if workload.GetUID() != "e9e8a3e9-6cb4-4301-ace1-2c0cef3bd61e" {
|
||||
t.Errorf("wrong UID")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIsAttached(t *testing.T) {
|
||||
w := `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"deployment.kubernetes.io/revision":"3"},"creationTimestamp":"2021-06-21T04:52:05Z","generation":3,"name":"emailservice","namespace":"default"},"spec":{"progressDeadlineSeconds":600,"replicas":1,"revisionHistoryLimit":10,"selector":{"matchLabels":{"app":"emailservice"}},"strategy":{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"25%"},"type":"RollingUpdate"},"template":{"metadata":{"annotations":{"armo.last-update":"21-06-2021 06:40:42","armo.wlid":"wlid://cluster-david-demo/namespace-default/deployment-emailservice"},"creationTimestamp":null,"labels":{"app":"emailservice","armo.attach":"true"}},"spec":{"containers":[{"env":[{"name":"PORT","value":"8080"},{"name":"DISABLE_PROFILER","value":"1"}],"image":"gcr.io/google-samples/microservices-demo/emailservice:v0.2.3","imagePullPolicy":"IfNotPresent","livenessProbe":{"exec":{"command":["/bin/grpc_health_probe","-addr=:8080"]},"failureThreshold":3,"periodSeconds":5,"successThreshold":1,"timeoutSeconds":1},"name":"server","ports":[{"containerPort":8080,"protocol":"TCP"}],"readinessProbe":{"exec":{"command":["/bin/grpc_health_probe","-addr=:8080"]},"failureThreshold":3,"periodSeconds":5,"successThreshold":1,"timeoutSeconds":1},"resources":{"limits":{"cpu":"200m","memory":"128Mi"},"requests":{"cpu":"100m","memory":"64Mi"}},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"serviceAccount":"default","serviceAccountName":"default","terminationGracePeriodSeconds":5}}}}`
|
||||
workload, err := NewWorkload([]byte(w))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
if !workload.IsAttached() {
|
||||
t.Errorf("expected attached")
|
||||
}
|
||||
|
||||
}
|
||||
23
vendor/github.com/armosec/capacketsgo/k8sinterface/workloadmethodsutils.go
generated
vendored
23
vendor/github.com/armosec/capacketsgo/k8sinterface/workloadmethodsutils.go
generated
vendored
@@ -1,23 +0,0 @@
|
||||
package k8sinterface
|
||||
|
||||
func PodSpec(kind string) []string {
|
||||
switch kind {
|
||||
case "Pod", "Namespace":
|
||||
return []string{"spec"}
|
||||
case "CronJob":
|
||||
return []string{"spec", "jobTemplate", "spec", "template", "spec"}
|
||||
default:
|
||||
return []string{"spec", "template", "spec"}
|
||||
}
|
||||
}
|
||||
|
||||
func PodMetadata(kind string) []string {
|
||||
switch kind {
|
||||
case "Pod", "Namespace", "Secret":
|
||||
return []string{"metadata"}
|
||||
case "CronJob":
|
||||
return []string{"spec", "jobTemplate", "spec", "template", "metadata"}
|
||||
default:
|
||||
return []string{"spec", "template", "metadata"}
|
||||
}
|
||||
}
|
||||
1
vendor/github.com/armosec/capacketsgo/k8sshared/README.md
generated
vendored
1
vendor/github.com/armosec/capacketsgo/k8sshared/README.md
generated
vendored
@@ -1 +0,0 @@
|
||||
hold all shared k8s wrappers or k8s related utilities that are shared across projects
|
||||
59
vendor/github.com/armosec/capacketsgo/k8sshared/gojayunmarshaller.go
generated
vendored
59
vendor/github.com/armosec/capacketsgo/k8sshared/gojayunmarshaller.go
generated
vendored
@@ -1,59 +0,0 @@
|
||||
package k8sshared
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/francoispqt/gojay"
|
||||
)
|
||||
|
||||
// CAClusterName string `json:"caClusterName"`
|
||||
// CANamespace string `json:"caNamespace"`
|
||||
// Event json.RawMessage `json:"k8sV1Event"`
|
||||
|
||||
// UnmarshalJSONObject - File inside a pkg
|
||||
func (l *K8sAuditLog) UnmarshalJSONObject(dec *gojay.Decoder, key string) (err error) {
|
||||
|
||||
switch key {
|
||||
case "caClusterName":
|
||||
err = dec.String(&(l.CAClusterName))
|
||||
|
||||
case "caNamespace":
|
||||
err = dec.String(&(l.CANamespace))
|
||||
|
||||
case "k8sV1Event":
|
||||
var tmp gojay.EmbeddedJSON
|
||||
|
||||
if err = dec.AddEmbeddedJSON(&tmp); err != nil {
|
||||
return fmt.Errorf("failed to UnmarshalJSONObject k8sV1Event, error: %v", err)
|
||||
}
|
||||
l.Event = []byte(tmp)
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func (logs *K8sAuditLogs) UnmarshalJSONArray(dec *gojay.Decoder) error {
|
||||
lae := K8sAuditLog{}
|
||||
if err := dec.Object(&lae); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*logs = append(*logs, lae)
|
||||
return nil
|
||||
}
|
||||
|
||||
// func (logs []K8sAuditLog) UnmarshalJSONArray(dec *gojay.Decoder) error {
|
||||
// lae := K8sAuditLog{}
|
||||
// if err := dec.Object(&lae); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// logs = append(logs, lae)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (file *K8sAuditLog) NKeys() int {
|
||||
return 0
|
||||
}
|
||||
51
vendor/github.com/armosec/capacketsgo/k8sshared/k8sshared_mock.go
generated
vendored
51
vendor/github.com/armosec/capacketsgo/k8sshared/k8sshared_mock.go
generated
vendored
@@ -1,51 +0,0 @@
|
||||
package k8sshared
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
audit "k8s.io/apiserver/pkg/apis/audit"
|
||||
)
|
||||
|
||||
func GetEventAuditMockAsString() string {
|
||||
return `{
|
||||
"kind": "Event",
|
||||
"apiVersion": "audit.k8s.io/v1",
|
||||
"level": "Metadata",
|
||||
"auditID": "1847e1e1-d66b-4661-b458-4dc553cd8539",
|
||||
"stage": "ResponseComplete",
|
||||
"requestURI": "/apis/storage.k8s.io/v1?timeout=32s",
|
||||
"verb": "get",
|
||||
"user": {
|
||||
"username": "system:serviceaccount:kube-system:generic-garbage-collector",
|
||||
"uid": "83093a4c-3f5f-433e-8fd4-4a2cc23eead8",
|
||||
"groups": [
|
||||
"system:serviceaccounts",
|
||||
"system:serviceaccounts:kube-system",
|
||||
"system:authenticated"
|
||||
]
|
||||
},
|
||||
"sourceIPs": [
|
||||
"192.168.49.2"
|
||||
],
|
||||
"userAgent": "kube-controller-manager/v1.20.0 (linux/amd64) kubernetes/af46c47/system:serviceaccount:kube-system:generic-garbage-collector",
|
||||
"responseStatus": {
|
||||
"metadata": {},
|
||||
"code": 200
|
||||
},
|
||||
"requestReceivedTimestamp": "2021-02-18T08:28:43.237861Z",
|
||||
"stageTimestamp": "2021-02-18T08:28:43.238551Z",
|
||||
"annotations": {
|
||||
"authentication.k8s.io/legacy-token": "system:serviceaccount:kube-system:generic-garbage-collector",
|
||||
"authorization.k8s.io/decision": "allow",
|
||||
"authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding \"system:discovery\" of ClusterRole \"system:discovery\" to Group \"system:authenticated\""
|
||||
}
|
||||
}`
|
||||
}
|
||||
|
||||
func GetK8sAuditEventMock() (audit.Event, error) {
|
||||
tmp := audit.Event{}
|
||||
a := []byte(GetEventAuditMockAsString())
|
||||
err := json.Unmarshal(a, &tmp)
|
||||
|
||||
return tmp, err
|
||||
}
|
||||
44
vendor/github.com/armosec/capacketsgo/k8sshared/k8sshared_test.go
generated
vendored
44
vendor/github.com/armosec/capacketsgo/k8sshared/k8sshared_test.go
generated
vendored
@@ -1,44 +0,0 @@
|
||||
package k8sshared
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/armosec/capacketsgo/cautils"
|
||||
)
|
||||
|
||||
func TestAuditStructure(t *testing.T) {
|
||||
auditRAW, err := GetK8sAuditEventMock()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("failed to get unmarshald mock %v", err.Error())
|
||||
}
|
||||
|
||||
audit, err := Newk8sAuditLog("testcluster", "", &auditRAW)
|
||||
if err != nil {
|
||||
t.Errorf("failed to create ca-k8s-audit object due to : %v", err.Error())
|
||||
}
|
||||
|
||||
res, err := json.Marshal(audit)
|
||||
if err != nil {
|
||||
t.Errorf("failed to get marshal audit wrapper %v", err.Error())
|
||||
}
|
||||
|
||||
fmt.Printf("\n\nres: %v\n\n", string(res))
|
||||
|
||||
audit2 := K8sAuditLog{}
|
||||
|
||||
json.Unmarshal(res, &audit2)
|
||||
|
||||
if cautils.AsSHA256(audit2) != cautils.AsSHA256(*audit) {
|
||||
t.Errorf("failed to get umarshal(marshal audit wrapper)\n========audit2=======\n%v\n\noriginal:\n:%v", audit2, audit)
|
||||
}
|
||||
|
||||
auditRAW2 := audit2.GetRawK8sEvent()
|
||||
|
||||
if cautils.AsSHA256(*auditRAW2) != cautils.AsSHA256(auditRAW) {
|
||||
t.Errorf("failed to get raw audit is different from k8s original audit:\nreplacement:\n%v\n\noriginal: %v", *auditRAW2, auditRAW)
|
||||
}
|
||||
|
||||
}
|
||||
5
vendor/github.com/armosec/capacketsgo/k8sshared/prefixs.go
generated
vendored
5
vendor/github.com/armosec/capacketsgo/k8sshared/prefixs.go
generated
vendored
@@ -1,5 +0,0 @@
|
||||
package k8sshared
|
||||
|
||||
const (
|
||||
K8sAuditLogPrefix = "_k8sAuditLogs"
|
||||
)
|
||||
25
vendor/github.com/armosec/capacketsgo/k8sshared/probes/readinessprobe.go
generated
vendored
25
vendor/github.com/armosec/capacketsgo/k8sshared/probes/readinessprobe.go
generated
vendored
@@ -1,25 +0,0 @@
|
||||
package probes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// server initialization
|
||||
const (
|
||||
ReadinessPath = "readiness"
|
||||
ReadinessPort = "8000"
|
||||
)
|
||||
|
||||
// InitReadinessV1 initialize readiness handler
|
||||
func InitReadinessV1(isReadinessReady *bool) {
|
||||
http.HandleFunc(fmt.Sprintf("/v1/%s", ReadinessPath), func(w http.ResponseWriter, _ *http.Request) {
|
||||
if *isReadinessReady {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
}
|
||||
},
|
||||
)
|
||||
http.ListenAndServe(":8000", nil)
|
||||
}
|
||||
41
vendor/github.com/armosec/capacketsgo/k8sshared/wrappers.go
generated
vendored
41
vendor/github.com/armosec/capacketsgo/k8sshared/wrappers.go
generated
vendored
@@ -1,41 +0,0 @@
|
||||
package k8sshared
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
k8saudit "k8s.io/apiserver/pkg/apis/audit"
|
||||
)
|
||||
|
||||
// K8sAuditLog - ARMO audit event wrapper
|
||||
type K8sAuditLog struct {
|
||||
CAClusterName string `json:"caClusterName"`
|
||||
CANamespace string `json:"caNamespace"`
|
||||
Event json.RawMessage `json:"k8sV1Event"`
|
||||
}
|
||||
|
||||
//K8sAuditLogs - slice of K8sAuditLog
|
||||
type K8sAuditLogs []K8sAuditLog
|
||||
|
||||
func (v *K8sAuditLog) Validate() bool {
|
||||
return len(v.CAClusterName) > 0
|
||||
}
|
||||
|
||||
func (v *K8sAuditLog) GetRawK8sEvent() *k8saudit.Event {
|
||||
tmp := &k8saudit.Event{}
|
||||
|
||||
json.Unmarshal(v.Event, &tmp)
|
||||
return tmp
|
||||
}
|
||||
|
||||
func Newk8sAuditLog(cluster, namespace string, auditRAW *k8saudit.Event) (*K8sAuditLog, error) {
|
||||
|
||||
audit := &K8sAuditLog{CAClusterName: cluster, CANamespace: namespace}
|
||||
b, err := json.Marshal(*auditRAW)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal audit event, reason: %s", err.Error())
|
||||
}
|
||||
audit.Event = b
|
||||
|
||||
return audit, nil
|
||||
}
|
||||
18
vendor/github.com/armosec/capacketsgo/notificationserver/apis.go
generated
vendored
18
vendor/github.com/armosec/capacketsgo/notificationserver/apis.go
generated
vendored
@@ -1,18 +0,0 @@
|
||||
package notificationserver
|
||||
|
||||
// server paths
|
||||
const (
|
||||
PathWebsocketV1 = "/v1/waitfornotification"
|
||||
PathRESTV1 = "/v1/sendnotification"
|
||||
)
|
||||
|
||||
const (
|
||||
TargetCustomer = "customerGUID"
|
||||
TargetCluster = "clusterName"
|
||||
TargetComponent = "clusterComponent"
|
||||
)
|
||||
|
||||
const (
|
||||
TargetComponentPostureValue = "PolicyValidator"
|
||||
TargetComponentLoggerValue = "Logger"
|
||||
)
|
||||
8
vendor/github.com/armosec/capacketsgo/notificationserver/datastructures.go
generated
vendored
8
vendor/github.com/armosec/capacketsgo/notificationserver/datastructures.go
generated
vendored
@@ -1,8 +0,0 @@
|
||||
package notificationserver
|
||||
|
||||
// Notification passed between servers
|
||||
type Notification struct {
|
||||
Target map[string]string `json:"target"`
|
||||
SendSynchronicity bool `json:"sendSynchronicity"`
|
||||
Notification interface{} `json:"notification"`
|
||||
}
|
||||
12
vendor/github.com/armosec/capacketsgo/notificationserver/datastructures_mock.go
generated
vendored
12
vendor/github.com/armosec/capacketsgo/notificationserver/datastructures_mock.go
generated
vendored
@@ -1,12 +0,0 @@
|
||||
package notificationserver
|
||||
|
||||
func MockNotificationA() *Notification {
|
||||
return &Notification{
|
||||
Target: map[string]string{
|
||||
TargetCluster: "",
|
||||
TargetCustomer: "",
|
||||
TargetComponent: TargetComponentPostureValue,
|
||||
},
|
||||
Notification: nil,
|
||||
}
|
||||
}
|
||||
105
vendor/github.com/armosec/capacketsgo/notificationserver/edge.go
generated
vendored
105
vendor/github.com/armosec/capacketsgo/notificationserver/edge.go
generated
vendored
@@ -1,105 +0,0 @@
|
||||
package notificationserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
// PushNotificationServer push notification to rest api server. if jsonFormat is set to false, will Marshal useing bson
|
||||
func PushNotificationServer(edgeURL string, targetMap map[string]string, message interface{}, jsonFormat bool) error {
|
||||
var err error
|
||||
|
||||
glog.Infof("Pushing notification to: '%s'", edgeURL)
|
||||
|
||||
// setup notification
|
||||
notf, err := setNotification(targetMap, message, jsonFormat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// push notification
|
||||
client := http.Client{}
|
||||
for i := 0; i < 3; i++ {
|
||||
if err = sendCommandToEdge(&client, edgeURL, notf); err == nil {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
err = fmt.Errorf("error sending url: '%s', reason: %s", edgeURL, err.Error())
|
||||
}
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
// sendCommandToEdge sends the HTTP request
|
||||
func sendCommandToEdge(client *http.Client, edgeURL string, message []byte) error {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
glog.Errorf("In sendCommandToEdge, recover, reason: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
req, err := http.NewRequest("POST", edgeURL, bytes.NewReader(message))
|
||||
req.Close = true
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to SendCommandToCluster, url: %s, data: %s, reason: %s", edgeURL, string(message), err.Error())
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to SendCommandToCluster, url: %s, data: %s, reason: %s", edgeURL, string(message), err.Error())
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
respStr, err := httpRespToString(resp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to SendCommandToCluster, url: %s, data: %s, reason: %s, response: %s", edgeURL, string(message), err.Error(), respStr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setNotification(targetMap map[string]string, message interface{}, jsonFormat bool) ([]byte, error) {
|
||||
notification := Notification{
|
||||
Target: targetMap,
|
||||
Notification: message,
|
||||
}
|
||||
|
||||
var err error
|
||||
var m []byte
|
||||
if jsonFormat {
|
||||
if m, err = json.Marshal(notification); err != nil {
|
||||
err = fmt.Errorf("failed marshling message to bson. message: '%v', reason: '%s'", notification, err.Error())
|
||||
}
|
||||
} else {
|
||||
|
||||
if m, err = bson.Marshal(notification); err != nil {
|
||||
err = fmt.Errorf("failed marshling message to bson. message: '%v', reason: '%s'", notification, err.Error())
|
||||
}
|
||||
}
|
||||
return m, err
|
||||
}
|
||||
|
||||
// HTTPRespToString parses the body as string and checks the HTTP status code
|
||||
func httpRespToString(resp *http.Response) (string, error) {
|
||||
if resp == nil {
|
||||
return "", fmt.Errorf("empty response")
|
||||
}
|
||||
strBuilder := strings.Builder{}
|
||||
if resp.ContentLength > 0 {
|
||||
strBuilder.Grow(int(resp.ContentLength))
|
||||
}
|
||||
_, err := io.Copy(&strBuilder, resp.Body)
|
||||
if err != nil {
|
||||
return strBuilder.String(), err
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
err = fmt.Errorf("Response status: %d. content: %s", resp.StatusCode, strBuilder.String())
|
||||
}
|
||||
return strBuilder.String(), err
|
||||
}
|
||||
58
vendor/github.com/armosec/capacketsgo/ocimage/oaimageapiutils.go
generated
vendored
58
vendor/github.com/armosec/capacketsgo/ocimage/oaimageapiutils.go
generated
vendored
@@ -1,58 +0,0 @@
|
||||
package ocimage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// URLEncoder encode url
|
||||
func URLEncoder(oldURL string) string {
|
||||
fullURL := strings.Split(oldURL, "?")
|
||||
baseURL, err := url.Parse(fullURL[0])
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Prepare Query Parameters
|
||||
if len(fullURL) > 1 {
|
||||
params := url.Values{}
|
||||
queryParams := strings.Split(fullURL[1], "&")
|
||||
for _, i := range queryParams {
|
||||
queryParam := strings.Split(i, "=")
|
||||
val := ""
|
||||
if len(queryParam) > 1 {
|
||||
val = queryParam[1]
|
||||
}
|
||||
params.Add(queryParam[0], val)
|
||||
}
|
||||
baseURL.RawQuery = params.Encode()
|
||||
}
|
||||
|
||||
return baseURL.String()
|
||||
}
|
||||
|
||||
// GetSecuredImageID - gets imagename+tag or with full repo, secrets map and returns the imageid
|
||||
func (ocimg *OCImage) GetSecuredImageID(imageName string, secrets map[string]types.AuthConfig) (string, error) {
|
||||
glog.Infof("trying to get Img: %v using secrets", imageName)
|
||||
|
||||
for secretName, regAuth := range secrets {
|
||||
// If server address is known, then try pulling image based on sever address, otherwise try using all secretes
|
||||
if regAuth.ServerAddress == "" || strings.HasPrefix(imageName, regAuth.ServerAddress) {
|
||||
glog.Infof("Pulling image '%s' using '%s' secret", imageName, secretName)
|
||||
|
||||
// Pulling image with credentials
|
||||
imageid, err := ocimg.GetImage(imageName, regAuth.Username, regAuth.Password)
|
||||
if err == nil {
|
||||
glog.Infof("Pulling image '%s' using secret succeeded, image id: %s", imageName, imageid)
|
||||
return imageid, nil
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("failed to pull image '%s' using secrets, secrets: '%v'", imageName, secrets)
|
||||
}
|
||||
109
vendor/github.com/armosec/capacketsgo/ocimage/ocimage_test.go
generated
vendored
109
vendor/github.com/armosec/capacketsgo/ocimage/ocimage_test.go
generated
vendored
@@ -1,109 +0,0 @@
|
||||
package ocimage
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "io"
|
||||
// "os"
|
||||
// "testing"
|
||||
// )
|
||||
|
||||
// func base(img, usr, pass string) (*OCImage, string, error) {
|
||||
// baseURL := "http://10.107.26.199:8080"
|
||||
// oci := MakeOCImage(baseURL)
|
||||
// imgid, err := oci.GetImage(img, usr, pass)
|
||||
|
||||
// return oci, imgid, err
|
||||
// }
|
||||
// func TestGetSingleFile(t *testing.T) {
|
||||
// fmt.Printf("do nothing")
|
||||
// oci, imgid, err := base("nginx:latest", "", "")
|
||||
// if err != nil {
|
||||
// t.Errorf("can't get image ")
|
||||
// }
|
||||
// os, s, err := oci.GetSingleFile(imgid, "/etc/os-release", true)
|
||||
// if err != nil {
|
||||
// t.Errorf("couldnt get file %s", err.Error())
|
||||
// }
|
||||
// fmt.Printf("file content: %s\n%s\n", string(os), s)
|
||||
// t.Errorf("f")
|
||||
// }
|
||||
|
||||
// func TestManifest(t *testing.T) {
|
||||
// fmt.Printf("do nothing")
|
||||
// oci, imgid, err := base("nginx:latest", "", "")
|
||||
// if err != nil {
|
||||
// t.Errorf("can't get image ")
|
||||
// }
|
||||
// manifest, err := oci.GetManifest(imgid)
|
||||
// if err != nil {
|
||||
// t.Errorf("couldnt get file %s", err.Error())
|
||||
// }
|
||||
// fmt.Printf("manifest content: %v\n\n", manifest)
|
||||
// t.Errorf("f")
|
||||
// }
|
||||
|
||||
// //gets 404 when no files are found
|
||||
// func TestMultipleFilesNonExisting(t *testing.T) {
|
||||
// fmt.Printf("do nothing")
|
||||
// oci, imgid, err := base("nginx:latest", "", "")
|
||||
// if err != nil {
|
||||
// t.Errorf("can't get image ")
|
||||
// }
|
||||
// filestar, err := oci.GetMultipleFiles(imgid, []string{"/ethhhc/os-release", "ngjjjinx"}, true, false)
|
||||
// if err != nil {
|
||||
// t.Errorf("couldnt get file %s", err.Error())
|
||||
// return
|
||||
// }
|
||||
|
||||
// for {
|
||||
// tarHdr, err := filestar.Next()
|
||||
// if err == io.EOF {
|
||||
// break
|
||||
// }
|
||||
// if err != nil {
|
||||
// t.Errorf("error: %s", err.Error())
|
||||
// continue
|
||||
// }
|
||||
|
||||
// fmt.Printf("Contents of %s:\n", tarHdr.Name)
|
||||
// if _, err := io.Copy(os.Stdout, filestar); err != nil {
|
||||
// t.Errorf("error: %s", err.Error())
|
||||
// }
|
||||
// fmt.Printf("%v\n", tarHdr)
|
||||
// }
|
||||
|
||||
// t.Errorf("f")
|
||||
// }
|
||||
|
||||
// //gets Symlink mapper as usual (missing files has no key)
|
||||
// func TestMultipleFilesPartialExisting(t *testing.T) {
|
||||
// fmt.Printf("do nothing")
|
||||
// oci, imgid, err := base("nginx:latest", "", "")
|
||||
// if err != nil {
|
||||
// t.Errorf("can't get image ")
|
||||
// }
|
||||
// filestar, err := oci.GetMultipleFiles(imgid, []string{"/etc/os-release", "ngjjjinx"}, true, false)
|
||||
// if err != nil {
|
||||
// t.Errorf("couldnt get file %s", err.Error())
|
||||
// return
|
||||
// }
|
||||
|
||||
// for {
|
||||
// tarHdr, err := filestar.Next()
|
||||
// if err == io.EOF {
|
||||
// break
|
||||
// }
|
||||
// if err != nil {
|
||||
// t.Errorf("error: %s", err.Error())
|
||||
// continue
|
||||
// }
|
||||
|
||||
// fmt.Printf("Contents of %s:\n", tarHdr.Name)
|
||||
// if _, err := io.Copy(os.Stdout, filestar); err != nil {
|
||||
// t.Errorf("error: %s", err.Error())
|
||||
// }
|
||||
// fmt.Printf("%v\n", tarHdr)
|
||||
// }
|
||||
|
||||
// t.Errorf("f")
|
||||
// }
|
||||
284
vendor/github.com/armosec/capacketsgo/ocimage/ocimageapi.go
generated
vendored
284
vendor/github.com/armosec/capacketsgo/ocimage/ocimageapi.go
generated
vendored
@@ -1,284 +0,0 @@
|
||||
package ocimage
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
var MAX_RETRIES int = 3
|
||||
|
||||
// IOCImage - ocimage interface - https://asterix.cyberarmor.io/cyberarmor/ocimage
|
||||
type IOCImage interface {
|
||||
GetImage(imageTag, user, password string) (string, error)
|
||||
GetSingleFile(fileName string, followSymLink bool) ([]byte, string, error)
|
||||
GetMultipleFiles(fileNames []string, followSymLink, doesExist bool) ([]byte, error)
|
||||
GetClient() *http.Client
|
||||
FileList(imageid string, dir string, from int, to int, recursive bool, noDir bool) ([]FileMetadata, error)
|
||||
Describe(imageID string) (*ImageMetadata, error)
|
||||
}
|
||||
|
||||
// OCImage - structure, holds url and api version
|
||||
type OCImage struct {
|
||||
url string
|
||||
apiVer string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func (oci *OCImage) GetClient() *http.Client {
|
||||
return oci.client
|
||||
}
|
||||
|
||||
// Init - init
|
||||
func MakeOCImage(ociURL string) *OCImage {
|
||||
oci := &OCImage{url: ociURL, apiVer: "v1", client: &http.Client{}}
|
||||
|
||||
return oci
|
||||
}
|
||||
|
||||
func (oci *OCImage) GetManifest(imageid string) (*OciImageManifest, error) {
|
||||
|
||||
newurl := fmt.Sprintf("%s/%s/images/id/%s/manifest", oci.url, oci.apiVer, imageid)
|
||||
req, _ := http.NewRequest("GET", newurl, nil)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := oci.GetClient().Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting manifest for imageid: %s failed due to: %s", imageid, err.Error())
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return nil, fmt.Errorf("getting manifest for imageid: %s failed due to: status code %v %v", imageid, resp.StatusCode, resp.Status)
|
||||
}
|
||||
jsonRaw, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
manifest := OciImageManifest{}
|
||||
if err := json.Unmarshal(jsonRaw, &manifest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &manifest, nil
|
||||
}
|
||||
|
||||
// GetImage -
|
||||
func (oci *OCImage) GetImage(imageTag, user, password string) (string, error) {
|
||||
newurl := oci.url + "/" + oci.apiVer + "/images/id"
|
||||
values := map[string]string{"image": imageTag}
|
||||
|
||||
if len(user) != 0 && len(password) != 0 {
|
||||
values["username"] = user
|
||||
values["password"] = password
|
||||
}
|
||||
|
||||
jsonValue, err := json.Marshal(values)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to marshal getImage request, reason: %s", err.Error())
|
||||
}
|
||||
glog.Infof("OCI GetImage, url: '%s'", newurl)
|
||||
for i := 0; i < MAX_RETRIES; i++ {
|
||||
resp, err := http.Post(newurl, "application/json", bytes.NewBuffer(jsonValue))
|
||||
if err != nil {
|
||||
glog.Infof("In GetImage oci, url: '%s', failed. retry: %d, reason: %s", newurl, i, err.Error())
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
bodyString := string(body)
|
||||
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
||||
return bodyString, nil
|
||||
} else {
|
||||
glog.Errorf("requesting: %v - will retry error (%s): %s", newurl, resp.Status, bodyString)
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("request '%s' failed, reason: max retries exceeded", newurl)
|
||||
}
|
||||
|
||||
// FileList - ls = the containerized version
|
||||
func (oci *OCImage) FileList(imageid string, dir string, from int, to int, recursive bool, noDir bool) ([]FileMetadata, error) {
|
||||
newurl := oci.url + "/" + oci.apiVer + "/images/id/" + imageid + "/list"
|
||||
fmt.Printf("%v %v %v %v %v %v $v", newurl, dir, from, to, recursive, noDir)
|
||||
var slashwrist []FileMetadata
|
||||
|
||||
req, _ := http.NewRequest("GET", newurl, nil)
|
||||
req.Header.Add("Accept", "application/json")
|
||||
q := req.URL.Query()
|
||||
if len(dir) > 0 {
|
||||
q.Add("dir", dir)
|
||||
}
|
||||
if from < to || to == -1 {
|
||||
fromstr := strconv.Itoa(from)
|
||||
tostr := strconv.Itoa(to)
|
||||
q.Add("from", fromstr)
|
||||
q.Add("to", tostr)
|
||||
}
|
||||
|
||||
q.Add("recursive", strconv.FormatBool(recursive))
|
||||
q.Add("no_dir", strconv.FormatBool(noDir))
|
||||
req.URL.RawQuery = q.Encode()
|
||||
|
||||
glog.Infof("OCI FileList, url: '%s'", req.URL.String())
|
||||
|
||||
for i := 0; i < MAX_RETRIES; i++ {
|
||||
resp, err := oci.GetClient().Do(req)
|
||||
|
||||
if err != nil {
|
||||
glog.Errorf("requesting: %v - will retry error: %v", newurl, err.Error())
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if respBody, err := ioutil.ReadAll(resp.Body); err == nil {
|
||||
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
||||
if err := json.Unmarshal(respBody, &slashwrist); err != nil {
|
||||
return slashwrist, fmt.Errorf("failed to marshal fileList response, reason: %s", err.Error())
|
||||
}
|
||||
return slashwrist, nil
|
||||
} else {
|
||||
glog.Errorf("requesting: %v - will retry error (%s): %s", newurl, resp.Status, respBody)
|
||||
}
|
||||
} else {
|
||||
glog.Errorf("requesting: %v - will retry error: %v", newurl, err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
return nil, fmt.Errorf("request '%s' failed, reason: max retries exceeded", newurl)
|
||||
|
||||
}
|
||||
|
||||
// Describe -
|
||||
func (oci *OCImage) Describe(imageid string) (ImageMetadata, error) {
|
||||
newurl := oci.url + "/" + oci.apiVer + "/images/id/" + imageid
|
||||
glog.Infof("OCI Describe, url: '%s'", newurl)
|
||||
|
||||
var slashwrist ImageMetadata
|
||||
|
||||
req, _ := http.NewRequest("GET", newurl, nil)
|
||||
req.Header.Add("Accept", "application/json")
|
||||
for i := 0; i < MAX_RETRIES; i++ {
|
||||
resp, err := oci.GetClient().Do(req)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
if respBody, err := ioutil.ReadAll(resp.Body); err == nil {
|
||||
if err := json.Unmarshal(respBody, &slashwrist); err != nil {
|
||||
return slashwrist, fmt.Errorf("failed to unmarshal describe response, reason: %s", err.Error())
|
||||
}
|
||||
return slashwrist, nil
|
||||
} else {
|
||||
glog.Errorf("requesting: %s - will retry error: %v", newurl, err.Error())
|
||||
}
|
||||
} else {
|
||||
glog.Errorf("requesting: %s - will retry error: %v", newurl, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return slashwrist, fmt.Errorf("request '%s' failed, reason: max retries exceeded", newurl)
|
||||
|
||||
}
|
||||
|
||||
func (oci *OCImage) GetMultipleFiles(imageid string, fileNames []string, followSymLink, doesExist bool) (*tar.Reader, error) {
|
||||
|
||||
if len(fileNames) == 0 || len(imageid) == 0 {
|
||||
return nil, fmt.Errorf("bad usage: u must specify non-empty filelist and imageid ")
|
||||
}
|
||||
newurl := oci.url + "/" + oci.apiVer + "/images/id/" + imageid + "/files"
|
||||
|
||||
req, err := http.NewRequest("GET", newurl, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("Accept", "octet-stream")
|
||||
|
||||
q := req.URL.Query()
|
||||
q.Add("followSymLink", strconv.FormatBool(followSymLink))
|
||||
q.Add("doesExist", strconv.FormatBool(doesExist))
|
||||
for _, filename := range fileNames {
|
||||
q.Add("file", filename)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
|
||||
resp, err := oci.GetClient().Do(req)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error requesting file '%s' from server reason: %s", fileNames, err.Error())
|
||||
glog.Errorf(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
|
||||
return nil, fmt.Errorf("error has occurred: " + resp.Status)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error: failed to read imageid %s files requested %v due to %s", imageid, fileNames, err.Error())
|
||||
}
|
||||
reader := bytes.NewReader(data)
|
||||
filestar := tar.NewReader(reader)
|
||||
|
||||
return filestar, nil
|
||||
}
|
||||
|
||||
// GetFile -
|
||||
func (oci *OCImage) GetSingleFile(imageid string, filepath string, followSymLink bool) ([]byte, string, error) {
|
||||
newurl := oci.url + "/" + oci.apiVer + "/images/id/" + imageid + "/files/" + filepath
|
||||
|
||||
glog.Infof("Requesting from OCI: '%s'", newurl)
|
||||
var slashwrist []byte
|
||||
|
||||
client := &http.Client{}
|
||||
|
||||
req, err := http.NewRequest("GET", newurl, nil)
|
||||
if err != nil {
|
||||
return slashwrist, "", err
|
||||
}
|
||||
req.Header.Add("Accept", "octet-stream")
|
||||
|
||||
q := req.URL.Query()
|
||||
q.Add("followSymLink", strconv.FormatBool(followSymLink))
|
||||
req.URL.RawQuery = q.Encode()
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error requesting file '%s' from server reason: %s", filepath, err.Error())
|
||||
glog.Errorf(err.Error())
|
||||
return slashwrist, "", err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
|
||||
return slashwrist, "error has occurred: " + resp.Status, fmt.Errorf("error has occurred: " + resp.Status)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
|
||||
return respBody, "success", err
|
||||
|
||||
}
|
||||
|
||||
// GetFile -
|
||||
func (oci *OCImage) GetFileWithRetries(imageid string, filepath string, followSymLink bool) ([]byte, string, error) {
|
||||
retry := 0
|
||||
for {
|
||||
respBody, status, err := oci.GetSingleFile(imageid, filepath, followSymLink)
|
||||
if err != nil && strings.Contains(err.Error(), "EOF") && retry < MAX_RETRIES {
|
||||
glog.Warningf("Request: '%s', received 'EOF'. Retying", filepath)
|
||||
retry++
|
||||
time.Sleep(1 * time.Second)
|
||||
} else {
|
||||
return respBody, status, err
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
45
vendor/github.com/armosec/capacketsgo/ocimage/ocimageapi_mock.go
generated
vendored
45
vendor/github.com/armosec/capacketsgo/ocimage/ocimageapi_mock.go
generated
vendored
@@ -1,45 +0,0 @@
|
||||
package ocimage
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// import "encoding/json"
|
||||
|
||||
// OCImageMock -
|
||||
type OCImageMock struct {
|
||||
}
|
||||
|
||||
// GetImage -
|
||||
func (ocim *OCImageMock) GetImage(imageTag, user, password string) (string, error) {
|
||||
return "5ac6aae02c212cafb36e853dcfe366bac4b1c1097fe8c10c923842f09c8bf7e4", nil
|
||||
|
||||
}
|
||||
|
||||
// // FileList - mock
|
||||
func (ocim *OCImageMock) FileList(imageid string, dir string, from int, to int, recursive bool, noDir bool) ([]FileMetadata, error) {
|
||||
listOfFiles := []FileMetadata{}
|
||||
list := `[{"isSymbolicLink":false,"layer":"sha256:f010348cae17a90a12165366416cb15c9606ea63a3735f9d967b843d33865f31","link":"","name":"etc/nginx","path":"etc/nginx","permissions":"0o40755"},{"isSymbolicLink":false,"layer":"sha256:1ce95ec4847ff9d80847f0a1836135255742c2160bc4ba52c829dfbc68a93291","link":"","name":"etc/apk","path":"etc/apk","permissions":"0o40755"},{"isSymbolicLink":false,"layer":"sha256:62bed320c887a0e141341a598b3a754c288bc91a15e66c7e1d10a941f63bc0c1","link":"","name":"etc/supervisor.d","path":"etc/supervisor.d","permissions":"0o40755"}]`
|
||||
json.Unmarshal([]byte(list), &listOfFiles)
|
||||
return listOfFiles, nil
|
||||
}
|
||||
|
||||
// // Describe -
|
||||
func (ocim *OCImageMock) Describe(imageID string) (*ImageMetadata, error) {
|
||||
imageData := &ImageMetadata{}
|
||||
id := `{"architecture":"amd64","info":{"architecture":"amd64","config":{"ArgsEscaped":true,"AttachStderr":false,"AttachStdin":false,"AttachStdout":false,"Cmd":["/nginx"],"Domainname":"","Entrypoint":["/entrypoint.sh"],"Env":["PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","LANG=C.UTF-8","GPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D","PYTHON_VERSION=3.6.5","PYTHON_PIP_VERSION=10.0.1","NGINX_VERSION=1.13.8","UWSGI_INI=/app/uwsgi.ini","UWSGI_CHEAPER=2","UWSGI_PROCESSES=16","NGINX_MAX_UPLOAD=0","NGINX_WORKER_PROCESSES=1","LISTEN_PORT=80","STATIC_URL=/static","STATIC_PATH=/app/static","STATIC_INDEX=0","PYTHONPATH=/app"],"ExposedPorts":{"443/tcp":{},"80/tcp":{}},"Hostname":"d98c43c06009","Image":"sha256:66531c940f46ea26a1db3c63583058b56f97b2e85f83feaa2a41b8e58e702419","Labels":{"maintainer":"Sebastian Ramirez <tiangolo@gmail.com>"},"OnBuild":[],"OpenStdin":false,"StdinOnce":false,"Tty":false,"User":"","Volumes":null,"WorkingDir":"/app"},"container":"8086c88edd59db391d40b0bd6463e6521ccf6e7ec97ccb4aa236d6612cebec1c","container_config":{"ArgsEscaped":true,"AttachStderr":false,"AttachStdin":false,"AttachStdout":false,"Cmd":["/bin/sh","-c","#(nop) COPY file:3f7d33a0228dc7f9feb6b386b9cac9f2730d691a447399a8c1ae2755e8477312 in /app/. "],"Domainname":"","Entrypoint":["/entrypoint.sh"],"Env":["PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","LANG=C.UTF-8","GPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D","PYTHON_VERSION=3.6.5","PYTHON_PIP_VERSION=10.0.1","NGINX_VERSION=1.13.8","UWSGI_INI=/app/uwsgi.ini","UWSGI_CHEAPER=2","UWSGI_PROCESSES=16","NGINX_MAX_UPLOAD=0","NGINX_WORKER_PROCESSES=1","LISTEN_PORT=80","STATIC_URL=/static","STATIC_PATH=/app/static","STATIC_INDEX=0","PYTHONPATH=/app"],"ExposedPorts":{"443/tcp":{},"80/tcp":{}},"Hostname":"d98c43c06009","Image":"sha256:66531c940f46ea26a1db3c63583058b56f97b2e85f83feaa2a41b8e58e702419","Labels":{"maintainer":"Sebastian Ramirez <tiangolo@gmail.com>"},"OnBuild":[],"OpenStdin":false,"StdinOnce":false,"Tty":false,"User":"","Volumes":null,"WorkingDir":"/app"},"created":"2018-11-25T11:37:00.787977594Z","docker_version":"1.13.1","id":"4944f7cd6bdbabd69dfde3efe800f996a43a373db9a5a07824ee30b908f61bfb","os":"linux","parent":"080f106513ef7ac9a5375e22ae6e56584bf745e401fbb21dd54d7fcf22ef8570"},"name":"signer","schemaVersion":1,"signatures":[{"header":{"alg":"ES256","jwk":{"crv":"P-256","kid":"W5FE:S6CL:XC37:EVE5:HSZD:OODU:4KWZ:WEIM:RRNN:MKXO:IO6H:Y7N4","kty":"EC","x":"DpcaARFTpltBfJ4cAGdE9Gp9AO2dEogJRBsWC9A2My0","y":"OTD5zOUaIa1bldgfGhVSpve-Urfxcpl1QS35hSBQoXQ"}},"protected":"eyJmb3JtYXRMZW5ndGgiOjM5MTc4LCJmb3JtYXRUYWlsIjoiQ24wIiwidGltZSI6IjIwMjAtMDUtMTRUMDc6NTc6MTBaIn0","signature":"hWCo_ezuNNz4e3M1opkK4Mrh9XcQE3K69ppL9_aboFaIPDzJWCZh2yt4zX4rM3dT3-2lLYuurFqgvw4dwLaJ4g"}],"tag":"70"}`
|
||||
json.Unmarshal([]byte(id), imageData)
|
||||
return imageData, nil
|
||||
}
|
||||
|
||||
func (ocim *OCImageMock) GetSingleFile(fileName string, followSymLink bool) ([]byte, string, error) {
|
||||
if strings.Contains(fileName, "-release") {
|
||||
os := []byte("PRETTY_NAME=\"Debian GNU/Linux 10 (buster)\"\nNAME=\"Debian GNU/Linux\"\nVERSION_ID=\"10\"\nVERSION=\"10 (buster)\"\nVERSION_CODENAME=buster\nID=debian\nHOME_URL=\"https://www.debian.org/\"\nSUPPORT_URL=\"https://www.debian.org/support\"\nBUG_REPORT_URL=\"https://bugs.debian.org/\"\n")
|
||||
|
||||
return os, "os", nil
|
||||
}
|
||||
|
||||
nginx := []byte("# Defaults for nginx initscript\n# sourced by /etc/init.d/nginx\n\n# Additional options that are passed to nginx\nDAEMON_ARGS=\"\"\n")
|
||||
return nginx, "nginxscript", nil
|
||||
}
|
||||
116
vendor/github.com/armosec/capacketsgo/ocimage/ocimagetypes.go
generated
vendored
116
vendor/github.com/armosec/capacketsgo/ocimage/ocimagetypes.go
generated
vendored
@@ -1,116 +0,0 @@
|
||||
package ocimage
|
||||
|
||||
import "github.com/docker/docker/api/types/container"
|
||||
|
||||
// FileMetadata file metatdata
|
||||
type FileMetadata struct {
|
||||
IsSymbolicLink bool `json:"isSymbolicLink"`
|
||||
Layer string `json:"layer"`
|
||||
Link string `json:"link"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Permissions string `json:"permissions"`
|
||||
}
|
||||
|
||||
// ImageMetadata image metatdata
|
||||
type ImageMetadata struct {
|
||||
Tag string `json:"tag"`
|
||||
Name string `json:"name"`
|
||||
Architecture string `json:"architecture"`
|
||||
SchemaVersion int `json:"naschemaVersionme"`
|
||||
Info ImageMetaInfo `json:"info"`
|
||||
Signatures []ImageMetaSignature `json:"signatures"`
|
||||
}
|
||||
|
||||
// ImageMetaInfo -
|
||||
type ImageMetaInfo struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Os string `json:"os,omitempty"`
|
||||
Parent string `json:"parent,omitempty"`
|
||||
Created string `json:"created,omitempty"`
|
||||
Container string `json:"container,omitempty"`
|
||||
Architecture string `json:"architecture,omitempty"`
|
||||
Config *container.Config `json:"config,omitempty"`
|
||||
ContainerConfig *container.Config `json:"container_config,omitempty"`
|
||||
}
|
||||
|
||||
// // ContainerInfo -
|
||||
// type ContainerInfo struct {
|
||||
// Tty bool `json:"Tty,omitempty"`
|
||||
// ArgsEscaped bool `json:"ArgsEscaped,omitempty"`
|
||||
// AttachStderr bool `json:"AttachStderr,omitempty"`
|
||||
// AttachStdin bool `json:"AttachStdin,omitempty"`
|
||||
// AttachStdout bool `json:"AttachStdout,omitempty"`
|
||||
// OpenStdin bool `json:"OpenStdin,omitempty"`
|
||||
// StdinOnce bool `json:"StdinOnce,omitempty"`
|
||||
// User string `json:"User,omitempty"`
|
||||
// Image string `json:"Image"`
|
||||
// Hostname string `json:"Hostname,omitempty"`
|
||||
// Domainname string `json:"Domainname,omitempty"`
|
||||
// WorkingDir string `json:"WorkingDir,omitempty"`
|
||||
// Cmd []string `json:"Cmd"`
|
||||
// Env []string `json:"Env,omitempty"`
|
||||
// Entrypoint []string `json:"Entrypoint"`
|
||||
// Volumes interface{} `json:"Volumes,omitempty"`
|
||||
// OnBuild []interface{} `json:"OnBuild,omitempty"`
|
||||
// Labels map[string]string `json:"Labels,omitempty"`
|
||||
// ExposedPorts map[string]interface{} `json:"ExposedPorts,omitempty"`
|
||||
// }
|
||||
|
||||
// ImageMetaSignature -
|
||||
type ImageMetaSignature struct {
|
||||
Protected string `json:"protected,omitempty"`
|
||||
Signature string `json:"signature,omitempty"`
|
||||
Header SignatureHeader `json:"header,omitempty"`
|
||||
}
|
||||
|
||||
// SignatureHeader -
|
||||
type SignatureHeader struct {
|
||||
Alg string `json:"alg,omitempty"`
|
||||
Jwk HeaderJwk `json:"jwk,omitempty"`
|
||||
}
|
||||
|
||||
// HeaderJwk -
|
||||
type HeaderJwk struct {
|
||||
Crv string `json:"crv,omitempty"`
|
||||
Kid string `json:"kid,omitempty"`
|
||||
Kty string `json:"kty,omitempty"`
|
||||
X string `json:"x,omitempty"`
|
||||
Y string `json:"y,omitempty"`
|
||||
}
|
||||
|
||||
type OciImageManifestConfig struct {
|
||||
Digest string `json:"digest"`
|
||||
MediaType string `json:"mediaType"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
type OciImageManifestRequestOptions struct {
|
||||
AllowRedirects bool `json:"allow_redirects"`
|
||||
Stream bool `json:"stream"`
|
||||
Verify bool `json:"verify"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
}
|
||||
|
||||
type OciImageManifestLayer struct {
|
||||
Digest string `json:"digest"`
|
||||
DownloadPath string `json:"dlPath"`
|
||||
MediaType string `json:"mediaType"`
|
||||
Size int `json:"size"`
|
||||
RequestOptions OciImageManifestRequestOptions `json:"request_options"`
|
||||
}
|
||||
|
||||
type OciImageManifest struct {
|
||||
Config OciImageManifestConfig `json:"config"`
|
||||
Layers []OciImageManifestLayer `json:"layers"`
|
||||
}
|
||||
|
||||
//{"isSymbolicLink":false,"layer":"sha256:86b54f4b6a4ebee33338eb7c182a9a3d51a69cce1eb9af95a992f4da8eabe3be","link":"","name":"var/lib/dpkg/info/libdbus-1-3.list","path":"var/lib/dpkg/info/libdbus-1-3.list","permissions":"0o100644"},
|
||||
type OciImageFsEntry struct {
|
||||
IsSymbolicLink bool `json:"isSymbolicLink"`
|
||||
Layer string `json:"layer"`
|
||||
Link string `json:"link"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Permissions string `json:"permissions"`
|
||||
}
|
||||
7
vendor/github.com/armosec/capacketsgo/opapolicy/apis.go
generated
vendored
7
vendor/github.com/armosec/capacketsgo/opapolicy/apis.go
generated
vendored
@@ -1,7 +0,0 @@
|
||||
package opapolicy
|
||||
|
||||
const (
|
||||
PostureRestAPIPathV1 = "/v1/posture"
|
||||
PostureRedisPrefix = "_postureReportv1"
|
||||
K8sPostureNotification = "/k8srestapi/v1/newPostureReport"
|
||||
)
|
||||
150
vendor/github.com/armosec/capacketsgo/opapolicy/datastructures.go
generated
vendored
150
vendor/github.com/armosec/capacketsgo/opapolicy/datastructures.go
generated
vendored
@@ -1,150 +0,0 @@
|
||||
package opapolicy
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
armotypes "github.com/armosec/capacketsgo/armotypes"
|
||||
)
|
||||
|
||||
type AlertScore float32
|
||||
type RuleLanguages string
|
||||
|
||||
const (
|
||||
RegoLanguage RuleLanguages = "Rego"
|
||||
RegoLanguage2 RuleLanguages = "rego"
|
||||
)
|
||||
|
||||
// RegoResponse the expected response of single run of rego policy
|
||||
type RuleResponse struct {
|
||||
AlertMessage string `json:"alertMessage"`
|
||||
PackageName string `json:"packagename"`
|
||||
AlertScore AlertScore `json:"alertScore"`
|
||||
// AlertObject AlertObject `json:"alertObject"`
|
||||
AlertObject AlertObject `json:"alertObject"` // TODO - replace interface to AlertObject
|
||||
Context []string `json:"context"` // TODO - Remove
|
||||
Rulename string `json:"rulename"` // TODO - Remove
|
||||
ExceptionName string `json:"exceptionName"`
|
||||
}
|
||||
|
||||
type AlertObject struct {
|
||||
K8SApiObjects []map[string]interface{} `json:"k8sApiObjects,omitempty"`
|
||||
ExternalObjects []map[string]interface{} `json:"externalObjects,omitempty"`
|
||||
}
|
||||
|
||||
type FrameworkReport struct {
|
||||
Name string `json:"name"`
|
||||
ControlReports []ControlReport `json:"controlReports"`
|
||||
}
|
||||
type ControlReport struct {
|
||||
Name string `json:"name"`
|
||||
RuleReports []RuleReport `json:"ruleReports"`
|
||||
Remediation string `json:"remediation"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
type RuleReport struct {
|
||||
Name string `json:"name"`
|
||||
Remediation string `json:"remediation"`
|
||||
RuleStatus RuleStatus `json:"ruleStatus"`
|
||||
RuleResponses []RuleResponse `json:"ruleResponses"`
|
||||
NumOfResources int
|
||||
}
|
||||
type RuleStatus struct {
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// PostureReport
|
||||
type PostureReport struct {
|
||||
CustomerGUID string `json:"customerGUID"`
|
||||
ClusterName string `json:"clusterName"`
|
||||
ReportID string `json:"reportID"`
|
||||
JobID string `json:"jobID"`
|
||||
ReportGenerationTime time.Time `json:"generationTime"`
|
||||
FrameworkReports []FrameworkReport `json:"frameworks"`
|
||||
}
|
||||
|
||||
// RuleMatchObjects defines which objects this rule applied on
|
||||
type RuleMatchObjects struct {
|
||||
APIGroups []string `json:"apiGroups"` // apps
|
||||
APIVersions []string `json:"apiVersions"` // v1/ v1beta1 / *
|
||||
Resources []string `json:"resources"` // dep.., pods,
|
||||
}
|
||||
|
||||
// RuleMatchObjects defines which objects this rule applied on
|
||||
type RuleDependency struct {
|
||||
PackageName string `json:"packageName"` // package name
|
||||
}
|
||||
|
||||
// PolicyRule represents single rule, the fundamental executable block of policy
|
||||
type PolicyRule struct {
|
||||
armotypes.PortalBase `json:",inline"`
|
||||
CreationTime string `json:"creationTime"`
|
||||
Rule string `json:"rule"` // multiline string!
|
||||
RuleLanguage RuleLanguages `json:"ruleLanguage"`
|
||||
Match []RuleMatchObjects `json:"match"`
|
||||
RuleDependencies []RuleDependency `json:"ruleDependencies"`
|
||||
Description string `json:"description"`
|
||||
Remediation string `json:"remediation"`
|
||||
RuleQuery string `json:"ruleQuery"` // default "armo_builtins" - DEPRECATED
|
||||
}
|
||||
|
||||
// Control represents a collection of rules which are combined together to single purpose
|
||||
type Control struct {
|
||||
armotypes.PortalBase `json:",inline"`
|
||||
CreationTime string `json:"creationTime"`
|
||||
Description string `json:"description"`
|
||||
Remediation string `json:"remediation"`
|
||||
Rules []PolicyRule `json:"rules"`
|
||||
// for new list of rules in POST/UPADTE requests
|
||||
RulesIDs *[]string `json:"rulesIDs,omitempty"`
|
||||
}
|
||||
|
||||
type UpdatedControl struct {
|
||||
Control `json:",inline"`
|
||||
Rules []interface{} `json:"rules"`
|
||||
}
|
||||
|
||||
// Framework represents a collection of controls which are combined together to expose comprehensive behavior
|
||||
type Framework struct {
|
||||
armotypes.PortalBase `json:",inline"`
|
||||
CreationTime string `json:"creationTime"`
|
||||
Description string `json:"description"`
|
||||
Controls []Control `json:"controls"`
|
||||
// for new list of controls in POST/UPADTE requests
|
||||
ControlsIDs *[]string `json:"controlsIDs,omitempty"`
|
||||
}
|
||||
|
||||
type UpdatedFramework struct {
|
||||
Framework `json:",inline"`
|
||||
Controls []interface{} `json:"controls"`
|
||||
}
|
||||
|
||||
type NotificationPolicyType string
|
||||
type NotificationPolicyKind string
|
||||
|
||||
// Supported NotificationTypes
|
||||
const (
|
||||
TypeValidateRules NotificationPolicyType = "validateRules"
|
||||
TypeExecPostureScan NotificationPolicyType = "execPostureScan"
|
||||
TypeUpdateRules NotificationPolicyType = "updateRules"
|
||||
)
|
||||
|
||||
// Supported NotificationKinds
|
||||
const (
|
||||
KindFramework NotificationPolicyKind = "Framework"
|
||||
KindControl NotificationPolicyKind = "Control"
|
||||
KindRule NotificationPolicyKind = "Rule"
|
||||
)
|
||||
|
||||
type PolicyNotification struct {
|
||||
NotificationType NotificationPolicyType `json:"notificationType"`
|
||||
Rules []PolicyIdentifier `json:"rules"`
|
||||
ReportID string `json:"reportID"`
|
||||
JobID string `json:"jobID"`
|
||||
Designators armotypes.PortalDesignator `json:"designators"`
|
||||
}
|
||||
|
||||
type PolicyIdentifier struct {
|
||||
Kind NotificationPolicyKind `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
300
vendor/github.com/armosec/capacketsgo/opapolicy/datastructures_mock.go
generated
vendored
300
vendor/github.com/armosec/capacketsgo/opapolicy/datastructures_mock.go
generated
vendored
@@ -1,300 +0,0 @@
|
||||
package opapolicy
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
armotypes "github.com/armosec/capacketsgo/armotypes"
|
||||
)
|
||||
|
||||
// Mock A
|
||||
var (
|
||||
AMockCustomerGUID = "5d817063-096f-4d91-b39b-8665240080af"
|
||||
AMockJobID = "36b6f9e1-3b63-4628-994d-cbe16f81e9c7"
|
||||
AMockReportID = "2c31e4da-c6fe-440d-9b8a-785b80c8576a"
|
||||
AMockClusterName = "clusterA"
|
||||
AMockFrameworkName = "testFrameworkA"
|
||||
AMockControlName = "testControlA"
|
||||
AMockRuleName = "testRuleA"
|
||||
AMockPortalBase = *armotypes.MockPortalBase(AMockCustomerGUID, "", nil)
|
||||
)
|
||||
|
||||
func MockRuleResponseA() *RuleResponse {
|
||||
return &RuleResponse{
|
||||
AlertMessage: "test alert message A",
|
||||
AlertScore: 0,
|
||||
Rulename: AMockRuleName,
|
||||
PackageName: "test.package.name.A",
|
||||
Context: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
func MockFrameworkReportA() *FrameworkReport {
|
||||
return &FrameworkReport{
|
||||
Name: AMockFrameworkName,
|
||||
ControlReports: []ControlReport{
|
||||
{
|
||||
Name: AMockControlName,
|
||||
RuleReports: []RuleReport{
|
||||
{
|
||||
Name: AMockRuleName,
|
||||
Remediation: "remove privilegedContainer: True flag from your pod spec",
|
||||
RuleResponses: []RuleResponse{
|
||||
*MockRuleResponseA(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func MockPostureReportA() *PostureReport {
|
||||
return &PostureReport{
|
||||
CustomerGUID: AMockCustomerGUID,
|
||||
ClusterName: AMockClusterName,
|
||||
ReportID: AMockReportID,
|
||||
JobID: AMockJobID,
|
||||
ReportGenerationTime: time.Now().UTC(),
|
||||
FrameworkReports: []FrameworkReport{*MockFrameworkReportA()},
|
||||
}
|
||||
}
|
||||
|
||||
func MockFrameworkA() *Framework {
|
||||
return &Framework{
|
||||
PortalBase: *armotypes.MockPortalBase("aaaaaaaa-096f-4d91-b39b-8665240080af", AMockFrameworkName, nil),
|
||||
CreationTime: "",
|
||||
Description: "mock framework descryption",
|
||||
Controls: []Control{
|
||||
{
|
||||
PortalBase: *armotypes.MockPortalBase("aaaaaaaa-aaaa-4d91-b39b-8665240080af", AMockControlName, nil),
|
||||
Rules: []PolicyRule{
|
||||
*MockRuleA(),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func MockRuleUntrustedRegistries() *PolicyRule {
|
||||
return &PolicyRule{
|
||||
PortalBase: *armotypes.MockPortalBase("aaaaaaaa-aaaa-aaaa-b39b-8665240080af", AMockControlName, nil),
|
||||
Rule: `
|
||||
package armo_builtins
|
||||
# Check for images from blacklisted repos
|
||||
|
||||
untrusted_registries(z) = x {
|
||||
x := ["015253967648.dkr.ecr.eu-central-1.amazonaws.com/"]
|
||||
}
|
||||
|
||||
public_registries(z) = y{
|
||||
y := ["quay.io/kiali/","quay.io/datawire/","quay.io/keycloak/","quay.io/bitnami/"]
|
||||
}
|
||||
|
||||
untrustedImageRepo[msga] {
|
||||
pod := input[_]
|
||||
k := pod.kind
|
||||
k == "Pod"
|
||||
container := pod.spec.containers[_]
|
||||
image := container.image
|
||||
repo_prefix := untrusted_registries(image)[_]
|
||||
startswith(image, repo_prefix)
|
||||
selfLink := pod.metadata.selfLink
|
||||
containerName := container.name
|
||||
|
||||
msga := {
|
||||
"alertMessage": sprintf("image '%v' in container '%s' in [%s] comes from untrusted registry", [image, containerName, selfLink]),
|
||||
"alert": true,
|
||||
"prevent": false,
|
||||
"alertScore": 2,
|
||||
"alertObject": [{"pod":pod}]
|
||||
}
|
||||
}
|
||||
|
||||
untrustedImageRepo[msga] {
|
||||
pod := input[_]
|
||||
k := pod.kind
|
||||
k == "Pod"
|
||||
container := pod.spec.containers[_]
|
||||
image := container.image
|
||||
repo_prefix := public_registries(image)[_]
|
||||
startswith(pod, repo_prefix)
|
||||
selfLink := input.metadata.selfLink
|
||||
containerName := container.name
|
||||
|
||||
msga := {
|
||||
"alertMessage": sprintf("image '%v' in container '%s' in [%s] comes from public registry", [image, containerName, selfLink]),
|
||||
"alert": true,
|
||||
"prevent": false,
|
||||
"alertScore": 1,
|
||||
"alertObject": [{"pod":pod}]
|
||||
}
|
||||
}
|
||||
`,
|
||||
RuleLanguage: RegoLanguage,
|
||||
Match: []RuleMatchObjects{
|
||||
{
|
||||
APIVersions: []string{"v1"},
|
||||
APIGroups: []string{"*"},
|
||||
Resources: []string{"pods"},
|
||||
},
|
||||
},
|
||||
RuleDependencies: []RuleDependency{
|
||||
{
|
||||
PackageName: "kubernetes.api.client",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func MockRuleA() *PolicyRule {
|
||||
return &PolicyRule{
|
||||
PortalBase: *armotypes.MockPortalBase("aaaaaaaa-aaaa-aaaa-b39b-8665240080af", AMockControlName, nil),
|
||||
Rule: MockRegoPrivilegedPods(), //
|
||||
RuleLanguage: RegoLanguage,
|
||||
Match: []RuleMatchObjects{
|
||||
{
|
||||
APIVersions: []string{"v1"},
|
||||
APIGroups: []string{"*"},
|
||||
Resources: []string{"pods"},
|
||||
},
|
||||
},
|
||||
RuleDependencies: []RuleDependency{
|
||||
{
|
||||
PackageName: "kubernetes.api.client",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func MockRuleB() *PolicyRule {
|
||||
return &PolicyRule{
|
||||
PortalBase: *armotypes.MockPortalBase("bbbbbbbb-aaaa-aaaa-b39b-8665240080af", AMockControlName, nil),
|
||||
Rule: MockExternalFacingService(), //
|
||||
RuleLanguage: RegoLanguage,
|
||||
Match: []RuleMatchObjects{
|
||||
{
|
||||
APIVersions: []string{"v1"},
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"pods"},
|
||||
},
|
||||
},
|
||||
RuleDependencies: []RuleDependency{
|
||||
{
|
||||
PackageName: "kubernetes.api.client",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func MockPolicyNotificationA() *PolicyNotification {
|
||||
return &PolicyNotification{
|
||||
NotificationType: TypeExecPostureScan,
|
||||
ReportID: AMockReportID,
|
||||
JobID: AMockJobID,
|
||||
Designators: armotypes.PortalDesignator{},
|
||||
Rules: []PolicyIdentifier{
|
||||
{
|
||||
Kind: KindFramework,
|
||||
Name: AMockFrameworkName,
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
func MockTemp() string {
|
||||
return `
|
||||
package armo_builtins
|
||||
import data.kubernetes.api.client as client
|
||||
deny[msga] {
|
||||
#object := input[_]
|
||||
object := client.query_all("pods")
|
||||
obj := object.body.items[_]
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": "found object",
|
||||
"alertScore": 3,
|
||||
"alertObject": {"object": obj},
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
func MockRegoPrivilegedPods() string {
|
||||
return `package armo_builtins
|
||||
|
||||
import data.kubernetes.api.client as client
|
||||
|
||||
# Deny mutating action unless user is in group owning the resource
|
||||
|
||||
#privileged pods
|
||||
deny[msga] {
|
||||
|
||||
pod := input[_]
|
||||
containers := pod.spec.containers[_]
|
||||
containers.securityContext.privileged == true
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("the following pods are defined as privileged: %v", [pod]),
|
||||
"alertScore": 3,
|
||||
"alertObject": pod,
|
||||
}
|
||||
}
|
||||
|
||||
#handles majority of workload resources
|
||||
deny[msga] {
|
||||
wl := input[_]
|
||||
spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"}
|
||||
spec_template_spec_patterns[wl.kind]
|
||||
containers := wl.spec.template.spec.containers[_]
|
||||
containers.securityContext.privileged == true
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("the following workloads are defined as privileged: %v", [wl]),
|
||||
"alertScore": 3,
|
||||
"alertObject": wl,
|
||||
}
|
||||
}
|
||||
|
||||
#handles cronjob
|
||||
deny[msga] {
|
||||
wl := input[_]
|
||||
wl.kind == "CronJob"
|
||||
containers := wl.spec.jobTemplate.spec.template.spec.containers[_]
|
||||
containers.securityContext.privileged == true
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("the following cronjobs are defined as privileged: %v", [wl]),
|
||||
"alertScore": 3,
|
||||
"alertObject": wl,
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
func MockExternalFacingService() string {
|
||||
return "\n\tpackage armo_builtins\n\n\timport data.kubernetes.api.client as client\n\timport data.cautils as cautils\n\ndeny[msga] {\n\n\twl := input[_]\n\tcluster_resource := client.query_all(\n\t\t\"services\"\n\t)\n\n\tlabels := wl.metadata.labels\n\tfiltered_labels := json.remove(labels, [\"pod-template-hash\"])\n \n#service := cluster_resource.body.items[i]\nservices := [svc | cluster_resource.body.items[i].metadata.namespace == wl.metadata.namespace; svc := cluster_resource.body.items[i]]\nservice := services[_]\nnp_or_lb := {\"NodePort\", \"LoadBalancer\"}\nnp_or_lb[service.spec.type]\ncautils.is_subobject(service.spec.selector,filtered_labels)\n\n msga := {\n\t\t\"alertMessage\": sprintf(\"%v pod %v expose external facing service: %v\",[wl.metadata.namespace, wl.metadata.name, service.metadata.name]),\n\t\t\"alertScore\": 2,\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertObject\": {\"srvc\":service}\n\t}\n}\n\t"
|
||||
}
|
||||
func GetRuntimePods() string {
|
||||
return `
|
||||
package armo_builtins
|
||||
|
||||
import data.kubernetes.api.client as client
|
||||
|
||||
|
||||
deny[msga] {
|
||||
|
||||
|
||||
cluster_resource := client.query_all(
|
||||
"pods"
|
||||
)
|
||||
|
||||
pod := cluster_resource.body.items[i]
|
||||
msga := {
|
||||
"alertMessage": "got something",
|
||||
"alertScore": 2,
|
||||
"packagename": "armo_builtins",
|
||||
"alertObject": {"pod": pod}
|
||||
}
|
||||
}
|
||||
|
||||
`
|
||||
}
|
||||
42
vendor/github.com/armosec/capacketsgo/opapolicy/datastructures_test.go
generated
vendored
42
vendor/github.com/armosec/capacketsgo/opapolicy/datastructures_test.go
generated
vendored
@@ -1,42 +0,0 @@
|
||||
package opapolicy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMockPolicyNotificationA(t *testing.T) {
|
||||
policy := MockPolicyNotificationA()
|
||||
bp, err := json.Marshal(policy)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
t.Logf("%s\n", string(bp))
|
||||
// t.Errorf("%s\n", string(bp))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMockFrameworkA(t *testing.T) {
|
||||
policy := MockFrameworkA()
|
||||
bp, err := json.Marshal(policy)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
t.Logf("%s\n", string(bp))
|
||||
// t.Errorf("%s\n", string(bp))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMockPostureReportA(t *testing.T) {
|
||||
policy := MockPostureReportA()
|
||||
bp, err := json.Marshal(policy)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
// t.Errorf("%s\n", string(bp))
|
||||
t.Logf("%s\n", string(bp))
|
||||
}
|
||||
|
||||
}
|
||||
89
vendor/github.com/armosec/capacketsgo/opapolicy/datastructuresmethods.go
generated
vendored
89
vendor/github.com/armosec/capacketsgo/opapolicy/datastructuresmethods.go
generated
vendored
@@ -1,89 +0,0 @@
|
||||
package opapolicy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/armosec/armopa/rego"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func (pn *PolicyNotification) ToJSONBytesBuffer() (*bytes.Buffer, error) {
|
||||
res, err := json.Marshal(pn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bytes.NewBuffer(res), err
|
||||
}
|
||||
|
||||
func (ruleReport *RuleReport) GetRuleStatus() (string, []RuleResponse, []RuleResponse) {
|
||||
if len(ruleReport.RuleResponses) == 0 {
|
||||
return "success", nil, nil
|
||||
}
|
||||
exceptions := make([]RuleResponse, 0)
|
||||
failed := make([]RuleResponse, 0)
|
||||
|
||||
for _, rule := range ruleReport.RuleResponses {
|
||||
if rule.ExceptionName != "" {
|
||||
failed = append(failed, rule)
|
||||
} else {
|
||||
exceptions = append(exceptions, rule)
|
||||
}
|
||||
}
|
||||
|
||||
status := "failed"
|
||||
if len(failed) == 0 && len(exceptions) > 0 {
|
||||
status = "warning"
|
||||
}
|
||||
return status, failed, exceptions
|
||||
}
|
||||
func ParseRegoResult(regoResult *rego.ResultSet) ([]RuleResponse, error) {
|
||||
var errs error
|
||||
ruleResponses := []RuleResponse{}
|
||||
for _, result := range *regoResult {
|
||||
for desicionIdx := range result.Expressions {
|
||||
if resMap, ok := result.Expressions[desicionIdx].Value.(map[string]interface{}); ok {
|
||||
for objName := range resMap {
|
||||
jsonBytes, err := json.Marshal(resMap[objName])
|
||||
if err != nil {
|
||||
err = fmt.Errorf("in parseRegoResult, json.Marshal failed. name: %s, obj: %v, reason: %s", objName, resMap[objName], err)
|
||||
glog.Error(err)
|
||||
errs = fmt.Errorf("%s\n%s", errs, err)
|
||||
continue
|
||||
}
|
||||
desObj := make([]RuleResponse, 0)
|
||||
if err := json.Unmarshal(jsonBytes, &desObj); err != nil {
|
||||
err = fmt.Errorf("in parseRegoResult, json.Unmarshal failed. name: %s, obj: %v, reason: %s", objName, resMap[objName], err)
|
||||
glog.Error(err)
|
||||
errs = fmt.Errorf("%s\n%s", errs, err)
|
||||
continue
|
||||
}
|
||||
ruleResponses = append(ruleResponses, desObj...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ruleResponses, errs
|
||||
}
|
||||
|
||||
func (controlReport *ControlReport) GetNumberOfResources() int {
|
||||
sum := 0
|
||||
for i := range controlReport.RuleReports {
|
||||
sum += controlReport.RuleReports[i].NumOfResources
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
func (controlReport *ControlReport) Passed() bool {
|
||||
for i := range controlReport.RuleReports {
|
||||
if len(controlReport.RuleReports[i].RuleResponses) > 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (controlReport *ControlReport) Failed() bool {
|
||||
return !controlReport.Passed()
|
||||
}
|
||||
47
vendor/github.com/armosec/capacketsgo/opapolicy/gojayunmarshaller.go
generated
vendored
47
vendor/github.com/armosec/capacketsgo/opapolicy/gojayunmarshaller.go
generated
vendored
@@ -1,47 +0,0 @@
|
||||
package opapolicy
|
||||
|
||||
import (
|
||||
"github.com/francoispqt/gojay"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
responsible on fast unmarshaling of various COMMON containerscan structures and substructures
|
||||
|
||||
*/
|
||||
// UnmarshalJSONObject - File inside a pkg
|
||||
func (r *PostureReport) UnmarshalJSONObject(dec *gojay.Decoder, key string) (err error) {
|
||||
|
||||
switch key {
|
||||
case "customerGUID":
|
||||
err = dec.String(&(r.CustomerGUID))
|
||||
|
||||
case "clusterName":
|
||||
err = dec.String(&(r.ClusterName))
|
||||
|
||||
case "reportID":
|
||||
err = dec.String(&(r.ReportID))
|
||||
case "jobID":
|
||||
err = dec.String(&(r.JobID))
|
||||
case "generationTime":
|
||||
err = dec.Time(&(r.ReportGenerationTime), time.RFC3339)
|
||||
r.ReportGenerationTime = r.ReportGenerationTime.Local()
|
||||
}
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
// func (files *PkgFiles) UnmarshalJSONArray(dec *gojay.Decoder) error {
|
||||
// lae := PackageFile{}
|
||||
// if err := dec.Object(&lae); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// *files = append(*files, lae)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (file *PostureReport) NKeys() int {
|
||||
return 0
|
||||
}
|
||||
//------------------------
|
||||
204
vendor/github.com/armosec/capacketsgo/opapolicy/resources/dependencies.go
generated
vendored
204
vendor/github.com/armosec/capacketsgo/opapolicy/resources/dependencies.go
generated
vendored
@@ -1,204 +0,0 @@
|
||||
package resources
|
||||
|
||||
var RegoCAUtils = `
|
||||
package cautils
|
||||
|
||||
list_contains(lista,element) {
|
||||
some i
|
||||
lista[i] == element
|
||||
}
|
||||
|
||||
# getPodName(metadata) = name {
|
||||
# name := metadata.generateName
|
||||
#}
|
||||
getPodName(metadata) = name {
|
||||
name := metadata.name
|
||||
}
|
||||
|
||||
#returns subobject ,sub1 is partial to parent, e.g parent = {a:a,b:b,c:c,d:d}
|
||||
# sub1 = {b:b,c:c} - result is {b:b,c:c}, if sub1={b:b,e:f} returns {b:b}
|
||||
object_intersection(parent,sub1) = r{
|
||||
|
||||
r := {k:p | p := sub1[k]
|
||||
parent[k]== p
|
||||
}
|
||||
}
|
||||
|
||||
#returns if parent contains sub(both are objects not sets!!)
|
||||
is_subobject(sub,parent) {
|
||||
object_intersection(sub,parent) == sub
|
||||
}
|
||||
`
|
||||
|
||||
var RegoDesignators = `
|
||||
package designators
|
||||
|
||||
import data.cautils
|
||||
#functions that related to designators
|
||||
|
||||
#allowed_namespace
|
||||
#@input@: receive as part of the input object "included_namespaces" list
|
||||
#@input@: item's namespace as "namespace"
|
||||
#returns true if namespace exists in that list
|
||||
included_namespaces(namespace){
|
||||
cautils.list_contains(["default"],namespace)
|
||||
}
|
||||
|
||||
#forbidden_namespaces
|
||||
#@input@: receive as part of the input object "forbidden_namespaces" list
|
||||
#@input@: item's namespace as "namespace"
|
||||
#returns true if namespace exists in that list
|
||||
excluded_namespaces(namespace){
|
||||
not cautils.list_contains(["excluded"],namespace)
|
||||
}
|
||||
|
||||
forbidden_wlids(wlid){
|
||||
input.forbidden_wlids[_] == wlid
|
||||
}
|
||||
|
||||
filter_k8s_object(obj) = filtered {
|
||||
#put
|
||||
filtered := obj
|
||||
#filtered := [ x | cautils.list_contains(["default"],obj[i].metadata.namespace) ; x := obj[i] ]
|
||||
# filtered := [ x | not cautils.list_contains([],filter1Set[i].metadata.namespace); x := filter1Set[i]]
|
||||
|
||||
}
|
||||
`
|
||||
var RegoKubernetesApiClient = `
|
||||
package kubernetes.api.client
|
||||
|
||||
# service account token
|
||||
token := data.k8sconfig.token
|
||||
|
||||
# Cluster host
|
||||
host := data.k8sconfig.host
|
||||
|
||||
# default certificate path
|
||||
# crt_file := "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
||||
crt_file := data.k8sconfig.crtfile
|
||||
|
||||
client_crt_file := data.k8sconfig.clientcrtfile
|
||||
client_key_file := data.k8sconfig.clientkeyfile
|
||||
|
||||
|
||||
# This information could be retrieved from the kubernetes API
|
||||
# too, but would essentially require a request per API group,
|
||||
# so for now use a lookup table for the most common resources.
|
||||
resource_group_mapping := {
|
||||
"services": "api/v1",
|
||||
"pods": "api/v1",
|
||||
"configmaps": "api/v1",
|
||||
"secrets": "api/v1",
|
||||
"persistentvolumeclaims": "api/v1",
|
||||
"daemonsets": "apis/apps/v1",
|
||||
"deployments": "apis/apps/v1",
|
||||
"statefulsets": "apis/apps/v1",
|
||||
"horizontalpodautoscalers": "api/autoscaling/v1",
|
||||
"jobs": "apis/batch/v1",
|
||||
"cronjobs": "apis/batch/v1beta1",
|
||||
"ingresses": "api/extensions/v1beta1",
|
||||
"replicasets": "apis/apps/v1",
|
||||
"networkpolicies": "apis/networking.k8s.io/v1",
|
||||
"clusterroles": "apis/rbac.authorization.k8s.io/v1",
|
||||
"clusterrolebindings": "apis/rbac.authorization.k8s.io/v1",
|
||||
"roles": "apis/rbac.authorization.k8s.io/v1",
|
||||
"rolebindings": "apis/rbac.authorization.k8s.io/v1",
|
||||
"serviceaccounts": "api/v1"
|
||||
}
|
||||
|
||||
# Query for given resource/name in provided namespace
|
||||
# Example: query_ns("deployments", "my-app", "default")
|
||||
query_name_ns(resource, name, namespace) = http.send({
|
||||
"url": sprintf("%v/%v/namespaces/%v/%v/%v", [
|
||||
host,
|
||||
resource_group_mapping[resource],
|
||||
namespace,
|
||||
resource,
|
||||
name,
|
||||
]),
|
||||
"method": "get",
|
||||
"headers": {"authorization": token},
|
||||
"tls_client_cert_file": client_crt_file,
|
||||
"tls_client_key_file": client_key_file,
|
||||
"tls_ca_cert_file": crt_file,
|
||||
"raise_error": true,
|
||||
})
|
||||
|
||||
# Query for given resource type using label selectors
|
||||
# https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api
|
||||
# Example: query_label_selector_ns("deployments", {"app": "opa-kubernetes-api-client"}, "default")
|
||||
query_label_selector_ns(resource, selector, namespace) = http.send({
|
||||
"url": sprintf("%v/%v/namespaces/%v/%v?labelSelector=%v", [
|
||||
host,
|
||||
resource_group_mapping[resource],
|
||||
namespace,
|
||||
resource,
|
||||
label_map_to_query_string(selector),
|
||||
]),
|
||||
"method": "get",
|
||||
"headers": {"authorization": token},
|
||||
"tls_client_cert_file": client_crt_file,
|
||||
"tls_client_key_file": client_key_file,
|
||||
"tls_ca_cert_file": crt_file,
|
||||
"raise_error": true,
|
||||
})
|
||||
|
||||
# x := field_transform_to_qry_param("spec.selector",input)
|
||||
# input = {"app": "acmefit", "service": "catalog-db"}
|
||||
# result: "spec.selector.app%3Dacmefit,spec.selector.service%3Dcatalog-db"
|
||||
|
||||
|
||||
query_field_selector_ns(resource, field, selector, namespace) = http.send({
|
||||
"url": sprintf("%v/%v/namespaces/%v/%v?fieldSelector=%v", [
|
||||
host,
|
||||
resource_group_mapping[resource],
|
||||
namespace,
|
||||
resource,
|
||||
field_transform_to_qry_param(field,selector),
|
||||
]),
|
||||
"method": "get",
|
||||
"headers": {"authorization": token},
|
||||
"tls_client_cert_file": client_crt_file,
|
||||
"tls_client_key_file": client_key_file,
|
||||
"tls_ca_cert_file": crt_file,
|
||||
"raise_error": true,
|
||||
|
||||
})
|
||||
|
||||
# # Query for all resources of type resource in all namespaces
|
||||
# # Example: query_all("deployments")
|
||||
# query_all(resource) = http.send({
|
||||
# "url": sprintf("https://%v:%v/%v/%v", [
|
||||
# ip,
|
||||
# port,
|
||||
# resource_group_mapping[resource],
|
||||
# resource,
|
||||
# ]),
|
||||
# "method": "get",
|
||||
# "headers": {"authorization": sprintf("Bearer %v", [token])},
|
||||
# "tls_client_cert_file": crt_file,
|
||||
# "raise_error": true,
|
||||
# })
|
||||
|
||||
# Query for all resources of type resource in all namespaces
|
||||
# Example: query_all("deployments")
|
||||
query_all(resource) = http.send({
|
||||
"url": sprintf("%v/%v/%v", [
|
||||
host,
|
||||
resource_group_mapping[resource],
|
||||
resource,
|
||||
]),
|
||||
"method": "get",
|
||||
"headers": {"authorization": token},
|
||||
"tls_client_cert_file": client_crt_file,
|
||||
"tls_client_key_file": client_key_file,
|
||||
"tls_ca_cert_file": crt_file,
|
||||
"raise_error": true,
|
||||
})
|
||||
|
||||
field_transform_to_qry_param(field,map) = finala {
|
||||
mid := {concat(".",[field,key]): val | val := map[key]}
|
||||
finala := label_map_to_query_string(mid)
|
||||
}
|
||||
label_map_to_query_string(map) = concat(",", [str | val := map[key]; str := concat("%3D", [key, val])])
|
||||
`
|
||||
20
vendor/github.com/armosec/capacketsgo/opapolicy/resources/rego/modules/cronJob.reg
generated
vendored
20
vendor/github.com/armosec/capacketsgo/opapolicy/resources/rego/modules/cronJob.reg
generated
vendored
@@ -1,20 +0,0 @@
|
||||
package armo_builtins
|
||||
|
||||
# import data.kubernetes.api.client as client
|
||||
import data.cautils as cautils
|
||||
|
||||
|
||||
# alert cronjobs
|
||||
|
||||
#handles cronjob
|
||||
deny[msga] {
|
||||
|
||||
wl := input[_]
|
||||
wl.kind == "CronJob"
|
||||
msga := {
|
||||
"alertMessage": sprintf("the following cronjobs are defined: %v", [wl]),
|
||||
"alertScore": 2,
|
||||
"packagename": "armo_builtins",
|
||||
"alertObject": wl
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package armo_builtins
|
||||
|
||||
import data.kubernetes.api.client as client
|
||||
|
||||
|
||||
# input: pod
|
||||
# apiversion: v1
|
||||
# does:
|
||||
# returns the external facing services of that pod
|
||||
#
|
||||
#
|
||||
deny[msga] {
|
||||
pod := input[_]
|
||||
podns := pod.metadata.namespace
|
||||
podname := getName(pod.metadata)
|
||||
# pod := client.query_name_ns("pods","frontend-86c5ffb485-kfp9d", "default")
|
||||
labels := pod.body.metadata.labels
|
||||
filtered_labels := json.remove(labels, ["pod-template-hash"])
|
||||
|
||||
cluster_resource := client.query_all(
|
||||
"services"
|
||||
)
|
||||
|
||||
|
||||
services := [svc | cluster_resource.body.items[i].metadata.namespace == podns; svc := cluster_resource.body.items[i]]
|
||||
service := services[_]
|
||||
np_or_lb := {"NodePort", "LoadBalancer"}
|
||||
np_or_lb[service.spec.type]
|
||||
service.spec.selector == filtered_labels
|
||||
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("pod %v/%v exposed services: %v\n", [podns,podname,service]),
|
||||
"alertScore": 7,
|
||||
"alertObject": {"service":service,"labels":filtered_labels, "podname":podname,"namespace":podns}
|
||||
}
|
||||
}
|
||||
|
||||
getName(metadata) = name {
|
||||
name := metadata.generateName
|
||||
}
|
||||
getName(metadata) = name {
|
||||
name := metadata.name
|
||||
}
|
||||
57
vendor/github.com/armosec/capacketsgo/opapolicy/resources/rego/modules/hostpath.reg
generated
vendored
57
vendor/github.com/armosec/capacketsgo/opapolicy/resources/rego/modules/hostpath.reg
generated
vendored
@@ -1,57 +0,0 @@
|
||||
package armo_builtins
|
||||
#import data.kubernetes.api.client as client
|
||||
import data.cautils as cautils
|
||||
|
||||
# input: pod
|
||||
# apiversion: v1
|
||||
# does:
|
||||
# returns hostPath volumes
|
||||
#
|
||||
#
|
||||
deny[msga] {
|
||||
pod := input[_]
|
||||
pod.kind == "Pod"
|
||||
volumes := pod.spec.volumes
|
||||
volume := volumes[_]
|
||||
# crsrcs.body.spec.containers[_].volumeMounts[_].name = volume.name
|
||||
volume.hostPath
|
||||
podname := cautils.getPodName(pod.metadata)
|
||||
obj := {"volume":volume,"podname": podname}
|
||||
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("pod: %v has {%v,%v} ashostPath volume \n\n\n", [podname, volume]),
|
||||
"alertScore": 7,
|
||||
"alertObject": [obj]
|
||||
}
|
||||
}
|
||||
|
||||
isRWMount(mount) {
|
||||
not mount.readOnly
|
||||
}
|
||||
isRWMount(mount) {
|
||||
mount.readOnly == false
|
||||
}
|
||||
|
||||
|
||||
#handles majority of workload resources
|
||||
deny[msga] {
|
||||
|
||||
wl := input[_]
|
||||
spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"}
|
||||
spec_template_spec_patterns[wl.kind]
|
||||
volumes := wl.spec.template.spec.volumes
|
||||
volume := volumes[_]
|
||||
volume.hostPath
|
||||
wlname := cautils.getPodName(wl.metadata)
|
||||
obj := {"volume":volume,"podname": wlname}
|
||||
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("%v: %v has {%v,%v} as hostPath volume\n\n\n", [wl.kind,wlname, volume]),
|
||||
"alertScore": 7,
|
||||
"alertObject": [obj]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
56
vendor/github.com/armosec/capacketsgo/opapolicy/resources/rego/modules/privileged.reg
generated
vendored
56
vendor/github.com/armosec/capacketsgo/opapolicy/resources/rego/modules/privileged.reg
generated
vendored
@@ -1,56 +0,0 @@
|
||||
package armo_builtins
|
||||
|
||||
#import data.kubernetes.api.client as client
|
||||
|
||||
|
||||
# Deny mutating action unless user is in group owning the resource
|
||||
|
||||
|
||||
#privileged pods
|
||||
deny[msga] {
|
||||
|
||||
|
||||
pod := input[_]
|
||||
containers := pod.spec.containers[_]
|
||||
containers.securityContext.privileged == true
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("the following pods are defined as privileged: %v", [pod]),
|
||||
"alertScore": 3,
|
||||
"alertObject": pod,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#handles majority of workload resources
|
||||
deny[msga] {
|
||||
|
||||
wl := input[_]
|
||||
spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"}
|
||||
spec_template_spec_patterns[wl.kind]
|
||||
containers := wl.spec.template.spec.containers[_]
|
||||
containers.securityContext.privileged == true
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("the following workloads are defined as privileged: %v", [wl]),
|
||||
"alertScore": 3,
|
||||
"alertObject": wl,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#handles cronjob
|
||||
deny[msga] {
|
||||
|
||||
wl := input[_]
|
||||
wl.kind == "CronJob"
|
||||
containers := wl.spec.jobTemplate.spec.template.spec.containers[_]
|
||||
containers.securityContext.privileged == true
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("the following cronjobs are defined as privileged: %v", [wl]),
|
||||
"alertScore": 3,
|
||||
"alertObject": wl,
|
||||
}
|
||||
}
|
||||
98
vendor/github.com/armosec/capacketsgo/opapolicy/resources/rego/modules/rbacsecrets.reg
generated
vendored
98
vendor/github.com/armosec/capacketsgo/opapolicy/resources/rego/modules/rbacsecrets.reg
generated
vendored
@@ -1,98 +0,0 @@
|
||||
package armo_builtins
|
||||
import data.kubernetes.api.client as client
|
||||
import data.cautils as cautils
|
||||
|
||||
|
||||
# input: None
|
||||
# apiversion: v1
|
||||
# does:
|
||||
# returns roles+ related subjects in rolebinding
|
||||
|
||||
|
||||
deny[msga] {
|
||||
# rsrc := client.query_all("roles")
|
||||
# role := rsrc.body.items[_]
|
||||
role := input[_]
|
||||
role.kind == "Role"
|
||||
rule := role.rules[_]
|
||||
cautils.list_contains(rule.resources,"secrets")
|
||||
canViewSecrets(rule)
|
||||
rbsrc := client.query_all("rolebindings")
|
||||
rolebinding := rbsrc.body.items[_]
|
||||
rolebinding.roleRef.kind == "Role"
|
||||
rolebinding.roleRef.name == role.metadata.name
|
||||
|
||||
|
||||
msga := {
|
||||
"alertMessage": sprintf("the following users: %v , got read secret access roles", [rolebinding.subjects]),
|
||||
"alertScore": 9,
|
||||
"packagename": "armo_builtins",
|
||||
"alertObject": {"role":role,"users":rolebinding.subjects}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
# input: None
|
||||
# apiversion: v1
|
||||
# does:
|
||||
# returns clusterroles+ related subjects in rolebinding
|
||||
|
||||
|
||||
deny[msga] {
|
||||
# rsrc := client.query_all("clusterroles")
|
||||
# role := rsrc.body.items[_]
|
||||
role := input[_]
|
||||
role.kind == "ClusterRole"
|
||||
rule := role.rules[_]
|
||||
cautils.list_contains(rule.resources,"secrets")
|
||||
canViewSecrets(rule)
|
||||
rbsrc := client.query_all("rolebindings")
|
||||
rolebinding := rbsrc.body.items[_]
|
||||
rolebinding.roleRef.kind == "ClusterRole"
|
||||
rolebinding.roleRef.name == role.metadata.name
|
||||
|
||||
|
||||
msga := {
|
||||
"alertMessage": sprintf("the following users: %v , got read secret access roles", [rolebinding.subjects]),
|
||||
"alertScore": 9,
|
||||
"packagename": "armo_builtins",
|
||||
"alertObject": {"clusterrole":role,"users":rolebinding.subjects}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# input: None
|
||||
# apiversion: v1
|
||||
# does:
|
||||
# returns clusterroles+ related subjects in clusterrolebinding
|
||||
#
|
||||
#
|
||||
deny[msga] {
|
||||
# rsrc := client.query_all("clusterroles")
|
||||
# role := rsrc.body.items[_]
|
||||
role := input[_]
|
||||
role.kind == "ClusterRole"
|
||||
rule := role.rules[_]
|
||||
cautils.list_contains(rule.resources,"secrets")
|
||||
canViewSecrets(rule)
|
||||
rbsrc := client.query_all("clusterrolebindings")
|
||||
rolebinding := rbsrc.body.items[_]
|
||||
rolebinding.roleRef.kind == "ClusterRole"
|
||||
rolebinding.roleRef.name == role.metadata.name
|
||||
|
||||
|
||||
msga := {
|
||||
"alertMessage": sprintf("the following users: %v , got read secret access roles", [rolebinding.subjects]),
|
||||
"alertScore": 9,
|
||||
"packagename": "armo_builtins",
|
||||
"alertObject": {"clusterrole":role,"users":rolebinding.subjects}
|
||||
}
|
||||
}
|
||||
|
||||
canViewSecrets(rule) {
|
||||
cautils.list_contains(rule.verbs,"get")
|
||||
}
|
||||
canViewSecrets(rule) {
|
||||
cautils.list_contains(rule.verbs,"watch")
|
||||
}
|
||||
64
vendor/github.com/armosec/capacketsgo/opapolicy/resources/rego/modules/rwhostpath.reg
generated
vendored
64
vendor/github.com/armosec/capacketsgo/opapolicy/resources/rego/modules/rwhostpath.reg
generated
vendored
@@ -1,64 +0,0 @@
|
||||
package armo_builtins
|
||||
#import data.kubernetes.api.client as client
|
||||
import data.cautils as cautils
|
||||
|
||||
# input: pod
|
||||
# apiversion: v1
|
||||
# does:
|
||||
# returns rw hostpath volumes of that pod
|
||||
#
|
||||
#
|
||||
deny[msga] {
|
||||
pod := input[_]
|
||||
pod.kind == "Pod"
|
||||
volumes := pod.spec.volumes
|
||||
volume := volumes[_]
|
||||
# crsrcs.body.spec.containers[_].volumeMounts[_].name = volume.name
|
||||
mount := pod.spec.containers[_].volumeMounts[_]
|
||||
mount.name == volume.name
|
||||
volume.hostPath
|
||||
isRWMount(mount)
|
||||
podname := cautils.getPodName(pod.metadata)
|
||||
obj := {"volume":volume,"mount":mount,"podname": podname}
|
||||
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("pod: %v has {%v,%v} as rw hostPath volume and volumemount pair\n\n\n", [podname, volume,mount]),
|
||||
"alertScore": 7,
|
||||
"alertObject": [obj],
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
isRWMount(mount) {
|
||||
not mount.readOnly
|
||||
}
|
||||
isRWMount(mount) {
|
||||
mount.readOnly == false
|
||||
}
|
||||
|
||||
|
||||
#handles majority of workload resources
|
||||
deny[msga] {
|
||||
|
||||
wl := input[_]
|
||||
spec_template_spec_patterns := {"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job"}
|
||||
spec_template_spec_patterns[wl.kind]
|
||||
volumes := wl.spec.template.spec.volumes
|
||||
volume := volumes[_]
|
||||
mount := wl.spec.template.spec.containers[_].volumeMounts[_]
|
||||
mount.name == volume.name
|
||||
volume.hostPath
|
||||
isRWMount(mount)
|
||||
wlname := cautils.getPodName(wl.metadata)
|
||||
obj := {"volume":volume,"mount":mount,"podname": wlname}
|
||||
|
||||
msga := {
|
||||
"packagename": "armo_builtins",
|
||||
"alertMessage": sprintf("%v: %v has {%v,%v} as rw hostPath volume and volumemount pair\n\n\n", [wl.kind,wlname, volume,mount]),
|
||||
"alertScore": 7,
|
||||
"alertObject": [obj],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
package armo_builtins
|
||||
import data.kubernetes.api.client as client
|
||||
import data.cautils as cautils
|
||||
|
||||
# input: pod
|
||||
# apiversion: v1
|
||||
# does:
|
||||
# returns the external facing services of that pod
|
||||
#
|
||||
#
|
||||
deny[msga] {
|
||||
pod := input[_]
|
||||
podns := pod.metadata.namespace
|
||||
podname := cautils.getPodName(pod.metadata)
|
||||
# pod := client.query_name_ns("pods", "catalog-mongo-6f468d99b4-pn242", "default")
|
||||
labels := pod.body.metadata.labels
|
||||
filtered_labels := json.remove(labels, ["pod-template-hash"])
|
||||
|
||||
cluster_resource := client.query_all(
|
||||
"services"
|
||||
)
|
||||
|
||||
services := [svc | cluster_resource.body.items[i].metadata.namespace == podns; svc := cluster_resource.body.items[i]]
|
||||
service := services[_]
|
||||
service.spec.selector == filtered_labels
|
||||
|
||||
hasSSHPorts(service)
|
||||
|
||||
msga := {
|
||||
"alertMessage": sprintf("pod %v/%v exposed by SSH services: %v\n", [podns,podname,service]),
|
||||
"packagename": "armo_builtins",
|
||||
"alertScore": 7,
|
||||
"alertObject": [{"pod":pod,"service":{service}}]
|
||||
}
|
||||
}
|
||||
|
||||
hasSSHPorts(service) {
|
||||
port := service.spec.ports[_]
|
||||
port.port == 22
|
||||
}
|
||||
|
||||
|
||||
hasSSHPorts(service) {
|
||||
port := service.spec.ports[_]
|
||||
port.port == 2222
|
||||
}
|
||||
|
||||
hasSSHPorts(service) {
|
||||
port := service.spec.ports[_]
|
||||
port.targetPort == 22
|
||||
}
|
||||
|
||||
|
||||
hasSSHPorts(service) {
|
||||
port := service.spec.ports[_]
|
||||
port.targetPort == 2222
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"guid": "3b0467c9-488d-c244-99d0-90fbf600aaff",
|
||||
"name": "[Builtin] rule-deny-access-to-secrets",
|
||||
"creationTime": "2019-09-04T12:04:58.461455",
|
||||
"description": "determines which users can get/list/watch secrets",
|
||||
"attributes": {
|
||||
"m$K8sThreatMatrix": "Credential Access::List k8s Secrets"
|
||||
},
|
||||
"ruleDependencies": [
|
||||
{
|
||||
"packageName":"cautils"
|
||||
},
|
||||
{
|
||||
"packageName":"kubernetes.api.client"
|
||||
}
|
||||
],
|
||||
"remediation": "",
|
||||
"match": [
|
||||
{
|
||||
"resources": [
|
||||
"Role","ClusterRole"
|
||||
],
|
||||
"apiVersions": [
|
||||
"v1"
|
||||
],
|
||||
"apiGroups": [
|
||||
"rbac.authorization.k8s.io"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ruleLanguage": "Rego",
|
||||
"rule": "\npackage armo_builtins\nimport data.kubernetes.api.client as client\nimport data.cautils as cautils\n\n\n# input: None\n# apiversion: v1\n# does: \n#\treturns roles+ related subjects in rolebinding\n\n\ndeny[msga] {\n\t# rsrc := client.query_all(\"roles\")\n\t# role := rsrc.body.items[_]\n\trole := input[_]\n\trole.kind == \"Role\"\n\trule := role.rules[_]\n\tcautils.list_contains(rule.resources,\"secrets\")\n\tcanViewSecrets(rule)\n\trbsrc := client.query_all(\"rolebindings\")\n\trolebinding := rbsrc.body.items[_]\n\trolebinding.roleRef.kind == \"Role\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n \n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following users: %v , got read secret access roles\", [rolebinding.subjects]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 9,\n\t\t\"alertObject\": {\"role\":role,\"users\":rolebinding.subjects}\n\t\n\t}\n}\n\n\n\n# input: None\n# apiversion: v1\n# does: \n#\treturns clusterroles+ related subjects in rolebinding\n\n\ndeny[msga] {\n\t# rsrc := client.query_all(\"clusterroles\")\n\t# role := rsrc.body.items[_]\n\trole := input[_]\n\trole.kind == \"ClusterRole\"\n\trule := role.rules[_]\n\tcautils.list_contains(rule.resources,\"secrets\")\n\tcanViewSecrets(rule)\n\trbsrc := client.query_all(\"rolebindings\")\n\trolebinding := rbsrc.body.items[_]\n\trolebinding.roleRef.kind == \"ClusterRole\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n \n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following users: %v , got read secret access roles\", [rolebinding.subjects]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 9,\n\t\t\"alertObject\": {\"clusterrole\":role,\"users\":rolebinding.subjects}\n\t\n\t}\n}\n\n\n# input: None\n# apiversion: v1\n# does: \n#\treturns clusterroles+ related subjects in clusterrolebinding\n#\n#\ndeny[msga] {\n\t# rsrc := client.query_all(\"clusterroles\")\n\t# role := rsrc.body.items[_]\n\trole := input[_]\n\trole.kind == \"ClusterRole\"\n\trule := role.rules[_]\n\tcautils.list_contains(rule.resources,\"secrets\")\n\tcanViewSecrets(rule)\n\trbsrc := client.query_all(\"clusterrolebindings\")\n\trolebinding := rbsrc.body.items[_]\n\trolebinding.roleRef.kind == \"ClusterRole\"\n\trolebinding.roleRef.name == role.metadata.name\n\t\n \n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"the following users: %v , got read secret access roles\", [rolebinding.subjects]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 9,\n\t\t\"alertObject\": {\"clusterrole\":role,\"users\":rolebinding.subjects}\n\t\n\t}\n}\n\ncanViewSecrets(rule) {\n\tcautils.list_contains(rule.verbs,\"get\")\n}\ncanViewSecrets(rule) {\n\tcautils.list_contains(rule.verbs,\"watch\")\n}\n"
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"guid": "3b0467c9-488d-c244-99d0-90fbf600aaff",
|
||||
"name": "[Builtin] rule-can-ssh-to-pod",
|
||||
"creationTime": "2019-09-04T12:04:58.461455",
|
||||
"description": "denies pods with SSH ports opened(22/222)",
|
||||
"attributes": {
|
||||
"microsoftK8sThreatMatrix": "val1"
|
||||
},
|
||||
"ruleDependencies": [
|
||||
{
|
||||
"packageName":"cautils"
|
||||
},
|
||||
{
|
||||
"packageName":"kubernetes.api.client"
|
||||
}
|
||||
],
|
||||
"remediation": "create a network policy that protects SSH ports",
|
||||
"match": [
|
||||
{
|
||||
"resources": [
|
||||
"Pods"
|
||||
],
|
||||
"apiVersions": [
|
||||
"v1"
|
||||
],
|
||||
"apiGroups": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ruleLanguage": "Rego",
|
||||
"rule": "\npackage armo_builtins\nimport data.kubernetes.api.client as client\nimport data.cautils as cautils\n\n# input: pod\n# apiversion: v1\n# does: \n#\treturns the external facing services of that pod\n#\n#\ndeny[msga] {\n\tpod := input[_]\n\tpodns := pod.metadata.namespace\n\tpodname := cautils.getPodName(pod.metadata)\n\t# pod := client.query_name_ns(\"pods\", \"catalog-mongo-6f468d99b4-pn242\", \"default\")\n\tlabels := pod.body.metadata.labels\n\tfiltered_labels := json.remove(labels, [\"pod-template-hash\"])\n \n\t cluster_resource := client.query_all(\n\t \t\"services\"\n\t )\n\n\tservices := [svc | cluster_resource.body.items[i].metadata.namespace == podns; svc := cluster_resource.body.items[i]]\n\tservice := \tservices[_]\n\tservice.spec.selector == filtered_labels\n \n\thasSSHPorts(service)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"pod %v/%v exposed by SSH services: %v\n\", [podns,podname,service]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": [{\"pod\":pod,\"service\":{service}}]\n\t\n\t}\n}\n\nhasSSHPorts(service) {\n\tport := service.spec.ports[_]\n\tport.port == 22\n}\n\n\nhasSSHPorts(service) {\n\tport := service.spec.ports[_]\n\tport.port == 2222\n}\n\nhasSSHPorts(service) {\n\tport := service.spec.ports[_]\n\tport.targetPort == 22\n}\n\n\nhasSSHPorts(service) {\n\tport := service.spec.ports[_]\n\tport.targetPort == 2222\n}\n"
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"guid": "",
|
||||
"name": "[Builtin] rule-identify-blacklisted-image-registries",
|
||||
"creationTime": "",
|
||||
"description": "Identifying if pod container images are from unallowed registries",
|
||||
"attributes": {
|
||||
"m$K8sThreatMatrix": "Initial Access::Compromised images in registry"
|
||||
},
|
||||
"ruleDependencies": [
|
||||
{
|
||||
"packageName": "cautils"
|
||||
},
|
||||
{
|
||||
"packageName": "kubernetes.api.client"
|
||||
}
|
||||
],
|
||||
"remediation": "Use images from safe registry",
|
||||
"match": [
|
||||
{
|
||||
"resources": [
|
||||
"Pods"
|
||||
],
|
||||
"apiVersions": [
|
||||
"v1"
|
||||
],
|
||||
"apiGroups": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ruleLanguage": "Rego",
|
||||
"rule": "\npackage armo_builtins\n# Check for images from blacklisted repos\n\nuntrusted_registries(z) = x {\n\tx := [\"015253967648.dkr.ecr.eu-central-1.amazonaws.com/\"]\t\n}\n\npublic_registries(z) = y{\n\ty := [\"quay.io/kiali/\",\"quay.io/datawire/\",\"quay.io/keycloak/\",\"quay.io/bitnami/\"]\n}\n\nuntrustedImageRepo[msga] {\n\tpod := input[_]\n\tk := pod.kind\n\tk == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n\timage := container.image\n repo_prefix := untrusted_registries(image)[_]\n\tstartswith(image, repo_prefix)\n\tselfLink := pod.metadata.selfLink\n\tcontainerName := container.name\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"image '%v' in container '%s' in [%s] comes from untrusted registry\", [image, containerName, selfLink]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 2,\n\t\t\"alertObject\": [{\"pod\":pod}]\n\t}\n}\n\nuntrustedImageRepo[msga] {\n pod := input[_]\n\tk := pod.kind\n\tk == \"Pod\"\n\tcontainer := pod.spec.containers[_]\n\timage := container.image\n repo_prefix := public_registries(image)[_]\n\tstartswith(pod, repo_prefix)\n\tselfLink := input.metadata.selfLink\n\tcontainerName := container.name\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"image '%v' in container '%s' in [%s] comes from public registry\", [image, containerName, selfLink]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 1,\n\t\t\"alertObject\": [{\"pod\":pod}]\n\t}\n}"
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"guid": "3b0467c9-488d-c244-99d0-90fbf600aaff",
|
||||
"name": "[Builtin] rule-pod-external-facing",
|
||||
"creationTime": "2019-09-04T12:04:58.461455",
|
||||
"description": "denies pods with external facing services, grabs related services",
|
||||
"attributes": {
|
||||
"microsoftK8sThreatMatrix": "val1"
|
||||
},
|
||||
"ruleDependencies": [
|
||||
{
|
||||
"packageName":"kubernetes.api.client"
|
||||
}
|
||||
],
|
||||
"remediation": "create a network policy that controls which protect your cluster from unwanted connections and the outside world",
|
||||
"match": [
|
||||
{
|
||||
"resources": [
|
||||
"Pods"
|
||||
],
|
||||
"apiVersions": [
|
||||
"v1"
|
||||
],
|
||||
"apiGroups": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ruleLanguage": "Rego",
|
||||
"rule": "\npackage armo_builtins\n\nimport data.kubernetes.api.client as client\n\n\n# input: pod\n# apiversion: v1\n# does: \n#\treturns the external facing services of that pod\n#\n#\ndeny[msga] {\n\tpod := input[_]\n\tpodns := pod.metadata.namespace\n\tpodname := getName(pod.metadata)\n\t# pod := client.query_name_ns(\"pods\",\"frontend-86c5ffb485-kfp9d\", \"default\")\n\tlabels := pod.body.metadata.labels\n\tfiltered_labels := json.remove(labels, [\"pod-template-hash\"])\n \n\t cluster_resource := client.query_all(\n\t \t\"services\"\n\t )\n\n\n\tservices := [svc | cluster_resource.body.items[i].metadata.namespace == podns; svc := cluster_resource.body.items[i]]\n\tservice := \tservices[_]\n\tnp_or_lb := {\"NodePort\", \"LoadBalancer\"}\n\tnp_or_lb[service.spec.type]\n\tservice.spec.selector == filtered_labels\n \n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"pod %v/%v exposed services: %v\n\", [podns,podname,service]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": {\"service\":service,\"labels\":filtered_labels, \"podname\":podname,\"namespace\":podns}\n\t\n\t}\n}\n\ngetName(metadata) = name {\n\tname := metadata.generateName\n}\ngetName(metadata) = name {\n\tname := metadata.name\n}\n"
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"guid": "3b0467c9-488d-c244-99d0-90fbf600aaff",
|
||||
"name": "[Builtin] alert-any-hostpath",
|
||||
"creationTime": "2019-09-04T12:04:58.461455",
|
||||
"description": "determines if any workload contains a hostPath volume",
|
||||
"attributes": {
|
||||
"m$K8sThreatMatrix": "Privilege Escalation::hostPath mount"
|
||||
},
|
||||
"ruleDependencies": [
|
||||
{
|
||||
"packageName":"cautils"
|
||||
}
|
||||
],
|
||||
"remediation": "consider if hostPath is really necessary - reading sensitive data like hostPath credentials might endanger cluster, if so consider encrypting the data",
|
||||
|
||||
"match": [
|
||||
{
|
||||
"resources": [
|
||||
"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod"
|
||||
],
|
||||
"apiVersions": [
|
||||
"v1"
|
||||
],
|
||||
"apiGroups": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ruleLanguage": "Rego",
|
||||
"rule": "\npackage armo_builtins\nimport data.kubernetes.api.client as client\nimport data.cautils as cautils\n\n# input: pod\n# apiversion: v1\n# does: \n#\treturns hostPath volumes\n#\n#\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n volumes := pod.spec.volumes\n volume := volumes[_]\n # crsrcs.body.spec.containers[_].volumeMounts[_].name = volume.name\n volume.hostPath\n podname := cautils.getPodName(pod.metadata)\n obj := {\"volume\":volume,\"podname\": podname}\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"pod: %v has {%v,%v} ashostPath volume \n\n\n\", [podname, volume]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": [obj],\n\t\n\t}\n}\n\nisRWMount(mount) {\n not mount.readOnly\n}\nisRWMount(mount) {\n mount.readOnly == false\n}\n\n\n#handles majority of workload resources\ndeny[msga] {\n\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n volumes := wl.spec.template.spec.volumes\n volume := volumes[_]\n volume.hostPath\n wlname := cautils.getPodName(wl.metadata)\n obj := {\"volume\":volume,\"podname\": wlname}\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has {%v,%v} as hostPath volume\n\n\n\", [wl.kind,wlname, volume]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 7,\n\t\t\"alertObject\": [obj],\n\t\n\t}\n}\n\n\n"
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"guid": "82f19070-2826-4fe4-a079-f5f7e7a1b04d",
|
||||
"name": "[Builtin] instance-metadata-api-access",
|
||||
"attributes": {
|
||||
"m$K8sThreatMatrix": "Credential Access::Instance Metadata API"
|
||||
},
|
||||
"creationTime": "2021-04-25T10:48:48.861806",
|
||||
"rule": "package armo_builtins\n# Check for images from blacklisted repos\n\nmetadata_azure(z) = http.send({\n\t\"url\": \"http://169.254.169.254/metadata/instance?api-version=2020-09-01\",\n\t\"method\": \"get\",\n\t\"headers\": {\"Metadata\": \"true\"},\n\t\"raise_error\": true,\t\n})\n\nmetadata_gcp(z) = http.send({\n\t\"url\": \"http://169.254.169.254/computeMetadata/v1/?alt=json&recursive=true\",\n\t\"method\": \"get\",\n\t\"headers\": {\"Metadata-Flavor\": \"Google\"},\n\t\"raise_error\": true,\t\n})\n\nmetadata_aws(z) = metadata_object { \n\thostname := http.send({\n\t\"url\": \"http://169.254.169.254/latest/meta-data/local-hostname\",\n\t\"method\": \"get\",\n\t\"raise_error\": true,\t\n })\n\tmetadata_object := {\n\t\t\"raw_body\": hostname.raw_body,\n\t\t\"hostname\" : hostname.raw_body,\n\t\t\"status_code\" : hostname.status_code\n\t}\n}\n\nazure_metadata[msga] {\t\n\tmetadata_object := metadata_azure(\"aaa\")\n\tmetadata_object.status_code == 200\n\tnode_name := metadata_object.body.compute.name\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Node '%s' has access to Instance Metadata Services of Azure.\", [node_name]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 1,\n\t\t\"alertObject\": [{\"nodeMetadata\":metadata_object.body}]\n\t}\n}\n\ngcp_metadata[msga] {\t\n\tmetadata_object := metadata_gcp(\"aaa\")\n\tmetadata_object.status_code == 200\n\tnode_name := metadata_object.body.instance.hostname\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Node '%s' has access to Instance Metadata Services of GCP.\", [node_name]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 1,\n\t\t\"alertObject\": [{\"nodeMetadata\": metadata_object.raw_body}]\n\t}\n}\n\naws_metadata[msga] {\t\n\tmetadata_object := metadata_aws(\"aaa\")\n\tmetadata_object.status_code == 200\n\tnode_name := metadata_object.hostname\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Node '%s' has access to Instance Metadata Services of AWS.\", [node_name]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 1,\n\t\t\"alertObject\": [{\"nodeMetadata\": metadata_object.raw_body}]\n\t}\n}",
|
||||
"ruleLanguage": "Rego",
|
||||
"match": [
|
||||
{
|
||||
"apiGroups": [
|
||||
"*"
|
||||
],
|
||||
"apiVersions": [
|
||||
"*"
|
||||
],
|
||||
"resources": [
|
||||
"nodes"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ruleDependencies": [],
|
||||
"description": "Checks if there is access from the nodes to cloud prividers instance metadata services",
|
||||
"remediation": "From https://attack.mitre.org/techniques/T1552/005/ :Option A: Disable or Remove Feature or Program, Option B: Filter Network Traffic",
|
||||
"ruleQuery": ""
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"guid": "[Builtin] 3b0467c9-488d-c244-99d0-90fbf600aaff",
|
||||
"name": "rule-deny-cronjobs",
|
||||
"creationTime": "2019-09-04T12:04:58.461455",
|
||||
"description": "determines if it's cronjob",
|
||||
"attributes": {
|
||||
"m$K8sThreatMatrix": "Persistence::Cronjob"
|
||||
},
|
||||
"ruleDependencies": [
|
||||
{
|
||||
"packageName":"cautils"
|
||||
}
|
||||
],
|
||||
"remediation": "",
|
||||
"match": [
|
||||
{
|
||||
"resources": [
|
||||
"CronJob"
|
||||
],
|
||||
"apiVersions": [
|
||||
"v1beta1"
|
||||
],
|
||||
"apiGroups": [
|
||||
"batch"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ruleLanguage": "Rego",
|
||||
"rule": "\npackage armo_builtins\n\n# import data.kubernetes.api.client as client\nimport data.cautils as cautils\n\n\n# alert cronjobs\n\n#handles cronjob\ndeny[msga] {\n\n\twl := input[_]\n\twl.kind == \"CronJob\"\n msga := {\n\t\t\"alertMessage\": sprintf(\"the following cronjobs are defined: %v\", [wl]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 2,\n\t\t\"alertObject\": wl\n\t\n\t}\n}\n"
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"guid": "",
|
||||
"name": "[Builtin] rule-privilege-escalation",
|
||||
"creationTime": "2019-09-04T12:04:58.461455",
|
||||
"description": "determines if pods/deployments defined as privileged true",
|
||||
"attributes": {
|
||||
"mitre": "Privilege Escalation",
|
||||
"mitreCode": "TA0004",
|
||||
"m$K8sThreatMatrix": "Privilege Escalation::privileged container"
|
||||
},
|
||||
"ruleDependencies": [
|
||||
],
|
||||
"remediation": "avoid defining pods as privilleged",
|
||||
"match": [
|
||||
{
|
||||
"resources": [
|
||||
"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"
|
||||
],
|
||||
"apiVersions": [
|
||||
"v1"
|
||||
],
|
||||
"apiGroups": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ruleLanguage": "Rego",
|
||||
"rule": "\npackage armo_builtins\n\nimport data.kubernetes.api.client as client\nimport data.designators as scope\nimport data.cautils as cautils\n\n\n# Deny mutating action unless user is in group owning the resource\n\n\n#privileged pods\ndeny[msga] {\n\n \n\tpod := input[_]\n\tcontainers := pod.spec.containers[_]\n\tcontainers.securityContext.privileged == true\n msga := {\n\t\t\"alertMessage\": sprintf(\"the following pods are defined as privileged: %v\", [pod]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 3,\n\t\t\"alertObject\": pod,\n\t\n\t}\n}\n\n\n#handles majority of workload resources\ndeny[msga] {\n\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n\tcontainers := wl.spec.template.spec.containers[_]\n\tcontainers.securityContext.privileged == true\n msga := {\n\t\t\"alertMessage\": sprintf(\"the following workloads are defined as privileged: %v\", [wl]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 3,\n\t\t\"alertObject\": wl,\n\t\n\t}\n}\n\n\n\n#handles cronjob\ndeny[msga] {\n\n\twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainers := wl.spec.jobTemplate.spec.template.spec.containers[_]\n\tcontainers.securityContext.privileged == true\n msga := {\n\t\t\"alertMessage\": sprintf(\"the following cronjobs are defined as privileged: %v\", [wl]),\n\t\t\"alert\": true,\n\t\t\"prevent\": false,\n\t\t\"alertScore\": 3,\n\t\t\"alertObject\": wl,\n\t\n\t}\n}\n\n"
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"guid": "3b0467c9-488d-c244-99d0-90fbf600aaff",
|
||||
"name": "[Builtin] alert-rw-hostpath",
|
||||
"creationTime": "2019-09-04T12:04:58.461455",
|
||||
"description": "determines if any workload contains a hostPath volume with rw permissions",
|
||||
"attributes": {
|
||||
"m$K8sThreatMatrix": "Persistance::Writable hostPath mount"
|
||||
},
|
||||
"ruleDependencies": [
|
||||
{
|
||||
"packageName":"cautils"
|
||||
}
|
||||
],
|
||||
"remediation": "consider if hostPath is really necessary- sensitive data like hostPath credentials might endanger cluster, if so consider encrypting the data",
|
||||
|
||||
"match": [
|
||||
{
|
||||
"resources": [
|
||||
"Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod"
|
||||
],
|
||||
"apiVersions": [
|
||||
"v1"
|
||||
],
|
||||
"apiGroups": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ruleLanguage": "Rego",
|
||||
"rule": "\"\\npackage armo_builtins\\nimport data.kubernetes.api.client as client\\nimport data.cautils as cautils\\n\\n# input: pod\\n# apiversion: v1\\n# does: \\n#\\treturns hostPath volumes\\n#\\n#\\ndeny[msga] {\\n pod := input[_]\\n pod.kind == \\\"Pod\\\"\\n volumes := pod.spec.volumes\\n volume := volumes[_]\\n # crsrcs.body.spec.containers[_].volumeMounts[_].name = volume.name\\n volume.hostPath\\n podname := cautils.getPodName(pod.metadata)\\n obj := {\\\"volume\\\":volume,\\\"podname\\\": podname}\\n\\n\\tmsga := {\\n\\t\\t\\\"alertMessage\\\": sprintf(\\\"pod: %v has {%v,%v} ashostPath volume \\n\\n\\n\\\", [podname, volume]),\\n\\t\\t\\\"alert\\\": true,\\n\\t\\t\\\"prevent\\\": false,\\n\\t\\t\\\"alertScore\\\": 7,\\n\\t\\t\\\"alertObject\\\": [obj],\\n\\t\\n\\t}\\n}\\n\\nisRWMount(mount) {\\n not mount.readOnly\\n}\\nisRWMount(mount) {\\n mount.readOnly == false\\n}\\n\\n\\n#handles majority of workload resources\\ndeny[msga] {\\n\\n\\twl := input[_]\\n\\tspec_template_spec_patterns := {\\\"Deployment\\\",\\\"ReplicaSet\\\",\\\"DaemonSet\\\",\\\"StatefulSet\\\",\\\"Job\\\"}\\n\\tspec_template_spec_patterns[wl.kind]\\n volumes := wl.spec.template.spec.volumes\\n volume := volumes[_]\\n volume.hostPath\\n wlname := cautils.getPodName(wl.metadata)\\n obj := {\\\"volume\\\":volume,\\\"podname\\\": wlname}\\n\\n\\tmsga := {\\n\\t\\t\\\"alertMessage\\\": sprintf(\\\"%v: %v has {%v,%v} as hostPath volume\\n\\n\\n\\\", [wl.kind,wlname, volume]),\\n\\t\\t\\\"alert\\\": true,\\n\\t\\t\\\"prevent\\\": false,\\n\\t\\t\\\"alertScore\\\": 7,\\n\\t\\t\\\"alertObject\\\": [obj],\\n\\t\\n\\t}\\n}\\n\\n\\n\""
|
||||
}
|
||||
125
vendor/github.com/armosec/capacketsgo/opapolicy/resources/resourcesutils.go
generated
vendored
125
vendor/github.com/armosec/capacketsgo/opapolicy/resources/resourcesutils.go
generated
vendored
@@ -1,125 +0,0 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/armopa/storage"
|
||||
"github.com/armosec/armopa/storage/inmem"
|
||||
"github.com/armosec/armopa/util"
|
||||
"github.com/armosec/capacketsgo/k8sinterface"
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
var (
|
||||
RegoDependenciesPath = "/resources/rego/dependencies"
|
||||
)
|
||||
|
||||
type RegoDependenciesData struct {
|
||||
K8sConfig RegoK8sConfig `json:"k8sconfig"`
|
||||
}
|
||||
|
||||
type RegoK8sConfig struct {
|
||||
Token string `json:"token"`
|
||||
IP string `json:"ip"`
|
||||
Host string `json:"host"`
|
||||
Port string `json:"port"`
|
||||
CrtFile string `json:"crtfile"`
|
||||
ClientCrtFile string `json:"clientcrtfile"`
|
||||
ClientKeyFile string `json:"clientkeyfile"`
|
||||
// ClientKeyFile string `json:"crtfile"`
|
||||
}
|
||||
|
||||
func NewRegoDependenciesDataMock() *RegoDependenciesData {
|
||||
return NewRegoDependenciesData(k8sinterface.GetK8sConfig())
|
||||
}
|
||||
|
||||
func NewRegoDependenciesData(k8sConfig *rest.Config) *RegoDependenciesData {
|
||||
|
||||
regoDependenciesData := RegoDependenciesData{
|
||||
K8sConfig: *NewRegoK8sConfig(k8sConfig),
|
||||
}
|
||||
return ®oDependenciesData
|
||||
}
|
||||
func NewRegoK8sConfig(k8sConfig *rest.Config) *RegoK8sConfig {
|
||||
|
||||
host := k8sConfig.Host
|
||||
if host == "" {
|
||||
ip := os.Getenv("KUBERNETES_SERVICE_HOST")
|
||||
port := os.Getenv("KUBERNETES_SERVICE_PORT")
|
||||
host = fmt.Sprintf("https://%s:%s", ip, port)
|
||||
}
|
||||
|
||||
token := ""
|
||||
if k8sConfig.BearerToken != "" {
|
||||
token = fmt.Sprintf("Bearer %s", k8sConfig.BearerToken)
|
||||
}
|
||||
|
||||
// crtFile := os.Getenv("KUBERNETES_CRT_PATH")
|
||||
// if crtFile == "" {
|
||||
// crtFile = k8sConfig.CAFile
|
||||
// // crtFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
||||
// }
|
||||
|
||||
// glog.Infof("===========================================================================")
|
||||
// glog.Infof(fmt.Sprintf("%v", k8sConfig.String()))
|
||||
// glog.Infof("===========================================================================")
|
||||
|
||||
regoK8sConfig := RegoK8sConfig{
|
||||
Token: token,
|
||||
Host: k8sConfig.Host,
|
||||
CrtFile: k8sConfig.CAFile,
|
||||
ClientCrtFile: k8sConfig.CertFile,
|
||||
ClientKeyFile: k8sConfig.KeyFile,
|
||||
}
|
||||
return ®oK8sConfig
|
||||
}
|
||||
func (data *RegoDependenciesData) TOStorage() (storage.Store, error) {
|
||||
var jsonObj map[string]interface{}
|
||||
bytesData, err := json.Marshal(*data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// glog.Infof("RegoDependenciesData: %s", bytesData)
|
||||
if err := util.UnmarshalJSON(bytesData, &jsonObj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return inmem.NewFromObject(jsonObj), nil
|
||||
}
|
||||
|
||||
// LoadRegoDependenciesFromDir loads the policies list from *.rego file in given directory
|
||||
func LoadRegoFiles(dir string) map[string]string {
|
||||
|
||||
modules := make(map[string]string)
|
||||
|
||||
// Compile the module. The keys are used as identifiers in error messages.
|
||||
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err == nil && strings.HasSuffix(path, ".rego") && !info.IsDir() {
|
||||
content, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
glog.Errorf("LoadRegoFiles, Failed to load: %s: %v", path, err)
|
||||
} else {
|
||||
modules[strings.Trim(filepath.Base(path), ".rego")] = string(content)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return modules
|
||||
}
|
||||
|
||||
// LoadRegoModules loads the policies from variables
|
||||
func LoadRegoModules() map[string]string {
|
||||
|
||||
modules := make(map[string]string)
|
||||
modules["cautils"] = RegoCAUtils
|
||||
modules["designators"] = RegoDesignators
|
||||
modules["kubernetes.api.client"] = RegoKubernetesApiClient
|
||||
|
||||
return modules
|
||||
}
|
||||
17
vendor/github.com/armosec/capacketsgo/opapolicy/resources/resourcesutils_test.go
generated
vendored
17
vendor/github.com/armosec/capacketsgo/opapolicy/resources/resourcesutils_test.go
generated
vendored
@@ -1,17 +0,0 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadRegoDependenciesFromDir(t *testing.T) {
|
||||
dir, _ := os.Getwd()
|
||||
t.Errorf("%s", filepath.Join(dir, "rego/dependencies"))
|
||||
return
|
||||
// modules := LoadRegoDependenciesFromDir("")
|
||||
// if len(modules) == 0 {
|
||||
// t.Errorf("modules len == 0")
|
||||
// }
|
||||
}
|
||||
64
vendor/github.com/armosec/capacketsgo/secrethandling/apifields.go
generated
vendored
64
vendor/github.com/armosec/capacketsgo/secrethandling/apifields.go
generated
vendored
@@ -1,64 +0,0 @@
|
||||
package secrethandling
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// API fields
|
||||
var (
|
||||
WlidPrefix = "wlid://"
|
||||
ClusterWlidPrefix = "cluster-"
|
||||
NamespaceWlidPrefix = "namespace-"
|
||||
DataCenterWlidPrefix = "datacenter-"
|
||||
ProjectWlidPrefix = "project-"
|
||||
SecretSIDPrefix = "secret-"
|
||||
SubSecretSIDPrefix = "subsecret-"
|
||||
K8SKindsList = []string{"ComponentStatus", "ConfigMap", "ControllerRevision", "CronJob",
|
||||
"CustomResourceDefinition", "DaemonSet", "Deployment", "Endpoints", "Event", "HorizontalPodAutoscaler",
|
||||
"Ingress", "Job", "Lease", "LimitRange", "LocalSubjectAccessReview", "MutatingWebhookConfiguration",
|
||||
"Namespace", "NetworkPolicy", "Node", "PersistentVolume", "PersistentVolumeClaim", "Pod",
|
||||
"PodDisruptionBudget", "PodSecurityPolicy", "PodTemplate", "PriorityClass", "ReplicaSet",
|
||||
"ReplicationController", "ResourceQuota", "Role", "RoleBinding", "Secret", "SelfSubjectAccessReview",
|
||||
"SelfSubjectRulesReview", "Service", "ServiceAccount", "StatefulSet", "StorageClass",
|
||||
"SubjectAccessReview", "TokenReview", "ValidatingWebhookConfiguration", "VolumeAttachment"}
|
||||
NativeKindsList = []string{"Dockerized", "Native"}
|
||||
KindReverseMap = map[string]string{}
|
||||
)
|
||||
|
||||
// SecretTLVTag the tlv tag
|
||||
var SecretTLVTag = []byte{231, 197, 24, 237}
|
||||
|
||||
func init() {
|
||||
for _, kind := range K8SKindsList {
|
||||
KindReverseMap[strings.ToLower(strings.Replace(kind, "-", "", -1))] = kind
|
||||
}
|
||||
for _, kind := range NativeKindsList {
|
||||
KindReverseMap[strings.ToLower(strings.Replace(kind, "-", "", -1))] = kind
|
||||
}
|
||||
}
|
||||
|
||||
// IsKindK8S returns true if kind is a k8s
|
||||
func IsKindK8S(k string) bool {
|
||||
if val, ok := KindReverseMap[k]; ok {
|
||||
k = val
|
||||
}
|
||||
for _, k8sKind := range K8SKindsList {
|
||||
if k == k8sKind {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasSecretTLV is the byte slice an encrypted secret
|
||||
func HasSecretTLV(secret []byte) bool {
|
||||
return bytes.HasPrefix(secret, SecretTLVTag)
|
||||
}
|
||||
|
||||
// GetSecretTLVLength return TLV length
|
||||
func GetSecretTLVLength(secret []byte) uint32 {
|
||||
length := secret[len(SecretTLVTag) : len(SecretTLVTag)+4]
|
||||
return uint32(len(SecretTLVTag)+4) + binary.BigEndian.Uint32(length)
|
||||
}
|
||||
163
vendor/github.com/armosec/capacketsgo/secrethandling/inclustersecrethandling.go
generated
vendored
163
vendor/github.com/armosec/capacketsgo/secrethandling/inclustersecrethandling.go
generated
vendored
@@ -1,163 +0,0 @@
|
||||
package secrethandling
|
||||
|
||||
import (
|
||||
"context"
|
||||
b64 "encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/golang/glog"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// DockerConfigJsonstructure -
|
||||
type DockerConfigJsonstructure map[string]map[string]types.AuthConfig
|
||||
|
||||
func updateSecret(authConfig *types.AuthConfig, serverAddress string) {
|
||||
if authConfig.ServerAddress == "" {
|
||||
authConfig.ServerAddress = serverAddress
|
||||
}
|
||||
if authConfig.Username == "" || authConfig.Password == "" {
|
||||
glog.Infof("secret missing user name or password, using auth")
|
||||
auth := authConfig.Auth
|
||||
decodedAuth, err := b64.StdEncoding.DecodeString(auth)
|
||||
if err != nil {
|
||||
glog.Errorf("error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
splittedAuth := strings.Split(string(decodedAuth), ":")
|
||||
if len(splittedAuth) == 2 {
|
||||
authConfig.Username = splittedAuth[0]
|
||||
authConfig.Password = splittedAuth[1]
|
||||
}
|
||||
}
|
||||
if authConfig.Auth == "" {
|
||||
auth := fmt.Sprintf("%s:%s", authConfig.Username, authConfig.Password)
|
||||
authConfig.Auth = b64.StdEncoding.EncodeToString([]byte(auth))
|
||||
}
|
||||
}
|
||||
|
||||
func parseEncodedSecret(sec map[string][]byte) (string, string) {
|
||||
buser := sec[corev1.BasicAuthUsernameKey]
|
||||
bpsw := sec[corev1.BasicAuthPasswordKey]
|
||||
duser, _ := b64.StdEncoding.DecodeString(string(buser))
|
||||
dpsw, _ := b64.StdEncoding.DecodeString(string(bpsw))
|
||||
return string(duser), string(dpsw)
|
||||
|
||||
}
|
||||
func parseDecodedSecret(sec map[string]string) (string, string) {
|
||||
user := sec[corev1.BasicAuthUsernameKey]
|
||||
psw := sec[corev1.BasicAuthPasswordKey]
|
||||
return user, psw
|
||||
|
||||
}
|
||||
|
||||
// ReadSecret -
|
||||
func ReadSecret(secret interface{}, secretName string) (types.AuthConfig, error) {
|
||||
// Store secret based on it's structure
|
||||
var authConfig types.AuthConfig
|
||||
if sec, ok := secret.(*types.AuthConfig); ok {
|
||||
return *sec, nil
|
||||
}
|
||||
if sec, ok := secret.(map[string]string); ok {
|
||||
return types.AuthConfig{Username: sec["username"]}, nil
|
||||
}
|
||||
if sec, ok := secret.(DockerConfigJsonstructure); ok {
|
||||
if _, k := sec["auths"]; !k {
|
||||
return authConfig, fmt.Errorf("cant find auths")
|
||||
}
|
||||
for serverAddress, authConfig := range sec["auths"] {
|
||||
updateSecret(&authConfig, serverAddress)
|
||||
return authConfig, nil
|
||||
}
|
||||
}
|
||||
|
||||
return authConfig, fmt.Errorf("cant find secret")
|
||||
}
|
||||
|
||||
func GetSecret(clientset *kubernetes.Clientset, namespace, name string) (*types.AuthConfig, error) {
|
||||
res, err := clientset.CoreV1().Secrets(namespace).Get(context.Background(), name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Errorf("%v", err)
|
||||
}
|
||||
|
||||
// Read secret
|
||||
secret, err := GetSecretContent(res)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if secret == nil {
|
||||
err := fmt.Errorf("secret %s not found", name)
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
sec, err := ReadSecret(secret, name)
|
||||
if err != nil {
|
||||
return &sec, err
|
||||
}
|
||||
return &sec, nil
|
||||
|
||||
}
|
||||
|
||||
// GetSecretContent -
|
||||
func GetSecretContent(secret *corev1.Secret) (interface{}, error) {
|
||||
|
||||
// Secret types- https://github.com/kubernetes/kubernetes/blob/7693a1d5fe2a35b6e2e205f03ae9b3eddcdabc6b/pkg/apis/core/types.go#L4394-L4478
|
||||
switch secret.Type {
|
||||
case corev1.SecretTypeDockerConfigJson:
|
||||
sec := make(DockerConfigJsonstructure)
|
||||
if err := json.Unmarshal(secret.Data[corev1.DockerConfigJsonKey], &sec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sec, nil
|
||||
default:
|
||||
user, psw := "", ""
|
||||
if len(secret.Data) != 0 {
|
||||
user, psw = parseEncodedSecret(secret.Data)
|
||||
} else if len(secret.StringData) != 0 {
|
||||
userD, pswD := parseDecodedSecret(secret.StringData)
|
||||
if userD != "" {
|
||||
user = userD
|
||||
}
|
||||
if pswD != "" {
|
||||
psw = pswD
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("data not found in secret")
|
||||
}
|
||||
if user == "" || psw == "" {
|
||||
return nil, fmt.Errorf("username or password not found")
|
||||
}
|
||||
|
||||
return &types.AuthConfig{Username: user, Password: psw}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ParseSecret(res *corev1.Secret, name string) (*types.AuthConfig, error) {
|
||||
|
||||
// Read secret
|
||||
secret, err := GetSecretContent(res)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if secret == nil {
|
||||
err := fmt.Errorf("secret %s not found", name)
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
sec, err := ReadSecret(secret, name)
|
||||
if err != nil {
|
||||
return &sec, err
|
||||
}
|
||||
return &sec, nil
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user