Skip to content

Commit

Permalink
Merge branch 'feature-rebac' into css-4603/use-ofga
Browse files Browse the repository at this point in the history
Signed-off-by: Babak K. Shandiz <[email protected]>
  • Loading branch information
babakks committed Jul 11, 2023
2 parents b525753 + 5132ed1 commit ccbb88b
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 46 deletions.
16 changes: 10 additions & 6 deletions charms/jimm-k8s/lib/charms/openfga_k8s/v0/openfga.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def _on_openfga_store_created(self, event: OpenFGAStoreCreateEvent):

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 3
LIBPATCH = 4

logger = logging.getLogger(__name__)

Expand All @@ -88,23 +88,27 @@ class OpenFGAEvent(RelationEvent):

@property
def store_id(self):
return self.relation.data[self.relation.app].get("store_id")
return self.relation.data[self.relation.app].get("store_id", "")

@property
def token_secret_id(self):
return self.relation.data[self.relation.app].get("token_secret_id")
return self.relation.data[self.relation.app].get("token_secret_id", "")

@property
def token(self):
return self.relation.data[self.relation.app].get("token", "")

@property
def address(self):
return self.relation.data[self.relation.app].get("address")
return self.relation.data[self.relation.app].get("address", "")

@property
def scheme(self):
return self.relation.data[self.relation.app].get("scheme")
return self.relation.data[self.relation.app].get("scheme", "")

@property
def port(self):
return self.relation.data[self.relation.app].get("port")
return self.relation.data[self.relation.app].get("port", "")


class OpenFGAStoreCreateEvent(OpenFGAEvent):
Expand Down
76 changes: 52 additions & 24 deletions charms/jimm-k8s/src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@

WORKLOAD_CONTAINER = "jimm"

REQUIRED_SETTINGS = [
"JIMM_UUID",
"JIMM_DSN",
"CANDID_URL",
"OPENFGA_STORE",
"OPENFGA_AUTH_MODEL",
"OPENFGA_HOST",
"OPENFGA_SCHEME",
"OPENFGA_TOKEN",
"OPENFGA_PORT",
]
REQUIRED_SETTINGS = {
"JIMM_UUID": "missing uuid configuration",
"JIMM_DSN": "missing postgresql relation",
"CANDID_URL": "missing candid-url configuration",
"OPENFGA_STORE": "missing openfga relation",
"OPENFGA_AUTH_MODEL": "run create-authorization-model action",
"OPENFGA_HOST": "missing openfga relation",
"OPENFGA_SCHEME": "missing openfga relation",
"OPENFGA_TOKEN": "missing openfga relation",
"OPENFGA_PORT": "missing openfga relation",
}

DATABASE_NAME = "jimm"
OPENFGA_STORE_NAME = "jimm"
Expand All @@ -88,6 +88,7 @@ def __init__(self, *args):
super().__init__(*args)

self._state = State(self.app, lambda: self.model.get_relation("peer"))
self._unit_state = State(self.unit, lambda: self.model.get_relation("peer"))

self.framework.observe(self.on.peer_relation_changed, self._on_peer_relation_changed)
self.framework.observe(self.on.jimm_pebble_ready, self._on_jimm_pebble_ready)
Expand Down Expand Up @@ -236,6 +237,7 @@ def _update_workload(self, event):
return

self._ensure_bakery_agent_file(event)
self._ensure_vault_file(event)
self._install_dashboard(event)

dns_name = self._get_dns_name(event)
Expand Down Expand Up @@ -313,6 +315,7 @@ def _update_workload(self, event):
else:
logger.info("workload container not ready - defering")
event.defer()
return

dashboard_relation = self.model.get_relation("dashboard")
if dashboard_relation and self.unit.is_leader():
Expand All @@ -330,9 +333,12 @@ def _on_start(self, event):

def _on_stop(self, _):
"""Stop JIMM."""
container = self.unit.get_container(WORKLOAD_CONTAINER)
if container.can_connect():
container.stop()
try:
container = self.unit.get_container(WORKLOAD_CONTAINER)
if container.can_connect():
container.stop("jimm")
except Exception as e:
logger.info("failed to stop the jimm service: {}".format(e))
self._ready()

def _on_update_status(self, _):
Expand Down Expand Up @@ -392,10 +398,10 @@ def _ready(self):

env_vars = plan.services.get("jimm").environment

for setting in REQUIRED_SETTINGS:
for setting, message in REQUIRED_SETTINGS.items():
if not env_vars.get(setting, ""):
self.unit.status = BlockedStatus(
"{} configuration value not set".format(setting),
"{} configuration value not set: {}".format(setting, message),
)
return False

Expand All @@ -416,6 +422,7 @@ def _install_dashboard(self, event):
# this event.
if not container.can_connect():
event.defer()
return

# fetch the resource filename
try:
Expand Down Expand Up @@ -462,7 +469,7 @@ def _install_dashboard(self, event):

# remove the existing dashboard from the workload/
if container.exists(self._dashboard_path):
container.remove_path(self._dashboard_path)
container.remove_path(self._dashboard_path, recursive=True)

container.make_dir(self._dashboard_path, make_parents=True)

Expand Down Expand Up @@ -496,10 +503,14 @@ def _on_vault_relation_joined(self, event):
event.relation.data[self.unit]["access_address"] = json.dumps(self._get_network_address(event))
event.relation.data[self.unit]["isolated"] = json.dumps(False)

