reporthandling

package
v0.0.225 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 30, 2023 License: Apache-2.0 Imports: 17 Imported by: 27

Documentation

Index

Constants

View Source
const (
	ControlAttributeKeyTypeTag      = "controlTypeTags"
	ControlAttributeKeyAttackTracks = "attackTracks"
)
View Source
const (
	StatusPassed  string = "success"
	StatusWarning string = "warning"
	StatusIgnore  string = "ignore"
	StatusFailed  string = "failed"
)
View Source
const (
	SourceTypeJson               string = "JSON"
	SourceTypeYaml               string = "YAML"
	SourceTypeHelmChart          string = "Helm Chart"
	SourceTypeKustomizeDirectory string = "Kustomize Directory"
)

Variables

View Source
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)
)

Mock A

Functions

func AggregateResourcesByAPIServerPod

func AggregateResourcesByAPIServerPod(k8sObjects []workloadinterface.IMetadata) workloadinterface.IMetadata

Create custom object of apiserver pod. Has required fields + cmdline

func AggregateResourcesBySubjects

func AggregateResourcesBySubjects(k8sObjects []workloadinterface.IMetadata) ([]workloadinterface.IMetadata, error)

func DeepCopyMap

func DeepCopyMap(m map[string]interface{}) (map[string]interface{}, error)

DeepCopyMap performs a deep copy of the given map m.

func GetRuntimePods

func GetRuntimePods() string

func GetUniqueResources

func GetUniqueResources(k8sResources []map[string]interface{}) []map[string]interface{}

GetUniqueResources the list of resources can contain duplications, this function removes the resource duplication based on workloadinterface.GetID

func GetUniqueResourcesIDs

func GetUniqueResourcesIDs(k8sResourcesList []string) []string

GetUniqueResources the list of resources can contain duplications, this function removes the resource duplication based on workloadinterface.GetID

func MockExternalFacingService

func MockExternalFacingService() string

func MockRegoPrivilegedPods

func MockRegoPrivilegedPods() string

func MockTemp

func MockTemp() string

func RegoResourcesAggregator

func RegoResourcesAggregator(rule *PolicyRule, k8sObjects []workloadinterface.IMetadata) ([]workloadinterface.IMetadata, error)

func SetDefaultScore

func SetDefaultScore(frameworkReport *FrameworkReport)

SetDefaultScore sets the framework,control default score

func SetUniqueResourcesCounter

func SetUniqueResourcesCounter(frameworkReport *FrameworkReport)

SetDefaultScore sets the framework,control,rule resource counter

func StringInSlice

func StringInSlice(strSlice []string, str string) bool

func TrimUniqueIDs

func TrimUniqueIDs(origin, trimFrom []string) []string

TrimUniqueResources trim the list, this wil trim in case the same resource appears in the warning list and in the failed list

Types

type AlertObject

type AlertObject struct {
	K8SApiObjects   []map[string]interface{} `json:"k8sApiObjects,omitempty"`
	ExternalObjects map[string]interface{}   `json:"externalObjects,omitempty"`
}

type AlertScore

type AlertScore float32

type AttackTrackCategories added in v0.0.187

type AttackTrackCategories struct {
	AttackTrack string
	Categories  []string
}

type Control

type Control struct {
	armotypes.PortalBase `json:",inline" bson:"inline"`
	Control_ID           string              `json:"id,omitempty" bson:"id,omitempty"  ` // to be Deprecated
	ControlID            string              `json:"controlID" bson:"controlID"`
	CreationTime         string              `json:"creationTime" bson:"creationTime"`
	Description          string              `json:"description" bson:"description"`
	Remediation          string              `json:"remediation" bson:"remediation"`
	Rules                []PolicyRule        `json:"rules" bson:"rules,omitempty"`
	FrameworkNames       []string            `json:"frameworkNames,omitempty" bson:"frameworkNames,omitempty"` // frameworks this control is part of
	FixedInput           map[string][]string `json:"fixedInput,omitempty"`                                     // DEPRECATED
	// for new list of  rules in POST/UPADTE requests
	RulesIDs              *[]string `json:"rulesIDs,omitempty" bson:"rulesIDs,omitempty"`
	BaseScore             float32   `json:"baseScore,omitempty" bson:"baseScore,omitempty"`
	ARMOImprovementFactor float32   `json:"ARMOImprovementFactor,omitempty" bson:"ARMOImprovementFactor,omitempty"`
}

