1
0
mirror of https://github.com/aquasecurity/kube-bench.git synced 2024-12-24 07:28:06 +00:00

Merge branch 'master' into fixBooleansComparaison-issue125

This commit is contained in:
Liz Rice 2018-05-15 11:42:21 +01:00 committed by GitHub
commit 97e5bc9b97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 313 additions and 81 deletions

View File

@ -9,10 +9,11 @@ builds:
# Archive customization # Archive customization
archive: archive:
format: tar.gz format: tar.gz
fpm: nfpm:
vendor: Aqua Security vendor: Aqua Security
description: "The Kubernetes Bench for Security is a Go application that checks whether Kubernetes is deployed according to security best practices" description: "The Kubernetes Bench for Security is a Go application that checks whether Kubernetes is deployed according to security best practices"
license: Apache-2.0 license: Apache-2.0
homepage: https://github.com/aquasecurity/kube-bench
formats: formats:
- deb - deb
- rpm - rpm

View File

@ -1,6 +1,11 @@
--- ---
language: go language: go
sudo: required
services:
- docker
notifications: notifications:
email: false email: false
@ -16,6 +21,10 @@ install:
script: script:
- go test ./... - go test ./...
- docker build --tag kube-bench .
- docker run -v `pwd`:/host kube-bench install
- test -d cfg
- test -f kube-bench
after_success: after_success:
- test -n "$TRAVIS_TAG" && curl -sL https://git.io/goreleaser | bash - test -n "$TRAVIS_TAG" && curl -sL https://git.io/goreleaser | bash

View File

@ -1,13 +1,22 @@
FROM golang:1.9 FROM golang:1.9 AS build
WORKDIR /kube-bench WORKDIR /go/src/github.com/aquasecurity/kube-bench/
RUN go get github.com/aquasecurity/kube-bench ADD glide.lock glide.yaml ./
RUN go get github.com/Masterminds/glide && glide install
ADD main.go .
ADD check/ check/
ADD cmd/ cmd/
RUN CGO_ENABLED=0 go install -a -ldflags '-w'
FROM alpine:latest FROM alpine:3.7 AS run
WORKDIR / WORKDIR /opt/kube-bench/
COPY --from=0 /go/bin/kube-bench /kube-bench # add GNU ps for -C, -o cmd, and --no-headers support
COPY --from=0 /go/src/github.com/aquasecurity/kube-bench/cfg /cfg # https://github.com/aquasecurity/kube-bench/issues/109
COPY --from=0 /go/src/github.com/aquasecurity/kube-bench/entrypoint.sh /entrypoint.sh RUN apk --no-cache add procps
ENTRYPOINT /entrypoint.sh COPY --from=build /go/bin/kube-bench /usr/local/bin/kube-bench
ADD entrypoint.sh .
ADD cfg/ cfg/
ENTRYPOINT ["./entrypoint.sh"]
CMD ["install"]
# Build-time metadata as defined at http://label-schema.org # Build-time metadata as defined at http://label-schema.org
ARG BUILD_DATE ARG BUILD_DATE

View File

