tccli 3.0.1215.1__py2.py3-none-any.whl → 3.0.1217.1__py2.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.
- tccli/__init__.py +1 -1
- tccli/argparser.py +1 -1
- tccli/command.py +2 -2
- tccli/configure.py +46 -1
- 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 -3
- 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 +118 -4
- tccli/services/asr/v20190614/api.json +21 -20
- 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 +80 -4
- tccli/services/bi/v20220105/examples.json +1 -1
- tccli/services/billing/billing_client.py +53 -0
- tccli/services/billing/v20180709/api.json +330 -24
- tccli/services/billing/v20180709/examples.json +8 -0
- tccli/services/bsca/v20210811/api.json +223 -18
- tccli/services/bsca/v20210811/examples.json +4 -4
- 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/ccc_client.py +53 -0
- tccli/services/ccc/v20200210/api.json +541 -325
- tccli/services/ccc/v20200210/examples.json +26 -18
- tccli/services/cdb/cdb_client.py +13 -13
- tccli/services/cdb/v20170320/api.json +308 -274
- 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/cdn/v20180606/api.json +5 -3
- 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 +54 -4
- 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 +1895 -2011
- tccli/services/cfw/v20190904/examples.json +175 -171
- tccli/services/ciam/v20220331/api.json +316 -315
- tccli/services/ciam/v20220331/examples.json +49 -49
- 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/cloudaudit_client.py +30 -30
- tccli/services/cloudaudit/v20190319/api.json +254 -211
- tccli/services/cloudaudit/v20190319/examples.json +19 -19
- 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 +935 -147
- tccli/services/cls/v20201016/examples.json +43 -5
- tccli/services/csip/v20221121/api.json +2566 -2386
- tccli/services/csip/v20221121/examples.json +108 -108
- tccli/services/cvm/v20170312/api.json +191 -112
- tccli/services/cvm/v20170312/examples.json +2 -2
- tccli/services/cwp/cwp_client.py +4 -110
- tccli/services/cwp/v20180228/api.json +6498 -6252
- tccli/services/cwp/v20180228/examples.json +372 -412
- tccli/services/cynosdb/v20190107/api.json +170 -110
- tccli/services/cynosdb/v20190107/examples.json +91 -91
- tccli/services/dasb/v20191018/api.json +859 -637
- 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/domain/v20180808/api.json +3 -3
- tccli/services/domain/v20180808/examples.json +3 -3
- tccli/services/dts/v20211206/api.json +4 -4
- tccli/services/eb/v20210416/api.json +15 -15
- tccli/services/eb/v20210416/examples.json +1 -1
- 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/es_client.py +249 -37
- tccli/services/es/v20180416/api.json +550 -0
- tccli/services/es/v20180416/examples.json +33 -1
- tccli/services/ess/ess_client.py +53 -0
- tccli/services/ess/v20201111/api.json +192 -38
- tccli/services/ess/v20201111/examples.json +35 -9
- tccli/services/essbasic/essbasic_client.py +106 -0
- tccli/services/essbasic/v20210526/api.json +287 -60
- tccli/services/essbasic/v20210526/examples.json +58 -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/gaap/v20180529/api.json +44 -26
- tccli/services/gaap/v20180529/examples.json +24 -30
- 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 +73 -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 +279 -9
- 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 +10 -12
- 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 +2263 -758
- 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/organization_client.py +352 -34
- tccli/services/organization/v20210331/api.json +464 -4
- tccli/services/organization/v20210331/examples.json +49 -1
- 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/region/v20220627/api.json +1 -1
- tccli/services/rum/v20210622/api.json +9 -0
- tccli/services/scf/scf_client.py +269 -4
- tccli/services/scf/v20180416/api.json +569 -15
- tccli/services/scf/v20180416/examples.json +47 -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 +98 -5
- tccli/services/ssm/v20190923/api.json +292 -231
- tccli/services/ssm/v20190923/examples.json +42 -42
- tccli/services/tat/v20201028/api.json +124 -122
- tccli/services/tat/v20201028/examples.json +24 -30
- 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 +1984 -1437
- tccli/services/tcss/v20201101/examples.json +350 -368
- tccli/services/tdmq/v20200217/api.json +603 -464
- tccli/services/tdmq/v20200217/examples.json +105 -105
- tccli/services/tds/v20220801/api.json +4 -4
- tccli/services/tem/v20210701/api.json +429 -372
- tccli/services/tem/v20210701/examples.json +85 -85
- tccli/services/teo/teo_client.py +277 -12
- tccli/services/teo/v20220901/api.json +1029 -124
- tccli/services/teo/v20220901/examples.json +84 -8
- tccli/services/thpc/v20230321/api.json +5 -5
- tccli/services/tke/tke_client.py +270 -58
- tccli/services/tke/v20180525/api.json +79 -27
- tccli/services/tke/v20180525/examples.json +9 -1
- tccli/services/tke/v20220501/api.json +176 -0
- tccli/services/tke/v20220501/examples.json +24 -0
- tccli/services/tms/tms_client.py +4 -57
- tccli/services/tms/v20201229/api.json +0 -354
- tccli/services/tms/v20201229/examples.json +0 -8
- 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 +293 -52
- 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 +1195 -892
- tccli/services/vpc/v20170312/examples.json +84 -68
- tccli/services/vpc/vpc_client.py +168 -62
- tccli/services/waf/v20180125/api.json +2611 -2187
- tccli/services/waf/v20180125/examples.json +224 -284
- tccli/services/waf/waf_client.py +225 -119
- tccli/services/wav/v20210129/api.json +48 -48
- tccli/services/wav/v20210129/examples.json +4 -4
- tccli/services/wedata/v20210820/api.json +1595 -25
- tccli/services/wedata/v20210820/examples.json +44 -4
- tccli/services/wedata/wedata_client.py +265 -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.1215.1.dist-info → tccli-3.0.1217.1.dist-info}/METADATA +6 -2
- {tccli-3.0.1215.1.dist-info → tccli-3.0.1217.1.dist-info}/RECORD +278 -265
- tccli/services/cr/__init__.py +0 -4
- tccli/services/cr/cr_client.py +0 -1626
- tccli/services/cr/v20180321/api.json +0 -2829
- tccli/services/cr/v20180321/examples.json +0 -235
- {tccli-3.0.1215.1.dist-info → tccli-3.0.1217.1.dist-info}/WHEEL +0 -0
- {tccli-3.0.1215.1.dist-info → tccli-3.0.1217.1.dist-info}/entry_points.txt +0 -0
- {tccli-3.0.1215.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/configure.py
CHANGED
@@ -230,6 +230,50 @@ class ConfigureSetCommand(BasicConfigure):
|
|
230
230
|
self._init_configure(profile_name + '.credential', cred)
|
231
231
|
|
232
232
|
|
233
|
+
class ConfigureSetRootDomainCommand(BasicConfigure):
|
234
|
+
NAME = 'set-root-domain'
|
235
|
+
DESCRIPTION = 'Set the root domain name for all endpoints.'
|
236
|
+
USEAGE = 'tccli configure set-root-domain [root-domain-value] [--profile profile-name]'
|
237
|
+
AVAILABLECONFIG = "[cvm, cbs ...].endpoint: service [cvm cbs ...] access point root domain name"
|
238
|
+
EXAMPLES = "$ tccli configure set-root-domain internal.tencentcloudapi.com --profile test"
|
239
|
+
ARG_TABLE = [
|
240
|
+
{'name': 'varname',
|
241
|
+
'help_text': 'The name of the root domain value to set.',
|
242
|
+
'action': 'store',
|
243
|
+
'nargs': '+',
|
244
|
+
'cli_type_name': 'string',
|
245
|
+
'positional_arg': True},
|
246
|
+
]
|
247
|
+
|
248
|
+
def __init__(self):
|
249
|
+
super(ConfigureSetRootDomainCommand, self).__init__()
|
250
|
+
|
251
|
+
def _run_main(self, args, parsed_globals):
|
252
|
+
var_value = args.varname
|
253
|
+
if len(var_value) != 1:
|
254
|
+
raise ParamError("Unexpected format\n"
|
255
|
+
"Expected input format:\n\n"
|
256
|
+
" $tccli configure set-root-domain internal.tencentcloudapi.com\n")
|
257
|
+
profile_name = self._get_profile_name(parsed_globals)
|
258
|
+
profile_name = profile_name + '.configure'
|
259
|
+
|
260
|
+
conf_data = {}
|
261
|
+
is_exist, config_path = self._profile_existed(profile_name)
|
262
|
+
if is_exist:
|
263
|
+
conf_data = Utils.load_json_msg(config_path)
|
264
|
+
if profile_name.endswith(".configure"):
|
265
|
+
for mod in self._cli_data.get_available_services().keys():
|
266
|
+
if mod not in conf_data:
|
267
|
+
conf_data[mod] = {}
|
268
|
+
conf_data[mod]["endpoint"] = "%s.tencentcloudapi.com" % mod
|
269
|
+
if mod != 'autoscaling':
|
270
|
+
conf_data[mod]["endpoint"] = "%s.%s" % (mod, var_value[0])
|
271
|
+
else:
|
272
|
+
conf_data[mod]["endpoint"] = "as.%s" % var_value[0]
|
273
|
+
conf_data[mod]["version"] = self._cli_data.get_available_services()[mod][0]
|
274
|
+
Utils.dump_json_msg(config_path, conf_data)
|
275
|
+
|
276
|
+
|
233
277
|
class ConfigureGetCommand(BasicConfigure):
|
234
278
|
NAME = 'get'
|
235
279
|
DESCRIPTION = "get your profile(eg:SecretId, SecretKey, Region)."
|
@@ -342,7 +386,8 @@ class ConfigureCommand(BasicConfigure):
|
|
342
386
|
{'name': 'list', 'command_class': ConfigureListCommand},
|
343
387
|
{'name': 'get', 'command_class': ConfigureGetCommand},
|
344
388
|
{'name': 'set', 'command_class': ConfigureSetCommand},
|
345
|
-
{'name': 'remove', 'command_class': ConfigureRemoveCommand}
|
389
|
+
{'name': 'remove', 'command_class': ConfigureRemoveCommand},
|
390
|
+
{'name': 'set-root-domain', 'command_class': ConfigureSetRootDomainCommand},
|
346
391
|
]
|
347
392
|
|
348
393
|
VALUES_TO_PROMPT = [
|
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
|
],
|
@@ -236,9 +239,6 @@ SERVICE_VERSIONS = {
|
|
236
239
|
"cpdp": [
|
237
240
|
"2019-08-20"
|
238
241
|
],
|
239
|
-
"cr": [
|
240
|
-
"2018-03-21"
|
241
|
-
],
|
242
242
|
"csip": [
|
243
243
|
"2022-11-21"
|
244
244
|
],
|
@@ -401,6 +401,9 @@ SERVICE_VERSIONS = {
|
|
401
401
|
"iecp": [
|
402
402
|
"2021-09-14"
|
403
403
|
],
|
404
|
+
"ig": [
|
405
|
+
"2021-05-18"
|
406
|
+
],
|
404
407
|
"iir": [
|
405
408
|
"2020-04-17"
|
406
409
|
],
|