Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions keepercommander/commands/pam/pam_dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,12 @@ def __init__(self, inputs: GatewayActionIdpInputs, conversation_id=None):

def toJSON(self):
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4)


class GatewayActionIdpValidateDomain(GatewayAction):

def __init__(self, inputs: GatewayActionIdpInputs, conversation_id=None):
super().__init__('rm-validate-domain', inputs=inputs, conversation_id=conversation_id, is_scheduled=False)

def toJSON(self):
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4)
63 changes: 57 additions & 6 deletions keepercommander/commands/pam_cloud/pam_request_access.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import argparse
import json
import logging

from keeper_secrets_manager_core.utils import url_safe_str_to_bytes

from keepercommander.commands.base import Command, RecordMixin
from keepercommander.commands.pam.pam_dto import (
GatewayAction,
GatewayActionIdpInputs,
GatewayActionIdpValidateDomain,
)
from keepercommander.commands.pam.router_helper import router_send_action_to_gateway
from keepercommander.commands.pam_cloud.pam_idp import resolve_idp_config
from keepercommander.commands.tunnel.port_forward.tunnel_helpers import (
get_config_uid_from_record,
get_gateway_uid_from_record,
)
from keepercommander.error import CommandError
from keepercommander import api, vault
from keepercommander.proto import NotificationCenter_pb2, GraphSync_pb2
from keepercommander.proto import NotificationCenter_pb2, GraphSync_pb2, pam_pb2


ELIGIBLE_RECORD_TYPES = {'pamRemoteBrowser', 'pamDatabase', 'pamMachine'}
Expand Down Expand Up @@ -54,7 +66,48 @@ def execute(self, params, **kwargs):
if owner == params.user:
raise CommandError('pam-request-access', 'You are the owner of this record.')

# Build notification
# Resolve PAM config and IdP config for this resource
config_uid = get_config_uid_from_record(params, vault, record.record_uid)
if not config_uid:
raise CommandError('pam-request-access', 'Could not resolve PAM configuration for this resource.')

gateway_uid = get_gateway_uid_from_record(params, vault, record.record_uid)

# Validate the requesting user's domain against the IdP
try:
idp_config_uid = resolve_idp_config(params, config_uid)
except CommandError:
idp_config_uid = config_uid

inputs = GatewayActionIdpInputs(
configuration_uid=config_uid,
idp_config_uid=idp_config_uid,
user=params.user,
resourceUid=record.record_uid,
)
action = GatewayActionIdpValidateDomain(inputs=inputs)
conversation_id = GatewayAction.generate_conversation_id()
action.conversationId = conversation_id

router_response = router_send_action_to_gateway(
params=params,
gateway_action=action,
message_type=pam_pb2.CMT_GENERAL,
is_streaming=False,
destination_gateway_uid_str=gateway_uid,
)

if router_response:
response = router_response.get('response', {})
payload_str = response.get('payload')
if payload_str:
payload = json.loads(payload_str)
data = payload.get('data', {})
if isinstance(data, dict) and not data.get('success', True):
error_msg = data.get('error', 'Domain validation failed')
raise CommandError('pam-request-access', error_msg)

# Domain validated — send approval notification to record owner
record_uid_bytes = url_safe_str_to_bytes(record.record_uid)

record_ref = GraphSync_pb2.GraphSyncRef()
Expand All @@ -81,8 +134,6 @@ def execute(self, params, **kwargs):
batch_rq = NotificationCenter_pb2.NotificationsSendRequest()
batch_rq.notifications.append(send_rq)

#api.communicate_rest(params, batch_rq, 'vault/notifications_send')
api.communicate_rest(params, batch_rq, 'vault/notifications_send')

print(batch_rq)

logging.info(f'Credential request sent to {owner} for record "{record.title}".')
logging.info(f'Access request sent to {owner} for record "{record.title}".')
Loading