def setup_client(self) -> Container: """Setup client saml-sp container which we test SAML against""" sleep(1) client: DockerClient = from_env() container = client.containers.run( image="ghcr.io/beryju/oidc-test-client:latest", detach=True, network_mode="host", auto_remove=True, healthcheck=Healthcheck( test=["CMD", "wget", "--spider", "http://localhost:9009/health"], interval=5 * 100 * 1000000, start_period=1 * 100 * 1000000, ), environment={ "OIDC_CLIENT_ID": self.client_id, "OIDC_CLIENT_SECRET": self.client_secret, "OIDC_PROVIDER": f"{self.live_server_url}/application/o/{self.application_slug}/", }, ) while True: container.reload() status = container.attrs.get("State", {}).get("Health", {}).get("Status") if status == "healthy": return container self.logger.info("Container failed healthcheck") sleep(1)
def get_container_specs(self) -> Optional[dict[str, Any]]: return { "image": "ghcr.io/dexidp/dex:v2.28.1", "detach": True, "network_mode": "host", "auto_remove": True, "command": "dex serve /config.yml", "healthcheck": Healthcheck( test=[ "CMD", "wget", "--spider", "http://localhost:5556/dex/healthz" ], interval=5 * 100 * 1000000, start_period=1 * 100 * 1000000, ), "volumes": { abspath(CONFIG_PATH): { "bind": "/config.yml", "mode": "ro" } }, }
def setup_client(self, provider: SAMLProvider) -> Container: """Setup client saml-sp container which we test SAML against""" client: DockerClient = from_env() container = client.containers.run( image="beryju/saml-test-sp", detach=True, network_mode="host", auto_remove=True, healthcheck=Healthcheck( test=[ "CMD", "wget", "--spider", "http://localhost:9009/health" ], interval=5 * 100 * 1000000, start_period=1 * 100 * 1000000, ), environment={ "SP_ENTITY_ID": provider.issuer, "SP_SSO_BINDING": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", "SP_METADATA_URL": (self.url( "authentik_api:samlprovider-metadata", pk=provider.pk, ) + "?download"), }, ) while True: container.reload() status = container.attrs.get("State", {}).get("Health", {}).get("Status") if status == "healthy": return container LOGGER.info("Container failed healthcheck") sleep(1)
def ddb_url(docker_client: DockerClient) -> str: SECOND: int = 1_000_000_000 local_port: int = random.randint(49152, 65535) container: Container = docker_client.containers.run( "amazon/dynamodb-local", detach=True, healthcheck=Healthcheck( test= "curl -s -I http://localhost:8000 | grep -q 'HTTP/1.1 400 Bad Request'", interval=1 * SECOND, timeout=1 * SECOND, retries=3, ), ports={"8000/tcp": local_port}, remove=True, ) def health_status(): state = docker_client.api.inspect_container(container.id)["State"] return state["Health"]["Status"] while health_status() != "healthy": sleep(0.5) container.reload() yield f"http://localhost:{local_port}" container.stop()
def get_container_specs(self) -> Optional[dict[str, Any]]: """Setup client grafana container which we test OAuth against""" return { "image": "grafana/grafana:7.1.0", "detach": True, "network_mode": "host", "auto_remove": True, "healthcheck": Healthcheck( test=["CMD", "wget", "--spider", "http://localhost:3000"], interval=5 * 100 * 1000000, start_period=1 * 100 * 1000000, ), "environment": { "GF_AUTH_GITHUB_ENABLED": "true", "GF_AUTH_GITHUB_ALLOW_SIGN_UP": "true", "GF_AUTH_GITHUB_CLIENT_ID": self.client_id, "GF_AUTH_GITHUB_CLIENT_SECRET": self.client_secret, "GF_AUTH_GITHUB_SCOPES": "user:email,read:org", "GF_AUTH_GITHUB_AUTH_URL": self.url( "authentik_providers_oauth2_github:github-authorize" ), "GF_AUTH_GITHUB_TOKEN_URL": self.url( "authentik_providers_oauth2_github:github-access-token" ), "GF_AUTH_GITHUB_API_URL": self.url( "authentik_providers_oauth2_github:github-user" ), "GF_LOG_LEVEL": "debug", }, }
def swarm_healthcheck(self, allow_probe=False): if allow_probe and self.healthcheck['enabled']: return Healthcheck( test=["CMD", "curl", "-f", "http://localhost:8080/health"], interval=self.healthcheck['interval'] * self._SEC_RATE, timeout=self.healthcheck['timeout'] * self._SEC_RATE, retries=self.healthcheck['retries'], start_period=self.healthcheck['start_period'] * self._SEC_RATE) else: return None
def get_container_specs(self) -> Optional[dict[str, Any]]: return { "image": "mailhog/mailhog:v1.0.1", "detach": True, "network_mode": "host", "auto_remove": True, "healthcheck": Healthcheck( test=["CMD", "wget", "--spider", "http://localhost:8025"], interval=5 * 100 * 1000000, start_period=1 * 100 * 1000000, ), }
def get_container_specs(self) -> Optional[dict[str, Any]]: return { "image": "kristophjunge/test-saml-idp:1.15", "detach": True, "network_mode": "host", "auto_remove": True, "healthcheck": Healthcheck( test=["CMD", "curl", "http://localhost:8080"], interval=5 * 100 * 1000000, start_period=1 * 100 * 1000000, ), "environment": { "SIMPLESAMLPHP_SP_ENTITY_ID": "entity-id", "SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE": ( f"{self.live_server_url}/source/saml/saml-idp-test/acs/" ), }, }
def get_container_specs(self) -> Optional[dict[str, Any]]: return { "image": "grafana/grafana:7.1.0", "detach": True, "network_mode": "host", "auto_remove": True, "healthcheck": Healthcheck( test=["CMD", "wget", "--spider", "http://localhost:3000"], interval=5 * 100 * 1000000, start_period=1 * 100 * 1000000, ), "environment": { "GF_AUTH_GENERIC_OAUTH_ENABLED": "true", "GF_AUTH_GENERIC_OAUTH_CLIENT_ID": self.client_id, "GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET": self.client_secret, "GF_AUTH_GENERIC_OAUTH_SCOPES": "openid email profile", "GF_AUTH_GENERIC_OAUTH_AUTH_URL": (self.url("authentik_providers_oauth2:authorize")), "GF_AUTH_GENERIC_OAUTH_TOKEN_URL": (self.url("authentik_providers_oauth2:token")), "GF_AUTH_GENERIC_OAUTH_API_URL": (self.url("authentik_providers_oauth2:userinfo")), "GF_AUTH_SIGNOUT_REDIRECT_URL": (self.url( "authentik_providers_oauth2:end-session", application_slug=APPLICATION_SLUG, )), "GF_LOG_LEVEL": "debug", }, }
def get_parameters(self): """ Parse DockerRunBuilder options and create object with properties for docker-py run command :return: DockerContainerParameters """ import argparse parser = argparse.ArgumentParser(add_help=False) # without parameter parser.add_argument("-i", "--interactive", action="store_true", dest="stdin_open") parser.add_argument("-d", "--detach", action="store_true", dest="detach") parser.add_argument("-t", "--tty", action="store_true", dest="tty") parser.add_argument("--init", action="store_true", dest="init") parser.add_argument("--privileged", action="store_true", dest="privileged") parser.add_argument("-P", "--publish-all", action="store_true", dest="publish_all_ports") parser.add_argument("--read-only", action="store_true", dest="read_only") parser.add_argument("--rm", action="store_true", dest="remove") # string parameter parser.add_argument("--entrypoint", action="store", dest="entrypoint") parser.add_argument("-h", "--hostname", action="store", dest="hostname") parser.add_argument("--name", action="store", dest="name") parser.add_argument("--ipc", action="store", dest="ipc_mode") parser.add_argument("--isolation", action="store", dest="isolation") parser.add_argument("--mac-address", action="store", dest="mac_address") parser.add_argument("-m", "--memory", action="store", dest="mem_limit") parser.add_argument("--network", action="store", dest="network") parser.add_argument("--platform", action="store", dest="platform") parser.add_argument("--runtime", action="store", dest="runtime") parser.add_argument("--stop-signal", action="store", dest="stop_signal") parser.add_argument("-u", "--user", action="store", dest="user") parser.add_argument("-w", "--workdir", action="store", dest="working_dir") # int parameter parser.add_argument("--pids-limit", action="store", dest="pids_limit", type=int) # list parameter parser.add_argument("-e", "--env", action="append", dest="env_variables") parser.add_argument("--cap-add", action="append", dest="cap_add") parser.add_argument("--cap-drop", action="append", dest="cap_drop") parser.add_argument("--device", action="append", dest="devices") parser.add_argument("--dns", action="append", dest="dns") parser.add_argument("--group-add", action="append", dest="group_add") parser.add_argument("--mount", action="append", dest="mounts") parser.add_argument("-v", "--volume", action="append", dest="volumes") # dict parameter parser.add_argument("-l", "--label", action="append", dest="labels") parser.add_argument("-p", "--publish", action="append", dest="port_mappings") # health parser.add_argument("--health-cmd", action="store", dest="health_cmd") parser.add_argument("--health-interval", action="store", dest="health_interval", type=int) parser.add_argument("--health-retries", action="store", dest="health_retries", type=int) parser.add_argument("--health-timeout", action="store", dest="health_timeout", type=int) parser.add_argument("--no-healthcheck", action="store_true", dest="no_healthcheck") args, _ = parser.parse_known_args(args=self.options) command = self.arguments options_dict = vars(args) # create Healthcheck object if not options_dict.pop("no_healthcheck", None): options_dict["healthcheck"] = Healthcheck( test=options_dict.pop("health_cmd", None), interval=options_dict.pop("health_interval", None), timeout=options_dict.pop("health_timeout", None), retries=options_dict.pop("health_retries", None)) else: options_dict['healthcheck'] = None # parse dictionary # {'name': 'separator'} with_dictionary_parameter = {'labels': '='} for name, separator in with_dictionary_parameter.items(): if options_dict[name] is not None: dictionary = {} for item in options_dict[name]: try: key, value = item.split(separator) dictionary[key] = value except ValueError: dictionary = options_dict[name] raise ConuException( 'Wrong format of dictionary: {name}'.format( name=name)) break options_dict[name] = dictionary # parse ports # create dictionary according to https://docker-py.readthedocs.io/en/stable/containers.html if options_dict['port_mappings'] is not None: dictionary = {} for port_string in options_dict['port_mappings']: colon_count = port_string.count(':') if colon_count == 2: split_array = port_string.split(':') if split_array[1] == '': # format - ip::containerPort # create dictionary - {'1111/tcp': ('127.0.0.1', None)} dictionary[split_array[2]] = (split_array[0], None) else: # format - ip:hostPort:containerPort # create dictionary - {'1111/tcp': ('127.0.0.1', 1111)} dictionary[split_array[2]] = (split_array[0], int(split_array[1])) elif colon_count == 1: # format - hostPort:containerPort # create dictionary - {'2222/tcp': 3333} split_array = port_string.split(':') dictionary[split_array[1]] = int(split_array[0]) elif colon_count == 0: # format - containerPort # create dictionary - {'2222/tcp': None} dictionary[port_string] = None else: raise ConuException('Wrong format of port mappings') options_dict['port_mappings'] = dictionary container_parameters = DockerContainerParameters( cap_add=options_dict['cap_add'], cap_drop=options_dict['cap_drop'], command=command, detach=options_dict['detach'], devices=options_dict['devices'], dns=options_dict['dns'], entrypoint=options_dict['entrypoint'], env_variables=options_dict['env_variables'], group_add=options_dict['group_add'], healthcheck=options_dict['healthcheck'], hostname=options_dict['hostname'], init=options_dict['init'], ipc_mode=options_dict['ipc_mode'], isolation=options_dict['isolation'], labels=options_dict['labels'], mac_address=options_dict['mac_address'], mem_limit=options_dict['mem_limit'], mounts=options_dict['mounts'], name=options_dict['name'], network=options_dict['network'], pids_limit=options_dict['pids_limit'], platform=options_dict['platform'], port_mappings=options_dict['port_mappings'], privileged=options_dict['privileged'], publish_all_ports=options_dict['publish_all_ports'], read_only=options_dict['read_only'], remove=options_dict['remove'], runtime=options_dict['runtime'], stdin_open=options_dict['stdin_open'], stop_signal=options_dict['stop_signal'], tty=options_dict['tty'], user=options_dict['user'], volumes=options_dict['volumes'], working_dir=options_dict['working_dir']) return container_parameters