Control represents a collection of rules which are combined together to single purpose

func (*Control) GetAttackTrackCategories added in v0.0.187

func (control *Control) GetAttackTrackCategories(attackTrackName string) []string

func (*Control) GetControlId added in v0.0.187

func (control *Control) GetControlId() string

func (*Control) GetControlTypeTags added in v0.0.187

func (control *Control) GetControlTypeTags() []string

func (*Control) GetScore added in v0.0.187

func (control *Control) GetScore() float64

func (*Control) GetSeverity added in v0.0.187

func (control *Control) GetSeverity() int

type ControlConfigInputs

type ControlConfigInputs struct {
	Path        string `json:"path" bson:"path"`
	Name        string `json:"name" bson:"name"`
	Description string `json:"description" bson:"description"`
}

type ControlReport

type ControlReport struct {
	armotypes.PortalBase  `json:",inline"`
	Control_ID            string       `json:"id,omitempty"` // to be Deprecated
	ControlID             string       `json:"controlID"`
	Name                  string       `json:"name"`
	RuleReports           []RuleReport `json:"ruleReports"`
	Remediation           string       `json:"remediation"`
	Description           string       `json:"description"`
	Score                 float32      `json:"score"`
	BaseScore             float32      `json:"baseScore,omitempty"`
	ARMOImprovement       float32      `json:"ARMOImprovement,omitempty"`
	ResourceUniqueCounter `json:",inline"`
}

func (*ControlReport) Failed

func (controlReport *ControlReport) Failed() bool

func (*ControlReport) GetID

func (controlReport *ControlReport) GetID() string

func (*ControlReport) GetNumberOfFailedResources

func (controlReport *ControlReport) GetNumberOfFailedResources() int

func (*ControlReport) GetNumberOfResources

func (controlReport *ControlReport) GetNumberOfResources() int

func (*ControlReport) GetNumberOfWarningResources

func (controlReport *ControlReport) GetNumberOfWarningResources() int

func (*ControlReport) GetStatus

func (controlReport *ControlReport) GetStatus() string

func (*ControlReport) ListControlsInputKinds

func (controlReport *ControlReport) ListControlsInputKinds() []string

func (*ControlReport) ListResourcesIDs

func (controlReport *ControlReport) ListResourcesIDs() *ResourcesIDs

GetResourcesPerControl - return unique lists of resource IDs: all,warning,failed

func (*ControlReport) Passed

func (controlReport *ControlReport) Passed() bool

func (*ControlReport) RemoveData

func (controlReport *ControlReport) RemoveData(keepFields, keepMetadataFields []string)

func (*ControlReport) SetDefaultScore

func (controlReport *ControlReport) SetDefaultScore()

func (*ControlReport) SetNumberOfFailedResources

func (controlReport *ControlReport) SetNumberOfFailedResources(n int)

func (*ControlReport) SetNumberOfResources

func (controlReport *ControlReport) SetNumberOfResources(n int)

func (*ControlReport) SetNumberOfWarningResources

func (controlReport *ControlReport) SetNumberOfWarningResources(n int)

func (*ControlReport) SetResourcesCounters

func (controlReport *ControlReport) SetResourcesCounters()

func (*ControlReport) Warning

func (controlReport *ControlReport) Warning() bool

type Framework

type Framework struct {
	armotypes.PortalBase `json:",inline" bson:"inline"`
	CreationTime         string    `json:"creationTime" bson:"creationTime"`
	Description          string    `json:"description" bson:"description"`
	Controls             []Control `json:"controls" bson:"-"`
	// for new list of  controls in POST/UPADTE requests
	ControlsIDs *[]string                       `json:"controlsIDs,omitempty" bson:"controlsIDs,omitempty"`
	SubSections map[string]*FrameworkSubSection `json:"subSections,omitempty" bson:"subSections,omitempty"`
}

Framework represents a collection of controls which are combined together to expose comprehensive behavior

func MockFrameworkA

