cmdbox


Namecmdbox JSON
Version 0.6.2.3 PyPI version JSON
download
home_pagehttps://github.com/hamacom2004jp/cmdbox
Summarycmdbox: It is a command line application with a plugin mechanism.
upload_time2025-07-13 04:25:55
maintainerhamacom2004jp
docs_urlNone
authorhamacom2004jp
requires_python>=3.8
licenseMIT
keywords cli restapi redis fastapi
VCS
bugtrack_url
requirements argcomplete async-timeout collectlicense cryptography fastapi gevent gunicorn itsdangerous numpy Pillow python-multipart pycryptodome plyer psycopg pyjwt pystray questionary redis requests rich six sphinx sphinx-rtd-theme sphinx_fontawesome sphinx-intl sphinx-sitemap tabulate twine uvicorn wheel
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # cmdbox (Command Development Application)

- It is a command development application with a plugin mechanism.
- Documentation is [here](https://hamacom2004jp.github.io/cmdbox/).
- With cmdbox, you can easily implement commands with complex options.
- The implemented commands can be called from the CLI / RESTAPI / Web / Edge screen.
- The implemented commands can be executed on a remote server via redis.

![cmdbox operation image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/orverview.drawio.png)

# Install

- Install cmdbox with the following command.
- Also install the docker version of the redis server.

```bash
docker run -p 6379:6379 --name redis -e REDIS_PASSWORD=password -it ubuntu/redis:latest
pip install cmdbox
cmdbox -v
```

- When using SAML in web mode, install the modules with dependencies.
```bash
pip install xmlsec==1.3.13 python3-saml
apt-get install -y pkg-config libxml2-dev libxmlsec1-dev libxmlsec1-openssl build-essential libopencv-dev
```

- When using `--agent use` in web mode, install the modules with dependencies.
```bash
pip install google-adk litellm fastmcp
```

# Run

- Run the cmdbox server.

```bash
cmdbox -m server -c start &
```

- Run the cmdbox web.

```bash
cmdbox -m web -c start --signin_file .cmdbox/user_list.yml &
```

- Run the cmdbox web with agent.
- Below is an example of using Google vertexai.
- Other available options include Azure OpenAI and Ollama.

```bash
cmdbox -m web -c start --signin_file .cmdbox/user_list.yml --agent use --llmprov vertexai --llmmodel gemini-2.0-flash --llmlocation us-central1 --llmsvaccountfile <account json file>
```


# Tutorial

- Open the ```.sample/sample_project``` folder in the current directory with VSCode.

![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme001.png)

- Install dependent libraries.

```bash
python -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
```

- Run the project.

![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme002.png)

- The localhost web screen will open.

![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme003.png)

- Enter ```user01 / user01``` for the initial ID and PW to sign in.
- Using this web screen, you can easily execute the commands implemented in cmdbox.

![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme004.png)

- Let's look at the command to get a list of files as an example.
- Press the plus button under Commands to open the Add dialog.
- Then enter the following.

![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme005.png)

- Press the ```Save``` button once and then press the ```Execute``` button.
- The results of the command execution are displayed.

![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme006.png)

- Open the saved ```client_time``` and press the ```Raw``` button.
- You will see how to execute the same command on the command line; the RESTAPI URL is also displayed.

![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme007.png)


## How to implement a new command using cmdbox

- Under the ```sample/app/features/cli``` folder, you will find an implementation of the ```sample_client_time``` mentioned earlier.
- The implementation is as follows. (Slightly abbreviated display)
- Create the following code and save it in the ```sample/app/features/cli``` folder.

```python
from cmdbox.app import common, feature
from typing import Dict, Any, Tuple, Union, List
import argparse
import datetime
import logging


class ClientTime(feature.Feature):
    def get_mode(self) -> Union[str, List[str]]:
        return "client"

    def get_cmd(self):
        return 'time'

    def get_option(self):
        return dict(
            type=Options.T_STR, default=None, required=False, multi=False, hide=False, use_redis=self.USE_REDIS_FALSE,
            description_ja="クライアント側の現在時刻を表示します。",
            description_en="Displays the current time at the client side.",
            choice=[
                dict(opt="timedelta", type=Options.T_INT, default=9, required=False, multi=False, hide=False, choice=None,
                        description_ja="時差の時間数を指定します。",
                        description_en="Specify the number of hours of time difference."),
            ])

    def apprun(self, logger:logging.Logger, args:argparse.Namespace, tm:float, pf:List[Dict[str, float]]=[]) -> Tuple[int, Dict[str, Any], Any]:
        tz = datetime.timezone(datetime.timedelta(hours=args.timedelta))
        dt = datetime.datetime.now(tz)
        ret = dict(success=dict(data=dt.strftime('%Y-%m-%d %H:%M:%S')))
        common.print_format(ret, args.format, tm, args.output_json, args.output_json_append, pf=pf)
        if 'success' not in ret:
            return 1, ret, None
        return 0, ret, None

    def edgerun(self, opt, tool, logger, timeout, prevres = None):
        status, res = tool.exec_cmd(opt, logger, timeout, prevres)
        tool.notify(res)
        yield 1, res
```

- If you want to implement server-side processing, please refer to ```sample_server_time```.

```python
from cmdbox.app import common, client, feature
from cmdbox.app.commons import redis_client
from cmdbox.app.options import Options
from pathlib import Path
from typing import Dict, Any, Tuple, Union, List
import argparse
import datetime
import logging


class ServerTime(feature.Feature):
    def get_mode(self) -> Union[str, List[str]]:
        return "server"

    def get_cmd(self):
        return 'time'

    def get_option(self):
        return dict(
            type=Options.T_STR, default=None, required=False, multi=False, hide=False, use_redis=self.USE_REDIS_FALSE,
            description_ja="サーバー側の現在時刻を表示します。",
            description_en="Displays the current time at the server side.",
            choice=[
                dict(opt="host", type=Options.T_STR, default=self.default_host, required=True, multi=False, hide=True, choice=None,
                        description_ja="Redisサーバーのサービスホストを指定します。",
                        description_en="Specify the service host of the Redis server."),
                dict(opt="port", type=Options.T_INT, default=self.default_port, required=True, multi=False, hide=True, choice=None,
                        description_ja="Redisサーバーのサービスポートを指定します。",
                        description_en="Specify the service port of the Redis server."),
                dict(opt="password", type=Options.T_STR, default=self.default_pass, required=True, multi=False, hide=True, choice=None,
                        description_ja="Redisサーバーのアクセスパスワード(任意)を指定します。省略時は `password` を使用します。",
                        description_en="Specify the access password of the Redis server (optional). If omitted, `password` is used."),
                dict(opt="svname", type=Options.T_STR, default=self.default_svname, required=True, multi=False, hide=True, choice=None,
                        description_ja="サーバーのサービス名を指定します。省略時は `server` を使用します。",
                        description_en="Specify the service name of the inference server. If omitted, `server` is used."),
                dict(opt="timedelta", type=Options.T_INT, default=9, required=False, multi=False, hide=False, choice=None,
                        description_ja="時差の時間数を指定します。",
                        description_en="Specify the number of hours of time difference."),
                dict(opt="retry_count", type=Options.T_INT, default=3, required=False, multi=False, hide=True, choice=None,
                        description_ja="Redisサーバーへの再接続回数を指定します。0以下を指定すると永遠に再接続を行います。",
                        description_en="Specifies the number of reconnections to the Redis server.If less than 0 is specified, reconnection is forever."),
                dict(opt="retry_interval", type=Options.T_INT, default=5, required=False, multi=False, hide=True, choice=None,
                        description_ja="Redisサーバーに再接続までの秒数を指定します。",
                        description_en="Specifies the number of seconds before reconnecting to the Redis server."),
                dict(opt="timeout", type=Options.T_INT, default="15", required=False, multi=False, hide=True, choice=None,
                        description_ja="サーバーの応答が返ってくるまでの最大待ち時間を指定。",
                        description_en="Specify the maximum waiting time until the server responds."),
            ])

    def get_svcmd(self):
        return 'server_time'

    def apprun(self, logger:logging.Logger, args:argparse.Namespace, tm:float, pf:List[Dict[str, float]]=[]) -> Tuple[int, Dict[str, Any], Any]:
        cl = client.Client(logger, redis_host=args.host, redis_port=args.port, redis_password=args.password, svname=args.svname)
        ret = cl.redis_cli.send_cmd(self.get_svcmd(), [str(args.timedelta)],
                                    retry_count=args.retry_count, retry_interval=args.retry_interval, timeout=args.timeout)
        common.print_format(ret, args.format, tm, args.output_json, args.output_json_append, pf=pf)
        if 'success' not in ret:
            return 1, ret, None
        return 0, ret, None

    def is_cluster_redirect(self):
        return False

    def svrun(self, data_dir:Path, logger:logging.Logger, redis_cli:redis_client.RedisClient, msg:List[str],
              sessions:Dict[str, Dict[str, Any]]) -> int:
        td = 9 if msg[2] == None else int(msg[2])
        tz = datetime.timezone(datetime.timedelta(hours=td))
        dt = datetime.datetime.now(tz)
        ret = dict(success=dict(data=dt.strftime('%Y-%m-%d %H:%M:%S')))
        redis_cli.rpush(msg[1], ret)
        return self.RESP_SCCESS

    def edgerun(self, opt, tool, logger, timeout, prevres = None):
        status, res = tool.exec_cmd(opt, logger, timeout, prevres)
        tool.notify(res)
        yield 1, res
```

- Open the file ```sample/extensions/features.yml```. The file should look something like this.
- This file specifies where new commands are to be read.
- For example, if you want to add a package to read, add a new ```package``` and ```prefix``` to ```features.cli```.
- Note that ```features.web``` can be used to add a new web screen.
- If you only want to call commands added in ```features.cli``` via RESTAPI, no additional implementation is needed in ```features.web```.


```yml
features:
  cli:                                  # Specify a list of package names in which the module implementing the command is located.
    - package: cmdbox.app.features.cli  # Package Name. Classes inheriting from cmdbox.app.feature.Feature.
      prefix: cmdbox_                   # Module name prefix. Modules that begin with this letter are eligible.
      exclude_modules: []               # Specify the module name to exclude from the list of modules to be loaded.
  web:                                  # Specify a list of package names with modules that implement web screens and RESTAPIs.
    - package: cmdbox.app.features.web  # Package Name. Classes inheriting from cmdbox.app.feature.WebFeature .
      prefix: cmdbox_web_               # Module name prefix. Modules that begin with this letter are eligible.
args:                                   # Specifies default or forced arguments for the specified command.
  cli:                                  # Specify rules to apply default values or force arguments.
    - rule:                             # Specify the rules for applying default values and forced arguments for each command line option.
                                        #   e.g. mode: web
      default:                          # Specify a default value for each item to be set when a rule is matched.
                                        #   e.g. doc_root: f"{Path(self.ver.__file__).parent / 'web'}"
      coercion:                         # Specify a coercion value for each item to be set when a rule is matched.
                                        #   e.g. doc_root: f"{Path(self.ver.__file__).parent / 'web'}"
aliases:                                # Specify the alias for the specified command.
  cli:                                  # Specify the alias for the command line.
    - source:                           # Specifies the command from which the alias originates.
        mode:                           # Specify the mode of the source command. The exact match "mode" is selected.
                                        #   e.g. client
        cmd:                            # Specify the source command to be aliased. The regex match "cmd" is selected.
                                        #   e.g. (.+)_(.+)
      target:                           # Specifies the command to be aliased to.
        mode:                           # Specify the mode of the target command. Create an alias for this “mode”.
                                        #   e.g. CLIENT
        cmd:                            # Specify the target command to be aliased. Create an alias for this “cmd”, referring to the regular expression group of source by "{n}".
                                        #   e.g. {2}_{1}
        move:                           # Specify whether to move the regular expression group of the source to the target.
                                        #   e.g. true
  web:                                  # Specify the alias for the RESTAPI.
    - source:                           # Specifies the RESTAPI from which the alias originates.
        path:                           # Specify the path of the source RESTAPI. The regex match "path" is selected.
                                        #   e.g. /exec_(.+)
      target:                           # Specifies the RESTAPI to be aliased to.
        path:                           # Specify the path of the target RESTAPI. Create an alias for this “path”, referring to the regular expression group of source by "{n}".
                                        #   e.g. /{1}_exec
        move:                           # Specify whether to move the regular expression group of the source to the target.
                                        #   e.g. true
agentrule:                              # Specifies a list of rules that determine which commands the agent can execute.
  policy: deny                          # Specify the default policy for the rule. The value can be allow or deny.
  rules:                                # Specify the rules for the commands that the agent can execute according to the group to which the user belongs.
  - mode: audit                         # Specify the "mode" as the condition for applying the rule.
    cmds: [search, write]               # Specify the "cmd" to which the rule applies. Multiple items can be specified in a list.
    rule: allow                         # Specifies whether the specified command is allowed or not. Values are allow or deny.
  - mode: client
    cmds: [file_copy, file_download, file_list, file_mkdir, file_move, file_remove, file_rmdir, file_upload, server_info]
    rule: allow
  - mode: cmd
    cmds: [list, load]
    rule: allow
  - mode: server
    cmds: [list]
    rule: allow
  - mode: web
    cmds: [gencert, genpass, group_list, user_list]
    rule: allow
audit:
  enabled: true                         # Specify whether to enable the audit function.
  write:
    mode: audit                         # Specify the mode of the feature to be writed.
    cmd: write                          # Specify the command to be writed.
  search:
    mode: audit                         # Specify the mode of the feature to be searched.
    cmd: search                         # Specify the command to be searched.
  options:                              # Specify the options for the audit function.
    host: localhost                     # Specify the service host of the audit Redis server.However, if it is specified as a command line argument, it is ignored.
    port: 6379                          # Specify the service port of the audit Redis server.However, if it is specified as a command line argument, it is ignored.
    password: password                  # Specify the access password of the audit Redis server.However, if it is specified as a command line argument, it is ignored.
    svname: cmdbox                      # Specify the audit service name of the inference server.However, if it is specified as a command line argument, it is ignored.
    retry_count: 3                      # Specifies the number of reconnections to the audit Redis server.If less than 0 is specified, reconnection is forever.
    retry_interval: 1                   # Specifies the number of seconds before reconnecting to the audit Redis server.
    timeout: 15                         # Specify the maximum waiting time until the server responds.
    pg_enabled: False                   # Specify True if using the postgresql database server.
    pg_host: localhost                  # Specify the postgresql host.
    pg_port: 5432                       # Specify the postgresql port.
    pg_user: postgres                   # Specify the postgresql user name.
    pg_password: password               # Specify the postgresql password.
    pg_dbname: audit                    # Specify the postgresql database name.
    retention_period_days: 365          # Specify the number of days to retain audit logs.

```

- The following files should also be known when using commands on the web screen or RESTAPI.
- Open the file ```sample/extensions/user_list.yml```. The file should look something like this.
- This file manages the users and groups that are allowed Web access and their rules.
- The rule of the previous command is ```allow``` for users in the ```user``` group in ```cmdrule.rules```.


```yml
users:                         # A list of users, each of which is a map that contains the following fields.
- uid: 1                       # An ID that identifies a user. No two users can have the same ID.
  name: admin                  # A name that identifies the user. No two users can have the same name.
  password: XXXXX              # The user's password. The value is hashed with the hash function specified in the next hash field.
  hash: plain                  # The hash function used to hash the password, which can be plain, md5, sha1, or sha256, or oauth2, or saml.
  groups: [admin]              # A list of groups to which the user belongs, as specified in the groups field.
  email: admin@aaa.bbb.jp      # The email address of the user, used when authenticating using the provider specified in the oauth2 or saml field.
- uid: 101
  name: user01
  password: XXXXX
  hash: md5
  groups: [user]
  email: user01@aaa.bbb.jp
- uid: 102
  name: user02
  password: XXXXX
  hash: sha1
  groups: [readonly]
  email: user02@aaa.bbb.jp
- uid: 103
  name: user03
  password: XXXXX
  hash: sha256
  groups: [editor]
  email: user03@aaa.bbb.jp
groups:                        # A list of groups, each of which is a map that contains the following fields.
- gid: 1                       # An ID that identifies a group. No two groups can have the same ID.
  name: admin                  # A name that identifies the group. No two groups can have the same name.
- gid: 2
  name: guest
- gid: 101
  name: user
- gid: 102
  name: readonly
  parent: user                 # The parent group of the group. If the parent group is not specified, the group is a top-level group.
- gid: 103
  name: editor
  parent: user
cmdrule:                       # A list of command rules, Specify a rule that determines whether or not a command is executable when executed by a user in web mode.
  policy: deny                 # Specify the default policy for the rule. The value can be allow or deny.
  rules:                       # Specify rules to allow or deny execution of the command, depending on the group the user belongs to.
  - groups: [admin]
    rule: allow
  - groups: [user]             # Specify the groups to which the rule applies.
    mode: client               # Specify the "mode" as the condition for applying the rule.
    cmds: [file_download, file_list, server_info] # Specify the "cmd" to which the rule applies. Multiple items can be specified in a list.
    rule: allow                # Specifies whether or not the specified command is allowed for the specified group. The value can be allow or deny.
  - groups: [user]
    mode: server
    cmds: [list]
    rule: allow
  - groups: [user]
    mode: cmd
    cmds: [list, load]
    rule: allow
  - groups: [user, guest]
    mode: audit
    cmds: [write]
    rule: allow
  - groups: [user, guest]
    mode: web
    cmds: [genpass]
    rule: allow
  - groups: [editor]
    mode: client
    cmds: [file_copy, file_mkdir, file_move, file_remove, file_rmdir, file_upload]
    rule: allow
pathrule:                      # List of RESTAPI rules, rules that determine whether or not a RESTAPI can be executed when a user in web mode accesses it.
  policy: deny                 # Specify the default policy for the rule. The value can be allow or deny.
  rules:                       # Specify rules to allow or deny execution of the RESTAPI, depending on the group the user belongs to.
  - groups: [admin]            # Specify the groups to which the rule applies.
    paths: [/]                 # Specify the "path" to which the rule applies. Multiple items can be specified in a list.
    rule: allow                # Specifies whether or not the specified RESTAPI is allowed for the specified group. The value can be allow or deny.
  - groups: [guest]
    paths: [/signin, /assets, /copyright, /dosignin, /dosignout, /password/change,
            /gui, /get_server_opt, /usesignout, /versions_cmdbox, /versions_used]
    rule: allow
  - groups: [user]
    paths: [/signin, /assets, /bbforce_cmd, /copyright, /dosignin, /dosignout, /password/change,
            /gui/user_data/load, /gui/user_data/save, /gui/user_data/delete,
            /agent, /mcpsv,
            /exec_cmd, /exec_pipe, /filer, /result, /gui, /get_server_opt, /usesignout, /versions_cmdbox, /versions_used]
    rule: allow
  - groups: [readonly]
    paths: [/gui/del_cmd, /gui/del_pipe, /gui/save_cmd, /gui/save_pipe]
    rule: deny
  - groups: [editor]
    paths: [/gui/del_cmd, /gui/del_pipe, /gui/save_cmd, /gui/save_pipe]
    rule: allow
password:                       # Password settings.
  policy:                       # Password policy settings.
    enabled: true               # Specify whether or not to enable password policy.
    not_same_before: true       # Specify whether or not to allow the same password as the previous one.
    min_length: 16              # Specify the minimum length of the password.
    max_length: 64              # Specify the maximum length of the password.
    min_lowercase: 1            # Specify the minimum number of lowercase letters in the password.
    min_uppercase: 1            # Specify the minimum number of uppercase letters in the password.
    min_digit: 1                # Specify the minimum number of digits in the password.
    min_symbol: 1               # Specify the minimum number of symbol characters in the password.
    not_contain_username: true  # Specify whether or not to include the username in the password.
  expiration:                   # Password expiration settings.
    enabled: true               # Specify whether or not to enable password expiration.
    period: 90                  # Specify the number of days after which the password will expire.
    notify: 7                   # Specify the number of days before the password expires that a notification will be sent.
  lockout:                      # Account lockout settings.
    enabled: true               # Specify whether or not to enable account lockout.
    threshold: 5                # Specify the number of failed login attempts before the account is locked.
    reset: 30                   # Specify the number of minutes after which the failed login count will be reset.
apikey:
  gen_cert:                         # Specify whether to generate a certificate for API key.
    enabled: true                   # Specify whether to enable certificate generation for API key.
    privatekey: idp_private.pem     # Specify the destination file for the generated private key.
    certificate: idp_cert.pem       # Specify the destination file for the generated certificate.
    publickey: idp_public.pem       # Specify the destination file for the generated public key.
  gen_jwt:                          # Specify whether to generate JWT for API key.
    enabled: true                   # Specify whether to enable JWT generation for API key.
    privatekey: idp_private.pem     # Specify the private key file for JWT generation.
    privatekey_passphrase:          # Specify the passphrase for the private key file.
                                    # If the private key is encrypted, specify the passphrase here.
    algorithm: RS256                # Specify the algorithm used to generate the JWT. The value can be RS256, PS256, or ES256.
    claims:                         # Specify the claims to be included in the JWT.
      iss: identity_provider        # Specify the issuer of the JWT. This is usually the name of the identity provider.
      sub: app_user                 # Specify the subject of the JWT. This is usually the name of the application.
      aud: app_organization         # Specify the audience of the JWT. This is usually the name of the organization that will use the application.
      exp: 31536000                 # Specify the expiration time of the JWT in seconds. The default is 31536000 seconds (1 year).
  verify_jwt:                       # Specify whether to verify JWT for API key.
    enabled: true                   # Specify whether to enable JWT verification for API key.
    certificate: idp_cert.pem       # Specify the certificate file for JWT verification.
    publickey: idp_public.pem       # Specify the public key file for JWT verification. Not required if certificate exists.
    issuer: identity_provider       # Specify the issuer of the JWT. This is usually the name of the identity provider. (If not specified, no verification)
    audience: app_organization      # Specify the audience of the JWT. This is usually the name of the organization that will use the application. (If not specified, no verification)
    algorithm: RS256                # Specify the algorithm used to verify the JWT. The value can be RS256, PS256, or ES256.
oauth2:                             # OAuth2 settings.
  providers:                        # This is a per-provider setting for OAuth2.
    google:                         # Google's OAuth2 configuration.
      enabled: false                # Specify whether to enable Google's OAuth2.
      client_id: XXXXXXXXXXX        # Specify Google's OAuth2 client ID.
      client_secret: XXXXXXXXXXX    # Specify Google's OAuth2 client secret.
      redirect_uri: https://localhost:8443/oauth2/google/callback # Specify Google's OAuth2 redirect URI.
      scope: ['email']              # Specify the scope you want to retrieve with Google's OAuth2. Usually, just reading the email is sufficient.
      signin_module:                # Specify the module name that implements the sign-in.
        cmdbox.app.auth.google_signin
      note:                         # Specify a description such as Google's OAuth2 reference site.
      - https://developers.google.com/identity/protocols/oauth2/web-server?hl=ja#httprest
    github:                         # OAuth2 settings for GitHub.
      enabled: false                # Specify whether to enable OAuth2 for GitHub.
      client_id: XXXXXXXXXXX        # Specify the OAuth2 client ID for GitHub.
      client_secret: XXXXXXXXXXX    # Specify the GitHub OAuth2 client secret.
      redirect_uri: https://localhost:8443/oauth2/github/callback # Specify the OAuth2 redirect URI for GitHub.
      scope: ['user:email']         # Specify the scope you want to get from GitHub's OAuth2. Usually, just reading the email is sufficient.
      signin_module:                # Specify the module name that implements the sign-in.
        cmdbox.app.auth.github_signin
      note:                         # Specify a description, such as a reference site for OAuth2 on GitHub.
      - https://docs.github.com/ja/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#scopes
    azure:                          # OAuth2 settings for Azure AD.
      enabled: false                # Specify whether to enable OAuth2 for Azure AD.
      tenant_id: XXXXXXXXXXX        # Specify the tenant ID for Azure AD.
      client_id: XXXXXXXXXXX        # Specify the OAuth2 client ID for Azure AD.
      client_secret: XXXXXXXXXXX    # Specify the Azure AD OAuth2 client secret.
      redirect_uri: https://localhost:8443/oauth2/azure/callback # Specify the OAuth2 redirect URI for Azure AD.
      scope: ['openid', 'profile', 'email', 'https://graph.microsoft.com/mail.read']
      signin_module:                # Specify the module name that implements the sign-in.
        cmdbox.app.auth.azure_signin
      note:                         # Specify a description, such as a reference site for Azure AD's OAuth2.
      - https://learn.microsoft.com/ja-jp/entra/identity-platform/v2-oauth2-auth-code-flow
saml:                               # SAML settings.
  providers:                        # This is a per-provider setting for OAuth2.
    azure:                          # SAML settings for Azure AD.
      enabled: false                # Specify whether to enable SAML authentication for Azure AD.
      signin_module:                # Specify the module name that implements the sign-in.
        cmdbox.app.auth.azure_signin_saml # Specify the python3-saml configuration.
                                    # see) https://github.com/SAML-Toolkits/python3-saml
      sp:
        entityId: https://localhost:8443/
        assertionConsumerService:
          url: https://localhost:8443/saml/azure/callback
          binding: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
        attributeConsumingService: {}
        singleLogoutService:
          binding: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
        NameIDFormat: urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
        x509cert: ''
        privateKey: ''
      idp:
        entityId: https://sts.windows.net/{tenant-id}/
        singleSignOnService:
          url: https://login.microsoftonline.com/{tenant-id}/saml2
          binding: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
        x509cert: XXXXXXXXXXX
        singleLogoutService: {}
        certFingerprint: ''
        certFingerprintAlgorithm: sha1

```

- See the documentation for references to each file.
- Documentation is [here](https://hamacom2004jp.github.io/cmdbox/).


# Lisence

This project is licensed under the MIT License, see the LICENSE file for details

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/hamacom2004jp/cmdbox",
    "name": "cmdbox",
    "maintainer": "hamacom2004jp",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "hamacom2004jp@gmail.com",
    "keywords": "cli restapi redis fastapi",
    "author": "hamacom2004jp",
    "author_email": "hamacom2004jp@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/f7/51/f52bea7c2d055062b511e34999ab9ff170211353f6f525348c0e4ad1400d/cmdbox-0.6.2.3.tar.gz",
    "platform": null,
    "description": "# cmdbox (Command Development Application)\r\n\r\n- It is a command development application with a plugin mechanism.\r\n- Documentation is [here](https://hamacom2004jp.github.io/cmdbox/).\r\n- With cmdbox, you can easily implement commands with complex options.\r\n- The implemented commands can be called from the CLI / RESTAPI / Web / Edge screen.\r\n- The implemented commands can be executed on a remote server via redis.\r\n\r\n![cmdbox operation image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/orverview.drawio.png)\r\n\r\n# Install\r\n\r\n- Install cmdbox with the following command.\r\n- Also install the docker version of the redis server.\r\n\r\n```bash\r\ndocker run -p 6379:6379 --name redis -e REDIS_PASSWORD=password -it ubuntu/redis:latest\r\npip install cmdbox\r\ncmdbox -v\r\n```\r\n\r\n- When using SAML in web mode, install the modules with dependencies.\r\n```bash\r\npip install xmlsec==1.3.13 python3-saml\r\napt-get install -y pkg-config libxml2-dev libxmlsec1-dev libxmlsec1-openssl build-essential libopencv-dev\r\n```\r\n\r\n- When using `--agent use` in web mode, install the modules with dependencies.\r\n```bash\r\npip install google-adk litellm fastmcp\r\n```\r\n\r\n# Run\r\n\r\n- Run the cmdbox server.\r\n\r\n```bash\r\ncmdbox -m server -c start &\r\n```\r\n\r\n- Run the cmdbox web.\r\n\r\n```bash\r\ncmdbox -m web -c start --signin_file .cmdbox/user_list.yml &\r\n```\r\n\r\n- Run the cmdbox web with agent.\r\n- Below is an example of using Google vertexai.\r\n- Other available options include Azure OpenAI and Ollama.\r\n\r\n```bash\r\ncmdbox -m web -c start --signin_file .cmdbox/user_list.yml --agent use --llmprov vertexai --llmmodel gemini-2.0-flash --llmlocation us-central1 --llmsvaccountfile <account json file>\r\n```\r\n\r\n\r\n# Tutorial\r\n\r\n- Open the ```.sample/sample_project``` folder in the current directory with VSCode.\r\n\r\n![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme001.png)\r\n\r\n- Install dependent libraries.\r\n\r\n```bash\r\npython -m venv .venv\r\n. .venv/bin/activate\r\npip install -r requirements.txt\r\n```\r\n\r\n- Run the project.\r\n\r\n![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme002.png)\r\n\r\n- The localhost web screen will open.\r\n\r\n![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme003.png)\r\n\r\n- Enter ```user01 / user01``` for the initial ID and PW to sign in.\r\n- Using this web screen, you can easily execute the commands implemented in cmdbox.\r\n\r\n![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme004.png)\r\n\r\n- Let's look at the command to get a list of files as an example.\r\n- Press the plus button under Commands to open the Add dialog.\r\n- Then enter the following.\r\n\r\n![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme005.png)\r\n\r\n- Press the ```Save``` button once and then press the ```Execute``` button.\r\n- The results of the command execution are displayed.\r\n\r\n![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme006.png)\r\n\r\n- Open the saved ```client_time``` and press the ```Raw``` button.\r\n- You will see how to execute the same command on the command line; the RESTAPI URL is also displayed.\r\n\r\n![image](https://github.com/hamacom2004jp/cmdbox/raw/main/docs_src/static/ss/readme007.png)\r\n\r\n\r\n## How to implement a new command using cmdbox\r\n\r\n- Under the ```sample/app/features/cli``` folder, you will find an implementation of the ```sample_client_time``` mentioned earlier.\r\n- The implementation is as follows. (Slightly abbreviated display)\r\n- Create the following code and save it in the ```sample/app/features/cli``` folder.\r\n\r\n```python\r\nfrom cmdbox.app import common, feature\r\nfrom typing import Dict, Any, Tuple, Union, List\r\nimport argparse\r\nimport datetime\r\nimport logging\r\n\r\n\r\nclass ClientTime(feature.Feature):\r\n    def get_mode(self) -> Union[str, List[str]]:\r\n        return \"client\"\r\n\r\n    def get_cmd(self):\r\n        return 'time'\r\n\r\n    def get_option(self):\r\n        return dict(\r\n            type=Options.T_STR, default=None, required=False, multi=False, hide=False, use_redis=self.USE_REDIS_FALSE,\r\n            description_ja=\"\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u5074\u306e\u73fe\u5728\u6642\u523b\u3092\u8868\u793a\u3057\u307e\u3059\u3002\",\r\n            description_en=\"Displays the current time at the client side.\",\r\n            choice=[\r\n                dict(opt=\"timedelta\", type=Options.T_INT, default=9, required=False, multi=False, hide=False, choice=None,\r\n                        description_ja=\"\u6642\u5dee\u306e\u6642\u9593\u6570\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002\",\r\n                        description_en=\"Specify the number of hours of time difference.\"),\r\n            ])\r\n\r\n    def apprun(self, logger:logging.Logger, args:argparse.Namespace, tm:float, pf:List[Dict[str, float]]=[]) -> Tuple[int, Dict[str, Any], Any]:\r\n        tz = datetime.timezone(datetime.timedelta(hours=args.timedelta))\r\n        dt = datetime.datetime.now(tz)\r\n        ret = dict(success=dict(data=dt.strftime('%Y-%m-%d %H:%M:%S')))\r\n        common.print_format(ret, args.format, tm, args.output_json, args.output_json_append, pf=pf)\r\n        if 'success' not in ret:\r\n            return 1, ret, None\r\n        return 0, ret, None\r\n\r\n    def edgerun(self, opt, tool, logger, timeout, prevres = None):\r\n        status, res = tool.exec_cmd(opt, logger, timeout, prevres)\r\n        tool.notify(res)\r\n        yield 1, res\r\n```\r\n\r\n- If you want to implement server-side processing, please refer to ```sample_server_time```.\r\n\r\n```python\r\nfrom cmdbox.app import common, client, feature\r\nfrom cmdbox.app.commons import redis_client\r\nfrom cmdbox.app.options import Options\r\nfrom pathlib import Path\r\nfrom typing import Dict, Any, Tuple, Union, List\r\nimport argparse\r\nimport datetime\r\nimport logging\r\n\r\n\r\nclass ServerTime(feature.Feature):\r\n    def get_mode(self) -> Union[str, List[str]]:\r\n        return \"server\"\r\n\r\n    def get_cmd(self):\r\n        return 'time'\r\n\r\n    def get_option(self):\r\n        return dict(\r\n            type=Options.T_STR, default=None, required=False, multi=False, hide=False, use_redis=self.USE_REDIS_FALSE,\r\n            description_ja=\"\u30b5\u30fc\u30d0\u30fc\u5074\u306e\u73fe\u5728\u6642\u523b\u3092\u8868\u793a\u3057\u307e\u3059\u3002\",\r\n            description_en=\"Displays the current time at the server side.\",\r\n            choice=[\r\n                dict(opt=\"host\", type=Options.T_STR, default=self.default_host, required=True, multi=False, hide=True, choice=None,\r\n                        description_ja=\"Redis\u30b5\u30fc\u30d0\u30fc\u306e\u30b5\u30fc\u30d3\u30b9\u30db\u30b9\u30c8\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002\",\r\n                        description_en=\"Specify the service host of the Redis server.\"),\r\n                dict(opt=\"port\", type=Options.T_INT, default=self.default_port, required=True, multi=False, hide=True, choice=None,\r\n                        description_ja=\"Redis\u30b5\u30fc\u30d0\u30fc\u306e\u30b5\u30fc\u30d3\u30b9\u30dd\u30fc\u30c8\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002\",\r\n                        description_en=\"Specify the service port of the Redis server.\"),\r\n                dict(opt=\"password\", type=Options.T_STR, default=self.default_pass, required=True, multi=False, hide=True, choice=None,\r\n                        description_ja=\"Redis\u30b5\u30fc\u30d0\u30fc\u306e\u30a2\u30af\u30bb\u30b9\u30d1\u30b9\u30ef\u30fc\u30c9(\u4efb\u610f)\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002\u7701\u7565\u6642\u306f `password` \u3092\u4f7f\u7528\u3057\u307e\u3059\u3002\",\r\n                        description_en=\"Specify the access password of the Redis server (optional). If omitted, `password` is used.\"),\r\n                dict(opt=\"svname\", type=Options.T_STR, default=self.default_svname, required=True, multi=False, hide=True, choice=None,\r\n                        description_ja=\"\u30b5\u30fc\u30d0\u30fc\u306e\u30b5\u30fc\u30d3\u30b9\u540d\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002\u7701\u7565\u6642\u306f `server` \u3092\u4f7f\u7528\u3057\u307e\u3059\u3002\",\r\n                        description_en=\"Specify the service name of the inference server. If omitted, `server` is used.\"),\r\n                dict(opt=\"timedelta\", type=Options.T_INT, default=9, required=False, multi=False, hide=False, choice=None,\r\n                        description_ja=\"\u6642\u5dee\u306e\u6642\u9593\u6570\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002\",\r\n                        description_en=\"Specify the number of hours of time difference.\"),\r\n                dict(opt=\"retry_count\", type=Options.T_INT, default=3, required=False, multi=False, hide=True, choice=None,\r\n                        description_ja=\"Redis\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u518d\u63a5\u7d9a\u56de\u6570\u3092\u6307\u5b9a\u3057\u307e\u3059\u30020\u4ee5\u4e0b\u3092\u6307\u5b9a\u3059\u308b\u3068\u6c38\u9060\u306b\u518d\u63a5\u7d9a\u3092\u884c\u3044\u307e\u3059\u3002\",\r\n                        description_en=\"Specifies the number of reconnections to the Redis server.If less than 0 is specified, reconnection is forever.\"),\r\n                dict(opt=\"retry_interval\", type=Options.T_INT, default=5, required=False, multi=False, hide=True, choice=None,\r\n                        description_ja=\"Redis\u30b5\u30fc\u30d0\u30fc\u306b\u518d\u63a5\u7d9a\u307e\u3067\u306e\u79d2\u6570\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002\",\r\n                        description_en=\"Specifies the number of seconds before reconnecting to the Redis server.\"),\r\n                dict(opt=\"timeout\", type=Options.T_INT, default=\"15\", required=False, multi=False, hide=True, choice=None,\r\n                        description_ja=\"\u30b5\u30fc\u30d0\u30fc\u306e\u5fdc\u7b54\u304c\u8fd4\u3063\u3066\u304f\u308b\u307e\u3067\u306e\u6700\u5927\u5f85\u3061\u6642\u9593\u3092\u6307\u5b9a\u3002\",\r\n                        description_en=\"Specify the maximum waiting time until the server responds.\"),\r\n            ])\r\n\r\n    def get_svcmd(self):\r\n        return 'server_time'\r\n\r\n    def apprun(self, logger:logging.Logger, args:argparse.Namespace, tm:float, pf:List[Dict[str, float]]=[]) -> Tuple[int, Dict[str, Any], Any]:\r\n        cl = client.Client(logger, redis_host=args.host, redis_port=args.port, redis_password=args.password, svname=args.svname)\r\n        ret = cl.redis_cli.send_cmd(self.get_svcmd(), [str(args.timedelta)],\r\n                                    retry_count=args.retry_count, retry_interval=args.retry_interval, timeout=args.timeout)\r\n        common.print_format(ret, args.format, tm, args.output_json, args.output_json_append, pf=pf)\r\n        if 'success' not in ret:\r\n            return 1, ret, None\r\n        return 0, ret, None\r\n\r\n    def is_cluster_redirect(self):\r\n        return False\r\n\r\n    def svrun(self, data_dir:Path, logger:logging.Logger, redis_cli:redis_client.RedisClient, msg:List[str],\r\n              sessions:Dict[str, Dict[str, Any]]) -> int:\r\n        td = 9 if msg[2] == None else int(msg[2])\r\n        tz = datetime.timezone(datetime.timedelta(hours=td))\r\n        dt = datetime.datetime.now(tz)\r\n        ret = dict(success=dict(data=dt.strftime('%Y-%m-%d %H:%M:%S')))\r\n        redis_cli.rpush(msg[1], ret)\r\n        return self.RESP_SCCESS\r\n\r\n    def edgerun(self, opt, tool, logger, timeout, prevres = None):\r\n        status, res = tool.exec_cmd(opt, logger, timeout, prevres)\r\n        tool.notify(res)\r\n        yield 1, res\r\n```\r\n\r\n- Open the file ```sample/extensions/features.yml```. The file should look something like this.\r\n- This file specifies where new commands are to be read.\r\n- For example, if you want to add a package to read, add a new ```package``` and ```prefix``` to ```features.cli```.\r\n- Note that ```features.web``` can be used to add a new web screen.\r\n- If you only want to call commands added in ```features.cli``` via RESTAPI, no additional implementation is needed in ```features.web```.\r\n\r\n\r\n```yml\r\nfeatures:\r\n  cli:                                  # Specify a list of package names in which the module implementing the command is located.\r\n    - package: cmdbox.app.features.cli  # Package Name. Classes inheriting from cmdbox.app.feature.Feature.\r\n      prefix: cmdbox_                   # Module name prefix. Modules that begin with this letter are eligible.\r\n      exclude_modules: []               # Specify the module name to exclude from the list of modules to be loaded.\r\n  web:                                  # Specify a list of package names with modules that implement web screens and RESTAPIs.\r\n    - package: cmdbox.app.features.web  # Package Name. Classes inheriting from cmdbox.app.feature.WebFeature .\r\n      prefix: cmdbox_web_               # Module name prefix. Modules that begin with this letter are eligible.\r\nargs:                                   # Specifies default or forced arguments for the specified command.\r\n  cli:                                  # Specify rules to apply default values or force arguments.\r\n    - rule:                             # Specify the rules for applying default values and forced arguments for each command line option.\r\n                                        #   e.g. mode: web\r\n      default:                          # Specify a default value for each item to be set when a rule is matched.\r\n                                        #   e.g. doc_root: f\"{Path(self.ver.__file__).parent / 'web'}\"\r\n      coercion:                         # Specify a coercion value for each item to be set when a rule is matched.\r\n                                        #   e.g. doc_root: f\"{Path(self.ver.__file__).parent / 'web'}\"\r\naliases:                                # Specify the alias for the specified command.\r\n  cli:                                  # Specify the alias for the command line.\r\n    - source:                           # Specifies the command from which the alias originates.\r\n        mode:                           # Specify the mode of the source command. The exact match \"mode\" is selected.\r\n                                        #   e.g. client\r\n        cmd:                            # Specify the source command to be aliased. The regex match \"cmd\" is selected.\r\n                                        #   e.g. (.+)_(.+)\r\n      target:                           # Specifies the command to be aliased to.\r\n        mode:                           # Specify the mode of the target command. Create an alias for this \u201cmode\u201d.\r\n                                        #   e.g. CLIENT\r\n        cmd:                            # Specify the target command to be aliased. Create an alias for this \u201ccmd\u201d, referring to the regular expression group of source by \"{n}\".\r\n                                        #   e.g. {2}_{1}\r\n        move:                           # Specify whether to move the regular expression group of the source to the target.\r\n                                        #   e.g. true\r\n  web:                                  # Specify the alias for the RESTAPI.\r\n    - source:                           # Specifies the RESTAPI from which the alias originates.\r\n        path:                           # Specify the path of the source RESTAPI. The regex match \"path\" is selected.\r\n                                        #   e.g. /exec_(.+)\r\n      target:                           # Specifies the RESTAPI to be aliased to.\r\n        path:                           # Specify the path of the target RESTAPI. Create an alias for this \u201cpath\u201d, referring to the regular expression group of source by \"{n}\".\r\n                                        #   e.g. /{1}_exec\r\n        move:                           # Specify whether to move the regular expression group of the source to the target.\r\n                                        #   e.g. true\r\nagentrule:                              # Specifies a list of rules that determine which commands the agent can execute.\r\n  policy: deny                          # Specify the default policy for the rule. The value can be allow or deny.\r\n  rules:                                # Specify the rules for the commands that the agent can execute according to the group to which the user belongs.\r\n  - mode: audit                         # Specify the \"mode\" as the condition for applying the rule.\r\n    cmds: [search, write]               # Specify the \"cmd\" to which the rule applies. Multiple items can be specified in a list.\r\n    rule: allow                         # Specifies whether the specified command is allowed or not. Values are allow or deny.\r\n  - mode: client\r\n    cmds: [file_copy, file_download, file_list, file_mkdir, file_move, file_remove, file_rmdir, file_upload, server_info]\r\n    rule: allow\r\n  - mode: cmd\r\n    cmds: [list, load]\r\n    rule: allow\r\n  - mode: server\r\n    cmds: [list]\r\n    rule: allow\r\n  - mode: web\r\n    cmds: [gencert, genpass, group_list, user_list]\r\n    rule: allow\r\naudit:\r\n  enabled: true                         # Specify whether to enable the audit function.\r\n  write:\r\n    mode: audit                         # Specify the mode of the feature to be writed.\r\n    cmd: write                          # Specify the command to be writed.\r\n  search:\r\n    mode: audit                         # Specify the mode of the feature to be searched.\r\n    cmd: search                         # Specify the command to be searched.\r\n  options:                              # Specify the options for the audit function.\r\n    host: localhost                     # Specify the service host of the audit Redis server.However, if it is specified as a command line argument, it is ignored.\r\n    port: 6379                          # Specify the service port of the audit Redis server.However, if it is specified as a command line argument, it is ignored.\r\n    password: password                  # Specify the access password of the audit Redis server.However, if it is specified as a command line argument, it is ignored.\r\n    svname: cmdbox                      # Specify the audit service name of the inference server.However, if it is specified as a command line argument, it is ignored.\r\n    retry_count: 3                      # Specifies the number of reconnections to the audit Redis server.If less than 0 is specified, reconnection is forever.\r\n    retry_interval: 1                   # Specifies the number of seconds before reconnecting to the audit Redis server.\r\n    timeout: 15                         # Specify the maximum waiting time until the server responds.\r\n    pg_enabled: False                   # Specify True if using the postgresql database server.\r\n    pg_host: localhost                  # Specify the postgresql host.\r\n    pg_port: 5432                       # Specify the postgresql port.\r\n    pg_user: postgres                   # Specify the postgresql user name.\r\n    pg_password: password               # Specify the postgresql password.\r\n    pg_dbname: audit                    # Specify the postgresql database name.\r\n    retention_period_days: 365          # Specify the number of days to retain audit logs.\r\n\r\n```\r\n\r\n- The following files should also be known when using commands on the web screen or RESTAPI.\r\n- Open the file ```sample/extensions/user_list.yml```. The file should look something like this.\r\n- This file manages the users and groups that are allowed Web access and their rules.\r\n- The rule of the previous command is ```allow``` for users in the ```user``` group in ```cmdrule.rules```.\r\n\r\n\r\n```yml\r\nusers:                         # A list of users, each of which is a map that contains the following fields.\r\n- uid: 1                       # An ID that identifies a user. No two users can have the same ID.\r\n  name: admin                  # A name that identifies the user. No two users can have the same name.\r\n  password: XXXXX              # The user's password. The value is hashed with the hash function specified in the next hash field.\r\n  hash: plain                  # The hash function used to hash the password, which can be plain, md5, sha1, or sha256, or oauth2, or saml.\r\n  groups: [admin]              # A list of groups to which the user belongs, as specified in the groups field.\r\n  email: admin@aaa.bbb.jp      # The email address of the user, used when authenticating using the provider specified in the oauth2 or saml field.\r\n- uid: 101\r\n  name: user01\r\n  password: XXXXX\r\n  hash: md5\r\n  groups: [user]\r\n  email: user01@aaa.bbb.jp\r\n- uid: 102\r\n  name: user02\r\n  password: XXXXX\r\n  hash: sha1\r\n  groups: [readonly]\r\n  email: user02@aaa.bbb.jp\r\n- uid: 103\r\n  name: user03\r\n  password: XXXXX\r\n  hash: sha256\r\n  groups: [editor]\r\n  email: user03@aaa.bbb.jp\r\ngroups:                        # A list of groups, each of which is a map that contains the following fields.\r\n- gid: 1                       # An ID that identifies a group. No two groups can have the same ID.\r\n  name: admin                  # A name that identifies the group. No two groups can have the same name.\r\n- gid: 2\r\n  name: guest\r\n- gid: 101\r\n  name: user\r\n- gid: 102\r\n  name: readonly\r\n  parent: user                 # The parent group of the group. If the parent group is not specified, the group is a top-level group.\r\n- gid: 103\r\n  name: editor\r\n  parent: user\r\ncmdrule:                       # A list of command rules, Specify a rule that determines whether or not a command is executable when executed by a user in web mode.\r\n  policy: deny                 # Specify the default policy for the rule. The value can be allow or deny.\r\n  rules:                       # Specify rules to allow or deny execution of the command, depending on the group the user belongs to.\r\n  - groups: [admin]\r\n    rule: allow\r\n  - groups: [user]             # Specify the groups to which the rule applies.\r\n    mode: client               # Specify the \"mode\" as the condition for applying the rule.\r\n    cmds: [file_download, file_list, server_info] # Specify the \"cmd\" to which the rule applies. Multiple items can be specified in a list.\r\n    rule: allow                # Specifies whether or not the specified command is allowed for the specified group. The value can be allow or deny.\r\n  - groups: [user]\r\n    mode: server\r\n    cmds: [list]\r\n    rule: allow\r\n  - groups: [user]\r\n    mode: cmd\r\n    cmds: [list, load]\r\n    rule: allow\r\n  - groups: [user, guest]\r\n    mode: audit\r\n    cmds: [write]\r\n    rule: allow\r\n  - groups: [user, guest]\r\n    mode: web\r\n    cmds: [genpass]\r\n    rule: allow\r\n  - groups: [editor]\r\n    mode: client\r\n    cmds: [file_copy, file_mkdir, file_move, file_remove, file_rmdir, file_upload]\r\n    rule: allow\r\npathrule:                      # List of RESTAPI rules, rules that determine whether or not a RESTAPI can be executed when a user in web mode accesses it.\r\n  policy: deny                 # Specify the default policy for the rule. The value can be allow or deny.\r\n  rules:                       # Specify rules to allow or deny execution of the RESTAPI, depending on the group the user belongs to.\r\n  - groups: [admin]            # Specify the groups to which the rule applies.\r\n    paths: [/]                 # Specify the \"path\" to which the rule applies. Multiple items can be specified in a list.\r\n    rule: allow                # Specifies whether or not the specified RESTAPI is allowed for the specified group. The value can be allow or deny.\r\n  - groups: [guest]\r\n    paths: [/signin, /assets, /copyright, /dosignin, /dosignout, /password/change,\r\n            /gui, /get_server_opt, /usesignout, /versions_cmdbox, /versions_used]\r\n    rule: allow\r\n  - groups: [user]\r\n    paths: [/signin, /assets, /bbforce_cmd, /copyright, /dosignin, /dosignout, /password/change,\r\n            /gui/user_data/load, /gui/user_data/save, /gui/user_data/delete,\r\n            /agent, /mcpsv,\r\n            /exec_cmd, /exec_pipe, /filer, /result, /gui, /get_server_opt, /usesignout, /versions_cmdbox, /versions_used]\r\n    rule: allow\r\n  - groups: [readonly]\r\n    paths: [/gui/del_cmd, /gui/del_pipe, /gui/save_cmd, /gui/save_pipe]\r\n    rule: deny\r\n  - groups: [editor]\r\n    paths: [/gui/del_cmd, /gui/del_pipe, /gui/save_cmd, /gui/save_pipe]\r\n    rule: allow\r\npassword:                       # Password settings.\r\n  policy:                       # Password policy settings.\r\n    enabled: true               # Specify whether or not to enable password policy.\r\n    not_same_before: true       # Specify whether or not to allow the same password as the previous one.\r\n    min_length: 16              # Specify the minimum length of the password.\r\n    max_length: 64              # Specify the maximum length of the password.\r\n    min_lowercase: 1            # Specify the minimum number of lowercase letters in the password.\r\n    min_uppercase: 1            # Specify the minimum number of uppercase letters in the password.\r\n    min_digit: 1                # Specify the minimum number of digits in the password.\r\n    min_symbol: 1               # Specify the minimum number of symbol characters in the password.\r\n    not_contain_username: true  # Specify whether or not to include the username in the password.\r\n  expiration:                   # Password expiration settings.\r\n    enabled: true               # Specify whether or not to enable password expiration.\r\n    period: 90                  # Specify the number of days after which the password will expire.\r\n    notify: 7                   # Specify the number of days before the password expires that a notification will be sent.\r\n  lockout:                      # Account lockout settings.\r\n    enabled: true               # Specify whether or not to enable account lockout.\r\n    threshold: 5                # Specify the number of failed login attempts before the account is locked.\r\n    reset: 30                   # Specify the number of minutes after which the failed login count will be reset.\r\napikey:\r\n  gen_cert:                         # Specify whether to generate a certificate for API key.\r\n    enabled: true                   # Specify whether to enable certificate generation for API key.\r\n    privatekey: idp_private.pem     # Specify the destination file for the generated private key.\r\n    certificate: idp_cert.pem       # Specify the destination file for the generated certificate.\r\n    publickey: idp_public.pem       # Specify the destination file for the generated public key.\r\n  gen_jwt:                          # Specify whether to generate JWT for API key.\r\n    enabled: true                   # Specify whether to enable JWT generation for API key.\r\n    privatekey: idp_private.pem     # Specify the private key file for JWT generation.\r\n    privatekey_passphrase:          # Specify the passphrase for the private key file.\r\n                                    # If the private key is encrypted, specify the passphrase here.\r\n    algorithm: RS256                # Specify the algorithm used to generate the JWT. The value can be RS256, PS256, or ES256.\r\n    claims:                         # Specify the claims to be included in the JWT.\r\n      iss: identity_provider        # Specify the issuer of the JWT. This is usually the name of the identity provider.\r\n      sub: app_user                 # Specify the subject of the JWT. This is usually the name of the application.\r\n      aud: app_organization         # Specify the audience of the JWT. This is usually the name of the organization that will use the application.\r\n      exp: 31536000                 # Specify the expiration time of the JWT in seconds. The default is 31536000 seconds (1 year).\r\n  verify_jwt:                       # Specify whether to verify JWT for API key.\r\n    enabled: true                   # Specify whether to enable JWT verification for API key.\r\n    certificate: idp_cert.pem       # Specify the certificate file for JWT verification.\r\n    publickey: idp_public.pem       # Specify the public key file for JWT verification. Not required if certificate exists.\r\n    issuer: identity_provider       # Specify the issuer of the JWT. This is usually the name of the identity provider. (If not specified, no verification)\r\n    audience: app_organization      # Specify the audience of the JWT. This is usually the name of the organization that will use the application. (If not specified, no verification)\r\n    algorithm: RS256                # Specify the algorithm used to verify the JWT. The value can be RS256, PS256, or ES256.\r\noauth2:                             # OAuth2 settings.\r\n  providers:                        # This is a per-provider setting for OAuth2.\r\n    google:                         # Google's OAuth2 configuration.\r\n      enabled: false                # Specify whether to enable Google's OAuth2.\r\n      client_id: XXXXXXXXXXX        # Specify Google's OAuth2 client ID.\r\n      client_secret: XXXXXXXXXXX    # Specify Google's OAuth2 client secret.\r\n      redirect_uri: https://localhost:8443/oauth2/google/callback # Specify Google's OAuth2 redirect URI.\r\n      scope: ['email']              # Specify the scope you want to retrieve with Google's OAuth2. Usually, just reading the email is sufficient.\r\n      signin_module:                # Specify the module name that implements the sign-in.\r\n        cmdbox.app.auth.google_signin\r\n      note:                         # Specify a description such as Google's OAuth2 reference site.\r\n      - https://developers.google.com/identity/protocols/oauth2/web-server?hl=ja#httprest\r\n    github:                         # OAuth2 settings for GitHub.\r\n      enabled: false                # Specify whether to enable OAuth2 for GitHub.\r\n      client_id: XXXXXXXXXXX        # Specify the OAuth2 client ID for GitHub.\r\n      client_secret: XXXXXXXXXXX    # Specify the GitHub OAuth2 client secret.\r\n      redirect_uri: https://localhost:8443/oauth2/github/callback # Specify the OAuth2 redirect URI for GitHub.\r\n      scope: ['user:email']         # Specify the scope you want to get from GitHub's OAuth2. Usually, just reading the email is sufficient.\r\n      signin_module:                # Specify the module name that implements the sign-in.\r\n        cmdbox.app.auth.github_signin\r\n      note:                         # Specify a description, such as a reference site for OAuth2 on GitHub.\r\n      - https://docs.github.com/ja/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#scopes\r\n    azure:                          # OAuth2 settings for Azure AD.\r\n      enabled: false                # Specify whether to enable OAuth2 for Azure AD.\r\n      tenant_id: XXXXXXXXXXX        # Specify the tenant ID for Azure AD.\r\n      client_id: XXXXXXXXXXX        # Specify the OAuth2 client ID for Azure AD.\r\n      client_secret: XXXXXXXXXXX    # Specify the Azure AD OAuth2 client secret.\r\n      redirect_uri: https://localhost:8443/oauth2/azure/callback # Specify the OAuth2 redirect URI for Azure AD.\r\n      scope: ['openid', 'profile', 'email', 'https://graph.microsoft.com/mail.read']\r\n      signin_module:                # Specify the module name that implements the sign-in.\r\n        cmdbox.app.auth.azure_signin\r\n      note:                         # Specify a description, such as a reference site for Azure AD's OAuth2.\r\n      - https://learn.microsoft.com/ja-jp/entra/identity-platform/v2-oauth2-auth-code-flow\r\nsaml:                               # SAML settings.\r\n  providers:                        # This is a per-provider setting for OAuth2.\r\n    azure:                          # SAML settings for Azure AD.\r\n      enabled: false                # Specify whether to enable SAML authentication for Azure AD.\r\n      signin_module:                # Specify the module name that implements the sign-in.\r\n        cmdbox.app.auth.azure_signin_saml # Specify the python3-saml configuration.\r\n                                    # see) https://github.com/SAML-Toolkits/python3-saml\r\n      sp:\r\n        entityId: https://localhost:8443/\r\n        assertionConsumerService:\r\n          url: https://localhost:8443/saml/azure/callback\r\n          binding: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\r\n        attributeConsumingService: {}\r\n        singleLogoutService:\r\n          binding: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\r\n        NameIDFormat: urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\r\n        x509cert: ''\r\n        privateKey: ''\r\n      idp:\r\n        entityId: https://sts.windows.net/{tenant-id}/\r\n        singleSignOnService:\r\n          url: https://login.microsoftonline.com/{tenant-id}/saml2\r\n          binding: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\r\n        x509cert: XXXXXXXXXXX\r\n        singleLogoutService: {}\r\n        certFingerprint: ''\r\n        certFingerprintAlgorithm: sha1\r\n\r\n```\r\n\r\n- See the documentation for references to each file.\r\n- Documentation is [here](https://hamacom2004jp.github.io/cmdbox/).\r\n\r\n\r\n# Lisence\r\n\r\nThis project is licensed under the MIT License, see the LICENSE file for details\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "cmdbox: It is a command line application with a plugin mechanism.",
    "version": "0.6.2.3",
    "project_urls": {
        "Download": "https://github.com/hamacom2004jp/cmdbox",
        "Homepage": "https://github.com/hamacom2004jp/cmdbox"
    },
    "split_keywords": [
        "cli",
        "restapi",
        "redis",
        "fastapi"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "55f3789d77ca7b86145238f50f99456aed31c9d53aa16fc5116924c4ae08f83c",
                "md5": "57ca47eaf357c4ff1057d300ab6c4358",
                "sha256": "1c54fe5d3aaef2cd915a0047f9fa59e38380532191e8d333409f21559b73d521"
            },
            "downloads": -1,
            "filename": "cmdbox-0.6.2.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "57ca47eaf357c4ff1057d300ab6c4358",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 2264216,
            "upload_time": "2025-07-13T04:25:53",
            "upload_time_iso_8601": "2025-07-13T04:25:53.377645Z",
            "url": "https://files.pythonhosted.org/packages/55/f3/789d77ca7b86145238f50f99456aed31c9d53aa16fc5116924c4ae08f83c/cmdbox-0.6.2.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f751f52bea7c2d055062b511e34999ab9ff170211353f6f525348c0e4ad1400d",
                "md5": "54c896135a55e95c239f92481c19553d",
                "sha256": "cc0d20c1acf79283ef2bd22ad6b28d25c9a8a526ed3527f923162f34f690243c"
            },
            "downloads": -1,
            "filename": "cmdbox-0.6.2.3.tar.gz",
            "has_sig": false,
            "md5_digest": "54c896135a55e95c239f92481c19553d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 1890521,
            "upload_time": "2025-07-13T04:25:55",
            "upload_time_iso_8601": "2025-07-13T04:25:55.108145Z",
            "url": "https://files.pythonhosted.org/packages/f7/51/f52bea7c2d055062b511e34999ab9ff170211353f6f525348c0e4ad1400d/cmdbox-0.6.2.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-13 04:25:55",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "hamacom2004jp",
    "github_project": "cmdbox",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "argcomplete",
            "specs": []
        },
        {
            "name": "async-timeout",
            "specs": []
        },
        {
            "name": "collectlicense",
            "specs": []
        },
        {
            "name": "cryptography",
            "specs": []
        },
        {
            "name": "fastapi",
            "specs": []
        },
        {
            "name": "gevent",
            "specs": []
        },
        {
            "name": "gunicorn",
            "specs": []
        },
        {
            "name": "itsdangerous",
            "specs": []
        },
        {
            "name": "numpy",
            "specs": []
        },
        {
            "name": "Pillow",
            "specs": []
        },
        {
            "name": "python-multipart",
            "specs": []
        },
        {
            "name": "pycryptodome",
            "specs": []
        },
        {
            "name": "plyer",
            "specs": []
        },
        {
            "name": "psycopg",
            "specs": []
        },
        {
            "name": "pyjwt",
            "specs": []
        },
        {
            "name": "pystray",
            "specs": []
        },
        {
            "name": "questionary",
            "specs": []
        },
        {
            "name": "redis",
            "specs": []
        },
        {
            "name": "requests",
            "specs": []
        },
        {
            "name": "rich",
            "specs": []
        },
        {
            "name": "six",
            "specs": []
        },
        {
            "name": "sphinx",
            "specs": []
        },
        {
            "name": "sphinx-rtd-theme",
            "specs": []
        },
        {
            "name": "sphinx_fontawesome",
            "specs": []
        },
        {
            "name": "sphinx-intl",
            "specs": []
        },
        {
            "name": "sphinx-sitemap",
            "specs": []
        },
        {
            "name": "tabulate",
            "specs": []
        },
        {
            "name": "twine",
            "specs": []
        },
        {
            "name": "uvicorn",
            "specs": []
        },
        {
            "name": "wheel",
            "specs": []
        }
    ],
    "lcname": "cmdbox"
}
        
Elapsed time: 0.49015s