From 27e8ec1f1698b19490ca941f822438b115bf3c8e Mon Sep 17 00:00:00 2001 From: Dhaval D <343411+ossdhaval@users.noreply.github.com> Date: Thu, 15 Feb 2024 01:33:08 +0530 Subject: [PATCH] docs(jans-cli): update cli readme (#7730) * docs(config-cli): add install and config sections Signed-off-by: ossdhaval <343411+ossdhaval@users.noreply.github.com> * docs(config-cli): update tasks and op-id sections Signed-off-by: ossdhaval <343411+ossdhaval@users.noreply.github.com> * docs(config-cli): update CLI README with diagram and content Signed-off-by: ossdhaval <343411+ossdhaval@users.noreply.github.com> --------- Signed-off-by: ossdhaval <343411+ossdhaval@users.noreply.github.com> Co-authored-by: Mohammad Abudayyeh <47318409+moabu@users.noreply.github.com> --- .../config-tools/jans-cli/README.md | 329 +++++++++--------- docs/assets/jans-cli-structure.png | Bin 0 -> 31213 bytes 2 files changed, 163 insertions(+), 166 deletions(-) create mode 100644 docs/assets/jans-cli-structure.png diff --git a/docs/admin/config-guide/config-tools/jans-cli/README.md b/docs/admin/config-guide/config-tools/jans-cli/README.md index b845ac54206..6431ce9c85e 100644 --- a/docs/admin/config-guide/config-tools/jans-cli/README.md +++ b/docs/admin/config-guide/config-tools/jans-cli/README.md @@ -9,22 +9,75 @@ tags: # Janssen CLI -`jans-cli` module is a command line interface for configuring the Janssen software, providing both interactive and simple single line options for configuration. This module interacts with Janssen server via RESTful configuration APIs that server exposes. Using these REST APIs, `jans-cli` allows configuration of authorization server and its major modules for FIDO2, SCIM, OpenID Connect etc. -
-
+`jans-cli` module is a command line interface for configuring the Janssen +Server. This module interacts with Janssen Server via +[RESTful configuration APIs](./config-api/README.md) +that server exposes. `jans-cli` can be used to retrieve and update configuration +of Janssen Server. -

- -

+## Installation -Using this mode is more difficult than the TUI. If needed, help options are available by typing: +### On The Janssen Server +On a Janssen Server instance, the `jans-cli` will be already installed. + +It can be invoked executing following command on Janssen Server. + +```shell +/opt/jans/jans-cli/config-cli.py ``` -/opt/jans/jans-cli/config-cli.py --help -``` -It will print all information about how to configure Janssen Server using CLI mode: +### Stand-alone Installation + +`jans-cli` can be installed on any other machine and then use it to configure +remote server where Janssen Server is installed. + +- Follow [these instructions](../jans-tui/README.md#1-build-pyz-self-executable-file) and create a self-executable file +- Run the file as shown in the example below to enter CLI mode. Here, supplying the argument `--no-tui` is necessary, + otherwise it will switch to TUI mode. + ``` + $ ./jans-cli-tui.pyz --no-tui --host test.jans.io --client-id 2000.562981df-1623-4136-b1d0-aaa277edc48c --client-secret KU6ydImJZK6S --operation-id get-acrs + Please wait while retrieving data ... + Access token was not found. + Please visit verification url https://test.jans.io/device-code?user_code=LKHC-PBTR and authorize this device within 1800 secods + Please press «Enter» when ready + { + "defaultAcr": "simple_password_auth" + } + ``` + +## CLI Tool Configuration + +Janssen CLI tool stores its configuration under `/.config` +directory. Various settings for CLI tool can be found under this directory, +for example [logging levels](../../../../contribute/developer-faq.md#how-to-enable-debug-logs-for-jans-cli-and-tui-configuration-tools). + +This directory also contains SALT used by Janssen CLI tool. + +### CLI Authorization +To run operations on Janssen Server, CLI client will need to be authenticated and authorized by the server. Since CLI has limited input capabilities, it uses [Device Authorization Grant](https://datatracker.ietf.org/doc/html/rfc8628) flow to get required permissions in form of an access token. After successfully receiving the token, CLI can run operations on the Janssen server while the token is valid. The steps below will summarize this process. +1. Execution of CLI command will return the following message if a valid token is not found. + ``` + Access token was not found. + Please visit verification url and enter user code CGFZ-RTZR in 1800 seconds + Please press <> when ready + ``` +2. Take `` from the message above and use any browser to access it from a different device +3. User will be presented with a page where the user has to authenticate using id and password +4. After successful user authentication, the next screen allows the user to enter the user code. Use the user code presented on command-line instruction in step 1 above. +5. After successful code validation, the user is presented with OAuth permissions screen. This screen would list all the permissions requested by Jans CLI. The user can choose to `Allow` or `Not Allow` granting of these permissions. +6. After allowing the grant of requested permissions, the user should come back to the command-line interface and hit <> as instructed. This will enable CLI to run operations on the corresponding Janssen server. + +## Getting Help + +CLI `--help` switch prints all options available from CLI to configure Janssen +Server. Run command below + +```shell +/opt/jans/jans-cli/config-cli.py --help +``` +To see all options as below: ``` usage: config-cli.py [-h] [--host HOST] [--client-id CLIENT_ID] [--client_secret CLIENT_SECRET] [--plugins PLUGINS] [-debug] @@ -82,156 +135,133 @@ optional arguments: --output-access-token Prints jwt access token and exits root@testjans:~# ``` -We start with getting information about tasks, tasks are options of argument `--info`: -``` -Attribute, CacheConfiguration, CacheConfigurationInMemory, CacheConfigurationMemcached, CacheConfigurationNativePersistence, CacheConfigurationRedis, ConfigurationFido2, ConfigurationJWKJSONWebKeyJWK, ConfigurationLogging, ConfigurationProperties, ConfigurationSMTP, CustomScripts, DatabaseCouchbaseConfiguration, DatabaseLDAPConfiguration, DefaultAuthenticationMethod, OAuthOpenIDConnectClients, OAuthOpenIDConnectSectorIdentifiers, OAuthScopes, OAuthUMAResources -``` +## CLI Command Structure -To get information for a specific task we run command as below: -``` -/opt/jans/jans-cli/config-cli.py --info [task] -``` -for example: -``` -/opt/jans/jans-cli/config-cli.py --info DefaultAuthenticationMethod -``` +CLI operations are structurally grouped by `Operation Modes` and within +these modes, they are logically grouped together by tasks. Diagram below +depicts this structure. -It returns with some `operation id`: -``` -Operation ID: get-acrs - Description: Gets default authentication method. -Operation ID: put-acrs - Description: Updates default authentication method. - Schema: /components/schemas/AuthenticationMethod +![](../../../../assets/jans-cli-structure.png) -To get sample shema type /opt/jans/jans-cli/config-cli.py --schema , for example /opt/jans/jans-cli/config-cli.py --schema /components/schemas/AuthenticationMethod -``` -To perform any operation, you have to run command line with the operation id. for example: +### Operation Modes -``` -/opt/jans/jans-cli/config-cli.py --operation-id get-acrs -``` -It returns: +CLI offer three operation modes, JCA, SCIM and AUTH. JCA is the default mode. +To use SCIM and AUTH modes, the CLI command specifies `-scim` or `-auth` +switches. Use `-h` switch to get help on each mode. -```text -Getting access token for scope https://jans.io/oauth/config/acrs.readonly -{ - "defaultAcr": "simple_password_auth" -} +```shell +/opt/jans/jans-cli/config-cli.py -scim -h ``` -This is how we can execute single line command to get information about the Janssen Server. +The modes usually have different task(and hence operations). -## Operation Modes -Default operation mode is **jca**, i.e., all queries are done to Jans Config Api Server. CLI has also SCIM and OAUTH modes: -### SCIM Mode -To switch SCIM mode user `-scim` switch. For example to get help for SCIM mode: +### Tasks +`Tasks` are logical grouping of operation-ids so that users can easily list +all the operational-ids relevant to a particular aspect of Janssen Server +configuration using `--info` switch. For instance, +all the operation-ids related to attribute management are grouped under +`attribute` task. As mentioned, tasks are logical groupings, they don't perform +any operation on the server. Tasks can only be used with `--info` switch. -`/opt/jans/jans-cli/config-cli.py -scim -h` - -Only `--info` arguments will be different from **jca** mode: +Execute following command to see what all tasks are offered by jans-cli: +```shell +/opt/jans/jans-cli/config-cli.py --help ``` ---info {Discovery,Fido2Devices,FidoDevices,GlobalSearch,Group,User} + +Options listed for `--info` switch are tasks groups available. For example: + +```shell +usage: config-cli.py [-h] [--host HOST] [--client-id CLIENT_ID] [--client-secret CLIENT_SECRET] [--access-token ACCESS_TOKEN] [--plugins PLUGINS] + [-debug] [--debug-log-file DEBUG_LOG_FILE] [--operation-id OPERATION_ID] [--url-suffix URL_SUFFIX] + [--info {AdminUiLicense,AdminUiPermission,AdminUiRole,AdminUiRolePermissionsMapping,AdminUiWebhooks,Agama,AgamaConfiguration,Attribute,AuthServerHealthCheck,AuthSessionManagement,CacheConfiguration,CacheConfigurationInMemory,CacheConfigurationMemcached,CacheConfigurationNativePersistence,CacheConfigurationRedis,ClientAuthorization,ConfigurationConfigApi,ConfigurationJwkJsonWebKeyJwk,ConfigurationLogging,ConfigurationProperties,ConfigurationSmtp,ConfigurationUserManagement,CustomScripts,DatabaseLdapConfiguration,DefaultAuthenticationMethod,Fido2Configuration,Fido2Registration,HealthCheck,JansLinkConfiguration,MessageConfiguration,MessageConfigurationPostgres,MessageConfigurationRedis,OauthOpenidConnectClients,OauthScopes,OauthUmaResources,OrganizationConfiguration,Plugins,SamlConfiguration,SamlIdentityBroker,SamlTrustRelationship,ScimConfigManagement,StatisticsUser}] + [--op-mode {get,post,put,patch,delete}] [--endpoint-args ENDPOINT_ARGS] [--schema SCHEMA] [-CC CONFIG_API_MTLS_CLIENT_CERT] + [-CK CONFIG_API_MTLS_CLIENT_KEY] [--key-password KEY_PASSWORD] [-noverify] [-use-test-client] [--patch-add PATCH_ADD] + [--patch-replace PATCH_REPLACE] [--patch-remove PATCH_REMOVE] [-no-color] [--log-dir LOG_DIR] [--tmp-dir TMP_DIR] + [-revoke-session] [-scim] [-auth] [--data DATA] [--output-access-token] ``` -You can get information about operation `Discovery`: +To see operation-id available under a task, execute the command below with +the task name as an argument: +```shell +/opt/jans/jans-cli/config-cli.py --info Attribute ``` -/opt/jans/jans-cli/config-cli.py -scim --info Fido2Devices -Operation ID: get-fido2-devices - Description: Query Fido 2 resources + +Above will list all the operations under `Attribute` group. + +```shell +Operation ID: get-attributes + Description: Gets a list of Jans attributes. Parameters: - attributes: A comma-separated list of attribute names to return in the response [string] - excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] - userId: Used to restrict the search to fido 2 resources owned by a specific user [string] - filter: An expression specifying the search criteria. See section 3.4.2.2 of RFC 7644 [string] + limit: Search size - max size of the results to return [integer] + pattern: Search pattern [string] + status: Status of the attribute [string] startIndex: The 1-based index of the first query result [integer] - count: Specifies the desired maximum number of query results per page [integer] - sortBy: The attribute whose value will be used to order the returned responses [string] + sortBy: Attribute whose value will be used to order the returned response [string] sortOrder: Order in which the sortBy param is applied. Allowed values are "ascending" and "descending" [string] -Operation ID: get-fido2-device-by-id - Description: Retrieves a Fido 2 device by Id + fieldValuePair: Field and value pair for seraching [string] +Operation ID: put-attributes + Description: Updates an existing attribute + Schema: JansAttribute +Operation ID: post-attributes + Description: Adds a new attribute + Schema: JansAttribute +Operation ID: get-attributes-by-inum + Description: Gets an attribute based on inum Parameters: - attributes: A comma-separated list of attribute names to return in the response [string] - excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] - userId: Identifier (inum) of the device owner. This param is not required when underlying database is LDAP [string] - id: No description is provided for this parameter [string] -Operation ID: update-fido2-device-by-id - Description: Updates a Fido 2 resource. Update works in a replacement fashion&#58; every attribute value found in the payload sent will replace the one in the existing resource representation. Attributes not passed in the payload will be left intact. - + inum: Attribute Id [string] +Operation ID: delete-attributes-by-inum + Description: Deletes an attribute based on inum Parameters: - attributes: A comma-separated list of attribute names to return in the response [string] - excludedAttributes: When specified, the response will contain a default set of attributes minus those listed here (as a comma-separated list) [string] - id: No description is provided for this parameter [string] - Schema: Fido2DeviceResource - Schema: Fido2DeviceResource -Operation ID: delete-fido2-device-by-id - Description: Deletes a Fido 2 resource + inum: Attribute Id [string] +Operation ID: patch-attributes-by-inum + Description: Partially modify a JansAttribute Parameters: - id: Identifier of the resource to delete [string] -Operation ID: search-fido2-device - Description: Query Fido 2 resources - Parameters: - userId: Used to restrict the search to fido 2 resources owned by a specific user [string] - Schema: SearchRequest - Schema: SearchRequest - -To get sample schema type /opt/jans/jans-cli/config-cli.py -scim --schema , for example /opt/jans/jans-cli/config-cli.py -scim --schema SearchRequest + inum: Attribute Id [string] + Schema: Array of PatchRequest ``` +### Operation-ids +jans-cli's unit of work, or a command, is known as `operation-id`. Each +operation id is a configuration retrieval/update action on the Janssen Server. +For example: `get-attributes` is an operation that `Gets a list of Janssen +Server attributes`. -Here is how you can get sample schema for **SearchRequest**: +To perform any operation, you have to run command line with the operation id. +For example: -``` -/opt/jans/jans-cli/config-cli.py -scim --schema SearchRequest -{ - "schemas": [ - "string" - ], - "attributes": [ - "string" - ], - "excludedAttributes": [ - "string" - ], - "filter": "userName eq \"jhon\" and meta.lastModified gt \"2011-05-13T04:42:34Z\"", - "sortBy": "string", - "sortOrder": "string", - "startIndex": 143, - "count": 58 -} +```shell +/opt/jans/jans-cli/config-cli.py --operation-id get-acrs ``` -### AUTH Mode -To switch AUTH mode user `-auth` switch. For example to get help for AUTH mode: - -`/opt/jans/jans-cli/config-cli.py -auth -h` - -`--info` arguments will be: +It returns: -``` ---info {Authorization,ClientInfo,ClientRegistration,FidoU2F,JwkJsonWebKeySetJwks,Registration,ServerConfiguration,SessionManagement,Ssa,Token,TokenIntrospection,Uma2Resource,UmaScope,UmaUserManagedAccess,UserInfo} +```text +Getting access token for scope https://jans.io/oauth/config/acrs.readonly +{ + "defaultAcr": "simple_password_auth" +} ``` -To get information about operation `ClientRegistration`: +Certain operations need data to be able to execute while for others just the +operation id is enough. For instance in above example `get-acrs` operation did +not require any data to be passed and worked only with operation id. While +operations like `delete-attributes-by-inum`, `post-attributes` need additional +data to be able to execute. For example, for `delete-attributes-by-inum` to +execute, it needs to know the `inum` of the attribute to be deleted. -``` -/opt/jans/jans-cli/config-cli.py -auth --info ClientInfo -Operation ID: get_clientinfo - Description: The ClientInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the registered client. - Parameters: - access_token: No description is provided for this parameter [string] - Authorization: No description is provided for this parameter [string] -Operation ID: post_clientinfo - Description: The ClientInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the registered client. - Parameters: - Authorization: No description is provided for this parameter [string] - Parameters: - access_token*: Client-specific access token. -``` +For operations which need data the data elements are +passed to the operation in form of `parameters` and/or `schema`. +Operation description provided by `--info` switch details out what parameters +and schemas are applicable to each operation. +`Parameters` allow simple string based values to be passed to the operation, +while `schema` allows JSON structured data to be passed to the operation. +For examples of how operations can be used with parameters and schema, refer to +[Attribute](../../attribute-configuration.md). Read more about schema in [this +detail section](#about-schemas). ## Basic command-line switches @@ -241,8 +271,11 @@ Operation ID: post_clientinfo 4. `--endpoint-args` advanced usage for operation-id 5. `--data` usage to share data in operations +## About Schemas + -## Patch Request (schema) + +### Patch Request (schema) This schema file can be found in `/components/schemas/PatchRequest` for those which one support this operation. @@ -252,7 +285,7 @@ When you examine this sample schema, you will see three properties in an object: * __path__: Path of the property to be changed. use path separator `/` for config or `.` for SCIM to change a property inside an object. * __value__: New value to be assigned for each property defined in `path` -## Multiple Patch Request (schema) +### Multiple Patch Request (schema) When we need to perform multiple patch operations on any configuration endpoint, Instead of doing one by one, we can create a json file including all individual operation into an array. To clarify, please see below json file: @@ -293,7 +326,7 @@ After creating the json file, just run the patch operation command. /opt/jans/jans-cli/config-cli.py --operation-id [patch operation id name] --data [json file absolute url] ``` -## Quick Patch Operations +### Quick Patch Operations There is another patch request feature. It is a single line patch-request command line. It supports three types of operations: @@ -322,41 +355,5 @@ Multi valued arguments can be privede as `key:value1,key:vlaue2`, for example ``` /opt/jans/jans-cli/config-cli.py --operation-id=get-config-scripts --endpoint-args="fieldValuePair:scriptType=dynamic_scope,fieldValuePair:level=100" ``` -## CLI Authorization -To run operations on Janssen Server, CLI client will need to be authenticated and authorized by the server. Since CLI has limited input capabilities, it uses [Device Authorization Grant](https://datatracker.ietf.org/doc/html/rfc8628) flow to get required permissions in form of an access token. After successfully receiving the token, CLI can run operations on the Janssen server while the token is valid. The steps below will summarize this process. -1. Execution of CLI command will return the following message if a valid token is not found. - ``` - Access token was not found. - Please visit verification url and enter user code CGFZ-RTZR in 1800 seconds - Please press <> when ready - ``` -2. Take `` from the message above and use any browser to access it from a different device -3. User will be presented with a page where the user has to authenticate using id and password -4. After successful user authentication, the next screen allows the user to enter the user code. Use the user code presented on command-line instruction in step 1 above. -5. After successful code validation, the user is presented with OAuth permissions screen. This screen would list all the permissions requested by Jans CLI. The user can choose to `Allow` or `Not Allow` granting of these permissions. -6. After allowing the grant of requested permissions, the user should come back to the command-line interface and hit <> as instructed. This will enable CLI to run operations on the corresponding Janssen server. - -## Stand-alone Installation - -- Follow [these instructions](../jans-tui/README.md#1-build-pyz-self-executable-file) and create a self-executable file -- Run the file as shown in the example below to enter CLI mode. Here, supplying the argument `--no-tui` is necessary, -otherwise it will switch to TUI mode. -``` -$ ./jans-cli-tui.pyz --no-tui --host test.jans.io --client-id 2000.562981df-1623-4136-b1d0-aaa277edc48c --client-secret KU6ydImJZK6S --operation-id get-acrs -Please wait while retrieving data ... -Access token was not found. -Please visit verification url https://test.jans.io/device-code?user_code=LKHC-PBTR and authorize this device within 1800 secods -Please press «Enter» when ready -{ - "defaultAcr": "simple_password_auth" -} -``` - -## CLI Tool Configuration - -Janssen CLI tool stores its configuration under `/.config` -directory. Various settings for CLI tool can be found under this directory, -for example [logging levels](../../../../contribute/developer-faq.md#how-to-enable-debug-logs-for-jans-cli-and-tui-configuration-tools). -This directory also contains SALT used by Janssen CLI tool. \ No newline at end of file diff --git a/docs/assets/jans-cli-structure.png b/docs/assets/jans-cli-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..df7c731012e1307e30e66a60aeb4f88004be043c GIT binary patch literal 31213 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 KKbLh*2~7ZB6LxU` literal 0 HcmV?d00001