func MockFrameworkA() *Framework

type FrameworkReport

type FrameworkReport struct {
	Name                  string          `json:"name"`
	ControlReports        []ControlReport `json:"controlReports"`
	Score                 float32         `json:"score,omitempty"`
	ARMOImprovement       float32         `json:"ARMOImprovement,omitempty"`
	WCSScore              float32         `json:"wcsScore,omitempty"`
	ResourceUniqueCounter `json:",inline"`
}

func MockFrameworkReportA

func MockFrameworkReportA() *FrameworkReport

func (*FrameworkReport) Failed

func (frameworkReport *FrameworkReport) Failed() bool

func (*FrameworkReport) GetNumberOfFailedResources

func (frameworkReport *FrameworkReport) GetNumberOfFailedResources() int

func (*FrameworkReport) GetNumberOfResources

func (frameworkReport *FrameworkReport) GetNumberOfResources() int

func (*FrameworkReport) GetNumberOfWarningResources

func (frameworkReport *FrameworkReport) GetNumberOfWarningResources() int

func (*FrameworkReport) GetStatus

func (frameworkReport *FrameworkReport) GetStatus() string

func (*FrameworkReport) ListResourcesIDs

func (frameworkReport *FrameworkReport) ListResourcesIDs() *ResourcesIDs

GetResourcesPerControl - return unique lists of resource IDs: all,warning,failed

func (*FrameworkReport) Passed

func (frameworkReport *FrameworkReport) Passed() bool

func (*FrameworkReport) RemoveData

func (frameworkReport *FrameworkReport) RemoveData(keepFields, keepMetadataFields []string)

func (*FrameworkReport) SetDefaultScore

func (frameworkReport *FrameworkReport) SetDefaultScore()

func (*FrameworkReport) SetNumberOfFailedResources

func (frameworkReport *FrameworkReport) SetNumberOfFailedResources(n int)

func (*FrameworkReport) SetNumberOfResources

func (frameworkReport *FrameworkReport) SetNumberOfResources(n int)

func (*FrameworkReport) SetNumberOfWarningResources

func (frameworkReport *FrameworkReport) SetNumberOfWarningResources(n int)

func (*FrameworkReport) SetResourcesCounters

func (frameworkReport *FrameworkReport) SetResourcesCounters()

func (*FrameworkReport) Warning

func (frameworkReport *FrameworkReport) Warning() bool

type FrameworkSubSection

type FrameworkSubSection struct {
	armotypes.PortalBase `json:",inline" bson:"inline"`
	ID                   string                          `json:"id" bson:"id"`                                       // unique id inside the framework.
	SubSections          map[string]*FrameworkSubSection `json:"subSections,omitempty" bson:"subSections,omitempty"` // inner subsection
	ControlIDs           []string                        `json:"controlsIDs,omitempty" bson:"controlsIDs,omitempty"` // control ids.
	Controls             []*Control                      `json:"-" bson:"-"`                                         // controls list for fast access
}

type ICloudMetadata added in v0.0.217

type ICloudMetadata interface {
	// Get the suffix of the name. For example, for a cluster named "gke_project_zone_my-cluster" in GKE, the suffix is "my-cluster"
	GetName() string

	// Get full name as it appears in the config file
	GetFullName() string

	// Get provider name
	GetProvider() string

	// Get the prefix of the name. For example, for a cluster named "gke_project_zone_my-cluster" in GKE, the prefix is "gke_project_zone"
	GetPrefix() string
}

type IReportStatus

type IReportStatus interface {
	GetStatus() string
	Passed() bool
	Warning() bool
	Failed() bool
}

type IReportSummary

type IReportSummary interface {
	IReportStatus

	// Get
	SetNumberOfResources(n int)
	SetNumberOfWarningResources(n int)
	SetNumberOfFailedResources(n int)

	// Get
	GetNumberOfResources() int
	GetNumberOfWarningResources() int
	GetNumberOfFailedResources() int
}

type IResource

type IResource interface {
	workloadinterface.IMetadata //
	GetSource() *Source
	SetSource(s *Source)
}

IResource is an extension for IMetadata so we can include the source and other file metadata

type LastCommit

