cmdbox 0.5.3.1__py3-none-any.whl → 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cmdbox might be problematic. Click here for more details.
- cmdbox/app/auth/__init__.py +0 -0
- cmdbox/app/auth/azure_signin.py +38 -0
- cmdbox/app/auth/azure_signin_saml.py +12 -0
- cmdbox/app/auth/github_signin.py +38 -0
- cmdbox/app/auth/google_signin.py +32 -0
- cmdbox/app/auth/signin.py +490 -287
- cmdbox/app/auth/signin_saml.py +61 -0
- cmdbox/app/common.py +48 -3
- cmdbox/app/edge.py +182 -213
- cmdbox/app/edge_tool.py +177 -0
- cmdbox/app/feature.py +10 -10
- cmdbox/app/features/cli/agent_base.py +477 -0
- cmdbox/app/features/cli/audit_base.py +1 -1
- cmdbox/app/features/cli/cmdbox_audit_search.py +24 -1
- cmdbox/app/features/cli/cmdbox_client_file_download.py +1 -1
- cmdbox/app/features/cli/cmdbox_cmd_list.py +105 -0
- cmdbox/app/features/cli/cmdbox_cmd_load.py +104 -0
- cmdbox/app/features/cli/cmdbox_edge_config.py +21 -7
- cmdbox/app/features/cli/cmdbox_edge_start.py +1 -1
- cmdbox/app/features/cli/cmdbox_gui_start.py +9 -132
- cmdbox/app/features/cli/cmdbox_gui_stop.py +4 -21
- cmdbox/app/features/cli/cmdbox_server_start.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_apikey_add.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_apikey_del.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_genpass.py +0 -3
- cmdbox/app/features/cli/cmdbox_web_group_add.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_group_del.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_group_edit.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_group_list.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_start.py +119 -104
- cmdbox/app/features/cli/cmdbox_web_stop.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_user_add.py +4 -4
- cmdbox/app/features/cli/cmdbox_web_user_del.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_user_edit.py +4 -4
- cmdbox/app/features/cli/cmdbox_web_user_list.py +1 -1
- cmdbox/app/features/web/cmdbox_web_agent.py +250 -0
- cmdbox/app/features/web/cmdbox_web_do_signin.py +79 -103
- cmdbox/app/features/web/cmdbox_web_exec_cmd.py +8 -3
- cmdbox/app/features/web/cmdbox_web_signin.py +26 -4
- cmdbox/app/features/web/cmdbox_web_users.py +2 -0
- cmdbox/app/options.py +55 -2
- cmdbox/app/web.py +155 -27
- cmdbox/extensions/features.yml +18 -0
- cmdbox/extensions/sample_project/sample/app/features/cli/__init__.py +0 -0
- cmdbox/extensions/sample_project/sample/app/features/web/__init__.py +0 -0
- cmdbox/extensions/sample_project/sample/extensions/features.yml +23 -0
- cmdbox/extensions/sample_project/sample/extensions/user_list.yml +40 -6
- cmdbox/extensions/user_list.yml +37 -6
- cmdbox/licenses/{LICENSE.starlette.0.41.3(BSD License).txt → LICENSE.Authlib.1.5.2(BSD License).txt } +3 -1
- cmdbox/licenses/{LICENSE.pydantic_core.2.33.0(MIT License).txt → LICENSE.Deprecated.1.2.18(MIT License).txt } +2 -2
- cmdbox/licenses/{LICENSE.more-itertools.10.6.0(MIT License).txt → LICENSE.SQLAlchemy.2.0.40(MIT License).txt } +1 -1
- cmdbox/licenses/LICENSE.aiohttp.3.11.18(Apache Software License).txt +13 -0
- cmdbox/licenses/LICENSE.aiosignal.1.3.2(Apache Software License).txt +201 -0
- cmdbox/licenses/LICENSE.async-timeout.5.0.1(Apache Software License).txt +13 -0
- cmdbox/licenses/{LICENSE.watchfiles.1.0.0(MIT License).txt → LICENSE.attrs.25.3.0(UNKNOWN).txt} +1 -1
- cmdbox/licenses/{LICENSE.anyio.4.6.2.post1(MIT License).txt → LICENSE.cachetools.5.5.2(MIT License).txt } +1 -1
- cmdbox/licenses/LICENSE.distro.1.9.0(Apache Software License).txt +202 -0
- cmdbox/licenses/{LICENSE.pydantic_core.2.33.1(MIT License).txt → LICENSE.docstring_parser.0.16(MIT License).txt } +1 -1
- cmdbox/licenses/LICENSE.filelock.3.18.0(The Unlicense (Unlicense)).txt +24 -0
- cmdbox/licenses/LICENSE.frozenlist.1.6.0(Apache-2.0).txt +201 -0
- cmdbox/licenses/{LICENSE.starlette.0.46.1(BSD License).txt → LICENSE.fsspec.2025.3.2(BSD License).txt } +3 -1
- cmdbox/licenses/{LICENSE.argcomplete.3.6.1(Apache Software License).txt → LICENSE.google-adk.0.5.0(Apache Software License).txt } +25 -0
- cmdbox/licenses/LICENSE.google-api-python-client.2.169.0(Apache Software License).txt +201 -0
- cmdbox/licenses/LICENSE.google-auth-httplib2.0.2.0(Apache Software License).txt +201 -0
- cmdbox/licenses/LICENSE.google-auth.2.40.1(Apache Software License).txt +201 -0
- cmdbox/licenses/LICENSE.google-cloud-aiplatform.1.92.0(Apache 2.0).txt +202 -0
- cmdbox/licenses/LICENSE.google-cloud-bigquery.3.31.0(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.google-cloud-core.2.4.3(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.google-cloud-resource-manager.1.14.2(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.google-cloud-secret-manager.2.23.3(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.google-cloud-speech.2.32.0(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.google-cloud-storage.2.19.0(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.google-cloud-trace.1.16.1(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.google-crc32c.1.7.1(Apache 2.0).txt +202 -0
- cmdbox/licenses/LICENSE.google-genai.1.14.0(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.google-resumable-media.2.7.2(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.googleapis-common-protos.1.70.0(Apache Software License).txt +202 -0
- cmdbox/licenses/{LICENSE.fastapi.0.115.5(MIT License).txt → LICENSE.graphviz.0.20.3(MIT License).txt } +1 -1
- cmdbox/licenses/LICENSE.grpc-google-iam-v1.0.14.2(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.grpcio-status.1.71.0(Apache Software License).txt +610 -0
- cmdbox/licenses/LICENSE.grpcio.1.71.0(Apache Software License).txt +610 -0
- cmdbox/licenses/{LICENSE.uvicorn.0.34.0(BSD License).txt → LICENSE.httpcore.1.0.9(BSD License).txt } +1 -1
- cmdbox/licenses/LICENSE.httplib2.0.22.0(MIT License).txt +23 -0
- cmdbox/licenses/{LICENSE.tomli.2.1.0(MIT License).txt → LICENSE.httpx-sse.0.4.0(MIT).txt} +1 -1
- cmdbox/licenses/LICENSE.httpx.0.28.1(BSD License).txt +12 -0
- cmdbox/licenses/LICENSE.huggingface-hub.0.31.1(Apache Software License).txt +201 -0
- cmdbox/licenses/{LICENSE.charset-normalizer.3.4.0(MIT License).txt → LICENSE.jsonschema-specifications.2025.4.1(UNKNOWN).txt} +5 -7
- cmdbox/licenses/LICENSE.jsonschema.4.23.0(MIT License).txt +19 -0
- cmdbox/licenses/{LICENSE.pkginfo.1.10.0(MIT License).txt → LICENSE.litellm.1.69.0(MIT License).txt } +6 -1
- cmdbox/licenses/{LICENSE.redis.5.2.1(MIT License).txt → LICENSE.mcp.1.8.0(MIT License).txt } +1 -1
- cmdbox/licenses/LICENSE.multidict.6.4.3(Apache Software License).txt +13 -0
- cmdbox/licenses/{LICENSE.argcomplete.3.5.1(Apache Software License).txt → LICENSE.openai.1.75.0(Apache Software License).txt } +25 -1
- cmdbox/licenses/LICENSE.opentelemetry-api.1.33.0(Apache Software License).txt +201 -0
- cmdbox/licenses/LICENSE.opentelemetry-exporter-gcp-trace.1.9.0(Apache Software License).txt +201 -0
- cmdbox/licenses/LICENSE.opentelemetry-resourcedetector-gcp.1.9.0a0(Apache Software License).txt +201 -0
- cmdbox/licenses/LICENSE.opentelemetry-sdk.1.33.0(Apache Software License).txt +201 -0
- cmdbox/licenses/LICENSE.opentelemetry-semantic-conventions.0.54b0(Apache Software License).txt +201 -0
- cmdbox/licenses/LICENSE.propcache.0.3.1(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.proto-plus.1.26.1(Apache Software License).txt +202 -0
- cmdbox/licenses/{LICENSE.Pygments.2.18.0(BSD License).txt → LICENSE.protobuf.5.29.4(3-Clause BSD License).txt } +15 -8
- cmdbox/licenses/LICENSE.pyasn1.0.6.1(BSD License).txt +24 -0
- cmdbox/licenses/LICENSE.pyasn1_modules.0.4.2(BSD License).txt +24 -0
- cmdbox/licenses/LICENSE.pydantic-settings.2.9.1(MIT License).txt +21 -0
- cmdbox/licenses/{LICENSE.gevent.25.4.1(MIT).txt → LICENSE.pyparsing.3.2.3(MIT License).txt } +5 -12
- cmdbox/licenses/LICENSE.python-dateutil.2.9.0.post0(Apache Software License; BSD License).txt +54 -0
- cmdbox/licenses/LICENSE.referencing.0.36.2(UNKNOWN).txt +19 -0
- cmdbox/licenses/LICENSE.regex.2024.11.6(Apache Software License).txt +208 -0
- cmdbox/licenses/LICENSE.rpds-py.0.24.0(MIT).txt +19 -0
- cmdbox/licenses/{LICENSE.python-multipart.0.0.17(Apache Software License).txt → LICENSE.rsa.4.9.1(Apache Software License).txt } +1 -2
- cmdbox/licenses/{LICENSE.sphinx-intl.2.3.0(BSD License).txt → LICENSE.shapely.2.1.0(BSD License).txt } +6 -2
- cmdbox/licenses/LICENSE.sse-starlette.2.3.4(BSD License).txt +27 -0
- cmdbox/licenses/LICENSE.tiktoken.0.9.0(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.tokenizers.0.21.1(Apache Software License).txt +1 -0
- cmdbox/licenses/{LICENSE.six.1.16.0(MIT License).txt → LICENSE.tqdm.4.67.1(MIT License; Mozilla Public License 2.0 (MPL 2.0)).txt } +32 -1
- cmdbox/licenses/{LICENSE.rich.13.9.4(MIT License).txt → LICENSE.tzlocal.5.3.1(MIT License).txt } +3 -3
- cmdbox/licenses/LICENSE.uritemplate.4.1.1(Apache Software License; BSD License).txt +3 -0
- cmdbox/licenses/LICENSE.wrapt.1.17.2(BSD License).txt +24 -0
- cmdbox/licenses/LICENSE.yarl.1.20.0(Apache Software License).txt +202 -0
- cmdbox/licenses/files.txt +111 -17
- cmdbox/logconf_agent.yml +38 -0
- cmdbox/logconf_audit.yml +13 -5
- cmdbox/logconf_client.yml +13 -5
- cmdbox/logconf_cmdbox.yml +13 -5
- cmdbox/logconf_edge.yml +13 -5
- cmdbox/logconf_gui.yml +13 -5
- cmdbox/logconf_server.yml +13 -5
- cmdbox/logconf_web.yml +13 -5
- cmdbox/version.py +3 -2
- cmdbox/web/agent.html +263 -0
- cmdbox/web/assets/cmdbox/agent.js +335 -0
- cmdbox/web/assets/cmdbox/common.js +1111 -1020
- cmdbox/web/assets/cmdbox/signin.js +16 -3
- cmdbox/web/assets/cmdbox/users.js +1 -1
- cmdbox/web/assets/filer/filer.js +4 -2
- cmdbox/web/signin.html +10 -6
- {cmdbox-0.5.3.1.dist-info → cmdbox-0.6.0.dist-info}/METADATA +132 -35
- {cmdbox-0.5.3.1.dist-info → cmdbox-0.6.0.dist-info}/RECORD +161 -123
- cmdbox/app/features/web/cmdbox_web_load_pin.py +0 -43
- cmdbox/app/features/web/cmdbox_web_save_pin.py +0 -42
- cmdbox/licenses/LICENSE.Jinja2.3.1.4(BSD License).txt +0 -28
- cmdbox/licenses/LICENSE.Sphinx.8.1.3(BSD License).txt +0 -31
- cmdbox/licenses/LICENSE.babel.2.16.0(BSD License).txt +0 -27
- cmdbox/licenses/LICENSE.certifi.2025.1.31(Mozilla Public License 2.0 (MPL 2.0)).txt +0 -20
- cmdbox/licenses/LICENSE.click.8.1.8(BSD License).txt +0 -28
- cmdbox/licenses/LICENSE.cryptography.44.0.2(Apache Software License; BSD License).txt +0 -3
- cmdbox/licenses/LICENSE.greenlet.3.2.0(MIT AND Python-2.0).txt +0 -30
- cmdbox/licenses/LICENSE.keyring.25.5.0(MIT License).txt +0 -17
- cmdbox/licenses/LICENSE.numpy.2.2.4(BSD License).txt +0 -950
- cmdbox/licenses/LICENSE.pillow.11.0.0(CMU License (MIT-CMU)).txt +0 -1226
- cmdbox/licenses/LICENSE.pillow.11.1.0(CMU License (MIT-CMU)).txt +0 -1213
- cmdbox/licenses/LICENSE.prettytable.3.12.0(BSD License).txt +0 -30
- cmdbox/licenses/LICENSE.prompt_toolkit.3.0.50(BSD License).txt +0 -27
- cmdbox/licenses/LICENSE.psycopg.3.2.6(GNU Lesser General Public License v3 (LGPLv3)).txt +0 -165
- cmdbox/licenses/LICENSE.pydantic.2.11.1(MIT License).txt +0 -21
- cmdbox/licenses/LICENSE.pydantic.2.11.3(MIT License).txt +0 -21
- cmdbox/licenses/LICENSE.python-dotenv.1.0.1(BSD License).txt +0 -27
- cmdbox/licenses/LICENSE.twine.5.1.1(Apache Software License).txt +0 -174
- cmdbox/licenses/LICENSE.typing_extensions.4.13.0(UNKNOWN).txt +0 -279
- cmdbox/licenses/LICENSE.urllib3.2.2.3(MIT License).txt +0 -21
- cmdbox/licenses/LICENSE.urllib3.2.3.0(MIT License).txt +0 -21
- cmdbox/licenses/LICENSE.uvicorn.0.34.1(BSD License).txt +0 -27
- cmdbox/licenses/LICENSE.watchfiles.1.0.4(MIT License).txt +0 -21
- cmdbox/licenses/LICENSE.websockets.14.1(BSD License).txt +0 -24
- cmdbox/licenses/LICENSE.zope.interface.7.1.1(Zope Public License).txt +0 -44
- /cmdbox/licenses/{LICENSE.typing_extensions.4.12.2(Python Software Foundation License).txt → LICENSE.aiohappyeyeballs.2.6.1(Python Software Foundation License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.certifi.2024.8.30(Mozilla Public License 2.0 (MPL 2.0)).txt → LICENSE.certifi.2025.4.26(Mozilla Public License 2.0 (MPL 2.0)).txt} +0 -0
- /cmdbox/licenses/{LICENSE.charset-normalizer.3.4.1(MIT License).txt → LICENSE.charset-normalizer.3.4.2(MIT License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.click.8.1.7(BSD License).txt → LICENSE.click.8.2.0(UNKNOWN).txt} +0 -0
- /cmdbox/licenses/{LICENSE.cryptography.43.0.3(Apache Software License; BSD License).txt → LICENSE.cryptography.44.0.3(Apache Software License; BSD License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.gevent.24.11.1(MIT License).txt → LICENSE.gevent.25.4.2(MIT).txt} +0 -0
- /cmdbox/licenses/{LICENSE.importlib_metadata.8.5.0(Apache Software License).txt → LICENSE.google-api-core.2.24.2(Apache Software License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.greenlet.3.1.1(MIT License).txt → LICENSE.greenlet.3.2.2(MIT AND Python-2.0).txt} +0 -0
- /cmdbox/licenses/{LICENSE.h11.0.14.0(MIT License).txt → LICENSE.h11.0.16.0(MIT License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.nh3.0.2.18(MIT).txt → LICENSE.jiter.0.9.0(MIT License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.more-itertools.10.5.0(MIT License).txt → LICENSE.more-itertools.10.7.0(MIT License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.numpy.2.1.3(BSD License).txt → LICENSE.numpy.2.2.5(BSD License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.packaging.24.2(Apache Software License; BSD License).txt → LICENSE.packaging.25.0(Apache Software License; BSD License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.psycopg-binary.3.2.6(GNU Lesser General Public License v3 (LGPLv3)).txt → LICENSE.psycopg-binary.3.2.7(GNU Lesser General Public License v3 (LGPLv3)).txt} +0 -0
- /cmdbox/licenses/{LICENSE.psycopg-pool.3.2.6(GNU Lesser General Public License v3 (LGPLv3)).txt → LICENSE.psycopg.3.2.7(GNU Lesser General Public License v3 (LGPLv3)).txt} +0 -0
- /cmdbox/licenses/{LICENSE.pydantic.2.10.2(MIT License).txt → LICENSE.pydantic.2.11.4(MIT License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.pydantic_core.2.27.1(MIT License).txt → LICENSE.pydantic_core.2.33.2(MIT License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.redis.5.2.0(MIT License).txt → LICENSE.redis.6.0.0(MIT License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.snowballstemmer.2.2.0(BSD License).txt → LICENSE.snowballstemmer.3.0.1(BSD License).txt} +0 -0
- /cmdbox/licenses/{LICENSE.uvicorn.0.32.1(BSD License).txt → LICENSE.uvicorn.0.34.2(BSD License).txt} +0 -0
- {cmdbox-0.5.3.1.dist-info → cmdbox-0.6.0.dist-info}/LICENSE +0 -0
- {cmdbox-0.5.3.1.dist-info → cmdbox-0.6.0.dist-info}/WHEEL +0 -0
- {cmdbox-0.5.3.1.dist-info → cmdbox-0.6.0.dist-info}/entry_points.txt +0 -0
- {cmdbox-0.5.3.1.dist-info → cmdbox-0.6.0.dist-info}/top_level.txt +0 -0
cmdbox/app/edge.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from cmdbox.app import common, feature, options, web
|
|
1
|
+
from cmdbox.app import common, edge_tool, feature, options, web
|
|
2
2
|
from cmdbox.app.commons import convert
|
|
3
3
|
from cmdbox.app.options import Options
|
|
4
4
|
from fastapi import FastAPI, Request, HTTPException
|
|
@@ -26,7 +26,7 @@ class Edge(object):
|
|
|
26
26
|
self.appcls = appcls
|
|
27
27
|
self.ver = ver
|
|
28
28
|
self.options = options.Options.getInstance()
|
|
29
|
-
self.tool = Tool(logger, appcls, ver)
|
|
29
|
+
self.tool = edge_tool.Tool(logger, appcls, ver)
|
|
30
30
|
if self.ver is None:
|
|
31
31
|
raise ValueError('ver is None')
|
|
32
32
|
if self.appcls is None:
|
|
@@ -63,12 +63,30 @@ class Edge(object):
|
|
|
63
63
|
conf = common.loadopt(conf_file)
|
|
64
64
|
else:
|
|
65
65
|
conf = dict()
|
|
66
|
+
skip_opts = []
|
|
67
|
+
input_opts = []
|
|
68
|
+
def _show_opts(choice_show:Dict[str, List[str]], value:str, ref_opts:List[Dict[str, Any]]) -> None:
|
|
69
|
+
for k, v in choice_show.items():
|
|
70
|
+
if k == value:
|
|
71
|
+
input_opts.extend(v)
|
|
72
|
+
else:
|
|
73
|
+
skip_opts.extend(v)
|
|
74
|
+
for r in ref_opts:
|
|
75
|
+
for opt in v:
|
|
76
|
+
if 'opt' not in r or r['opt'] is None:
|
|
77
|
+
continue
|
|
78
|
+
if 'choice_show' not in r or r['choice_show'] is None:
|
|
79
|
+
continue
|
|
80
|
+
_show_opts(r['choice_show'], '', [o for o in ref_opts if o['opt'] == opt])
|
|
66
81
|
for r in ref_opts:
|
|
67
82
|
if 'opt' not in r or r['opt'] is None:
|
|
68
83
|
continue
|
|
69
84
|
opt = r['opt']
|
|
70
|
-
if opt in ['output_json', 'output_json_append', 'stdout_log', 'capture_stdout', 'capture_maxsize']:
|
|
85
|
+
if opt in ['tag', 'clmsg_id', 'output_json', 'output_json_append', 'stdout_log', 'capture_stdout', 'capture_maxsize']:
|
|
86
|
+
continue
|
|
87
|
+
if opt in skip_opts and opt not in input_opts:
|
|
71
88
|
continue
|
|
89
|
+
choice_show = r['choice_show'] if 'choice_show' in r else dict()
|
|
72
90
|
default = conf[opt] if opt in conf else None
|
|
73
91
|
default = r['default'] if default is None and 'default' in r else default
|
|
74
92
|
default = default if default is not None else ''
|
|
@@ -86,6 +104,7 @@ class Edge(object):
|
|
|
86
104
|
value = questionary.select(f"{opt}:({help}):", choice, default=default).ask()
|
|
87
105
|
else:
|
|
88
106
|
value = questionary.text(f"{opt}:({help}):", default=default, validate=lambda v:not required or len(v)>0).ask()
|
|
107
|
+
_show_opts(choice_show, value, ref_opts)
|
|
89
108
|
if r['type'] == Options.T_BOOL: value = value=='True'
|
|
90
109
|
if r['type'] == Options.T_INT: value = int(value)
|
|
91
110
|
if r['type'] == Options.T_FLOAT: value = float(value)
|
|
@@ -129,43 +148,71 @@ class Edge(object):
|
|
|
129
148
|
if 'auth_type' not in opt or opt['auth_type'] is None:
|
|
130
149
|
msg = dict(warn=f"Please run the `edge config` command. And please set the auth_type.")
|
|
131
150
|
return msg
|
|
132
|
-
if opt['auth_type'] == 'idpw'
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if opt['auth_type'] == 'idpw' and ('password' not in opt or opt['password'] is None):
|
|
136
|
-
msg = dict(warn=f"Please run the `edge config` command. And please set the password.")
|
|
137
|
-
return msg
|
|
138
|
-
if opt['auth_type'] == 'apikey' and ('apikey' not in opt or opt['apikey'] is None):
|
|
139
|
-
msg = dict(warn=f"Please run the `edge config` command. And please set the apikey.")
|
|
140
|
-
return msg
|
|
141
|
-
if opt['auth_type'] == 'oauth2' and ('oauth2' not in opt or opt['oauth2'] is None):
|
|
142
|
-
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2.")
|
|
143
|
-
return msg
|
|
144
|
-
if opt['auth_type'] == 'oauth2' and ('oauth2_port' not in opt or opt['oauth2_port'] is None):
|
|
145
|
-
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_port.")
|
|
146
|
-
return msg
|
|
147
|
-
if isinstance(opt['oauth2_port'], str):
|
|
148
|
-
if not opt['oauth2_port'].isdigit():
|
|
149
|
-
msg = dict(warn=f"Please set the numeric value in the oauth2_port. oauth2_port={opt['oauth2_port']}")
|
|
151
|
+
if opt['auth_type'] == 'idpw':
|
|
152
|
+
if 'user' not in opt or opt['user'] is None:
|
|
153
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the user.")
|
|
150
154
|
return msg
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_tenant_id.")
|
|
154
|
-
return msg
|
|
155
|
-
if opt['auth_type'] == 'oauth2' and ('oauth2_client_id' not in opt or opt['oauth2_client_id'] is None):
|
|
156
|
-
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_client_id.")
|
|
157
|
-
return msg
|
|
158
|
-
if opt['auth_type'] == 'oauth2' and ('oauth2_client_secret' not in opt or opt['oauth2_client_secret'] is None):
|
|
159
|
-
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_client_secret.")
|
|
160
|
-
return msg
|
|
161
|
-
if opt['auth_type'] == 'oauth2' and ('oauth2_timeout' not in opt or opt['oauth2_timeout'] is None):
|
|
162
|
-
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_timeout.")
|
|
163
|
-
return msg
|
|
164
|
-
if isinstance(opt['oauth2_timeout'], str):
|
|
165
|
-
if not opt['oauth2_timeout'].isdigit():
|
|
166
|
-
msg = dict(warn=f"Please set the numeric value in the oauth2_timeout. oauth2_timeout={opt['oauth2_timeout']}")
|
|
155
|
+
if 'password' not in opt or opt['password'] is None:
|
|
156
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the password.")
|
|
167
157
|
return msg
|
|
168
|
-
|
|
158
|
+
if opt['auth_type'] == 'apikey':
|
|
159
|
+
if 'apikey' not in opt or opt['apikey'] is None:
|
|
160
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the apikey.")
|
|
161
|
+
return msg
|
|
162
|
+
if opt['auth_type'] == 'oauth2':
|
|
163
|
+
if 'oauth2' not in opt or opt['oauth2'] is None:
|
|
164
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2.")
|
|
165
|
+
return msg
|
|
166
|
+
if 'oauth2_port' not in opt or opt['oauth2_port'] is None:
|
|
167
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_port.")
|
|
168
|
+
return msg
|
|
169
|
+
if isinstance(opt['oauth2_port'], str):
|
|
170
|
+
if not opt['oauth2_port'].isdigit():
|
|
171
|
+
msg = dict(warn=f"Please set the numeric value in the oauth2_port. oauth2_port={opt['oauth2_port']}")
|
|
172
|
+
return msg
|
|
173
|
+
opt['oauth2_port'] = int(opt['oauth2_port'])
|
|
174
|
+
if opt['oauth2'] == 'azure':
|
|
175
|
+
if 'oauth2_tenant_id' not in opt or opt['oauth2_tenant_id'] is None:
|
|
176
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_tenant_id.")
|
|
177
|
+
return msg
|
|
178
|
+
if 'oauth2_client_id' not in opt or opt['oauth2_client_id'] is None:
|
|
179
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_client_id.")
|
|
180
|
+
return msg
|
|
181
|
+
if 'oauth2_client_secret' not in opt or opt['oauth2_client_secret'] is None:
|
|
182
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_client_secret.")
|
|
183
|
+
return msg
|
|
184
|
+
if 'oauth2_timeout' not in opt or opt['oauth2_timeout'] is None:
|
|
185
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the oauth2_timeout.")
|
|
186
|
+
return msg
|
|
187
|
+
if isinstance(opt['oauth2_timeout'], str):
|
|
188
|
+
if not opt['oauth2_timeout'].isdigit():
|
|
189
|
+
msg = dict(warn=f"Please set the numeric value in the oauth2_timeout. oauth2_timeout={opt['oauth2_timeout']}")
|
|
190
|
+
return msg
|
|
191
|
+
opt['oauth2_timeout'] = int(opt['oauth2_timeout'])
|
|
192
|
+
if opt['auth_type'] == 'saml':
|
|
193
|
+
if 'saml' not in opt or opt['saml'] is None:
|
|
194
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the saml.")
|
|
195
|
+
return msg
|
|
196
|
+
if 'saml_port' not in opt or opt['saml_port'] is None:
|
|
197
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the saml.")
|
|
198
|
+
return msg
|
|
199
|
+
if isinstance(opt['saml_port'], str):
|
|
200
|
+
if not opt['saml_port'].isdigit():
|
|
201
|
+
msg = dict(warn=f"Please set the numeric value in the saml_port. saml_port={opt['saml_port']}")
|
|
202
|
+
return msg
|
|
203
|
+
opt['saml_port'] = int(opt['saml_port'])
|
|
204
|
+
if opt['saml'] == 'azure':
|
|
205
|
+
if 'saml_tenant_id' not in opt or opt['saml_tenant_id'] is None:
|
|
206
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the saml_tenant_id.")
|
|
207
|
+
return msg
|
|
208
|
+
if 'saml_timeout' not in opt or opt['saml_timeout'] is None:
|
|
209
|
+
msg = dict(warn=f"Please run the `edge config` command. And please set the saml_timeout.")
|
|
210
|
+
return msg
|
|
211
|
+
if isinstance(opt['saml_timeout'], str):
|
|
212
|
+
if not opt['saml_timeout'].isdigit():
|
|
213
|
+
msg = dict(warn=f"Please set the numeric value in the saml_timeout. saml_timeout={opt['saml_timeout']}")
|
|
214
|
+
return msg
|
|
215
|
+
opt['saml_timeout'] = int(opt['saml_timeout'])
|
|
169
216
|
if 'svcert_no_verify' not in opt or opt['svcert_no_verify'] is not True:
|
|
170
217
|
opt['svcert_no_verify'] = False
|
|
171
218
|
if 'timeout' not in opt or opt['timeout'] is None:
|
|
@@ -184,9 +231,12 @@ class Edge(object):
|
|
|
184
231
|
if self.svcert_no_verify:
|
|
185
232
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
186
233
|
status, msg = self.signin(opt.get('auth_type'), opt.get('user'), opt.get('password'), opt.get('apikey'),
|
|
187
|
-
opt.get('oauth2'), int(opt.get('oauth2_port')),
|
|
234
|
+
opt.get('oauth2'), int(opt.get('oauth2_port', 8091)),
|
|
188
235
|
opt.get('oauth2_tenant_id'), opt.get('oauth2_client_id'), opt.get('oauth2_client_secret'),
|
|
189
|
-
int(opt.get('oauth2_timeout'))
|
|
236
|
+
int(opt.get('oauth2_timeout', 60)),
|
|
237
|
+
opt.get('saml'), int(opt.get('saml_port', 8091)),
|
|
238
|
+
opt.get('saml_tenant_id'), int(opt.get('saml_timeout', 60)))
|
|
239
|
+
|
|
190
240
|
if status != 0:
|
|
191
241
|
return msg
|
|
192
242
|
|
|
@@ -247,8 +297,8 @@ class Edge(object):
|
|
|
247
297
|
def _job(thevent:threading.Event, pipe_cmd, prevq:queue.Queue):
|
|
248
298
|
resq:queue.Queue = pipe_cmd['resq']
|
|
249
299
|
del pipe_cmd['resq']
|
|
250
|
-
tool = Tool(self.logger, self.appcls, self.ver)
|
|
251
|
-
tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
300
|
+
tool = edge_tool.Tool(self.logger, self.appcls, self.ver)
|
|
301
|
+
tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2, self.saml)
|
|
252
302
|
feat:feature.Feature = self.options.get_cmd_attr(pipe_cmd['mode'], pipe_cmd['cmd'], 'feature')
|
|
253
303
|
while not thevent.is_set():
|
|
254
304
|
prevres = None if prevq is None else prevq.get(pipe_cmd['timeout'])
|
|
@@ -304,8 +354,8 @@ class Edge(object):
|
|
|
304
354
|
for opt in opts:
|
|
305
355
|
def mkcmd(opt):
|
|
306
356
|
def _ex():
|
|
307
|
-
tool = Tool(self.logger, self.appcls, self.ver)
|
|
308
|
-
tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
357
|
+
tool = edge_tool.Tool(self.logger, self.appcls, self.ver)
|
|
358
|
+
tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2, self.saml)
|
|
309
359
|
feat:feature.Feature = self.options.get_cmd_attr(opt['mode'], opt['cmd'], 'feature')
|
|
310
360
|
for status, ret in feat.edgerun(opt, tool, self.logger, self.timeout):
|
|
311
361
|
pass
|
|
@@ -329,7 +379,7 @@ class Edge(object):
|
|
|
329
379
|
items = []
|
|
330
380
|
items.append(pystray.MenuItem('Gui', lambda: self.tool.open_browser('/gui')))
|
|
331
381
|
for k, op in opens.items():
|
|
332
|
-
def mkop(tool:Tool, href):
|
|
382
|
+
def mkop(tool:edge_tool.Tool, href):
|
|
333
383
|
return lambda: tool.open_browser(href)
|
|
334
384
|
items.append(pystray.MenuItem(op['html'], mkop(self.tool, op['href'])))
|
|
335
385
|
return items
|
|
@@ -353,7 +403,9 @@ class Edge(object):
|
|
|
353
403
|
|
|
354
404
|
def signin(self, auth_type:str, user:str, password:str, apikey:str,
|
|
355
405
|
oauth2:str, oauth2_port:int, oauth2_tenant_id:str, oauth2_client_id:str, oauth2_client_secret:str,
|
|
356
|
-
oauth2_timeout:int
|
|
406
|
+
oauth2_timeout:int,
|
|
407
|
+
saml:str, saml_port:int, saml_tenant_id:str,
|
|
408
|
+
saml_timeout:int) -> Tuple[int, Dict[str, Any]]:
|
|
357
409
|
"""
|
|
358
410
|
サインインを行います
|
|
359
411
|
|
|
@@ -368,6 +420,10 @@ class Edge(object):
|
|
|
368
420
|
oauth2_client_id (str): OAuth2クライアントID
|
|
369
421
|
oauth2_client_secret (str): OAuth2クライアントシークレット
|
|
370
422
|
oauth2_timeout (int): OAuth2タイムアウト
|
|
423
|
+
saml (str): SAML
|
|
424
|
+
saml_port (int): SAMLポート
|
|
425
|
+
saml_tenant_id (str): SAMLテナントID
|
|
426
|
+
saml_timeout (int): SAMLタイムアウト
|
|
371
427
|
|
|
372
428
|
Returns:
|
|
373
429
|
Tuple[int, Dict[str, Any]]: 終了コード, メッセージ
|
|
@@ -375,13 +431,14 @@ class Edge(object):
|
|
|
375
431
|
self.session = requests.Session()
|
|
376
432
|
self.signed_in = False
|
|
377
433
|
self.oauth2 = oauth2
|
|
434
|
+
self.saml = saml
|
|
378
435
|
if auth_type == "noauth":
|
|
379
436
|
status, res, _ = self.site_request(self.session.get, "/gui")
|
|
380
437
|
if status != 0: return status, res
|
|
381
438
|
status, self.user_info = self.load_user_info()
|
|
382
439
|
self.user_info['auth_type'] = auth_type
|
|
383
440
|
if status != 0: return status, res
|
|
384
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
441
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2, self.saml)
|
|
385
442
|
return 0, dict(success="No auth.")
|
|
386
443
|
|
|
387
444
|
# ID/PW認証を使用する場合
|
|
@@ -398,7 +455,7 @@ class Edge(object):
|
|
|
398
455
|
self.user_info['auth_type'] = auth_type
|
|
399
456
|
self.user_info['password'] = password
|
|
400
457
|
if status != 0: return status, res
|
|
401
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
458
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2, self.saml)
|
|
402
459
|
return 0, dict(success="Signin Success.")
|
|
403
460
|
|
|
404
461
|
# APIKEY認証を使用する場合
|
|
@@ -413,7 +470,7 @@ class Edge(object):
|
|
|
413
470
|
self.user_info['auth_type'] = auth_type
|
|
414
471
|
self.user_info['apikey'] = apikey
|
|
415
472
|
if status != 0: return status, res
|
|
416
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
473
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2, self.saml)
|
|
417
474
|
return 0, dict(success="Signin Success.")
|
|
418
475
|
|
|
419
476
|
# OAuth2認証を使用する場合
|
|
@@ -453,9 +510,9 @@ class Edge(object):
|
|
|
453
510
|
status, self.user_info = self.load_user_info()
|
|
454
511
|
self.user_info['auth_type'] = auth_type
|
|
455
512
|
self.user_info['access_token'] = access_token
|
|
456
|
-
if status != 0: return
|
|
513
|
+
if status != 0: return res
|
|
457
514
|
self.signed_in = True
|
|
458
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
515
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2, self.saml)
|
|
459
516
|
return dict(success="Signin success. Please close your browser.")
|
|
460
517
|
except Exception as e:
|
|
461
518
|
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
@@ -519,9 +576,9 @@ class Edge(object):
|
|
|
519
576
|
status, self.user_info = self.load_user_info()
|
|
520
577
|
self.user_info['auth_type'] = auth_type
|
|
521
578
|
self.user_info['access_token'] = access_token
|
|
522
|
-
if status != 0: return
|
|
579
|
+
if status != 0: return res
|
|
523
580
|
self.signed_in = True
|
|
524
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
581
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2, self.saml)
|
|
525
582
|
return dict(success="Signin success. Please close your browser.")
|
|
526
583
|
except Exception as e:
|
|
527
584
|
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
@@ -549,7 +606,6 @@ class Edge(object):
|
|
|
549
606
|
time.sleep(1)
|
|
550
607
|
return 0, dict(success="Signin success.")
|
|
551
608
|
|
|
552
|
-
|
|
553
609
|
# Azure OAuth2を使用する場合
|
|
554
610
|
elif oauth2 == "azure":
|
|
555
611
|
if oauth2_tenant_id is None:
|
|
@@ -591,9 +647,9 @@ class Edge(object):
|
|
|
591
647
|
status, self.user_info = self.load_user_info()
|
|
592
648
|
self.user_info['auth_type'] = auth_type
|
|
593
649
|
self.user_info['access_token'] = access_token
|
|
594
|
-
if status != 0: return
|
|
650
|
+
if status != 0: return res
|
|
595
651
|
self.signed_in = True
|
|
596
|
-
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2)
|
|
652
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2, self.saml)
|
|
597
653
|
return dict(success="Signin success. Please close your browser.")
|
|
598
654
|
except Exception as e:
|
|
599
655
|
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
@@ -622,165 +678,78 @@ class Edge(object):
|
|
|
622
678
|
time.sleep(1)
|
|
623
679
|
return 0, dict(success="Signin success.")
|
|
624
680
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
Args:
|
|
684
|
-
opt (Dict[str, Any]): オプション
|
|
685
|
-
logger (logging.Logger): ロガー
|
|
686
|
-
timeout (int): タイムアウト時間
|
|
687
|
-
prevres (Any): 前コマンドの結果。pipeline実行の実行結果を参照する時に使用します。
|
|
688
|
-
|
|
689
|
-
Returns:
|
|
690
|
-
Tuple[int, Dict[str, Any], Any]: 終了コード, 結果
|
|
691
|
-
"""
|
|
692
|
-
if logger.level == logging.DEBUG:
|
|
693
|
-
logger.debug(f"exec_cmd: {self.endpoint}/exec_cmd/{opt['title']}")
|
|
694
|
-
if prevres is not None:
|
|
695
|
-
headers = {'content-type':'application/octet-stream'}
|
|
696
|
-
prevres = common.to_str(prevres)
|
|
697
|
-
res = self.session.post(f"{self.endpoint}/exec_cmd/{opt['title']}", headers=headers, data=prevres,
|
|
698
|
-
verify=not self.svcert_no_verify, timeout=timeout, allow_redirects=False)
|
|
699
|
-
else:
|
|
700
|
-
res = self.session.post(f"{self.endpoint}/exec_cmd/{opt['title']}",
|
|
701
|
-
verify=not self.svcert_no_verify, timeout=timeout, allow_redirects=False)
|
|
702
|
-
|
|
703
|
-
if res.status_code != 200:
|
|
704
|
-
msg = dict(warn=f"Access failed. status_code={res.status_code}")
|
|
705
|
-
logger.warning(f"Access failed. status_code={res.status_code}")
|
|
706
|
-
return 1, msg
|
|
707
|
-
else:
|
|
708
|
-
ret = msg = res.json()
|
|
709
|
-
if isinstance(msg, list):
|
|
710
|
-
if len(msg) == 0:
|
|
711
|
-
logger.warning(f"No result.")
|
|
712
|
-
return 1, dict(warn="No result.")
|
|
713
|
-
msg = msg[0]
|
|
714
|
-
if isinstance(msg, dict) and 'success' not in msg:
|
|
715
|
-
logger.warning(f"{msg}")
|
|
716
|
-
return 1, ret
|
|
717
|
-
if logger.level == logging.DEBUG:
|
|
718
|
-
logger.debug(f"{common.to_str(ret, slise=255)}")
|
|
719
|
-
return 0, ret
|
|
720
|
-
|
|
721
|
-
def pub_result(self, title:str, output:str, timeout:int) -> Tuple[int, Dict[str, Any]]:
|
|
722
|
-
"""
|
|
723
|
-
結果を公開します
|
|
724
|
-
|
|
725
|
-
Args:
|
|
726
|
-
title (str): タイトル
|
|
727
|
-
output (str): 出力
|
|
728
|
-
logger (logging.Logger): ロガー
|
|
729
|
-
timeout (int): タイムアウト時間
|
|
681
|
+
# saml認証を使用する場合
|
|
682
|
+
elif auth_type == "saml":
|
|
683
|
+
# Azure samlを使用する場合
|
|
684
|
+
if saml == "azure":
|
|
685
|
+
if saml_tenant_id is None:
|
|
686
|
+
return 1, dict(warn="Please specify the --saml_tenant_id option.")
|
|
687
|
+
saml_settings = dict(
|
|
688
|
+
strict=False,
|
|
689
|
+
debug=self.logger.level==logging.DEBUG,
|
|
690
|
+
idp=dict(
|
|
691
|
+
entityId=f'https://sts.windows.net/{saml_tenant_id}/',
|
|
692
|
+
singleSignOnService=dict(
|
|
693
|
+
url=f'https://login.microsoftonline.com/{saml_tenant_id}/saml2',
|
|
694
|
+
binding=f'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'),
|
|
695
|
+
certFingerprint='',
|
|
696
|
+
certFingerprintAlgorithm='sha1',
|
|
697
|
+
singleLogoutService=dict()),
|
|
698
|
+
sp=dict(
|
|
699
|
+
entityId=self.endpoint,
|
|
700
|
+
assertionConsumerService=dict(
|
|
701
|
+
url=f'http://localhost:{saml_port}/saml/azure/callback',
|
|
702
|
+
binding=f'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'),
|
|
703
|
+
attributeConsumingService=dict(),
|
|
704
|
+
singleLogoutService=dict(
|
|
705
|
+
binding=f'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'),
|
|
706
|
+
NameIDFormat=f'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
|
|
707
|
+
x509cert='',
|
|
708
|
+
privateKey=''))
|
|
709
|
+
request_data = dict(
|
|
710
|
+
https='off',
|
|
711
|
+
http_host='localhost',
|
|
712
|
+
server_port=saml_port,
|
|
713
|
+
script_name=f'/saml/azure/gui?next=gui',
|
|
714
|
+
post_data=dict(),
|
|
715
|
+
get_data=dict(n=common.random_string(8)),
|
|
716
|
+
)
|
|
717
|
+
from onelogin.saml2.auth import OneLogin_Saml2_Auth
|
|
718
|
+
auth = OneLogin_Saml2_Auth(request_data=request_data, old_settings=saml_settings)
|
|
719
|
+
|
|
720
|
+
# SAML認証のコールバックを受けるFastAPIサーバーを起動
|
|
721
|
+
fastapi = FastAPI()
|
|
722
|
+
@fastapi.post('/saml/azure/callback')
|
|
723
|
+
async def saml_azure_callback(req:Request):
|
|
724
|
+
form_data = await req.form()
|
|
725
|
+
try:
|
|
726
|
+
status, res, headers = self.site_request(self.session.post, f"/saml/azure/callback", data=form_data, ok_status=[200, 307])
|
|
727
|
+
if status != 0 or headers.get('signin') is None:
|
|
728
|
+
return dict(warn=f"Signin failed.")
|
|
729
|
+
status, self.user_info = self.load_user_info()
|
|
730
|
+
self.user_info['auth_type'] = auth_type
|
|
731
|
+
if status != 0: return res
|
|
732
|
+
self.signed_in = True
|
|
733
|
+
self.user_info['saml_token'] = convert.str2b64str(common.to_str(form_data._dict))
|
|
734
|
+
self.tool.set_session(self.session, self.svcert_no_verify, self.endpoint, self.icon_path, self.user_info, self.oauth2, self.saml)
|
|
735
|
+
return dict(success="Signin success. Please close your browser.")
|
|
736
|
+
except Exception as e:
|
|
737
|
+
raise HTTPException(status_code=500, detail=f'Failed to get token. {e}')
|
|
730
738
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
data = f'title={urllib.parse.quote(title)}&output={urllib.parse.quote(output)}'
|
|
736
|
-
headers = {'content-type':'application/x-www-form-urlencoded'}
|
|
737
|
-
res = self.session.post(f"{self.endpoint}/result/pub", headers=headers, data=data,
|
|
738
|
-
verify=not self.svcert_no_verify, timeout=timeout, allow_redirects=False)
|
|
739
|
-
if res.status_code != 200:
|
|
740
|
-
msg = dict(warn=f"Access failed. status_code={res.status_code}")
|
|
741
|
-
return 1, msg
|
|
742
|
-
else:
|
|
743
|
-
msg = res.json()
|
|
744
|
-
return 0, msg
|
|
739
|
+
if not hasattr(self, 'thUvicorn') or not self.thUvicorn.is_alive():
|
|
740
|
+
self.thUvicorn = web.ThreadedUvicorn(self.logger, Config(app=fastapi, host='localhost', port=saml_port), {})
|
|
741
|
+
self.thUvicorn.start()
|
|
742
|
+
time.sleep(1)
|
|
745
743
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
指定したパスをブラウザで開きます。
|
|
749
|
-
この時認証情報を含めて開きます。
|
|
744
|
+
# SAML認証のリクエストを送信
|
|
745
|
+
webbrowser.open(auth.login())
|
|
750
746
|
|
|
751
|
-
|
|
752
|
-
|
|
747
|
+
# 認証完了まで指定秒数待つ
|
|
748
|
+
tm = time.time()
|
|
749
|
+
while not self.signed_in:
|
|
750
|
+
if time.time() - tm > saml_timeout:
|
|
751
|
+
return 1, dict(warn="Signin Timeout.")
|
|
752
|
+
time.sleep(1)
|
|
753
|
+
return 0, dict(success="Signin success.")
|
|
753
754
|
|
|
754
|
-
Returns:
|
|
755
|
-
Tuple[int, Dict[str, str]]: 終了コード, メッセージ
|
|
756
|
-
"""
|
|
757
|
-
path = f"/{path}" if not path.startswith('/') else path
|
|
758
|
-
if not hasattr(self, 'user'):
|
|
759
|
-
webbrowser.open(f"{self.endpoint}{path}")
|
|
760
|
-
return 0, dict(success="Open browser.")
|
|
761
|
-
token = dict(auth_type=self.user['auth_type'])
|
|
762
|
-
if self.user['auth_type'] == "noauth":
|
|
763
|
-
webbrowser.open(f"{self.endpoint}{path}")
|
|
764
|
-
return 0, dict(success="Open browser.")
|
|
765
|
-
elif self.user['auth_type'] == "idpw":
|
|
766
|
-
hashed = self.user['password'] if self.user['hash']=='plain' else common.hash_password(self.user['password'], self.user['hash'])
|
|
767
|
-
token = dict(**token, **dict(user=self.user['name'], token=common.encrypt(path, hashed)))
|
|
768
|
-
token = convert.str2b64str(common.to_str(token))
|
|
769
|
-
webbrowser.open(f"{self.endpoint}/dosignin_token/{token}{path}")
|
|
770
|
-
return 0, dict(success="Open browser.")
|
|
771
|
-
elif self.user['auth_type'] == "apikey":
|
|
772
|
-
hashed = common.hash_password(self.user['apikey'], 'sha1')
|
|
773
|
-
token = dict(**token, **dict(user=self.user['name'], token=common.encrypt(path, hashed)))
|
|
774
|
-
token = convert.str2b64str(common.to_str(token))
|
|
775
|
-
webbrowser.open(f"{self.endpoint}/dosignin_token/{token}{path}")
|
|
776
|
-
return 0, dict(success="Open browser.")
|
|
777
|
-
elif self.user['auth_type'] == "oauth2" and self.oauth2 == 'google':
|
|
778
|
-
webbrowser.open(f"{self.endpoint}/oauth2/google/session/{self.user['access_token']}{path}")
|
|
779
|
-
return 0, dict(success="Open browser.")
|
|
780
|
-
elif self.user['auth_type'] == "oauth2" and self.oauth2 == 'github':
|
|
781
|
-
webbrowser.open(f"{self.endpoint}/oauth2/github/session/{self.user['access_token']}{path}")
|
|
782
|
-
return 0, dict(success="Open browser.")
|
|
783
|
-
elif self.user['auth_type'] == "oauth2" and self.oauth2 == 'azure':
|
|
784
|
-
webbrowser.open(f"{self.endpoint}/oauth2/azure/session/{self.user['access_token']}{path}")
|
|
785
|
-
return 0, dict(success="Open browser.")
|
|
786
755
|
return 1, dict(warn="unsupported auth_type.")
|