Skip to content

Commit

Permalink
Access Edges (#2195)
Browse files Browse the repository at this point in the history
  • Loading branch information
meln1k authored Oct 8, 2024
1 parent bce4ffc commit c6e9b82
Show file tree
Hide file tree
Showing 29 changed files with 2,011 additions and 152 deletions.
6 changes: 3 additions & 3 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/devcontainers/python:3.11
FROM mcr.microsoft.com/devcontainers/python:3.12

ARG USERNAME=vscode

Expand All @@ -15,8 +15,8 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends vim wget


RUN wget -qO- https://download.arangodb.com/arangodb310/DEBIAN/Release.key | apt-key add -
RUN echo 'deb https://download.arangodb.com/arangodb310/DEBIAN/ /' | tee /etc/apt/sources.list.d/arangodb.list
RUN wget -qO- https://download.arangodb.com/arangodb311/DEBIAN/Release.key | apt-key add -
RUN echo 'deb https://download.arangodb.com/arangodb311/DEBIAN/ /' | tee /etc/apt/sources.list.d/arangodb.list
RUN apt-get install -y apt-transport-https
RUN apt-get update
RUN apt-get install -y arangodb3-client
Expand Down
2 changes: 1 addition & 1 deletion .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ services:
# (Adding the "ports" property to this file will not forward from the container.)

arangodb:
image: arangodb:3.10.3
image: arangodb:3.11.11
restart: unless-stopped
# Uncomment the lines below in case you want to keep arangodb data in a separate volume
# volumes:
Expand Down
15 changes: 12 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,17 @@
"fixworker/test"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": false,
"python.formatting.provider": "black",
"python.testing.pytestEnabled": true,
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnSave": true
},
"black-formatter.args": [
"--line-length",
"120",
"--target-version",
"py39"
],
"search.exclude": {
"**/*.code-search": true,
"**/bower_components": true,
Expand All @@ -22,4 +31,4 @@
"python.analysis.extraPaths": [
"fixlib"
]
}
}
80 changes: 77 additions & 3 deletions fixlib/fixlib/baseresources.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
from abc import ABC
from copy import deepcopy
from datetime import datetime, timezone, timedelta
from enum import Enum, unique
from enum import Enum, StrEnum, unique
from functools import wraps, cached_property
from typing import Dict, Iterator, List, ClassVar, Optional, TypedDict, Any, TypeVar, Type, Callable, Set, Tuple
from collections import defaultdict

from attr import resolve_types
from attrs import define, field, Factory
from attrs import define, field, Factory, frozen, evolve
from prometheus_client import Counter, Summary

from fixlib.json import from_json as _from_json, to_json as _to_json
from fixlib.json import from_json as _from_json, to_json as _to_json, to_json_str
from fixlib.logger import log
from fixlib.types import Json
from fixlib.utils import make_valid_timestamp, utc_str, utc
Expand Down Expand Up @@ -68,6 +68,7 @@ class ModelReference(TypedDict, total=False):
class EdgeType(Enum):
default = "default"
delete = "delete"
iam = "iam"

@staticmethod
def from_value(value: Optional[str] = None) -> EdgeType:
Expand Down Expand Up @@ -1613,4 +1614,77 @@ def delete(self, graph: Any) -> bool:
return False


class PolicySourceKind(StrEnum):
principal = "principal" # e.g. IAM user, attached policy
group = "group" # policy comes from an IAM group
resource = "resource" # e.g. s3 bucket policy


ResourceConstraint = str

ConditionString = str


@frozen
class PolicySource:
kind: PolicySourceKind
uri: str


class HasResourcePolicy(ABC):
# returns a list of all policies that affects the resource (inline, attached, etc.)
def resource_policy(self, builder: Any) -> List[Tuple[PolicySource, Json]]:
raise NotImplementedError


@frozen
class PermissionCondition:
# if nonempty and any evals to true, access is granted, otherwise implicitly denied
allow: Optional[Tuple[ConditionString, ...]] = None
# if nonempty and any is evals to false, access is implicitly denied
boundary: Optional[Tuple[ConditionString, ...]] = None
# if nonempty and any evals to true, access is explicitly denied
deny: Optional[Tuple[ConditionString, ...]] = None


@frozen
class PermissionScope:
source: PolicySource
constraints: Tuple[ResourceConstraint, ...] # aka resource constraints
conditions: Optional[PermissionCondition] = None

def with_deny_conditions(self, deny_conditions: List[Json]) -> "PermissionScope":
c = self.conditions or PermissionCondition()
return evolve(self, conditions=evolve(c, deny=tuple([to_json_str(c) for c in deny_conditions])))

def with_boundary_conditions(self, boundary_conditions: List[Json]) -> "PermissionScope":
c = self.conditions or PermissionCondition()
return evolve(self, conditions=evolve(c, boundary=tuple([to_json_str(c) for c in boundary_conditions])))

def has_no_condititons(self) -> bool:
if self.conditions is None:
return True

if self.conditions.allow is None and self.conditions.boundary is None and self.conditions.deny is None:
return True

return False


class PermissionLevel(StrEnum):
list = "list"
read = "read"
tagging = "tagging"
write = "write"
permission_management = "permission"
unknown = "unknown" # in case a resource is not in the levels database


@frozen
class AccessPermission:
action: str
level: PermissionLevel
scopes: Tuple[PermissionScope, ...]


resolve_types(BaseResource) # noqa
13 changes: 7 additions & 6 deletions fixlib/fixlib/graph/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def merge(self, graph: Graph, skip_deferred_edges: bool = False) -> None:

try:
self._log_edge_creation = False
self.update(edges=graph.edges, nodes=graph.nodes)
self.update(edges=graph.edges(keys=True, data=True), nodes=graph.nodes)
self.deferred_edges.extend(graph.deferred_edges)
finally:
self._log_edge_creation = True
Expand Down Expand Up @@ -647,17 +647,18 @@ def export_graph(self) -> None:
if not self.found_replace_node:
log.warning(f"No nodes of kind {self.graph_merge_kind.kind} found in graph")
start_time = time()
for edge in self.graph.edges:
from_node = edge[0]
to_node = edge[1]
for from_node, to_node, key, data in self.graph.edges(keys=True, data=True):
if not isinstance(from_node, BaseResource) or not isinstance(to_node, BaseResource):
log.error(f"One of {from_node} and {to_node} is no base resource")
continue
edge_dict = {"from": from_node.chksum, "to": to_node.chksum}
if len(edge) == 3:
key = edge[2]
if key:
if isinstance(key, EdgeKey) and key.edge_type != EdgeType.default:
edge_dict["edge_type"] = key.edge_type.value

if reported := data.get("reported"):
edge_dict["reported"] = reported

edge_json = json.dumps(edge_dict) + "\n"
self.tempfile.write(edge_json.encode())
self.total_lines += 1
Expand Down
4 changes: 2 additions & 2 deletions fixlib/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ commands = flake8 --verbose
commands= pytest

[testenv:black]
commands = black --line-length 120 --check --diff --target-version py39 .
commands = black --line-length 120 --check --diff --target-version py311 .

[testenv:mypy]
commands= mypy --install-types --non-interactive --python-version 3.9 --strict fixlib
commands= mypy --install-types --non-interactive --python-version 3.11 --strict fixlib
Loading

0 comments on commit c6e9b82

Please sign in to comment.