type LastCommit struct {
	Hash           string    `json:"hash,omitempty"`           // commit hash
	Date           time.Time `json:"date,omitempty"`           // commit date
	CommitterName  string    `json:"committerName,omitempty"`  // committer name
	CommitterEmail string    `json:"committerEmail,omitempty"` // committer email
	Message        string    `json:"message,omitempty"`        // commit message
}

LastCommit - file in git repo last commit metadata

type PolicyRule

type PolicyRule struct {
	armotypes.PortalBase   `json:",inline" bson:"inline"`
	CreationTime           string                `json:"creationTime" bson:"creationTime"`
	Rule                   string                `json:"rule" bson:"rule`                                      // multiline string of raw.rego
	ResourceEnumerator     string                `json:"resourceEnumerator" bson:"resourceEnumerator"`         // multiline string of filter.rego, if exists
	RuleLanguage           RuleLanguages         `json:"ruleLanguage" bson:"ruleLanguage"`                     // default "rego"
	Match                  []RuleMatchObjects    `json:"match" bson:"match"`                                   // k8s resources this rule needs as inputs
	DynamicMatch           []RuleMatchObjects    `json:"dynamicMatch,omitempty" bson:"dynamicMatch,omitempty"` // NON-k8s resources this rule needs as inputs, acquired by host-scanner
	RuleDependencies       []RuleDependency      `json:"ruleDependencies" bson:"ruleDependencies"`             // packages this rule uses
	ConfigInputs           []string              `json:"configInputs" bson:"configInputs"`                     // DEPRECATED
	ControlConfigInputs    []ControlConfigInputs `json:"controlConfigInputs" bson:"controlConfigInputs" `      // list of inputs from postureControlInputs in customerConfig for this rule
	Description            string                `json:"description" bson:"description"`
	Remediation            string                `json:"remediation" bson:"remediation"`
	RuleQuery              string                `json:"ruleQuery" bson:"ruleQuery" `                          // default "armo_builtins" - DEPRECATED
	RelevantCloudProviders []string              `json:"relevantCloudProviders" bson:"relevantCloudProviders"` // rule is relevant only to clusters in these cloud providers
}

PolicyRule represents single rule, the fundamental executable block of policy

func MockRuleA

func MockRuleA() *PolicyRule

func MockRuleB

func MockRuleB() *PolicyRule

func MockRuleUntrustedRegistries

func MockRuleUntrustedRegistries() *PolicyRule

type PostureReport

type PostureReport struct {
	CustomerGUID         string                `json:"customerGUID"`
	ClusterName          string                `json:"clusterName"`
	ClusterAPIServerInfo *version.Info         `json:"clusterAPIServerInfo"`
	ClusterCloudProvider string                `json:"clusterCloudProvider"`
	ReportID             string                `json:"reportID"`
	JobID                string                `json:"jobID"`
	ReportGenerationTime time.Time             `json:"generationTime"`
	FrameworkReports     []FrameworkReport     `json:"frameworks"`            // DEPRECATED
	RBACObjects          rbacutils.RbacObjects `json:"rbacObjects,omitempty"` // all rbac objects in cluster - roles, clusterroles, rolebindings, clusterrolebindings
	Resources            []Resource            `json:"resource,omitempty"`
}

PostureReport

func MockPostureReportA

func MockPostureReportA() *PostureReport

func (*PostureReport) NKeys

func (file *PostureReport) NKeys() int

func (*PostureReport) RemoveData

func (postureReport *PostureReport) RemoveData(keepFields, keepMetadataFields []string)

TODO - receive list full json paths

func (*PostureReport) UnmarshalJSONObject

func (r *PostureReport) UnmarshalJSONObject(dec *gojay.Decoder, key string) (err error)
responsible on fast unmarshaling of various COMMON containerscan structures and substructures

UnmarshalJSONObject - File inside a pkg

type Resource

type Resource struct {
	ResourceID string         `json:"resourceID"`
	Object     interface{}    `json:"object"`
	IMetadata  ik8s.IMetadata `json:"-"`
	Source     *Source        `json:"source,omitempty"`
}

func NewResource

func NewResource(obj map[string]interface{}) *Resource

func NewResourceIMetadata