@ -3,9 +3,9 @@
[![Docker image](https://images.microbadger.com/badges/image/aquasec/kube-bench.svg)](https://microbadger.com/images/aquasec/kube-bench "Get your own image badge on microbadger.com") [![Docker image](https://images.microbadger.com/badges/image/aquasec/kube-bench.svg)](https://microbadger.com/images/aquasec/kube-bench "Get your own image badge on microbadger.com")
[![Source commit](https://images.microbadger.com/badges/commit/aquasec/kube-bench.svg)](https://microbadger.com/images/aquasec/kube-bench) [![Source commit](https://images.microbadger.com/badges/commit/aquasec/kube-bench.svg)](https://microbadger.com/images/aquasec/kube-bench)
# kube-bench <img src="images/kube-bench.png" width="200" alt="kube-bench logo">
The Kubernetes Bench for Security is a Go application that checks whether Kubernetes is deployed securely by running the checks documented in the CIS Kubernetes Benchmark. kube-bench is a Go application that checks whether Kubernetes is deployed securely by running the checks documented in the CIS Kubernetes Benchmark.
Tests are configured with YAML files, making this tool easy to update as test specifications evolve. Tests are configured with YAML files, making this tool easy to update as test specifications evolve.
@ -17,12 +17,50 @@ kube-bench supports the tests for multiple versions of Kubernetes (1.6, 1.7 and
## Installation ## Installation
You can either install kube-bench through a dedicated container, or compile it from source: You can choose to
* run kube-bench from inside a container (sharing PID namespace with the host)
* run a container that installs kube-bench on the host, and then run kube-bench directly on the host
* install the latest binaries from the [Releases page](https://github.com/aquasecurity/kube-bench/releases),
* compile it from source.
1. Container installation: ### Running inside a container
Run ```docker run --rm -v `pwd`:/host aquasec/kube-bench:latest```. This will copy the kube-bench binary and configuration to you host. You can then run ```./kube-bench <master|node>```.
You can avoid installing kube-bench on the host by running it inside a container using the host PID namespace.
```
docker run --pid=host aquasec/kube-bench:latest <master|node>
```
You can even use your own configs by mounting them over the default ones in `/opt/kube-bench/cfg/`
```
docker run --pid=host -v path/to/my-config.yaml:/opt/kube-bench/cfg/config.yaml aquasec/kube-bench:latest <master|node>
```
### Running in a kubernetes cluster
Run the master check
```
kubectl run --rm -i -t kube-bench-master --image=aquasec/kube-bench:latest --restart=Never --overrides="{ \"apiVersion\": \"v1\", \"spec\": { \"hostPID\": true, \"nodeSelector\": { \"kubernetes.io/role\": \"master\" }, \"tolerations\": [ { \"key\": \"node-role.kubernetes.io/master\", \"operator\": \"Exists\", \"effect\": \"NoSchedule\" } ] } }" -- master --version 1.8
```
Run the node check
```
kubectl run --rm -i -t kube-bench-node --image=aquasec/kube-bench:latest --restart=Never --overrides="{ \"apiVersion\": \"v1\", \"spec\": { \"hostPID\": true } }" -- node --version 1.8
```
### Installing from a container
This command copies the kube-bench binary and configuration files to your host from the Docker container:
```
docker run --rm -v `pwd`:/host aquasec/kube-bench:latest install
```
You can then run `./kube-bench <master|node>`.
### Installing from sources
2. Install from sources:
If Go is installed on the target machines, you can simply clone this repository and run as follows (assuming your [$GOPATH is set](https://github.com/golang/go/wiki/GOPATH)): If Go is installed on the target machines, you can simply clone this repository and run as follows (assuming your [$GOPATH is set](https://github.com/golang/go/wiki/GOPATH)):
```go get github.com/aquasecurity/kube-bench ```go get github.com/aquasecurity/kube-bench
@ -30,25 +68,13 @@ go get github.com/Masterminds/glide
cd $GOPATH/src/github.com/aquasecurity/kube-bench cd $GOPATH/src/github.com/aquasecurity/kube-bench
$GOPATH/bin/glide install $GOPATH/bin/glide install
go build -o kube-bench . go build -o kube-bench .
./kube-bench <master|node>
```
## Usage # See all supported options
```./kube-bench [command]``` ./kube-bench --help
``` # Run the all checks on a master node
Available Commands: ./kube-bench master
federated Run benchmark checks for a Kubernetes federated deployment.
help Help about any command
master Run benchmark checks for a Kubernetes master node.
node Run benchmark checks for a Kubernetes node.
Flags:
-c, --check string A comma-delimited list of checks to run as specified in CIS document. Example --check="1.1.1,1.1.2"
--config string config file (default is ./cfg/config.yaml)
-g, --group string Run all the checks under this comma-delimited list of groups. Example --group="1.1"
--json Prints the results as JSON
-v, --verbose verbose output (default false)
``` ```
## Configuration ## Configuration

View File

@ -418,7 +418,7 @@ groups:
- id: 1.1.26 - id: 1.1.26
text: "Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as text: "Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as
appropriate (Scored" appropriate (Scored)"
audit: "ps -ef | grep $apiserverbin | grep -v grep" audit: "ps -ef | grep $apiserverbin | grep -v grep"
tests: tests:
bin_op: and bin_op: and
@ -610,7 +610,7 @@ groups:
remediation: | remediation: |
Edit the API server pod specification file $apiserverconf Edit the API server pod specification file $apiserverconf
and set the below parameter as appropriate and if needed. For example, and set the below parameter as appropriate and if needed. For example,
--request-timeout=300 --request-timeout=300s
scored: true scored: true
- id: 1.2 - id: 1.2
@ -666,7 +666,7 @@ groups:
scored: true scored: true
- id: 1.3.3 - id: 1.3.3
text: "Ensure that the --use-service-account-credentials argument is set" text: "Ensure that the --use-service-account-credentials argument is set (Scored)"
audit: "ps -ef | grep $controllermanagerbin | grep -v grep" audit: "ps -ef | grep $controllermanagerbin | grep -v grep"
tests: tests:
test_items: test_items:

View File

@ -17,6 +17,7 @@ package cmd
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"path/filepath"
"github.com/aquasecurity/kube-bench/check" "github.com/aquasecurity/kube-bench/check"
"github.com/golang/glog" "github.com/golang/glog"
@ -46,10 +47,22 @@ func runChecks(t check.NodeType) {
nodetype = "federated" nodetype = "federated"
} }
ver := getKubeVersion() var ver string
path := fmt.Sprintf("%s/%s", cfgDir, ver) if kubeVersion != "" {
ver = kubeVersion
} else {
ver = getKubeVersion()
}
switch ver {
case "1.9", "1.10":
continueWithError(nil, fmt.Sprintf("No CIS spec for %s - using tests from CIS 1.2.0 spec for Kubernetes 1.8\n", ver))
ver = "1.8"
}
path := filepath.Join(cfgDir, ver)
def := filepath.Join(path, file)
def := fmt.Sprintf("%s/%s", path, file)
in, err := ioutil.ReadFile(def) in, err := ioutil.ReadFile(def)
if err != nil { if err != nil {
exitWithError(fmt.Errorf("error opening %s controls file: %v", t, err)) exitWithError(fmt.Errorf("error opening %s controls file: %v", t, err))
@ -124,41 +137,48 @@ func colorPrint(state check.State, s string) {
// prettyPrint outputs the results to stdout in human-readable format // prettyPrint outputs the results to stdout in human-readable format
func prettyPrint(r *check.Controls, summary check.Summary) { func prettyPrint(r *check.Controls, summary check.Summary) {
colorPrint(check.INFO, fmt.Sprintf("%s %s\n", r.ID, r.Text)) // Print check results.
for _, g := range r.Groups { if !noResults {
colorPrint(check.INFO, fmt.Sprintf("%s %s\n", g.ID, g.Text)) colorPrint(check.INFO, fmt.Sprintf("%s %s\n", r.ID, r.Text))
for _, c := range g.Checks {
colorPrint(c.State, fmt.Sprintf("%s %s\n", c.ID, c.Text))
}
}
fmt.Println()
// Print remediations.
if summary.Fail > 0 || summary.Warn > 0 {
colors[check.WARN].Printf("== Remediations ==\n")
for _, g := range r.Groups { for _, g := range r.Groups {
colorPrint(check.INFO, fmt.Sprintf("%s %s\n", g.ID, g.Text))
for _, c := range g.Checks { for _, c := range g.Checks {
if c.State != check.PASS { colorPrint(c.State, fmt.Sprintf("%s %s\n", c.ID, c.Text))
fmt.Printf("%s %s\n", c.ID, c.Remediation)
}
} }
} }
fmt.Println() fmt.Println()
} }
// Print summary setting output color to highest severity. // Print remediations.
var res check.State if !noRemediations {
if summary.Fail > 0 { if summary.Fail > 0 || summary.Warn > 0 {
res = check.FAIL colors[check.WARN].Printf("== Remediations ==\n")
} else if summary.Warn > 0 { for _, g := range r.Groups {
res = check.WARN for _, c := range g.Checks {
} else { if c.State != check.PASS {
res = check.PASS fmt.Printf("%s %s\n", c.ID, c.Remediation)
}
}
}
fmt.Println()
}
} }
colors[res].Printf("== Summary ==\n") // Print summary setting output color to highest severity.
fmt.Printf("%d checks PASS\n%d checks FAIL\n%d checks WARN\n", if !noSummary {
summary.Pass, summary.Fail, summary.Warn, var res check.State
) if summary.Fail > 0 {
res = check.FAIL
} else if summary.Warn > 0 {
res = check.WARN
} else {
res = check.PASS
}
colors[res].Printf("== Summary ==\n")
fmt.Printf("%d checks PASS\n%d checks FAIL\n%d checks WARN\n",
summary.Pass, summary.Fail, summary.Warn,
)
}
} }

View File

@ -26,9 +26,10 @@ import (
var ( var (
envVarsPrefix = "KUBE_BENCH" envVarsPrefix = "KUBE_BENCH"
cfgDir = "./cfg"
defaultKubeVersion = "1.6" defaultKubeVersion = "1.6"
kubeVersion string
cfgFile string cfgFile string
cfgDir string
jsonFmt bool jsonFmt bool
pgSQL bool pgSQL bool
checkList string checkList string
@ -36,13 +37,16 @@ var (
masterFile string masterFile string
nodeFile string nodeFile string
federatedFile string federatedFile string
noResults bool
noSummary bool
noRemediations bool
) )
// RootCmd represents the base command when called without any subcommands // RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{ var RootCmd = &cobra.Command{
Use: os.Args[0], Use: os.Args[0],
Short: "Run CIS Benchmarks checks against a Kubernetes deployment", Short: "Run CIS Benchmarks checks against a Kubernetes deployment",
Long: `This tool runs the CIS Kubernetes 1.6 Benchmark v1.0.0 checks.`, Long: `This tool runs the CIS Kubernetes Benchmark (http://www.cisecurity.org/benchmark/kubernetes/)`,
} }
// Execute adds all child commands to the root command sets flags appropriately. // Execute adds all child commands to the root command sets flags appropriately.
@ -60,8 +64,13 @@ func Execute() {
func init() { func init() {
cobra.OnInitialize(initConfig) cobra.OnInitialize(initConfig)
// Output control
RootCmd.PersistentFlags().BoolVar(&noResults, "noresults", false, "Disable printing of results section")
RootCmd.PersistentFlags().BoolVar(&noSummary, "nosummary", false, "Disable printing of summary section")
RootCmd.PersistentFlags().BoolVar(&noRemediations, "noremediations", false, "Disable printing of remediations section")
RootCmd.PersistentFlags().BoolVar(&jsonFmt, "json", false, "Prints the results as JSON") RootCmd.PersistentFlags().BoolVar(&jsonFmt, "json", false, "Prints the results as JSON")
RootCmd.PersistentFlags().BoolVar(&pgSQL, "pgsql", false, "Save the results to PostgreSQL") RootCmd.PersistentFlags().BoolVar(&pgSQL, "pgsql", false, "Save the results to PostgreSQL")
RootCmd.PersistentFlags().StringVarP( RootCmd.PersistentFlags().StringVarP(
&checkList, &checkList,
"check", "check",
@ -77,6 +86,8 @@ func init() {
`Run all the checks under this comma-delimited list of groups. Example --group="1.1"`, `Run all the checks under this comma-delimited list of groups. Example --group="1.1"`,
) )
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is ./cfg/config.yaml)") RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is ./cfg/config.yaml)")
RootCmd.PersistentFlags().StringVarP(&cfgDir, "config-dir", "D", "./cfg/", "config directory")
RootCmd.PersistentFlags().StringVar(&kubeVersion, "version", "", "Manually specify Kubernetes version, automatically detected if unset")
goflag.CommandLine.VisitAll(func(goflag *goflag.Flag) { goflag.CommandLine.VisitAll(func(goflag *goflag.Flag) {
RootCmd.PersistentFlags().AddGoFlag(goflag) RootCmd.PersistentFlags().AddGoFlag(goflag)

View File

@ -215,10 +215,19 @@ func multiWordReplace(s string, subname string, sub string) string {
func getKubeVersion() string { func getKubeVersion() string {
// These executables might not be on the user's path. // These executables might not be on the user's path.
_, err := exec.LookPath("kubectl") _, err := exec.LookPath("kubectl")
if err != nil { if err != nil {
exitWithError(fmt.Errorf("kubernetes version check failed: %v", err)) _, err = exec.LookPath("kubelet")
if err != nil {
exitWithError(fmt.Errorf("Version check failed: need kubectl or kubelet binaries to get kubernetes version.\nAlternately, you can specify the version with --version"))
}
return getKubeVersionFromKubelet()
} }
return getKubeVersionFromKubectl()
}
func getKubeVersionFromKubectl() string {
cmd := exec.Command("kubectl", "version", "--short") cmd := exec.Command("kubectl", "version", "--short")
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
@ -228,6 +237,17 @@ func getKubeVersion() string {
return getVersionFromKubectlOutput(string(out)) return getVersionFromKubectlOutput(string(out))
} }
func getKubeVersionFromKubelet() string {
cmd := exec.Command("kubelet", "--version")
out, err := cmd.CombinedOutput()
if err != nil {
continueWithError(fmt.Errorf("%s", out), "")
}
return getVersionFromKubeletOutput(string(out))
}
func getVersionFromKubectlOutput(s string) string { func getVersionFromKubectlOutput(s string) string {
serverVersionRe := regexp.MustCompile(`Server Version: v(\d+.\d+)`) serverVersionRe := regexp.MustCompile(`Server Version: v(\d+.\d+)`)
subs := serverVersionRe.FindStringSubmatch(s) subs := serverVersionRe.FindStringSubmatch(s)
@ -238,6 +258,16 @@ func getVersionFromKubectlOutput(s string) string {
return subs[1] return subs[1]
} }
func getVersionFromKubeletOutput(s string) string {
serverVersionRe := regexp.MustCompile(`Kubernetes v(\d+.\d+)`)
subs := serverVersionRe.FindStringSubmatch(s)
if len(subs) < 2 {
printlnWarn(fmt.Sprintf("Unable to get kubelet version, using default version: %s", defaultKubeVersion))
return defaultKubeVersion
}
return subs[1]
}
func makeSubstitutions(s string, ext string, m map[string]string) string { func makeSubstitutions(s string, ext string, m map[string]string) string {
for k, v := range m { for k, v := range m {
subst := "$" + k + ext subst := "$" + k + ext

View File

@ -1,14 +1,19 @@
#!/bin/sh #!/bin/sh -e
if [ -d /host ]; then if [ "$1" == "install" ]; then
mkdir -p /host/cfg/ if [ -d /host ]; then
yes | cp -rf /cfg/* /host/cfg/ mkdir -p /host/cfg/
yes | cp -rf /kube-bench /host/ yes | cp -rf cfg/* /host/cfg/
echo "===============================================" yes | cp -rf /usr/local/bin/kube-bench /host/
echo "kube-bench is now installed on your host " echo "==============================================="
echo "Run ./kube-bench to perform a security check " echo "kube-bench is now installed on your host "
echo "===============================================" echo "Run ./kube-bench to perform a security check "
echo "==============================================="
else
echo "Usage:"
echo " install: docker run --rm -v \`pwd\`:/host aquasec/kube-bench install"
echo " run: docker run --rm --pid=host aquasec/kube-bench [command]"
exit
fi
else else
echo "Usage:" exec kube-bench "$@"
echo " docker run --rm -v \`pwd\`:/host aquasec/kube-bench"
exit
fi fi

0
hooks/build Normal file → Executable file
View File

BIN
images/kube-bench.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

121
images/kube-bench.svg Normal file
View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 831.49597 755.90533"
height="755.90533"
width="831.49597"
xml:space="preserve"
id="svg2"
version="1.1"><metadata
id="metadata8"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs6"><clipPath
id="clipPath22"
clipPathUnits="userSpaceOnUse"><path
id="path20"
d="M 0,566.929 H 623.622 V 0 H 0 Z" /></clipPath></defs><g
transform="matrix(1.3333333,0,0,-1.3333333,0,755.90533)"
id="g10"><g
transform="translate(314.8111,521.959)"
id="g12"><path
id="path14"
style="fill:#0ab1d5;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 0,0 -106.784,-145.31 0,-280.384 105.477,-147.025 Z" /></g><g
id="g16"><g
clip-path="url(#clipPath22)"
id="g18"><g
transform="translate(51.8912,72.061)"
id="g24"><path
id="path26"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 71.061 c 0,3.629 2.86,6.6 6.6,6.6 3.74,0 6.6,-2.971 6.6,-6.6 V 32.45 h 2.97 c 1.32,0 2.42,0.551 3.52,1.981 L 33.44,52.69 c 1.43,1.981 3.081,3.3 5.72,3.3 3.63,0 6.271,-2.969 6.271,-6.599 0,-1.87 -0.881,-3.411 -1.981,-4.731 L 29.59,27.5 44.44,3.96 C 45.32,2.641 45.76,1.21 45.76,0 c 0,-3.63 -2.97,-6.6 -6.6,-6.6 -2.309,0 -4.4,1.54 -5.5,3.411 L 19.8,19.25 c -0.88,1.431 -1.98,2.091 -3.52,2.091 H 13.2 L 13.2,0 C 13.2,-3.63 10.34,-6.6 6.6,-6.6 2.86,-6.6 0,-3.63 0,0" /></g><g
transform="translate(104.9547,86.8013)"
id="g28"><path
id="path30"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 34.65 c 0,3.63 2.97,6.6 6.6,6.6 3.629,0 6.6,-2.97 6.6,-6.6 V 2.86 c 0,-8.47 3.409,-11.44 9.57,-11.44 4.73,0 9.24,2.86 11.33,4.95 v 38.28 c 0,3.63 2.97,6.6 6.6,6.6 3.63,0 6.6,-2.97 6.6,-6.6 v -50.16 c 0,-3.3 -2.53,-5.83 -5.72,-5.83 -2.97,0 -5.06,2.09 -5.72,4.95 l -0.55,2.42 C 32.12,-17.16 26.18,-21.34 18.149,-21.34 5.06,-21.34 0,-11.99 0,0" /></g><g
transform="translate(197.5084,90.4312)"
id="g32"><path
id="path34"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 12.65 c 0,8.47 -2.971,12.54 -10.341,12.54 -4.069,0 -8.029,-2.2 -10.559,-4.839 V -7.59 c 2.53,-2.639 6.49,-4.95 10.559,-4.95 C -2.971,-12.54 0,-8.47 0,0 m -34.101,-19.14 v 71.83 c 0,3.63 2.861,6.601 6.6,6.601 3.74,0 6.601,-2.971 6.601,-6.601 V 31.57 c 3.08,3.191 8.359,6.05 14.299,6.05 13.09,0 19.8,-8.8 19.8,-23.54 V -1.319 c 0,-14.741 -6.819,-23.651 -20.13,-23.651 -6.16,0 -11.88,2.97 -14.96,6.491 l -0.66,-2.201 c -0.769,-2.53 -3.08,-4.29 -5.72,-4.29 -3.299,0 -5.83,2.75 -5.83,5.83" /></g><g
transform="translate(251.7047,102.311)"
id="g36"><path
id="path38"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c 0,9.57 -1.87,14.301 -9.9,14.301 -7.92,0 -9.9,-4.181 -9.9,-14.301 z M -33,-15.069 V 2.2 c 0,14.521 7.479,23.54 23.1,23.54 15.95,0 22.77,-8.689 22.77,-23.54 v -7.37 c 0,-2.859 -2.309,-5.17 -5.17,-5.17 h -27.5 v -5.939 c 0,-4.62 2.86,-9.13 10.89,-9.13 5.72,0 8.8,0.88 13.09,2.97 0.66,0.33 1.54,0.66 2.42,0.66 2.97,0 5.39,-2.42 5.39,-5.391 0,-2.309 -1.429,-3.96 -3.52,-5.17 -5.17,-2.97 -10.23,-4.51 -17.93,-4.51 -15.73,0 -23.54,8.25 -23.54,21.781" /></g><g
transform="translate(271.7564,99.4517)"
id="g40"><path
id="path42"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c 0,3.3 2.53,5.83 5.721,5.83 h 19.91 c 3.3,0 5.83,-2.53 5.83,-5.83 0,-3.19 -2.53,-5.72 -5.83,-5.72 H 5.721 C 2.53,-5.72 0,-3.19 0,0" /></g><g
transform="translate(345.776,90.4312)"
id="g44"><path
id="path46"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 12.65 c 0,8.47 -2.971,12.54 -10.341,12.54 -4.069,0 -8.029,-2.2 -10.559,-4.839 V -7.59 c 2.53,-2.639 6.49,-4.95 10.559,-4.95 C -2.971,-12.54 0,-8.47 0,0 m -34.101,-19.14 v 71.83 c 0,3.63 2.861,6.601 6.6,6.601 3.74,0 6.601,-2.971 6.601,-6.601 V 31.57 c 3.08,3.191 8.359,6.05 14.299,6.05 13.09,0 19.8,-8.8 19.8,-23.54 V -1.319 c 0,-14.741 -6.819,-23.651 -20.13,-23.651 -6.16,0 -11.88,2.97 -14.96,6.491 l -0.66,-2.201 c -0.769,-2.53 -3.08,-4.29 -5.72,-4.29 -3.299,0 -5.83,2.75 -5.83,5.83" /></g><g
transform="translate(399.9723,102.311)"
id="g48"><path
id="path50"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c 0,9.57 -1.87,14.301 -9.9,14.301 -7.92,0 -9.9,-4.181 -9.9,-14.301 z M -33,-15.069 V 2.2 c 0,14.521 7.479,23.54 23.1,23.54 15.95,0 22.77,-8.689 22.77,-23.54 v -7.37 c 0,-2.859 -2.309,-5.17 -5.17,-5.17 h -27.5 v -5.939 c 0,-4.62 2.86,-9.13 10.89,-9.13 5.72,0 8.8,0.88 13.09,2.97 0.66,0.33 1.54,0.66 2.42,0.66 2.97,0 5.39,-2.42 5.39,-5.391 0,-2.309 -1.429,-3.96 -3.52,-5.17 -5.17,-2.97 -10.23,-4.51 -17.93,-4.51 -15.73,0 -23.54,8.25 -23.54,21.781" /></g><g
transform="translate(421.8512,72.061)"
id="g52"><path
id="path54"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 50.16 c 0,3.301 2.53,5.83 5.72,5.83 2.97,0 5.06,-2.09 5.72,-4.949 l 0.55,-2.421 c 3.19,3.191 9.13,7.37 17.16,7.37 13.09,0 18.15,-9.349 18.15,-21.34 V 0 c 0,-3.63 -2.97,-6.6 -6.6,-6.6 -3.63,0 -6.599,2.97 -6.599,6.6 v 31.79 c 0,8.471 -3.411,11.44 -9.571,11.44 -4.73,0 -9.24,-2.86 -11.33,-4.95 L 13.2,0 C 13.2,-3.63 10.23,-6.6 6.6,-6.6 2.97,-6.6 0,-3.63 0,0" /></g><g
transform="translate(478.358,89.1118)"
id="g56"><path
id="path58"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 15.29 c 0,14.52 8.36,23.649 24.31,23.649 8.36,0 14.08,-3.08 18.15,-8.029 1.21,-1.54 1.87,-2.75 1.87,-4.511 0,-3.299 -2.53,-5.83 -5.83,-5.83 -1.76,0 -3.08,0.66 -4.4,1.981 -2.75,2.75 -5.39,4.62 -9.79,4.62 -8.69,0 -11.11,-5.83 -11.11,-12.981 L 13.2,1.1 c 0,-7.151 2.75,-12.981 11.44,-12.981 4.4,0 7.04,1.87 9.79,4.62 1.32,1.321 2.31,1.981 4.29,1.981 3.3,0 5.94,-2.531 5.94,-5.83 0,-1.76 -0.66,-2.97 -1.87,-4.51 C 38.72,-20.57 33,-23.65 24.64,-23.65 8.689,-23.65 0,-14.521 0,0" /></g><g
transform="translate(530.5396,72.061)"
id="g60"><path
id="path62"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 71.061 c 0,3.629 2.86,6.6 6.6,6.6 3.74,0 6.6,-2.971 6.6,-6.6 v -21.34 c 3.41,2.969 9.02,6.269 16.17,6.269 13.09,0 18.26,-9.349 18.26,-21.34 V 0 c 0,-3.63 -2.859,-6.6 -6.6,-6.6 -3.74,0 -6.6,2.97 -6.6,6.6 v 31.79 c 0,8.471 -3.52,11.44 -9.68,11.44 -4.729,0 -9.46,-2.86 -11.55,-4.95 V 0 C 13.2,-3.63 10.34,-6.6 6.6,-6.6 2.86,-6.6 0,-3.63 0,0" /></g><g
transform="translate(249.2096,192.0259)"
id="g64"><path
id="path66"
style="fill:#f1df36;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 h 0.008 l 131.211,0.031 h 0.013 c 3.063,0 6.107,0.66 8.916,1.863 L 65.602,49.549 -8.531,1.7 C -5.83,0.6 -2.923,0 0,0" /></g><g
transform="translate(420.2877,374.9341)"
id="g68"><path
id="path70"
style="fill:#faaf42;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 -105.477,-133.359 74.547,-47.655 c 3.392,1.452 6.439,3.697 8.747,6.559 l 75.104,93.431 6.686,8.317 c 1.38,1.714 2.479,3.637 3.289,5.675 0.384,0.965 0.701,1.954 0.95,2.962 z" /></g><g
transform="translate(145.3785,311.2251)"
id="g72"><path
id="path74"
style="fill:#faaf42;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c 0.583,-2.568 1.609,-5.036 3.054,-7.245 0.401,-0.614 0.83,-1.209 1.285,-1.783 l 81.823,-101.735 c 2.396,-2.975 5.588,-5.289 9.138,-6.736 L 169.433,-69.65 62.648,65.424 Z" /></g><g
transform="translate(179.4977,457.7324)"
id="g76"><path
id="path78"
style="fill:#9ad7ec;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c -2.408,-2.762 -4.144,-6.1 -4.985,-9.762 l -29.149,-126.8 c -0.65,-2.826 -0.715,-5.774 -0.239,-8.633 0.073,-0.44 0.155,-0.878 0.254,-1.312 l 62.648,65.424 z" /></g><g
transform="translate(484.1334,310.8643)"
id="g80"><path
id="path82"
style="fill:#9ad7ec;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 0,0 C 0.837,3.378 0.913,6.943 0.131,10.337 L -29.076,137.21 c -0.791,3.437 -2.374,6.586 -4.566,9.236 L -63.846,64.07 Z" /></g><g
transform="translate(317.7506,366.4487)"
id="g84"><path
id="path86"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 0,0 40.622,41.329 H 14.038 L -18.791,6.272 V 77.598 H -39.47 V -56.101 h 20.679 v 40.069 l 3.269,3.181 33.46,-43.25 h 27.03 z" /></g><g
transform="translate(275.7818,468.8486)"
id="g88"><path
id="path90"
style="fill:#1280c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 39.028,53.109 c -0.01,0 -0.022,10e-4 -0.033,10e-4 -0.047,0 -0.094,-0.003 -0.141,-0.003 C 38.521,53.105 38.187,53.099 37.853,53.082 37.814,53.08 37.776,53.072 37.738,53.07 34.783,52.909 31.86,52.166 29.192,50.889 L -89.022,-5.593 c -2.809,-1.342 -5.266,-3.235 -7.262,-5.523 L -67.755,-92.199 0,0.03 Z" /></g><g
transform="translate(442.8853,463.2578)"
id="g92"><path
id="path94"
style="fill:#1280c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 -118.288,56.48 c -3.039,1.455 -6.412,2.215 -9.785,2.22 L -22.598,-88.324 7.606,-5.947 C 5.558,-3.467 2.978,-1.422 0,0" /></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 10 KiB