diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..d1587865 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,34 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +# Describe the bug +A clear and concise description of what the bug is. + +# Environment +OS: the OS + version you’re running Kubescape on, e.g Ubuntu 22.04 LTS +Version: the version that Kubescape reports when you run `kubescape version` +``` +Your current version is: +``` + +# Steps To Reproduce +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +# Expected behavior +A clear and concise description of what you expected to happen. + +# Actual Behavior +A clear and concise description of what happened. If applicable, add screenshots to help explain your problem. + +# Additional context +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..bbcbbe7d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..b2d8493c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +## Describe your changes + +## Screenshots - If Any (Optional) + +## Issue ticket number and link + +## Checklist before requesting a review +- [ ] My code follows the style guidelines of this project +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have performed a self-review of my code +- [ ] If it is a core feature, I have added thorough tests. +- [ ] New and existing unit tests pass locally with my changes + +**Please open the PR against the `dev` branch (Unless the PR contains only documentation changes)** diff --git a/.github/workflows/close-typos-issues.yaml b/.github/workflows/close-typos-issues.yaml new file mode 100644 index 00000000..46b3275b --- /dev/null +++ b/.github/workflows/close-typos-issues.yaml @@ -0,0 +1,18 @@ +on: + issues: + types: [opened, labeled] + +jobs: + build: + if: ${{ github.event.label.name == 'typo' }} + runs-on: ubuntu-latest + auto_close_issues: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Automatically close typo issues + uses: lucasbento/auto-close-issues@v1.0.2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + issue-close-message: "@${issue.user.login}: Hello! :wave:\n\nThis issue is being automatically closed, Please open a PR with a relevant fix." diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f228a7ac..297639fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ When contributing, we categorize contributions into two: If you have a small change, feel free to fire up a Pull Request. When planning a bigger change, please first discuss the change you wish to make via issue, -email, or any other method with the owners of this repository before making a change. Most likely your changes or features are great, but sometimes we might already going to this direction (or the exact opposite ;-) ) and we don't want to waste your time. +email, or any other method with the owners of this repository before making a change. Most likely your changes or features are great, but sometimes we might be already going to this direction (or the exact opposite ;-) ) and we don't want to waste your time. Please note we have a code of conduct, please follow it in all your interactions with the project. @@ -20,7 +20,7 @@ Please note we have a code of conduct, please follow it in all your interactions 2. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters. 3. Open Pull Request to `dev` branch - we test the component before merging into the `master` branch -4. We will merge the Pull Request in once you have the sign-off. +4. We will merge the Pull Request once you have the sign-off. ## Code of Conduct @@ -55,12 +55,12 @@ advances * Other conduct which could reasonably be considered inappropriate in a professional setting -We will distance those who are constantly adhere to unacceptable behavior. +We will distance those who constantly adhere to unacceptable behavior. ### Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in +behavior and are expected to take appropriate and fair corrective actions in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or @@ -97,4 +97,4 @@ This Code of Conduct is adapted from the [Contributor Covenant][homepage], versi available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/Makefile b/Makefile index 1fd42de0..f45b5953 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ export CGO_ENABLED=1 # build and install libgit2 libgit2: - git submodule update --init --recursive + -git submodule update --init --recursive cd git2go; make install-static # go build tags diff --git a/README.md b/README.md index c4fc63cf..4deb6bd6 100644 --- a/README.md +++ b/README.md @@ -3,29 +3,22 @@ [![build](https://github.com/kubescape/kubescape/actions/workflows/build.yaml/badge.svg)](https://github.com/kubescape/kubescape/actions/workflows/build.yaml) [![Go Report Card](https://goreportcard.com/badge/github.com/kubescape/kubescape)](https://goreportcard.com/report/github.com/kubescape/kubescape) +:sunglasses: [Want to contribute?](#being-a-part-of-the-team) :innocent: -Kubescape is a K8s open-source tool providing a multi-cloud K8s single pane of glass, including risk analysis, security compliance, RBAC visualizer and image vulnerabilities scanning. +Kubescape is a K8s open-source tool providing a Kubernetes single pane of glass, including risk analysis, security compliance, RBAC visualizer, and image vulnerabilities scanning. Kubescape scans K8s clusters, YAML files, and HELM charts, detecting misconfigurations according to multiple frameworks (such as the [NSA-CISA](https://www.armosec.io/blog/kubernetes-hardening-guidance-summary-by-armo/?utm_source=github&utm_medium=repository), [MITRE ATT&CK®](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/)), software vulnerabilities, and RBAC (role-based-access-control) violations at early stages of the CI/CD pipeline, calculates risk score instantly and shows risk trends over time. -It became one of the fastest-growing Kubernetes tools among developers due to its easy-to-use CLI interface, flexible output formats, and automated scanning capabilities, saving Kubernetes users and admins’ precious time, effort, and resources. + +It has become one of the fastest-growing Kubernetes tools among developers due to its easy-to-use CLI interface, flexible output formats, and automated scanning capabilities, saving Kubernetes users and admins precious time, effort, and resources. Kubescape integrates natively with other DevOps tools, including Jenkins, CircleCI, Github workflows, Prometheus, and Slack, and supports multi-cloud K8s deployments like EKS, GKE, and AKS.
- - - # Kubescape CLI:
- - # TL;DR ## Install: ```sh @@ -49,7 +42,7 @@ kubescape scan --submit --enable-host-scan --verbose
-> Kubescape is an open source project, we welcome your feedback and ideas for improvement. We’re also aiming to collaborate with the Kubernetes community to help make the tests themselves more robust and complete as Kubernetes develops. +> Kubescape is an open source project. We welcome your feedback and ideas for improvement. We’re also aiming to collaborate with the Kubernetes community to help make the tests more robust and complete as Kubernetes develops.
@@ -58,17 +51,17 @@ kubescape scan --submit --enable-host-scan --verbose
-# Being part of the team +# Being a part of the team We invite you to our team! We are excited about this project and want to return the love we get. Want to contribute? Want to discuss something? Have an issue? -* Feel free to pick a task from the [roadmap](docs/roadmap.md) or suggest a feature of your own. [Contact us](MAINTAINERS.md) directly for more information :) -* Open a issue, we are trying to respond within 48 hours -* [Join us](https://armosec.github.io/kubescape) in a discussion on our discord server! +* Feel free to pick a task from the [issues](https://github.com/kubescape/kubescape/issues?q=is%3Aissue+is%3Aopen+label%3A%22open+for+contribution%22), [roadmap](docs/roadmap.md) or suggest a feature of your own. [Contact us](MAINTAINERS.md) directly for more information :) +* Open an issue, we are trying to respond within 48 hours +* [Join us](https://discord.com/invite/WKZRaCtBxN) in the discussion on our discord server! -[logo](https://armosec.github.io/kubescape/) +[logo](https://discord.com/invite/WKZRaCtBxN) ![discord](https://img.shields.io/discord/893048809884643379) @@ -87,12 +80,12 @@ Want to contribute? Want to discuss something? Have an issue? * [Scan Kubescape on an air-gapped environment (offline support)](https://youtu.be/IGXL9s37smM) * [Managing exceptions in the Kubescape SaaS version](https://youtu.be/OzpvxGmCR80) * [Configure and run customized frameworks](https://youtu.be/12Sanq_rEhs) -* Customize controls configurations. [Kubescape CLI](https://youtu.be/955psg6TVu4), [Kubescape SaaS](https://youtu.be/lIMVSVhH33o) - -
Windows +* Customize control configurations. [Kubescape CLI](https://youtu.be/955psg6TVu4), [Kubescape SaaS](https://youtu.be/lIMVSVhH33o) ## Install on Windows +
Windows + **Requires powershell v5.0+** ``` powershell @@ -106,10 +99,11 @@ Set-ExecutionPolicy RemoteSigned -scope CurrentUser ```
-
MacOS ## Install on macOS +
MacOS + 1. ```sh brew tap kubescape/tap ``` @@ -118,10 +112,10 @@ Set-ExecutionPolicy RemoteSigned -scope CurrentUser ```
-
Nix/NixOS - ## Install on NixOS or with nix (Community) +
Nix/NixOS + Direct issues installing `kubescape` via `nix` through the channels mentioned [here](https://nixos.wiki/wiki/Support) You can use `nix` on Linux or macOS and on other platforms unofficially. @@ -203,7 +197,7 @@ kubescape scan *.yaml --submit kubescape scan https://github.com/kubescape/kubescape --submit ``` -#### Display all scanned resources (including the resources who passed) +#### Display all scanned resources (including the resources which passed) ``` kubescape scan --verbose ``` @@ -243,7 +237,7 @@ kubescape scan --exceptions examples/exceptions/exclude-kube-namespaces.json ``` kubescape scan --submit ``` -> Kubescape will load the default values file +> Kubescape will load the default value file ### Offline/Air-gaped Environment Support @@ -263,11 +257,11 @@ kubescape download artifacts --output path/to/local/dir kubescape scan --use-artifacts-from path/to/local/dir ``` -#### Download a single artifacts +#### Download a single artifact -You can also download a single artifacts and scan with the `--use-from` flag +You can also download a single artifact and scan with the `--use-from` flag -1. Download and save in file, if file name not specified, will save in `~/.kubescape/.json` +1. Download and save in file, if file name is not specified, will save in `~/.kubescape/.json` ``` kubescape download framework nsa --output /path/nsa.json ``` @@ -298,9 +292,9 @@ View Kubescape scan results directly in [Lens IDE](https://k8slens.dev/) using k # Building Kubescape -
Windows +## Build on Windows -## Windows +
Windows 1. Install MSYS2 & build libgit _(needed only for the first time)_ @@ -323,9 +317,9 @@ View Kubescape scan results directly in [Lens IDE](https://k8slens.dev/) using k ```
-
Linux / MacOS +## Build on Linux/MacOS -## Linux / MacOS +
Linux / MacOS 1. Install libgit2 dependency _(needed only for the first time)_ @@ -357,7 +351,7 @@ View Kubescape scan results directly in [Lens IDE](https://k8slens.dev/) using k ## VS code configuration samples -You can use the samples files below to setup your VS code environment for building and debugging purposes. +You can use the sample files below to setup your VS code environment for building and debugging purposes.
.vscode/settings.json @@ -402,13 +396,13 @@ You can use the samples files below to setup your VS code environment for buildi # Under the hood ## Technology -Kubescape based on [OPA engine](https://github.com/open-policy-agent/opa) and ARMO's posture controls. +Kubescape is based on the [OPA engine](https://github.com/open-policy-agent/opa) and ARMO's posture controls. -The tools retrieves Kubernetes objects from the API server and runs a set of [rego's snippets](https://www.openpolicyagent.org/docs/latest/policy-language/) developed by [ARMO](https://www.armosec.io?utm_source=github&utm_medium=repository). +The tools retrieve Kubernetes objects from the API server and run a set of [rego's snippets](https://www.openpolicyagent.org/docs/latest/policy-language/) developed by [ARMO](https://www.armosec.io?utm_source=github&utm_medium=repository). -The results by default printed in a pretty "console friendly" manner, but they can be retrieved in JSON format for further processing. +The results by default are printed in a pretty "console friendly" manner, but they can be retrieved in JSON format for further processing. -Kubescape is an open source project, we welcome your feedback and ideas for improvement. We’re also aiming to collaborate with the Kubernetes community to help make the tests themselves more robust and complete as Kubernetes develops. +Kubescape is an open source project, we welcome your feedback and ideas for improvement. We’re also aiming to collaborate with the Kubernetes community to help make the tests more robust and complete as Kubernetes develops. ## Thanks to all the contributors ❤️ diff --git a/core/pkg/resourcehandler/k8sresources.go b/core/pkg/resourcehandler/k8sresources.go index 8035335e..52ab967f 100644 --- a/core/pkg/resourcehandler/k8sresources.go +++ b/core/pkg/resourcehandler/k8sresources.go @@ -104,7 +104,9 @@ func (k8sHandler *K8sResourceHandler) GetResources(sessionObj *cautils.OPASessio // using hostSensor mock cautils.SetInfoMapForResources("failed to init host scanner", hostResources, sessionObj.InfoMap) } else { - sessionObj.InfoMap = infoMap + if len(infoMap) > 0 { + sessionObj.InfoMap = infoMap + } } } else { cautils.SetInfoMapForResources("enable-host-scan flag not used. For more information: https://hub.armosec.io/docs/host-sensor", hostResources, sessionObj.InfoMap) diff --git a/docs/kubescape.png b/docs/kubescape.png index cfa8ffc1..e0de21e4 100755 Binary files a/docs/kubescape.png and b/docs/kubescape.png differ diff --git a/docs/proposals/container-image-vulnerability-adaptor.md b/docs/proposals/container-image-vulnerability-adaptor.md index dce83f45..2d8a5e78 100644 --- a/docs/proposals/container-image-vulnerability-adaptor.md +++ b/docs/proposals/container-image-vulnerability-adaptor.md @@ -6,23 +6,23 @@ source #287 ### Big picture -* Kubescape team is planning to create controls which take into account image vulnerabilities, example: looking for public internet facing workloads with critical vulnerabilities. These are seriously effecting the security health of a cluster and therefore we think it is important to cover it. We think that most container registries are/will support image scanning like Harbor and therefore the ability to get information from them is important. -* There are information in the image repository which is important for existing controls as well. They are incomplete without it, example see this issue: Non-root containers check is broken #19 . These are not necessarily image vulnerability related. Can be information in the image manifest (like the issue before), but it can be the image BOM related. +* Kubescape team is planning to create controls which take into account image vulnerabilities, example: looking for public internet facing workloads with critical vulnerabilities. These are seriously affecting the security health of a cluster and therefore we think it is important to cover it. We think that most container registries are/will support image scanning like Harbor and therefore ,the ability to get information from them is important. +* There is information in the image repository which is important for the existing controls as well. They are incomplete without it, example see this issue: Non-root containers check is broken #19 . These are not necessarily image vulnerability related. Can be information in the image manifest (like the issue before), but it can be the image BOM related. ### Relation to this proposal -There are multiple changes and design decisions needs to be made before Kubescape will support the before outlined controls. However, a focal point the whole picutre is the ability to access vulnerability databases of container images. We anticipate that most container image repositories will support image vulnerability scanning, some major players are already do. Since there is no a single API available which all of these data sources support it is important to create an adaption layer within Kubescape so different datasources can serve Kubescape's goals. +Multiple changes and design decisions need to be made before Kubescape will support the above outlined controls. However, a focal point in the whole picture is the ability to access vulnerability of databases of container images. We anticipate that most container image repositories will support image vulnerability scanning, like some major players already do. Since there is no single API available which all of these data sources support, it is important to create an adaption layer within Kubescape so that different datasources can serve Kubescape's goals. ## High level design of Kubescape ### Layers -* Controls and Rules: that actual control logic implementation, the "tests" themselves. Implemented in rego +* Controls and Rules: That actual control logic implementation, the "tests" themselves. Implemented in rego * OPA engine: the [OPA](https://github.com/open-policy-agent/opa) rego interpreter * Rules processor: Kubescape component, it enumerates and runs the controls while also preparing the all the input data that the controls need for running -* Data sources: set of different modules providing data to the Rules processor so it can run the controls with them. Examples: Kubernetes objects, cloud vendor API objects and adding in this proposal the vulnerability infomration -* Cloud Image Vulnerability adaption interface: the subject of this proposal, it gives a common interface for different registry/vulnerability vendors to adapt to. -* CIV adaptors: specific implementation of the CIV interface, example Harbor adaption +* Data sources: Set of different modules providing data to the Rules processor so that it can run the controls with them. Examples: Kubernetes objects, cloud vendor API objects and adding the vulnerability information in this proposal +* Cloud Image Vulnerability adaption interface: The subject of this proposal, it gives a common interface for different registry/vulnerability vendors to adapt to. +* CIV adaptors: Specific implementation of the CIV interface, example Harbor adaption ``` ----------------------- | Controls/Rules (rego) | @@ -62,7 +62,7 @@ The interface needs to cover the following functionalities: * Getting vulnerability information for a given image * Getting image information * Image manifests - * Image BOMs (bill of material) + * Image BOMs (Bill Of Material) ## Go API proposal @@ -102,7 +102,7 @@ type ContainerImageInformation struct { type IContainerImageVulnerabilityAdaptor interface { // Credentials are coming from user input (CLI or configuration file) and they are abstracted at string to string map level - // so and example use would be like registry: "simpledockerregistry:80" and credentials like {"username":"joedoe","password":"abcd1234"} + // so an example use would be like registry: "simpledockerregistry:80" and credentials like {"username":"joedoe","password":"abcd1234"} Login(registry string, credentials map[string]string) error // For "help" purposes @@ -132,7 +132,7 @@ The objects received from the interface will be converted to an Imetadata compat "name": "nginx:latest" }, "data": { - // returned by the adaptor API (structure like our backend gives for an image + // returned by the adaptor API (structure like our backend gives for an image) } } ``` @@ -168,9 +168,9 @@ The rego results will be a combination of the k8s artifact and the list of relev }, "data": { - // returned by the adaptor API (structure like our backend gives for an image + // returned by the adaptor API (structure like our backend gives for an image) } } ] } -``` \ No newline at end of file +``` diff --git a/docs/roadmap.md b/docs/roadmap.md index 144a462c..5c8ec191 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -12,27 +12,35 @@ The features serve different stages of the workflow of the users: The items in the Kubescape roadmap are split into 3 major groups based on the feature planning maturity: -* [Planning](#planning) - we have tickets open for these issues with a more or less clear vision of design. -* [Backlog](#backlog) - features that were discussed at a high level but are not ready for development -* [Wishlist](#wishlist) - features we are dreaming of in 😀 and want to push them gradually forward +* [Planning](#planning-) - we have tickets open for these issues with a more or less clear vision of design. +* [Backlog](#backlog-) - features that were discussed at a high level but are not ready for development +* [Wishlist](#wishlist-) - features we are dreaming of in 😀 and want to push them gradually forward ## Planning 👷 + +* ##### Storing scan results in cluster + We want Kubescape scan results (both cluster and image scan) to be stored in the cluster locally as `CRD`s. This will enable easier integration with results by other projects as well as with scripting via `kubectl`. This will also make image scan based controls to avoid accessing external resources for image vulnerability scan results. + +* ##### Vulnerability prioritization based on workload file activity + Implementing an eBPF agent (based on Falco or Tracee) which tracks file activity in workloads to prioritize container image vulnerabilities. + +* ##### Prioritization engine using MITRE Attack matrix based attack chains + Create a security issue prioritization engine which scores resources based on control based attack chains. All of Kubescape controls can be arranged into attack categories of MITRE Attack matrix. The Attack matrix categories can be connected to each other based on a theoretical attack (ie. you can't have privilege escalation without initial access). Each of the Kubescape controls are to be categorized in these system and Kubescape will calculate priority score based on the interconnections between failed controls. + * ##### Integration with image registries We want to expand Kubescape to integrate with different image registries and read image vulnerability information from there. This will allow Kubescape to give contextual security information about vulnerabilities. Container registry integration -* ##### Kubescape as a microservice - Create a REST API for Kubescape so it can constantly run in a cluster, and other components like Prometheus can scrape results. * ##### Kubescape CLI control over cluster operations Add functionality to Kubescape CLI to trigger operations in Kubescape cluster components (example: trigger image scans, etc.) -* ##### Produce md/HTML reports - Create scan reports for different output formats. * ##### Git integration for pull requests Create insightful GitHub actions for Kubescape + ## Backlog 📅 * ##### JSON path for HELM charts Today, Kubescape can point to issues in the Kubernetes object. We want to develop this feature so Kubescape will be able to point to the misconfigured source file (HELM). * ##### Create Kubescape HELM plugin + Producing scan results in the context of HELM * ##### Kubescape based admission controller Implement admission controller API for Kubescape microservice to enable users to use Kubescape rules as policies @@ -59,7 +67,7 @@ The items in the Kubescape roadmap are split into 3 major groups based on the fe * Image vulnerability scanning based controls * Assisted remediation (telling where/what to fix) * Integration with Prometheus -* Confiugration of controls (customizing rules for a given environment) +* Configuration of controls (customizing rules for a given environment) * Installation in the cluster for continuous monitoring * Host scanner * Cloud vendor API integration diff --git a/httphandler/README.md b/httphandler/README.md index b40a9ec7..b80e9887 100644 --- a/httphandler/README.md +++ b/httphandler/README.md @@ -155,7 +155,7 @@ curl --header "Content-Type: application/json" \ #### Data profiling Analyze profiled data using [pprof](https://github.com/google/pprof/blob/main/doc/README.md). -[How ro use](https://pkg.go.dev/net/http/pprof) +[How to use](https://pkg.go.dev/net/http/pprof) example: ```bash diff --git a/httphandler/examples/prometheus/README.md b/httphandler/examples/prometheus/README.md index d97da1ee..6d785c20 100644 --- a/httphandler/examples/prometheus/README.md +++ b/httphandler/examples/prometheus/README.md @@ -23,7 +23,7 @@ All kubescape related metrics begin with `kubescape` -> `riskScore` is the output of an algorithm calculating the risk of the vulinrability. `0` indicates there is no risk and `100` indicates highest risk. +> `riskScore` is the output of an algorithm calculating the risk of the vulnerability. `0` indicates there is no risk and `100` indicates highest risk. #### Cluster scope metrics diff --git a/httphandler/listener/setup.go b/httphandler/listener/setup.go index 57616657..634e4d70 100644 --- a/httphandler/listener/setup.go +++ b/httphandler/listener/setup.go @@ -19,7 +19,7 @@ const ( scanPath = "/v1/scan" statusPath = "/v1/status" resultsPath = "/v1/results" - prometheusMmeticsPath = "/v1/metrics" + prometheusMetricsPath = "/v1/metrics" livePath = "/livez" readyPath = "/readyz" ) @@ -45,7 +45,7 @@ func SetupHTTPListener() error { // listen httpHandler := handlerequestsv1.NewHTTPHandler() - rtr.HandleFunc(prometheusMmeticsPath, httpHandler.Metrics) + rtr.HandleFunc(prometheusMetricsPath, httpHandler.Metrics) rtr.HandleFunc(scanPath, httpHandler.Scan) rtr.HandleFunc(statusPath, httpHandler.Status) rtr.HandleFunc(resultsPath, httpHandler.Results) @@ -75,7 +75,7 @@ func loadTLSKey(certFile, keyFile string) (*tls.Certificate, error) { pair, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { - return nil, fmt.Errorf("filed to load key pair: %v", err) + return nil, fmt.Errorf("failed to load key pair: %v", err) } return &pair, nil }