func NewResourceIMetadata(obj workloadinterface.IMetadata) *Resource

func (*Resource) GetApiVersion

func (r *Resource) GetApiVersion() string

func (*Resource) GetID

func (r *Resource) GetID() string

func (*Resource) GetKind

func (r *Resource) GetKind() string

func (*Resource) GetName

func (r *Resource) GetName() string

func (*Resource) GetNamespace

func (r *Resource) GetNamespace() string

func (*Resource) GetObject

func (r *Resource) GetObject() map[string]interface{}

func (*Resource) GetObjectType

func (r *Resource) GetObjectType() workloadinterface.ObjectType

func (*Resource) GetSource

func (r *Resource) GetSource() *Source

func (*Resource) GetWorkload

func (r *Resource) GetWorkload() map[string]interface{}

func (*Resource) SetApiVersion

func (r *Resource) SetApiVersion(s string)

func (*Resource) SetKind

func (r *Resource) SetKind(s string)

func (*Resource) SetName

func (r *Resource) SetName(s string)

func (*Resource) SetNamespace

func (r *Resource) SetNamespace(s string)

func (*Resource) SetObject

func (r *Resource) SetObject(m map[string]interface{})

func (*Resource) SetSource

func (r *Resource) SetSource(s *Source)

func (*Resource) SetWorkload

func (r *Resource) SetWorkload(m map[string]interface{})

type ResourceUniqueCounter

type ResourceUniqueCounter struct {
	TotalResources   int `json:"totalResources"`
	FailedResources  int `json:"failedResources"`
	WarningResources int `json:"warningResources"`
}

type ResourcesIDs

type ResourcesIDs struct {
	// contains filtered or unexported fields
}

func (*ResourcesIDs) GetAllResources

func (r *ResourcesIDs) GetAllResources() []string

func (*ResourcesIDs) GetFailedResources

func (r *ResourcesIDs) GetFailedResources() []string

func (*ResourcesIDs) GetPassedResources

func (r *ResourcesIDs) GetPassedResources() []string

func (*ResourcesIDs) GetWarningResources

func (r *ResourcesIDs) GetWarningResources() []string

type RuleDependency

type RuleDependency struct {
	PackageName string `json:"packageName" bson:"packageName"`
}

type RuleLanguages

type RuleLanguages string
const (
	RegoLanguage  RuleLanguages = "Rego"
	RegoLanguage2 RuleLanguages = "rego"
)

type RuleMatchObjects

type RuleMatchObjects struct {
	APIGroups   []string `json:"apiGroups" bson:"apiGroups"`     // apps
	APIVersions []string `json:"apiVersions" bson:"apiVersions"` // v1/ v1beta1 / *
	Resources   []string `json:"resources" bson:"resources"`     // dep.., pods,
}

RuleMatchObjects defines which objects this rule applied on

type RuleReport

type RuleReport struct {
	Name                  string         `json:"name"`
	Remediation           string         `json:"remediation"`
	RuleStatus            RuleStatus     `json:"ruleStatus"` // did we run the rule or not (if there where compile errors, the value will be failed)
	RuleResponses         []RuleResponse `json:"ruleResponses"`
	ListInputKinds        []string       `json:"listInputIDs"`
	ResourceUniqueCounter `json:",inline"`
}

func (*RuleReport) Failed

func (ruleReport *RuleReport) Failed() bool

func (*RuleReport) GetAllResourcesIDs

func (ruleReport *RuleReport) GetAllResourcesIDs() []string

func (*RuleReport) GetFailedResources

func (ruleReport *RuleReport) GetFailedResources() []map[string]interface{}

DO NOT USE!

func (ruleReport *RuleReport) GetAllResources() []map[string]interface{} {
	return ruleReport.ListInputResources
}

func (*RuleReport) GetNumberOfFailedResources

func (ruleReport *RuleReport) GetNumberOfFailedResources() int

func (*RuleReport) GetNumberOfResources

func (ruleReport *RuleReport) GetNumberOfResources() int

func (*RuleReport) GetNumberOfWarningResources

func (ruleReport *RuleReport) GetNumberOfWarningResources() int

func (*RuleReport) GetStatus

func (ruleReport *RuleReport) GetStatus() string

