Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ def get_docker_image(self) -> str:
def get_record_env_key(self) -> str:
return f'{self.get_integration_name().upper()}_RECORD'

def get_integration_service_ports(self, config) -> List[str]:
"""Return host:container port mappings for the integration container. Override if needed."""
return []

def get_commander_service_name(self) -> str:
return f'commander-{self.get_integration_name().lower()}'

Expand Down Expand Up @@ -250,7 +254,7 @@ def _run_integration_setup(self, params, setup_result: SetupResult,
record_uid = self._create_integration_record(params, record_name, setup_result.folder_uid, custom_fields)

DockerSetupPrinter.print_step(2, 2, f"Updating docker-compose.yml with {name} App service...")
self._update_docker_compose(setup_result, service_config, record_uid)
self._update_docker_compose(setup_result, service_config, record_uid, config)

return record_uid, config

Expand Down Expand Up @@ -306,7 +310,7 @@ def _update_record_custom_fields(self, params, record_uid: str, custom_fields: L

def _update_docker_compose(self, setup_result: SetupResult,
service_config: ServiceConfig,
record_uid: str) -> None:
record_uid: str, config=None) -> None:
compose_file = os.path.join(os.getcwd(), 'docker-compose.yml')
service_name = self.get_docker_service_name()

Expand All @@ -329,7 +333,8 @@ def _update_docker_compose(self, setup_result: SetupResult,
container_name=self.get_docker_container_name(),
image=self.get_docker_image(),
record_uid=record_uid,
record_env_key=self.get_record_env_key()
record_env_key=self.get_record_env_key(),
ports=self.get_integration_service_ports(config)
).build()

with open(compose_file, 'w') as f:
Expand Down
17 changes: 17 additions & 0 deletions keepercommander/service/commands/integrations/teams_app_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@

"""Teams App integration setup command."""

from typing import List

from .... import vault
from ....display import bcolors
from ...docker import TeamsConfig
from ...config.config_validation import ConfigValidator, ValidationError
from .integration_setup_base import IntegrationSetupCommand


Expand Down Expand Up @@ -66,6 +69,16 @@ def collect_integration_config(self):
"Invalid Team ID (must be 32 hex characters in pattern xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)"
)

print(f"\n{bcolors.BOLD}TEAMS_BOT_PORT:{bcolors.ENDC}")
print(f" Port on which the Teams bot will listen for incoming requests")
while True:
bot_port_input = input(f"{bcolors.OKBLUE}Bot Port [Press Enter for 3978]:{bcolors.ENDC} ").strip() or '3978'
try:
bot_port = ConfigValidator.validate_port(bot_port_input)
break
except ValidationError as e:
print(f"{bcolors.FAIL}Error: {str(e)}{bcolors.ENDC}")

pedm_enabled, pedm_interval = self._collect_pedm_config()
da_enabled, da_interval = self._collect_device_approval_config()

Expand All @@ -77,6 +90,7 @@ def collect_integration_config(self):
tenant_id=tenant_id,
approvals_channel_id=approvals_channel_id,
approvals_team_id=approvals_team_id,
bot_port=bot_port,
pedm_enabled=pedm_enabled,
pedm_polling_interval=pedm_interval,
device_approval_enabled=da_enabled,
Expand All @@ -96,6 +110,9 @@ def build_record_custom_fields(self, config):
vault.TypedField.new_field('text', str(config.device_approval_polling_interval), 'device_approval_polling_interval'),
]

def get_integration_service_ports(self, config) -> List[str]:
return [f'{config.bot_port}:{config.bot_port}']

# ── Display ───────────────────────────────────────────────────

def print_integration_specific_resources(self, config):
Expand Down
36 changes: 20 additions & 16 deletions keepercommander/service/docker/compose_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@ def build_dict(self) -> Dict[str, Any]:

def add_integration_service(self, service_name: str, container_name: str,
image: str, record_uid: str,
record_env_key: str) -> 'DockerComposeBuilder':
record_env_key: str,
ports: List[str] = None) -> 'DockerComposeBuilder':
"""Add an integration service to the compose file. Returns self."""
if self.commander_service_name not in self._services:
self._services[self.commander_service_name] = self._build_commander_service()
self._services[service_name] = self._build_integration_service(
container_name, image, record_uid, record_env_key
container_name, image, record_uid, record_env_key, ports or []
)
return self

Expand All @@ -65,23 +66,26 @@ def _build_commander_service(self) -> Dict[str, Any]:
return service

def _build_integration_service(self, container_name: str, image: str,
record_uid: str,
record_env_key: str) -> Dict[str, Any]:
return {
record_uid: str, record_env_key: str,
ports: List[str] = None) -> Dict[str, Any]:
service: Dict[str, Any] = {
'container_name': container_name,
'image': image,
'environment': {
'KSM_CONFIG': self.setup_result.b64_config,
'COMMANDER_RECORD': self.setup_result.record_uid,
record_env_key: record_uid
},
'depends_on': {
self.commander_service_name: {
'condition': 'service_healthy'
}
},
'restart': 'unless-stopped'
}
if ports:
service['ports'] = ports
service['environment'] = {
'KSM_CONFIG': self.setup_result.b64_config,
'COMMANDER_RECORD': self.setup_result.record_uid,
record_env_key: record_uid
}
service['depends_on'] = {
self.commander_service_name: {
'condition': 'service_healthy'
}
}
service['restart'] = 'unless-stopped'
return service

def _build_service_command(self) -> None:
port = self.config['port']
Expand Down
1 change: 1 addition & 0 deletions keepercommander/service/docker/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class TeamsConfig:
tenant_id: str
approvals_channel_id: str
approvals_team_id: str
bot_port: int = 3978
pedm_enabled: bool = False
pedm_polling_interval: int = 120
device_approval_enabled: bool = False
Expand Down