@requires_state_setter
def _on_vault_relation_changed(self, event):
def _ensure_vault_file(self, event):
container = self.unit.get_container(WORKLOAD_CONTAINER)

if not self._unit_state.is_ready():
logger.info("unit state not ready")
event.defer()
return

# if we can't connect to the container we should defer
# this event.
if not container.can_connect():
Expand All @@ -509,6 +520,16 @@ def _on_vault_relation_changed(self, event):
if container.exists(self._vault_secret_filename):
container.remove_path(self._vault_secret_filename)

secret_data = self._unit_state.vault_secret_data
if secret_data:
self._push_to_workload(self._vault_secret_filename, secret_data, event)

def _on_vault_relation_changed(self, event):
if not self._unit_state.is_ready() or not self._state.is_ready():
logger.info("state not ready")
event.defer()
return

addr = _json_data(event, "vault_url")
if not addr:
return
Expand All @@ -523,9 +544,13 @@ def _on_vault_relation_changed(self, event):
secret["data"]["role_id"] = role_id

secret_data = json.dumps(secret)
self._push_to_workload(self._vault_secret_filename, secret_data, event)

self._state.vault_address = addr
logger.error("setting unit state data {}".format(secret_data))
self._unit_state.vault_secret_data = secret_data
if self.unit.is_leader():
self._state.vault_address = addr

self._update_workload(event)

def _path_exists_in_workload(self, path: str):
"""Returns true if the specified path exists in the
Expand Down Expand Up @@ -564,11 +589,14 @@ def _on_openfga_store_created(self, event: OpenFGAStoreCreateEvent):
if not event.store_id:
return

# secret = self.model.get_secret(id=event.token_secret_id)
# secret_content = secret.get_content()
token = event.token
if event.token_secret_id:
secret = self.model.get_secret(id=event.token_secret_id)
secret_content = secret.get_content()
token = secret_content["token"]

self._state.openfga_store_id = event.store_id
self._state.openfga_token = event.token # secret_content["token"]
self._state.openfga_token = token
self._state.openfga_address = event.address
self._state.openfga_port = event.port
self._state.openfga_scheme = event.scheme
Expand Down
3 changes: 2 additions & 1 deletion charms/jimm-k8s/tests/unit/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ def setUp(self):
self.addCleanup(self.tempdir.cleanup)
self.harness.charm.framework.charm_dir = pathlib.Path(self.tempdir.name)

self.harness.add_relation("peer", "jimm")
jimm_id = self.harness.add_relation("peer", "juju-jimm-k8s")
self.harness.add_relation_unit(jimm_id, "juju-jimm-k8s/1")
self.harness.container_pebble_ready("jimm")

rel_id = self.harness.add_relation("ingress", "nginx-ingress")
Expand Down
19 changes: 11 additions & 8 deletions charms/jimm/charmcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ type: "charm"
parts:
charm:
prime:
- ./templates
- ./files
- README.md
charm-python-packages: [setuptools]
- ./templates
- ./files
- README.md
charm-python-packages:
- setuptools
- cosl
- pydantic==1.10
bases:
# Ensure run-on is the same or newer than build-on
# since jimm-server is a Go binary using CGO dependencies
- build-on:
- name: "ubuntu"
channel: "20.04"
- name: "ubuntu"
channel: "20.04"
run-on:
- name: "ubuntu"
channel: "20.04"
- name: "ubuntu"
channel: "20.04"
2 changes: 1 addition & 1 deletion charms/jimm/lib/charms/grafana_agent/v0/cos_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class _MetricsEndpointDict(TypedDict):
LIBAPI = 0
LIBPATCH = 3

PYDEPS = ["cosl", "pydantic"]
PYDEPS = ["cosl", "pydantic==1.10"]

DEFAULT_RELATION_NAME = "cos-agent"
DEFAULT_PEER_RELATION_NAME = "peers"
Expand Down
6 changes: 5 additions & 1 deletion charms/jimm/lib/charms/openfga_k8s/v0/openfga.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def _on_openfga_store_created(self, event: OpenFGAStoreCreateEvent):

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 3
LIBPATCH = 4

logger = logging.getLogger(__name__)

Expand All @@ -93,6 +93,10 @@ def store_id(self):
@property
def token_secret_id(self):
return self.relation.data[self.relation.app].get("token_secret_id")

@property
def token(self):
return self.relation.data[self.relation.app].get("token")

@property
def address(self):
Expand Down
2 changes: 1 addition & 1 deletion charms/jimm/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ Jinja2 >= 2.11.3
ops >= 2.0.0
charmhelpers >= 0.20.22
hvac >= 0.11.0
pydantic
pydantic == 1.10
cosl
11 changes: 7 additions & 4 deletions charms/jimm/src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,16 +409,19 @@ def _on_openfga_store_created(self, event: OpenFGAStoreCreateEvent):
if not event.store_id:
return

logger.error("token secret {}".format(event.token_secret_id))
secret = self.model.get_secret(id=event.token_secret_id)
secret_content = secret.get_content()
token = event.token
if event.token_secret_id:
logger.error("token secret {}".format(event.token_secret_id))
secret = self.model.get_secret(id=event.token_secret_id)
secret_content = secret.get_content()
token = secret_content["token"]

args = {
"openfga_host": event.address,
"openfga_port": event.port,
"openfga_scheme": event.scheme,
"openfga_store": event.store_id,
"openfga_token": secret_content["token"],
"openfga_token": token,
}

with open(self._env_filename("openfga"), "wt") as f:
Expand Down

0 comments on commit ccbb88b

Please sign in to comment.