func (*RuleReport) GetWarnignResources

func (ruleReport *RuleReport) GetWarnignResources() []map[string]interface{}

func (*RuleReport) ListResourcesIDs

func (ruleReport *RuleReport) ListResourcesIDs() *ResourcesIDs

func (*RuleReport) Passed

func (ruleReport *RuleReport) Passed() bool

func (*RuleReport) RemoveData

func (ruleReport *RuleReport) RemoveData(keepFields, keepMetadataFields []string)

func (*RuleReport) SetNumberOfFailedResources

func (ruleReport *RuleReport) SetNumberOfFailedResources(n int)

func (*RuleReport) SetNumberOfResources

func (ruleReport *RuleReport) SetNumberOfResources(n int)

func (*RuleReport) SetNumberOfWarningResources

func (ruleReport *RuleReport) SetNumberOfWarningResources(n int)

func (*RuleReport) SetResourcesCounters

func (ruleReport *RuleReport) SetResourcesCounters()

func (*RuleReport) Warning

func (ruleReport *RuleReport) Warning() bool

type RuleResponse

type RuleResponse struct {
	AlertMessage string                            `json:"alertMessage"`
	FailedPaths  []string                          `json:"failedPaths"`          // path in yaml that led to failure of this resource
	FixPaths     []armotypes.FixPath               `json:"fixPaths"`             // path in yaml to be added to fix this resource
	FixCommand   string                            `json:"fixCommand,omitempty"` // command to fix this resource
	RuleStatus   string                            `json:"ruleStatus"`
	PackageName  string                            `json:"packagename"`
	AlertScore   AlertScore                        `json:"alertScore"`
	AlertObject  AlertObject                       `json:"alertObject"`
	Context      []string                          `json:"context,omitempty"`  // TODO - Remove
	Rulename     string                            `json:"rulename,omitempty"` // TODO - Remove
	Exception    *armotypes.PostureExceptionPolicy `json:"exception,omitempty"`
}

RegoResponse the expected response of single run of rego policy

func MockRuleResponseA

func MockRuleResponseA() *RuleResponse

func ParseRegoResult

func ParseRegoResult(regoResult *rego.ResultSet) ([]RuleResponse, error)

func RemoveResponse

func RemoveResponse(slice []RuleResponse, index int) []RuleResponse

func (*RuleResponse) Failed

func (ruleResponse *RuleResponse) Failed() bool

func (*RuleResponse) GetFailedResources

func (ruleResponse *RuleResponse) GetFailedResources() []map[string]interface{}

func (*RuleResponse) GetStatus

func (ruleResponse *RuleResponse) GetStatus() string

func (*RuleResponse) GetWarnignResources

func (ruleResponse *RuleResponse) GetWarnignResources() []map[string]interface{}

func (*RuleResponse) Passed

func (ruleResponse *RuleResponse) Passed() bool

func (*RuleResponse) RemoveData

func (ruleResponse *RuleResponse) RemoveData(keepFields, keepMetadataFields []string)

func (*RuleResponse) Warning

func (ruleResponse *RuleResponse) Warning() bool

type RuleStatus

type RuleStatus struct {
	Status  string `json:"status"`
	Message string `json:"message"`
}

type Source

type Source struct {
	Path                   string     `json:"path,omitempty"`                   // deprecated
	RelativePath           string     `json:"relativePath,omitempty"`           // relative path from the repo base
	FileType               string     `json:"fileType,omitempty"`               // file type
	HelmChartName          string     `json:"helmChartName,omitempty"`          // helm chart name (if FileType is "Helm Chart")
	KustomizeDirectoryName string     `json:"kustomizeDirectoryName,omitempty"` //Kustomize Directory name if File is from Kustomize Directory
	LastCommit             LastCommit `json:"lastCommit,omitempty"`
}

Source - File source metadata

type UpdatedControl

type UpdatedControl struct {
	Control `json:",inline"`
	Rules   []interface{} `json:"rules"`
}

type UpdatedFramework

type UpdatedFramework struct {
	Framework `json:",inline"`
	Controls  []interface{} `json:"controls"`
}

Directories

Path Synopsis
attacktrack
helpers
v1
results

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL