forked from falcosecurity/client-py
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add grpc channel credentials Use makefile instead of bash script Fix time build: makefile to download and build the protos Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com> chore: do not commit .proto files Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com> docs: example plus build instructions into the README Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com> chore: remove protos and generated python code from the root Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com> new: workaround the issues python has with code generated from protobuf Read more here: protocolbuffers/protobuf#881 Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com> new(falco): generated python API into falco/schema and falco/svc Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com> update(falco/domain): update the import paths Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com> update(falco): client import paths updated Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
- Loading branch information
mmat
authored and
Mattia
committed
Feb 3, 2020
1 parent
e8dcf8c
commit e1a980e
Showing
24 changed files
with
958 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
|
||
.pytest_cache/ | ||
|
||
**/*.proto |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
SHELL := /bin/bash | ||
|
||
PROTOC ?= $(shell which protoc) | ||
GRPC_PYTHON_PLUGIN ?= $(shell which grpc_python_plugin) | ||
|
||
PROTOS := protos/schema.proto protos/output.proto | ||
PROTO_URLS := https://raw.githubusercontent.com/falcosecurity/falco/dev/userspace/falco/schema.proto https://raw.githubusercontent.com/falcosecurity/falco/dev/userspace/falco/output.proto | ||
PROTO_SHAS := a1f427c114b945d0880b55058862b74015d036aa722985ca6e5474ab4ed19f69 4ce2f3e6d6ebc07a74535c4f21da73e44c6ef848ab83627b1ac987058be5ece9 | ||
|
||
PROTO_DIRS := $(dir ${PROTOS}) | ||
PROTO_DIRS_INCLUDES := $(patsubst %/, -I %, ${PROTO_DIRS}) | ||
|
||
SCHEMA_OUT_DIR := falco/schema | ||
GRPC_OUT_DIR := falco/svc | ||
|
||
.PHONY: protos | ||
protos: ${PROTOS} | ||
|
||
# $(1): the proto path | ||
# $(2): the proto URL | ||
# $(3): the proto SHA256 | ||
define download_rule | ||
$(1): | ||
@rm -f $(1) | ||
@mkdir -p ${PROTO_DIRS} ${SCHEMA_OUT_DIR} ${GRPC_OUT_DIR} | ||
@curl --silent -Lo $(1) $(2) | ||
@echo $(3) $(1) | sha256sum -c | ||
@sed -i '/option go_package/d' $(1) | ||
${PROTOC} ${PROTO_DIRS_INCLUDES} --python_out=${SCHEMA_OUT_DIR} --grpc_out=${GRPC_OUT_DIR} --plugin=protoc-gen-grpc=${GRPC_PYTHON_PLUGIN} $(1) | ||
endef | ||
$(foreach PROTO,$(PROTOS),\ | ||
$(eval $(call download_rule,$(PROTO),$(firstword $(PROTO_URLS)),$(firstword $(PROTO_SHAS))))\ | ||
$(eval PROTO_URLS := $(wordlist 2,$(words $(PROTO_URLS)),$(PROTO_URLS)))\ | ||
$(eval PROTO_SHAS := $(wordlist 2,$(words $(PROTO_SHAS)),$(PROTO_SHAS)))\ | ||
) | ||
|
||
.PHONY: clean | ||
clean: ${PROTO_DIRS} | ||
@rm -rf $^ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,34 @@ | ||
# client-py | ||
|
||
> Python client and SDK for Falco | ||
## Usage | ||
|
||
### Output subscribe | ||
|
||
```python | ||
import falco | ||
client = falco.Client(grpc_endpoint="localhost:5060", client_crt="/tmp/client.crt", client_key="/tmp/client.key", ca_root="/tmp/ca.crt") | ||
for event in client.subscribe(falco.Request(keepalive=True)): | ||
print(event) | ||
``` | ||
|
||
## Development | ||
|
||
### Dependencies | ||
|
||
**TBD** | ||
|
||
### Update protos | ||
|
||
Perform the following edits to the Makefile: | ||
|
||
1. Update the PROTOS array with the destination path of the .proto file. | ||
2. Update the PROTO_URLS array with the URL from which to download it. | ||
3. Update thr PROTO_SHAS array with the SHA256 sum of the file to download. | ||
4. Execute the following commands: | ||
|
||
```console | ||
make clean | ||
make protos | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from falco.client import Client # noqa: F401 | ||
from falco.domain import Request, Response # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import grpc | ||
|
||
from falco.client_credentials import get_grpc_channel_credentials | ||
from falco.domain import Response | ||
from falco.svc.output_pb2_grpc import serviceStub | ||
|
||
|
||
class Client: | ||
def __init__(self, grpc_endpoint, client_crt, client_key, ca_root, *args, **kw): | ||
self._client = serviceStub( | ||
grpc.secure_channel( | ||
grpc_endpoint, | ||
credentials=get_grpc_channel_credentials(client_crt, client_key, ca_root), | ||
options=[("grpc.max_receive_message_length", 1024 * 1024 * 512)], | ||
), | ||
) | ||
|
||
def subscribe(self, request): # TODO: test | ||
pb_req = request.to_proto() | ||
|
||
for pb_resp in self._client.subscribe(pb_req): | ||
yield Response.from_proto(pb_resp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import grpc | ||
|
||
from falco.utils import load_file | ||
|
||
|
||
def get_grpc_channel_credentials(client_crt, client_key, ca_root): | ||
"""Returns a ChannelCredentials object to use with the grpc channel | ||
https://grpc.github.io/grpc/python/grpc.html#create-client-credentials | ||
""" | ||
|
||
root_certificates = load_file(ca_root) | ||
private_key = load_file(client_key) | ||
certificate_chain = load_file(client_crt) | ||
|
||
return grpc.ssl_channel_credentials( | ||
root_certificates=root_certificates, private_key=private_key, certificate_chain=certificate_chain, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from falco.domain.request import Request # noqa: F401 | ||
from falco.domain.response import Response # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
from falco.schema.output_pb2 import request | ||
|
||
|
||
class Request: | ||
__slots__ = ("keepalive",) | ||
|
||
def __init__(self, keepalive=None): | ||
self.keepalive = keepalive | ||
|
||
def __repr__(self): | ||
return f"{self.__class__.__name__}(keepalive={self.keepalive})" | ||
|
||
@classmethod | ||
def from_proto(cls, pb_request): | ||
return cls(keepalive=pb_request.keepalive) | ||
|
||
def to_proto(self): | ||
return request(keepalive=self.keepalive) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
from datetime import datetime | ||
from enum import Enum | ||
from typing import Dict | ||
|
||
from dateutil import tz | ||
|
||
from falco.utils import pb_timestamp_from_datetime | ||
from falco.schema.output_pb2 import response | ||
from falco.schema.schema_pb2 import priority, source | ||
|
||
|
||
class Response: | ||
__slots__ = ( | ||
"time", | ||
"_priority", | ||
"_source", | ||
"rule", | ||
"output", | ||
"output_fields", | ||
"hostname", | ||
) | ||
|
||
class Priority(Enum): | ||
EMERGENCY = "emergency" | ||
ALERT = "alert" | ||
CRITICAL = "critical" | ||
ERROR = "error" | ||
WARNING = "warning" | ||
NOTICE = "notice" | ||
INFORMATIONAL = "informational" | ||
DEBUG = "debug" | ||
|
||
PB_PRIORITY_TO_PRIORITY_MAP = { | ||
0: Priority.EMERGENCY, | ||
1: Priority.ALERT, | ||
2: Priority.CRITICAL, | ||
3: Priority.ERROR, | ||
4: Priority.WARNING, | ||
5: Priority.NOTICE, | ||
6: Priority.INFORMATIONAL, | ||
7: Priority.DEBUG, | ||
} | ||
|
||
class Source(Enum): | ||
SYSCALL = "syscall" | ||
K8S_AUDIT = "k8s_audit" | ||
|
||
PB_SOURCE_TO_SOURCE_MAP = { | ||
0: Source.SYSCALL, | ||
1: Source.K8S_AUDIT, | ||
} | ||
|
||
def __init__( | ||
self, time=None, priority=None, source=None, rule=None, output=None, output_fields=None, hostname=None, | ||
): | ||
self.time: datetime = time.astimezone(tz.tzutc()) | ||
self.priority: Response.Priority = priority | ||
self.source: Response.Source = source | ||
self.rule: str = rule | ||
self.output: str = output | ||
self.output_fields: Dict = output_fields | ||
self.hostname: str = hostname | ||
|
||
def __repr__(self): | ||
return f"{self.__class__.__name__}(time={self.time}, priority={self.priority}, source={self.source}, rule={self.rule}, output={self.output}, output_fields={self.output_fields}, hostname={self.hostname})" | ||
|
||
@property | ||
def priority(self): | ||
return self._priority | ||
|
||
@priority.setter | ||
def priority(self, p): | ||
self._priority = None | ||
if p and isinstance(p, Response.Priority): | ||
self._priority = p | ||
|
||
@property | ||
def source(self): | ||
return self._source | ||
|
||
@source.setter | ||
def source(self, s): | ||
self._source = None | ||
if s and isinstance(s, Response.Source): | ||
self._source = s | ||
|
||
@classmethod | ||
def from_proto(cls, pb_response): | ||
timestamp_dt = datetime.fromtimestamp(pb_response.time.seconds + pb_response.time.nanos / 1e9) | ||
|
||
return cls( | ||
time=timestamp_dt, | ||
priority=Response.PB_PRIORITY_TO_PRIORITY_MAP[pb_response.priority], | ||
source=Response.PB_SOURCE_TO_SOURCE_MAP[pb_response.source], | ||
rule=pb_response.rule, | ||
output=pb_response.output, | ||
output_fields=pb_response.output_fields, | ||
hostname=pb_response.hostname, | ||
) | ||
|
||
def to_proto(self): | ||
return response( | ||
time=pb_timestamp_from_datetime(self.time), | ||
priority=priority.Value(self.priority.value), | ||
source=source.Value(self.source.value), | ||
rule=self.rule, | ||
output=self.output, | ||
output_fields=self.output_fields, | ||
hostname=self.hostname, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import sys | ||
import os | ||
|
||
sys.path.append(os.path.abspath(os.path.dirname(__file__))) |
Oops, something went wrong.