tccli 3.0.1216.1__py2.py3-none-any.whl → 3.0.1217.1__py2.py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- tccli/__init__.py +1 -1
- tccli/argparser.py +1 -1
- tccli/command.py +2 -2
- tccli/credentials.py +25 -0
- tccli/main.py +6 -2
- tccli/plugins/sso/__init__.py +61 -0
- tccli/plugins/sso/configs.py +4 -0
- tccli/plugins/sso/configure.py +45 -0
- tccli/plugins/sso/login.py +144 -0
- tccli/plugins/sso/logout.py +21 -0
- tccli/plugins/sso/terminal.py +161 -0
- tccli/plugins/sso/texts.py +40 -0
- tccli/services/__init__.py +6 -0
- tccli/services/acp/v20220105/api.json +7 -7
- tccli/services/acp/v20220105/examples.json +2 -2
- tccli/services/aiart/v20221229/api.json +29 -29
- tccli/services/aiart/v20221229/examples.json +8 -8
- tccli/services/apigateway/v20180808/api.json +18 -17
- tccli/services/apigateway/v20180808/examples.json +12 -12
- tccli/services/apm/v20210622/api.json +98 -4
- tccli/services/asr/v20190614/api.json +18 -17
- tccli/services/asr/v20190614/examples.json +13 -13
- tccli/services/autoscaling/v20180419/api.json +371 -309
- tccli/services/autoscaling/v20180419/examples.json +17 -17
- tccli/services/batch/v20170312/api.json +7 -7
- tccli/services/bda/v20200324/api.json +39 -31
- tccli/services/bda/v20200324/examples.json +9 -9
- tccli/services/bh/__init__.py +4 -0
- tccli/services/bh/bh_client.py +3428 -0
- tccli/services/bh/v20230418/api.json +8180 -0
- tccli/services/bh/v20230418/examples.json +519 -0
- tccli/services/bi/v20220105/api.json +48 -0
- tccli/services/billing/v20180709/api.json +26 -24
- tccli/services/bsca/v20210811/api.json +1 -1
- tccli/services/btoe/v20210514/api.json +4 -4
- tccli/services/btoe/v20210514/examples.json +2 -2
- tccli/services/ca/v20230228/api.json +60 -0
- tccli/services/cam/v20190116/api.json +11 -11
- tccli/services/cat/v20180409/api.json +9 -0
- tccli/services/cbs/v20170312/api.json +200 -188
- tccli/services/cbs/v20170312/examples.json +4 -4
- tccli/services/ccc/v20200210/api.json +390 -323
- tccli/services/ccc/v20200210/examples.json +15 -15
- tccli/services/cdb/cdb_client.py +13 -13
- tccli/services/cdb/v20170320/api.json +295 -270
- tccli/services/cdb/v20170320/examples.json +38 -38
- tccli/services/cdc/v20201214/api.json +283 -270
- tccli/services/cdc/v20201214/examples.json +26 -26
- tccli/services/cds/v20180420/api.json +82 -76
- tccli/services/cds/v20180420/examples.json +1 -1
- tccli/services/cdwch/v20200915/api.json +1 -1
- tccli/services/cdwdoris/v20211228/api.json +42 -2
- tccli/services/cdz/v20221123/api.json +41 -5
- tccli/services/cfg/v20210820/api.json +31 -0
- tccli/services/cfs/v20190719/api.json +89 -1
- tccli/services/cfs/v20190719/examples.json +1 -1
- tccli/services/cfw/cfw_client.py +0 -53
- tccli/services/cfw/v20190904/api.json +1849 -1999
- tccli/services/cfw/v20190904/examples.json +157 -159
- tccli/services/ckafka/v20190819/api.json +104 -75
- tccli/services/clb/v20180317/api.json +48 -26
- tccli/services/clb/v20180317/examples.json +1 -1
- tccli/services/cloudapp/v20220530/api.json +5 -1
- tccli/services/cloudaudit/v20190319/api.json +58 -44
- tccli/services/cloudaudit/v20190319/examples.json +6 -6
- tccli/services/cloudstudio/v20230508/api.json +38 -37
- tccli/services/cloudstudio/v20230508/examples.json +4 -4
- tccli/services/cls/cls_client.py +216 -4
- tccli/services/cls/v20201016/api.json +536 -47
- tccli/services/cls/v20201016/examples.json +34 -2
- tccli/services/csip/v20221121/api.json +2562 -2382
- tccli/services/csip/v20221121/examples.json +108 -108
- tccli/services/cvm/v20170312/api.json +149 -112
- tccli/services/cvm/v20170312/examples.json +2 -2
- tccli/services/cwp/cwp_client.py +4 -110
- tccli/services/cwp/v20180228/api.json +6338 -6146
- tccli/services/cwp/v20180228/examples.json +342 -370
- tccli/services/cynosdb/v20190107/api.json +93 -81
- tccli/services/cynosdb/v20190107/examples.json +70 -70
- tccli/services/dasb/v20191018/api.json +796 -651
- tccli/services/dasb/v20191018/examples.json +101 -101
- tccli/services/dcdb/dcdb_client.py +114 -61
- tccli/services/dcdb/v20180411/api.json +141 -7
- tccli/services/dcdb/v20180411/examples.json +32 -0
- tccli/services/dlc/v20210125/api.json +21 -11
- tccli/services/dnspod/dnspod_client.py +417 -46
- tccli/services/dnspod/v20210323/api.json +751 -30
- tccli/services/dnspod/v20210323/examples.json +62 -0
- tccli/services/dts/v20211206/api.json +4 -4
- tccli/services/ecm/v20190719/api.json +2 -2
- tccli/services/emr/v20190103/api.json +339 -114
- tccli/services/emr/v20190103/examples.json +64 -82
- tccli/services/es/v20180416/api.json +29 -0
- tccli/services/es/v20180416/examples.json +1 -1
- tccli/services/ess/v20201111/api.json +49 -31
- tccli/services/ess/v20201111/examples.json +20 -8
- tccli/services/essbasic/v20210526/api.json +54 -49
- tccli/services/essbasic/v20210526/examples.json +36 -18
- tccli/services/facefusion/v20181201/api.json +47 -45
- tccli/services/facefusion/v20181201/examples.json +2 -2
- tccli/services/facefusion/v20220927/api.json +54 -48
- tccli/services/facefusion/v20220927/examples.json +5 -5
- tccli/services/faceid/v20180301/api.json +497 -496
- tccli/services/faceid/v20180301/examples.json +219 -101
- tccli/services/fmu/v20191213/api.json +59 -67
- tccli/services/fmu/v20191213/examples.json +22 -22
- tccli/services/ft/v20200304/api.json +53 -57
- tccli/services/ft/v20200304/examples.json +14 -14
- tccli/services/gme/v20180711/api.json +21 -11
- tccli/services/gme/v20180711/examples.json +1 -1
- tccli/services/hai/v20230812/api.json +116 -9
- tccli/services/hai/v20230812/examples.json +4 -4
- tccli/services/hunyuan/hunyuan_client.py +436 -12
- tccli/services/hunyuan/v20230901/api.json +1482 -118
- tccli/services/hunyuan/v20230901/examples.json +82 -18
- tccli/services/iai/v20180301/api.json +23 -19
- tccli/services/iai/v20180301/examples.json +2 -2
- tccli/services/iai/v20200303/api.json +530 -511
- tccli/services/iai/v20200303/examples.json +116 -86
- tccli/services/ig/__init__.py +4 -0
- tccli/services/ig/ig_client.py +195 -0
- tccli/services/ig/v20210518/api.json +83 -0
- tccli/services/ig/v20210518/examples.json +13 -0
- tccli/services/ioa/ioa_client.py +53 -0
- tccli/services/ioa/v20220601/api.json +662 -413
- tccli/services/ioa/v20220601/examples.json +24 -10
- tccli/services/iotexplorer/v20190423/api.json +33 -13
- tccli/services/iotexplorer/v20190423/examples.json +3 -3
- tccli/services/iotvideo/iotvideo_client.py +106 -0
- tccli/services/iotvideo/v20191126/api.json +256 -24
- tccli/services/iotvideo/v20191126/examples.json +19 -3
- tccli/services/iotvideo/v20201215/api.json +1 -1
- tccli/services/iotvideo/v20201215/examples.json +1 -1
- tccli/services/iotvideo/v20211125/api.json +1 -1
- tccli/services/iotvideo/v20211125/examples.json +2 -2
- tccli/services/iss/iss_client.py +69 -122
- tccli/services/iss/v20230517/api.json +10 -54
- tccli/services/iss/v20230517/examples.json +0 -14
- tccli/services/kms/v20190118/api.json +301 -268
- tccli/services/kms/v20190118/examples.json +45 -51
- tccli/services/lcic/lcic_client.py +159 -0
- tccli/services/lcic/v20220817/api.json +273 -1
- tccli/services/lcic/v20220817/examples.json +24 -0
- tccli/services/lighthouse/v20200324/api.json +56 -0
- tccli/services/live/live_client.py +159 -0
- tccli/services/live/v20180801/api.json +244 -0
- tccli/services/live/v20180801/examples.json +24 -0
- tccli/services/lke/v20231130/api.json +17 -17
- tccli/services/lke/v20231130/examples.json +19 -25
- tccli/services/mariadb/v20170312/api.json +7 -7
- tccli/services/market/v20191010/api.json +3 -3
- tccli/services/market/v20191010/examples.json +2 -2
- tccli/services/mmps/v20200710/api.json +47 -47
- tccli/services/mmps/v20200710/examples.json +3 -3
- tccli/services/mongodb/v20190725/api.json +4 -4
- tccli/services/monitor/v20180724/api.json +46 -19
- tccli/services/mps/v20190612/api.json +282 -5
- tccli/services/mps/v20190612/examples.json +25 -1
- tccli/services/mqtt/v20240516/api.json +2 -2
- tccli/services/mrs/v20200910/api.json +72 -34
- tccli/services/mrs/v20200910/examples.json +2 -2
- tccli/services/ms/v20180408/api.json +535 -506
- tccli/services/ms/v20180408/examples.json +25 -25
- tccli/services/oceanus/v20190422/api.json +130 -0
- tccli/services/ocr/ocr_client.py +232 -20
- tccli/services/ocr/v20181119/api.json +2265 -760
- tccli/services/ocr/v20181119/examples.json +200 -180
- tccli/services/omics/v20221128/api.json +614 -553
- tccli/services/omics/v20221128/examples.json +9 -9
- tccli/services/organization/v20210331/api.json +13 -4
- tccli/services/organization/v20210331/examples.json +2 -2
- tccli/services/partners/v20180321/api.json +244 -234
- tccli/services/partners/v20180321/examples.json +19 -19
- tccli/services/privatedns/privatedns_client.py +428 -4
- tccli/services/privatedns/v20201028/api.json +815 -11
- tccli/services/privatedns/v20201028/examples.json +64 -0
- tccli/services/pts/v20210728/api.json +18 -0
- tccli/services/pts/v20210728/examples.json +1 -1
- tccli/services/rce/rce_client.py +53 -0
- tccli/services/rce/v20201103/api.json +146 -0
- tccli/services/rce/v20201103/examples.json +8 -0
- tccli/services/redis/v20180412/api.json +42 -42
- tccli/services/redis/v20180412/examples.json +19 -19
- tccli/services/rum/v20210622/api.json +9 -0
- tccli/services/scf/v20180416/api.json +15 -15
- tccli/services/scf/v20180416/examples.json +1 -1
- tccli/services/smop/v20201203/api.json +46 -42
- tccli/services/smop/v20201203/examples.json +2 -2
- tccli/services/soe/v20180724/api.json +10 -10
- tccli/services/sqlserver/v20180328/api.json +21 -8
- tccli/services/sqlserver/v20180328/examples.json +5 -5
- tccli/services/ssl/v20191205/api.json +97 -4
- tccli/services/ssm/v20190923/api.json +292 -231
- tccli/services/ssm/v20190923/examples.json +42 -42
- tccli/services/tat/v20201028/api.json +97 -97
- tccli/services/tat/v20201028/examples.json +20 -26
- tccli/services/tchd/v20230306/api.json +5 -5
- tccli/services/tchd/v20230306/examples.json +3 -3
- tccli/services/tcr/v20190924/api.json +1 -1
- tccli/services/tcr/v20190924/examples.json +1 -1
- tccli/services/tcss/v20201101/api.json +1973 -1426
- tccli/services/tcss/v20201101/examples.json +346 -364
- tccli/services/tdmq/v20200217/api.json +539 -401
- tccli/services/tdmq/v20200217/examples.json +104 -104
- tccli/services/tds/v20220801/api.json +4 -4
- tccli/services/tem/v20210701/api.json +287 -271
- tccli/services/tem/v20210701/examples.json +59 -59
- tccli/services/teo/v20220901/api.json +37 -9
- tccli/services/teo/v20220901/examples.json +13 -7
- tccli/services/thpc/v20230321/api.json +5 -5
- tccli/services/tke/tke_client.py +217 -58
- tccli/services/tke/v20180525/api.json +36 -27
- tccli/services/tke/v20180525/examples.json +1 -1
- tccli/services/tke/v20220501/api.json +176 -0
- tccli/services/tke/v20220501/examples.json +24 -0
- tccli/services/tmt/v20180321/api.json +38 -8
- tccli/services/trp/v20210515/api.json +86 -74
- tccli/services/trp/v20210515/examples.json +65 -65
- tccli/services/trro/v20220325/api.json +72 -71
- tccli/services/trro/v20220325/examples.json +8 -8
- tccli/services/trtc/trtc_client.py +8 -61
- tccli/services/trtc/v20190722/api.json +72 -30
- tccli/services/trtc/v20190722/examples.json +3 -11
- tccli/services/tse/tse_client.py +110 -4
- tccli/services/tse/v20201207/api.json +122 -7
- tccli/services/tse/v20201207/examples.json +25 -9
- tccli/services/vclm/v20240523/api.json +225 -82
- tccli/services/vclm/v20240523/examples.json +13 -19
- tccli/services/vod/v20180717/api.json +431 -4
- tccli/services/vod/v20180717/examples.json +25 -5
- tccli/services/vod/v20240718/api.json +11 -11
- tccli/services/vod/v20240718/examples.json +4 -4
- tccli/services/vod/vod_client.py +53 -0
- tccli/services/vpc/v20170312/api.json +1090 -862
- tccli/services/vpc/v20170312/examples.json +74 -66
- tccli/services/vpc/vpc_client.py +61 -8
- tccli/services/waf/v20180125/api.json +2540 -2177
- tccli/services/waf/v20180125/examples.json +216 -284
- tccli/services/waf/waf_client.py +172 -119
- tccli/services/wav/v20210129/api.json +48 -48
- tccli/services/wav/v20210129/examples.json +4 -4
- tccli/services/wedata/v20210820/api.json +909 -25
- tccli/services/wedata/v20210820/examples.json +28 -4
- tccli/services/wedata/wedata_client.py +159 -0
- tccli/services/weilingwith/v20230427/api.json +6 -6
- tccli/services/weilingwith/v20230427/examples.json +3 -3
- tccli/sso.py +229 -0
- {tccli-3.0.1216.1.dist-info → tccli-3.0.1217.1.dist-info}/METADATA +2 -2
- {tccli-3.0.1216.1.dist-info → tccli-3.0.1217.1.dist-info}/RECORD +252 -235
- {tccli-3.0.1216.1.dist-info → tccli-3.0.1217.1.dist-info}/WHEEL +0 -0
- {tccli-3.0.1216.1.dist-info → tccli-3.0.1217.1.dist-info}/entry_points.txt +0 -0
- {tccli-3.0.1216.1.dist-info → tccli-3.0.1217.1.dist-info}/license_files/LICENSE +0 -0
tccli/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '3.0.
|
1
|
+
__version__ = '3.0.1217.1'
|
tccli/argparser.py
CHANGED
@@ -58,7 +58,7 @@ class BaseArgParser(argparse.ArgumentParser):
|
|
58
58
|
def parse_known_args(self, args=None, namespace=None):
|
59
59
|
parsed, remaining = super(BaseArgParser, self).parse_known_args(args, namespace)
|
60
60
|
terminal_encoding = getattr(sys.stdin, 'encoding', 'utf-8')
|
61
|
-
if terminal_encoding is None:
|
61
|
+
if terminal_encoding is None or terminal_encoding == 'cp65001':
|
62
62
|
terminal_encoding = 'utf-8'
|
63
63
|
for arg, value in vars(parsed).items():
|
64
64
|
if isinstance(value, six.binary_type):
|
tccli/command.py
CHANGED
@@ -7,7 +7,7 @@ import tccli.services as Services
|
|
7
7
|
import tccli.options_define as Options_define
|
8
8
|
from collections import OrderedDict
|
9
9
|
|
10
|
-
from tccli import
|
10
|
+
from tccli import credentials
|
11
11
|
from tccli.utils import Utils
|
12
12
|
from tccli.argument import CLIArgument, CustomArgument, ListArgument, BooleanArgument
|
13
13
|
from tccli.exceptions import UnknownArgumentError
|
@@ -291,7 +291,7 @@ class ActionCommand(BaseCommand):
|
|
291
291
|
action_parameters = self.cli_unfold_argument.build_action_parameters(parsed_args)
|
292
292
|
else:
|
293
293
|
action_parameters = self._build_action_parameters(parsed_args, self.argument_map)
|
294
|
-
|
294
|
+
credentials.maybe_refresh_credential(parsed_globals.profile if parsed_globals.profile else "default")
|
295
295
|
return self._action_caller(action_parameters, vars(parsed_globals))
|
296
296
|
|
297
297
|
def create_help_command(self):
|
tccli/credentials.py
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
import json
|
2
|
+
import os
|
3
|
+
|
4
|
+
from tccli import oauth, sso
|
5
|
+
|
6
|
+
|
7
|
+
def maybe_refresh_credential(profile):
|
8
|
+
try:
|
9
|
+
with open(cred_path_of_profile(profile), "r") as cred_file:
|
10
|
+
cred = json.load(cred_file)
|
11
|
+
except IOError:
|
12
|
+
# file not found, don't check
|
13
|
+
return
|
14
|
+
|
15
|
+
if cred.get("type", "") == "oauth":
|
16
|
+
oauth.maybe_refresh_credential(profile)
|
17
|
+
return
|
18
|
+
|
19
|
+
if cred.get("type", "") == "sso":
|
20
|
+
sso.maybe_refresh_credential(profile)
|
21
|
+
return
|
22
|
+
|
23
|
+
|
24
|
+
def cred_path_of_profile(profile):
|
25
|
+
return os.path.join(os.path.expanduser("~"), ".tccli", profile + ".credential")
|
tccli/main.py
CHANGED
@@ -4,14 +4,18 @@ import _locale
|
|
4
4
|
_locale._getdefaultlocale = (lambda *args: ['zh_CN', 'utf8'])
|
5
5
|
|
6
6
|
import io
|
7
|
-
import os
|
8
7
|
import sys
|
9
8
|
import six
|
10
|
-
import signal
|
11
9
|
from tccli.log import init
|
12
10
|
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
|
13
11
|
|
14
12
|
try:
|
13
|
+
# cp65001 is utf-8 on windows platform
|
14
|
+
# python2 doesn't support cp65001 codec
|
15
|
+
if getattr(sys.stdin, 'encoding', 'utf-8') == "cp65001":
|
16
|
+
import codecs
|
17
|
+
codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None)
|
18
|
+
|
15
19
|
reload(sys) # Python 2.7
|
16
20
|
sys.setdefaultencoding('utf8')
|
17
21
|
except NameError:
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
from tccli.plugins.sso.login import login_command_entrypoint
|
3
|
+
from tccli.plugins.sso.logout import logout_command_entrypoint
|
4
|
+
from tccli.plugins.sso.configure import configure_command_entrypoint
|
5
|
+
|
6
|
+
service_name = "sso"
|
7
|
+
service_version = "2024-10-14"
|
8
|
+
|
9
|
+
_spec = {
|
10
|
+
"metadata": {
|
11
|
+
"serviceShortName": service_name,
|
12
|
+
"apiVersion": service_version,
|
13
|
+
"description": "sso related commands",
|
14
|
+
},
|
15
|
+
"actions": {
|
16
|
+
"configure": {
|
17
|
+
"name": "配置",
|
18
|
+
"document": "configure login url",
|
19
|
+
"input": "configureRequest",
|
20
|
+
"output": "configureResponse",
|
21
|
+
"action_caller": configure_command_entrypoint,
|
22
|
+
},
|
23
|
+
"login": {
|
24
|
+
"name": "登录",
|
25
|
+
"document": "login through sso",
|
26
|
+
"input": "loginRequest",
|
27
|
+
"output": "loginResponse",
|
28
|
+
"action_caller": login_command_entrypoint,
|
29
|
+
},
|
30
|
+
"logout": {
|
31
|
+
"name": "登出",
|
32
|
+
"document": "remove local credential file",
|
33
|
+
"input": "logoutRequest",
|
34
|
+
"output": "logoutResponse",
|
35
|
+
"action_caller": logout_command_entrypoint,
|
36
|
+
},
|
37
|
+
},
|
38
|
+
"objects": {
|
39
|
+
"loginRequest": {"members": []},
|
40
|
+
"loginResponse": {"members": []},
|
41
|
+
"logoutRequest": {"members": []},
|
42
|
+
"logoutResponse": {"members": []},
|
43
|
+
"configureRequest": {"members": [
|
44
|
+
{
|
45
|
+
"name": "url",
|
46
|
+
"member": "string",
|
47
|
+
"type": "string",
|
48
|
+
"required": True,
|
49
|
+
"document": "url for sso authentication",
|
50
|
+
},
|
51
|
+
]},
|
52
|
+
"configureResponse": {"members": []},
|
53
|
+
},
|
54
|
+
"version": "1.0",
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
def register_service(specs):
|
59
|
+
specs[service_name] = {
|
60
|
+
service_version: _spec,
|
61
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
import json
|
3
|
+
try:
|
4
|
+
from urlparse import urlparse
|
5
|
+
except ImportError:
|
6
|
+
from urllib.parse import urlparse
|
7
|
+
|
8
|
+
from tccli import sso
|
9
|
+
from tccli.plugins.sso import texts, configs
|
10
|
+
|
11
|
+
|
12
|
+
def configure_command_entrypoint(args, parsed_globals):
|
13
|
+
language = parsed_globals.get("language")
|
14
|
+
if not language:
|
15
|
+
language = configs.DEFAULT_LANG
|
16
|
+
texts.set_lang(language)
|
17
|
+
|
18
|
+
profile = parsed_globals.get("profile", "default")
|
19
|
+
if not profile:
|
20
|
+
profile = "default"
|
21
|
+
|
22
|
+
cred_data = {}
|
23
|
+
try:
|
24
|
+
with open(sso.cred_path_of_profile(profile), "r") as cred_file:
|
25
|
+
cred_data = json.load(cred_file)
|
26
|
+
except IOError:
|
27
|
+
pass
|
28
|
+
|
29
|
+
if "sso" not in cred_data:
|
30
|
+
cred_data["sso"] = {}
|
31
|
+
|
32
|
+
auth_url = args.get("url")
|
33
|
+
if not auth_url.startswith("http://") and not auth_url.startswith("https://"):
|
34
|
+
auth_url = "https://" + auth_url
|
35
|
+
|
36
|
+
parsed_url = urlparse(auth_url)
|
37
|
+
if not (parsed_url.scheme in ("http", "https") and parsed_url.netloc):
|
38
|
+
print(texts.get("invalid_auth_url") % auth_url)
|
39
|
+
return
|
40
|
+
|
41
|
+
cred_data["sso"]["authUrl"] = auth_url
|
42
|
+
with open(sso.cred_path_of_profile(profile), "w") as cred_file:
|
43
|
+
json.dump(cred_data, cred_file, indent=4)
|
44
|
+
|
45
|
+
print(texts.get("configure_succeed") % auth_url)
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
import json
|
3
|
+
import os.path
|
4
|
+
import random
|
5
|
+
import string
|
6
|
+
import sys
|
7
|
+
import time
|
8
|
+
import uuid
|
9
|
+
import webbrowser
|
10
|
+
|
11
|
+
from six.moves.urllib.parse import urlencode
|
12
|
+
|
13
|
+
from tccli import sso
|
14
|
+
from tccli.plugins.sso import texts, terminal, configs
|
15
|
+
from tccli.plugins.sso.texts import get as _
|
16
|
+
|
17
|
+
|
18
|
+
def print_message(msg):
|
19
|
+
print(msg)
|
20
|
+
sys.stdout.flush()
|
21
|
+
|
22
|
+
|
23
|
+
def login_command_entrypoint(args, parsed_globals):
|
24
|
+
language = parsed_globals.get("language")
|
25
|
+
if not language:
|
26
|
+
language = configs.DEFAULT_LANG
|
27
|
+
texts.set_lang(language)
|
28
|
+
|
29
|
+
profile = parsed_globals.get("profile", "default")
|
30
|
+
if not profile:
|
31
|
+
profile = "default"
|
32
|
+
|
33
|
+
login(profile, language)
|
34
|
+
|
35
|
+
|
36
|
+
def login(profile, language):
|
37
|
+
cred_path = sso.cred_path_of_profile(profile)
|
38
|
+
auth_url = ""
|
39
|
+
if os.path.exists(cred_path):
|
40
|
+
with open(cred_path, "r") as cred_file:
|
41
|
+
cred_data = json.load(cred_file)
|
42
|
+
auth_url = cred_data.get("sso", {}).get("authUrl", "")
|
43
|
+
|
44
|
+
if not auth_url:
|
45
|
+
profile_opt = ""
|
46
|
+
if profile != "default":
|
47
|
+
profile_opt = "--profile %s " % profile
|
48
|
+
print_message(_("auth_url_not_configured") % profile_opt)
|
49
|
+
return
|
50
|
+
|
51
|
+
characters = string.ascii_letters + string.digits
|
52
|
+
state = ''.join(random.choice(characters) for x in range(32))
|
53
|
+
|
54
|
+
token = _get_token(auth_url, state, language)
|
55
|
+
|
56
|
+
if token["State"] != state:
|
57
|
+
raise ValueError("invalid state %s" % token["state"])
|
58
|
+
|
59
|
+
print_message("")
|
60
|
+
|
61
|
+
login_token = token["Token"]
|
62
|
+
site = token["Site"]
|
63
|
+
accounts = sso.list_accounts_for_access_assignment(login_token, site)
|
64
|
+
if not accounts:
|
65
|
+
print_message(_("no_account"))
|
66
|
+
return
|
67
|
+
|
68
|
+
idx = terminal.select_from_items(
|
69
|
+
_("account_select_prompt"), ["%s:%s" % (x["Name"], x["Uin"]) for x in accounts], 10)
|
70
|
+
account = accounts[idx]
|
71
|
+
print_message("uin: %s" % account["Uin"])
|
72
|
+
print_message("username: %s" % account["Name"])
|
73
|
+
|
74
|
+
roles = sso.list_role_configurations_for_account(account["Uin"], login_token, site)
|
75
|
+
if not roles:
|
76
|
+
print_message(_("no_role"))
|
77
|
+
return
|
78
|
+
|
79
|
+
idx = terminal.select_from_items(
|
80
|
+
_("role_select_prompt"), [x["RoleConfigurationName"] for x in roles], 10)
|
81
|
+
role = roles[idx]
|
82
|
+
print_message("role: %s" % role["RoleConfigurationName"])
|
83
|
+
|
84
|
+
saml_resp = sso.gen_saml_response(
|
85
|
+
login_token, "RoleSAML", account["Uin"], "", role["RoleConfigurationId"], site)
|
86
|
+
|
87
|
+
token_info = sso.verify_login_skey(login_token, site)
|
88
|
+
|
89
|
+
role_arn = "qcs::cam::uin/%s:roleName/TencentCloudSSO-%s" % (account["Uin"], role["RoleConfigurationName"])
|
90
|
+
principal_arn = "qcs::cam::uin/%s:saml-provider/TencentReservedSSO-%s" % (account["Uin"], token_info["ZoneId"])
|
91
|
+
cred = sso.assume_role_with_saml(
|
92
|
+
saml_resp["SAMLResponse"], principal_arn, role_arn, "ses-%s" % uuid.uuid4(), 7200, site)
|
93
|
+
|
94
|
+
sso_info = {
|
95
|
+
"token": login_token,
|
96
|
+
"uin": account["Uin"],
|
97
|
+
"roleConfigurationId": role["RoleConfigurationId"],
|
98
|
+
"roleConfigurationName": role["RoleConfigurationName"],
|
99
|
+
"zoneId": token_info["ZoneId"],
|
100
|
+
"site": site,
|
101
|
+
"authUrl": auth_url,
|
102
|
+
"expiresAt": int(time.time()) + 3600 * 12,
|
103
|
+
}
|
104
|
+
sso.save_credential(cred, sso_info, profile)
|
105
|
+
|
106
|
+
print_message(_("login_success") % sso.cred_path_of_profile(profile))
|
107
|
+
|
108
|
+
|
109
|
+
def _get_token(auth_url, state, language):
|
110
|
+
cli_params = {
|
111
|
+
"lang": language,
|
112
|
+
"site": configs.SITE,
|
113
|
+
"state": state,
|
114
|
+
}
|
115
|
+
cli_query = urlencode(cli_params)
|
116
|
+
cli_url = configs.CLI_URL + "?" + cli_query
|
117
|
+
url_params = {
|
118
|
+
"loginType": "tccli",
|
119
|
+
"callback": cli_url,
|
120
|
+
"state": state,
|
121
|
+
}
|
122
|
+
url_query = urlencode(url_params)
|
123
|
+
auth_url = auth_url + "?" + url_query
|
124
|
+
|
125
|
+
print_message(_("try_login_with_url"))
|
126
|
+
print_message("")
|
127
|
+
print_message(auth_url)
|
128
|
+
|
129
|
+
webbrowser.open(auth_url)
|
130
|
+
|
131
|
+
while True:
|
132
|
+
time.sleep(1)
|
133
|
+
|
134
|
+
login_state = sso.check_login_state(state)
|
135
|
+
if "Error" in login_state:
|
136
|
+
raise ValueError(login_state["Error"])
|
137
|
+
|
138
|
+
if login_state["Status"] == "NotFound":
|
139
|
+
continue
|
140
|
+
|
141
|
+
if login_state["Status"] == "Finished":
|
142
|
+
return login_state["Token"]
|
143
|
+
|
144
|
+
raise ValueError("invalid resp: %s" % login_state)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
import os
|
3
|
+
|
4
|
+
from tccli import sso
|
5
|
+
from tccli.plugins.sso import texts, configs
|
6
|
+
|
7
|
+
|
8
|
+
def logout_command_entrypoint(args, parsed_globals):
|
9
|
+
language = parsed_globals.get("language")
|
10
|
+
if not language:
|
11
|
+
language = configs.DEFAULT_LANG
|
12
|
+
texts.set_lang(language)
|
13
|
+
|
14
|
+
profile = parsed_globals.get("profile", "default")
|
15
|
+
if not profile:
|
16
|
+
profile = "default"
|
17
|
+
|
18
|
+
cred_path = sso.cred_path_of_profile(profile)
|
19
|
+
if os.path.exists(cred_path):
|
20
|
+
os.remove(cred_path)
|
21
|
+
print(texts.get("logout_success") % cred_path)
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
import math
|
3
|
+
import sys
|
4
|
+
import os
|
5
|
+
from string import ascii_letters, digits, punctuation
|
6
|
+
|
7
|
+
_LEFT_ARROW = "LEFT_ARROW"
|
8
|
+
_RIGHT_ARROW = "RIGHT_ARROW"
|
9
|
+
_UP_ARROW = "UP_ARROW"
|
10
|
+
_DOWN_ARROW = "DOWN_ARROW"
|
11
|
+
_CTRL_C = "\x03"
|
12
|
+
_ENTER = "\r"
|
13
|
+
_BACKSPACE = "\x7f"
|
14
|
+
_EL = "\033[K"
|
15
|
+
_CPL = "\033[F"
|
16
|
+
_LIGHTBLUE = "\033[94m"
|
17
|
+
_LIGHTBLUE_END = "\033[0m"
|
18
|
+
|
19
|
+
_win = os.name == "nt"
|
20
|
+
|
21
|
+
|
22
|
+
class Printer(object):
|
23
|
+
def __init__(self):
|
24
|
+
self._n = 0
|
25
|
+
|
26
|
+
def print_lines(self, lines):
|
27
|
+
self.clear()
|
28
|
+
lines = [line + '\n' for line in lines]
|
29
|
+
sys.stdout.writelines(lines)
|
30
|
+
sys.stdout.flush()
|
31
|
+
self._n = len(lines)
|
32
|
+
|
33
|
+
def clear(self):
|
34
|
+
for _ in range(self._n):
|
35
|
+
self.move_up()
|
36
|
+
self.clear_cur_line()
|
37
|
+
|
38
|
+
@staticmethod
|
39
|
+
def clear_cur_line():
|
40
|
+
sys.stdout.write(_EL)
|
41
|
+
|
42
|
+
@staticmethod
|
43
|
+
def move_up():
|
44
|
+
sys.stdout.write(_CPL)
|
45
|
+
|
46
|
+
|
47
|
+
def _select_from_items_unix(prompt, items, page_size):
|
48
|
+
p = Printer()
|
49
|
+
|
50
|
+
selection = 0
|
51
|
+
search = ""
|
52
|
+
|
53
|
+
while True:
|
54
|
+
filtered_items = [item for item in items if search in item] if search else items
|
55
|
+
|
56
|
+
page_total = math.ceil(len(filtered_items) / float(page_size))
|
57
|
+
page_num = selection // page_size + 1
|
58
|
+
page_start = page_size * (page_num - 1)
|
59
|
+
page_items = list(filtered_items[page_start: page_start + page_size])
|
60
|
+
|
61
|
+
for i in range(len(page_items)):
|
62
|
+
selection_i = selection % page_size
|
63
|
+
selection_prompt = "* " if i == selection_i else " "
|
64
|
+
page_items[i] = selection_prompt + _LIGHTBLUE + page_items[i] + _LIGHTBLUE_END
|
65
|
+
|
66
|
+
page_lines = ["", "%s%s" % (prompt, search), ""] + page_items + ["", "page: %d/%d" % (page_num, page_total)]
|
67
|
+
p.print_lines(page_lines)
|
68
|
+
|
69
|
+
ch = _getch_wrap()
|
70
|
+
|
71
|
+
if ch == _CTRL_C:
|
72
|
+
raise KeyboardInterrupt()
|
73
|
+
|
74
|
+
if ch == _UP_ARROW:
|
75
|
+
selection = max(0, selection - 1)
|
76
|
+
elif ch == _DOWN_ARROW:
|
77
|
+
selection = min(len(filtered_items) - 1, selection + 1)
|
78
|
+
elif ch == _LEFT_ARROW:
|
79
|
+
if selection - page_size >= 0:
|
80
|
+
selection -= page_size
|
81
|
+
elif ch == _RIGHT_ARROW:
|
82
|
+
selection = min(len(filtered_items) - 1, selection + page_size)
|
83
|
+
elif ch == _BACKSPACE:
|
84
|
+
search = search[:len(search) - 1] if search else ""
|
85
|
+
selection = 0
|
86
|
+
elif ch == _ENTER:
|
87
|
+
idx = 0
|
88
|
+
matched = -1
|
89
|
+
|
90
|
+
for item in items:
|
91
|
+
if search in item:
|
92
|
+
matched += 1
|
93
|
+
if matched == selection:
|
94
|
+
p.print_lines([])
|
95
|
+
return idx
|
96
|
+
idx += 1
|
97
|
+
|
98
|
+
elif ch in (ascii_letters + digits + punctuation):
|
99
|
+
search += ch
|
100
|
+
selection = 0
|
101
|
+
|
102
|
+
|
103
|
+
def _select_from_items_win(prompt, items, page_size):
|
104
|
+
print("")
|
105
|
+
print("--------------------------------")
|
106
|
+
for i in range(len(items)):
|
107
|
+
print("%d. %s" % (i, items[i]))
|
108
|
+
|
109
|
+
print("--------------------------------")
|
110
|
+
sys.stdout.flush()
|
111
|
+
|
112
|
+
try:
|
113
|
+
input_func = raw_input
|
114
|
+
except NameError:
|
115
|
+
input_func = input
|
116
|
+
|
117
|
+
while True:
|
118
|
+
try:
|
119
|
+
sys.stdout.write(prompt)
|
120
|
+
idx = int(input_func())
|
121
|
+
if 0 <= idx < len(items):
|
122
|
+
return idx
|
123
|
+
except ValueError:
|
124
|
+
pass
|
125
|
+
|
126
|
+
|
127
|
+
select_from_items = _select_from_items_win if _win else _select_from_items_unix
|
128
|
+
|
129
|
+
if not _win:
|
130
|
+
def getch():
|
131
|
+
import sys
|
132
|
+
import tty
|
133
|
+
import termios
|
134
|
+
fd = sys.stdin.fileno()
|
135
|
+
old = termios.tcgetattr(fd)
|
136
|
+
try:
|
137
|
+
tty.setraw(fd)
|
138
|
+
return sys.stdin.read(1)
|
139
|
+
finally:
|
140
|
+
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
141
|
+
|
142
|
+
|
143
|
+
def _getch_wrap():
|
144
|
+
ch = getch()
|
145
|
+
if ch == "\x1b":
|
146
|
+
ch1 = getch()
|
147
|
+
if ch1 != "[":
|
148
|
+
raise KeyError(ch1)
|
149
|
+
ch2 = getch()
|
150
|
+
if ch2 == "A":
|
151
|
+
return _UP_ARROW
|
152
|
+
if ch2 == "B":
|
153
|
+
return _DOWN_ARROW
|
154
|
+
if ch2 == "C":
|
155
|
+
return _RIGHT_ARROW
|
156
|
+
if ch2 == "D":
|
157
|
+
return _LEFT_ARROW
|
158
|
+
|
159
|
+
raise KeyError(ch + ch1 + ch2)
|
160
|
+
else:
|
161
|
+
return ch
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
from tccli.plugins.sso import configs
|
3
|
+
|
4
|
+
_lang = configs.DEFAULT_LANG
|
5
|
+
|
6
|
+
texts = {
|
7
|
+
"zh-CN": {
|
8
|
+
"invalid_auth_url": "输入的 url 不合法: %s",
|
9
|
+
"auth_url_not_configured": "尚未配置 sso url, 使用 `tccli sso configure %s--url https://your-login-domain.com` 来进行配置",
|
10
|
+
"configure_succeed": "url 已配置为 '%s', 接下来可以使用 `tccli sso login` 进行登陆",
|
11
|
+
"try_login_with_url": "在浏览器中转到以下链接, 并根据提示完成登录:",
|
12
|
+
"account_select_prompt": "登录成功, 请选择您的用户: ",
|
13
|
+
"role_select_prompt": "请选择您的角色: ",
|
14
|
+
"login_success": "登录成功, 密钥凭证已被写入: %s",
|
15
|
+
"logout_success": "登出成功, 密钥凭证已被删除: %s",
|
16
|
+
"no_account": "未找到成员账号, 请确认是否同步过 CAM 角色",
|
17
|
+
"no_role": "当前成员账号不存在授权角色",
|
18
|
+
},
|
19
|
+
"en-US": {
|
20
|
+
"invalid_auth_url": "The entered url is invalid: %s",
|
21
|
+
"auth_url_not_configured": "sso url is not configured yet, use `tccli sso configure %s--url https://your-login-domain.com` to configure",
|
22
|
+
"configure_succeed": "The url has been configured as '%s', use `tccli sso login` to log in",
|
23
|
+
"try_login_with_url": "Go to the following link in your browser, and complete the sign-in prompts:",
|
24
|
+
"account_select_prompt": "Login succeed, choose your account: ",
|
25
|
+
"role_select_prompt": "choose your role: ",
|
26
|
+
"login_success": "Login succeed, credential has been written to %s",
|
27
|
+
"logout_success": "Logout succeed, credential has been removed: %s",
|
28
|
+
"no_account": "no account found, please confirm the account is synchronized",
|
29
|
+
"no_role": "no role found in current account",
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
|
34
|
+
def set_lang(lang):
|
35
|
+
global _lang
|
36
|
+
_lang = lang
|
37
|
+
|
38
|
+
|
39
|
+
def get(key):
|
40
|
+
return texts[_lang][key]
|
tccli/services/__init__.py
CHANGED
@@ -88,6 +88,9 @@ SERVICE_VERSIONS = {
|
|
88
88
|
"bda": [
|
89
89
|
"2020-03-24"
|
90
90
|
],
|
91
|
+
"bh": [
|
92
|
+
"2023-04-18"
|
93
|
+
],
|
91
94
|
"bi": [
|
92
95
|
"2022-01-05"
|
93
96
|
],
|
@@ -398,6 +401,9 @@ SERVICE_VERSIONS = {
|
|
398
401
|
"iecp": [
|
399
402
|
"2021-09-14"
|
400
403
|
],
|
404
|
+
"ig": [
|
405
|
+
"2021-05-18"
|
406
|
+
],
|
401
407
|
"iir": [
|
402
408
|
"2020-04-17"
|
403
409
|
],
|
@@ -519,7 +519,7 @@
|
|
519
519
|
{
|
520
520
|
"disabled": false,
|
521
521
|
"document": "联系人信息",
|
522
|
-
"example": "
|
522
|
+
"example": "张三",
|
523
523
|
"member": "string",
|
524
524
|
"name": "ContactName",
|
525
525
|
"required": false,
|
@@ -528,7 +528,7 @@
|
|
528
528
|
{
|
529
529
|
"disabled": false,
|
530
530
|
"document": "联系电话",
|
531
|
-
"example": "
|
531
|
+
"example": "138XXXXXXXX",
|
532
532
|
"member": "string",
|
533
533
|
"name": "TelNumber",
|
534
534
|
"required": false,
|
@@ -537,7 +537,7 @@
|
|
537
537
|
{
|
538
538
|
"disabled": false,
|
539
539
|
"document": "公司邮箱",
|
540
|
-
"example": "
|
540
|
+
"example": "user****@tencent.com",
|
541
541
|
"member": "string",
|
542
542
|
"name": "Email",
|
543
543
|
"required": false,
|
@@ -546,7 +546,7 @@
|
|
546
546
|
{
|
547
547
|
"disabled": false,
|
548
548
|
"document": "公司名称",
|
549
|
-
"example": "
|
549
|
+
"example": "****科技有限公司",
|
550
550
|
"member": "string",
|
551
551
|
"name": "CorpName",
|
552
552
|
"required": false,
|
@@ -564,7 +564,7 @@
|
|
564
564
|
{
|
565
565
|
"disabled": false,
|
566
566
|
"document": "备注信息",
|
567
|
-
"example": "备注信息",
|
567
|
+
"example": "Remark备注信息",
|
568
568
|
"member": "string",
|
569
569
|
"name": "Remark",
|
570
570
|
"required": false,
|
@@ -618,7 +618,7 @@
|
|
618
618
|
"example": "0",
|
619
619
|
"member": "int64",
|
620
620
|
"name": "Result",
|
621
|
-
"
|
621
|
+
"output_required": true,
|
622
622
|
"type": "int",
|
623
623
|
"value_allowed_null": false
|
624
624
|
},
|
@@ -628,7 +628,7 @@
|
|
628
628
|
"example": "170143813*******360",
|
629
629
|
"member": "string",
|
630
630
|
"name": "TaskID",
|
631
|
-
"
|
631
|
+
"output_required": true,
|
632
632
|
"type": "string",
|
633
633
|
"value_allowed_null": true
|
634
634
|
},
|
@@ -3,7 +3,7 @@
|
|
3
3
|
"CreateAppScanTask": [
|
4
4
|
{
|
5
5
|
"document": "",
|
6
|
-
"input": "POST / HTTP/1.1\nHost: acp.tencentcloudapi.com\nContent-Type: application/json\nX-TC-Action: CreateAppScanTask\n<公共请求参数>\n\n{\n \"Remark\": \"
|
6
|
+
"input": "POST / HTTP/1.1\nHost: acp.tencentcloudapi.com\nContent-Type: application/json\nX-TC-Action: CreateAppScanTask\n<公共请求参数>\n\n{\n \"Remark\": \"Remark备注信息\",\n \"Platform\": \"0\",\n \"TelNumber\": \"138XXXXXXXX\",\n \"Source\": \"2\",\n \"SalesPerson\": \"张三\",\n \"ContactName\": \"张三\",\n \"TaskType\": \"2\",\n \"CorpName\": \"****科技有限公司\",\n \"Email\": \"user****@tencent.com\",\n \"IsAgreePrivacy\": \"1\"\n}",
|
7
7
|
"output": "{\n \"Response\": {\n \"RequestId\": \"6c296e5b-48ad-4cfb-a90d-8010c9951341\",\n \"Result\": 0,\n \"TaskID\": \"271***520\"\n }\n}",
|
8
8
|
"title": "本地化任务"
|
9
9
|
},
|
@@ -21,7 +21,7 @@
|
|
21
21
|
},
|
22
22
|
{
|
23
23
|
"document": "",
|
24
|
-
"input": "POST / HTTP/1.1\nHost: acp.tencentcloudapi.com\nContent-Type: application/json\nX-TC-Action: CreateAppScanTask\n<公共请求参数>\n\n{\n \"PrivacyTextName\": \"腾讯iOA隐私保护指引.txt\",\n \"AppDownloadUrl\": \"https://bm****OYpo8YKRrbnTofaB.apk\",\n \"Platform\": \"0\",\n \"TelNumber\": \"
|
24
|
+
"input": "POST / HTTP/1.1\nHost: acp.tencentcloudapi.com\nContent-Type: application/json\nX-TC-Action: CreateAppScanTask\n<公共请求参数>\n\n{\n \"PrivacyTextName\": \"腾讯iOA隐私保护指引.txt\",\n \"AppDownloadUrl\": \"https://bm****OYpo8YKRrbnTofaB.apk\",\n \"Platform\": \"0\",\n \"TelNumber\": \"138XXXXXXXX\",\n \"AppName\": \"ioa\",\n \"PrivacyTextUrl\": \"https://bm****jc7yrar9xIKPYyvpEgVA.txt\",\n \"AppPackage\": \"com.***.i**oa\",\n \"Source\": \"2\",\n \"SalesPerson\": \"张三\",\n \"ContactName\": \"张三\",\n \"TaskType\": \"1\",\n \"CorpName\": \"****科技有限公司\",\n \"Email\": \"user****@tencent.com\",\n \"IsAgreePrivacy\": \"1\"\n}",
|
25
25
|
"output": "{\n \"Response\": {\n \"RequestId\": \"ab653763-5494-42db-b7d3-4afd9eb76410\",\n \"Result\": 0,\n \"TaskID\": \"271***344\"\n }\n}",
|
26
26
|
"title": "App专家版隐私合规诊断示例"
|
27
27
|
},
|