Browse Source

OpenID Connect realm settings and rest API docs (#40740)

This commit adds the relevant docs for the OpenID Connect
realm settings and the REST APIs that are exposed.
Ioannis Kakavas 6 years ago
parent
commit
1013101d77

+ 242 - 2
docs/reference/settings/security-settings.asciidoc

@@ -1074,8 +1074,7 @@ they cannot have individual passwords.
 
 If you are loading the IdP metadata over SSL/TLS (that is, `idp.metadata.path` 
 is a URL using the `https` protocol), the following settings can be used to 
-configure SSL. If these are not specified, then the 
-<<ssl-tls-settings,default SSL settings>> are used.
+configure SSL.
 
 NOTE: These settings are not used for any purpose other than loading metadata 
 over https.
@@ -1204,6 +1203,247 @@ If this setting is used, then the Kerberos realm does not perform role mapping a
 instead loads the user from the listed realms.
 See {stack-ov}/realm-chains.html#authorization_realms[Delegating authorization to another realm]
 
+[[ref-oidc-settings]]
+[float]
+===== OpenID Connect realm settings
+
+In addition to the <<ref-realm-settings,settings that are valid for all realms>>, you
+can specify the following settings:
+
+`op.issuer`::
+A verifiable Identifier for your OpenID Connect Provider. An Issuer
+Identifier is usually a case sensitive URL using the https scheme that contains
+scheme, host, and optionally, port number and path components and no query or
+fragment components. The value for this setting should be provided by your OpenID
+Connect Provider.
+
+`op.authorization_endpoint`::
+The URL for the Authorization Endpoint at the
+OpenID Connect Provider. The value for this setting should be provided by your OpenID
+Connect Provider.
+
+`op.token_endpoint`::
+The URL for the Token Endpoint at the OpenID Connect Provider.
+The value for this setting should be provided by your OpenID Connect Provider.
+
+`op.userinfo_endpoint`::
+The URL for the User Info Endpoint at the OpenID Connect Provider.
+The value for this setting should be provided by your OpenID Connect Provider.
+
+`op.endsession_endpoint`::
+The URL for the End Session Endpoint at the OpenID Connect
+Provider. The value for this setting should be provided by your OpenID Connect Provider.
+
+`op.jwkset_path`::
+The path or URL to a JSON Web Key Set with the key material that the OpenID Connect
+Provider uses for signing tokens and claims responses.
+If a path is provided, then it is resolved relative to the {es} config
+directory.
+If a URL is provided, then it must be either a `file` URL or a `https` URL.
+{es} automatically caches the retrieved JWK set to avoid unnecessary HTTP
+requests but will attempt to refresh the JWK upon signature verification
+failure, as this might indicate that the OpenID Connect Provider has
+rotated the signing keys.
+
+File based resources are polled at a frequency determined by the global {es}
+`resource.reload.interval.high` setting, which defaults to 5 seconds.
+
+`rp.client_id`::
+The OAuth 2.0 Client Identifier that was assigned to {es} during registration
+at the OpenID Connect Provider
+
+`rp.client_secret`(<<secure-settings,Secure>>)::
+The OAuth 2.0 Client Secret that was assigned to {es} during registration
+at the OpenID Connect Provider
+
+`rp.redirect_uri`::
+The Redirect URI within {kib}. Typically this is the
+"api/security/v1/oidc" endpoint of your Kibana server. For example,
+`https://kibana.example.com/api/security/v1/oidc`.
+
+`rp.response_type`::
+OAuth 2.0 Response Type value that determines the authorization
+processing flow to be used. Can be `code` for authorization code grant flow,
+or one of `id_token`, `id_token token` for the implicit flow.
+
+`rp.signature_algorithm`::
+The signature algorithm that will be used by {es} in order to verify the
+signature of the id tokens it will receive from the OpenID Connect Provider.
+Defaults to `RSA256`
+
+`rp.requested_scopes`::
+The scope values that will be requested by the OpenID Connect Provider as
+part of the Authentication Request. Optional, defaults to `openid`
+
+`rp.post_logout_redirect_uri`::
+The Redirect URI (usually within {kib}) that the OpenID Connect Provider
+should redirect the browser to after a successful Single Logout.
+
+`claims.principal`::
+The name of the OpenID Connect claim that contains the user's principal (username).
+
+`claims.groups`::
+The name of the OpenID Connect claim that contains the user's groups.
+
+`claims.name`::
+The name of the OpenID Connect claim that contains the user's full name.
+
+`claims.mail`::
+The name of the OpenID Connect claim that contains the user's email address.
+
+`claims.dn`::
+The name of the OpenID Connect claim that contains the user's X.509
+_Distinguished Name_.
+
+`claim_patterns.principal`::
+A Java regular expression that is matched against the OpenID Connect claim specified
+by `claims.principal` before it is applied to the user's _principal_ property.
+The attribute value must match the pattern and the value of the first
+_capturing group_ is used as the principal. For example, `^([^@]+)@example\\.com$`
+matches email addresses from the "example.com" domain and uses the local-part as
+the principal.
+
+`claim_patterns.groups`::
+As per `claim_patterns.principal`, but for the _group_ property.
+
+`claim_patterns.name`::
+As per `claim_patterns.principal`, but for the _name_ property.
+
+`claim_patterns.mail`::
+As per `claim_patterns.principal`, but for the _mail_ property.
+
+`claim_patterns.dn`::
+As per `claim_patterns.principal`, but for the _dn_ property.
+
+
+`allowed_clock_skew`::
+The maximum allowed clock skew to be taken into consideration when validating
+id tokens with regards to their creation and expiration times.
+
+`populate_user_metadata`::
+Specifies whether to populate the {es} user's metadata with the values that are
+provided by the OpenID Connect claims. Defaults to `true`.
+
+`http.connect_timeout`::
+Controls the behavior of the http client used for back-channel communication to
+the OpenID Connect Provider endpoints. Specifies the timeout until a connection
+ is established. A value of zero means the timeout is not used. Defaults to `5s`
+
+`http.connection_read_timeout`::
+Controls the behavior of the http client used for back-channel communication to
+the OpenID Connect Provider endpoints. Specifies the timeout used when
+requesting a connection from the connection manager. Defaults to `5s`
+
+`http.socket_timeout`::
+Controls the behavior of the http client used for back-channel communication to
+the OpenID Connect Provider endpoints. Specifies the socket timeout (SO_TIMEOUT)
+in milliseconds, which is the timeout for waiting for data or, put differently,
+a maximum period inactivity between two consecutive data packets). Defaults to
+`5s`
+
+`http.max_connections`::
+Controls the behavior of the http client used for back-channel communication to
+the OpenID Connect Provider endpoints. Specifies the maximum number of
+connections allowed across all endpoints.
+
+`http.max_endpoint_connections`::
+Controls the behavior of the http client used for back-channel communication to
+the OpenID Connect Provider endpoints. Specifies the maximum number of
+connections allowed per endpoint.
+
+[float]
+[[ref-oidc-ssl-settings]]
+===== OpenID Connect realm SSL settings
+
+The following settings can be used to configure SSL for all outgoing http connections
+to the OpenID Connect Provider endpoints.
+
+NOTE: These settings are _only_ used for the back-channel communication between
+{es} and the OpenID Connect Provider
+
+`ssl.key`::
+Specifies the path to the PEM encoded private key to use for http client
+authentication (if required). `ssl.key` and `ssl.keystore.path` cannot be used
+at the same time.
+
+`ssl.key_passphrase`::
+Specifies the passphrase to decrypt the PEM encoded private key (`ssl.key`) if it is
+encrypted. Cannot be used with `ssl.secure_key_passphrase`.
+
+`ssl.secure_key_passphrase` (<<secure-settings,Secure>>)::
+Specifies the passphrase to decrypt the PEM encoded private key (`ssl.key`) if it is
+encrypted. Cannot be used with `ssl.key_passphrase`.
+
+`ssl.certificate`::
+Specifies the path to the PEM encoded certificate (or certificate chain) that is associated
+with the key (`ssl.key`). This setting can be used only if `ssl.key` is set.
+
+`ssl.certificate_authorities`::
+Specifies the paths to the PEM encoded certificate authority certificates that should be
+trusted. `ssl.certificate_authorities` and `ssl.truststore.path` cannot be
+used at the same time.
+
+`ssl.keystore.path`::
+Specifies the path to the keystore that contains a private key and certificate.
+Must be either a Java Keystore (jks) or a PKCS#12 file.
+`ssl.key` and `ssl.keystore.path` cannot be used at the same time.
+
+`ssl.keystore.type`::
+The type of the keystore (`ssl.keystore.path`). Must be either `jks` or `PKCS12`.
+If the keystore path ends in ".p12", ".pfx" or "pkcs12", this setting defaults
+to `PKCS12`. Otherwise, it defaults to `jks`.
+
+`ssl.keystore.password`::
+The password to the keystore (`ssl.keystore.path`). This setting cannot be used
+with `ssl.keystore.secure_password`.
+
+`ssl.keystore.secure_password` (<<secure-settings,Secure>>)::
+The password to the keystore (`ssl.keystore.path`).
+This setting cannot be used with `ssl.keystore.password`.
+
+`ssl.keystore.key_password`::
+The password for the key in the keystore (`ssl.keystore.path`).
+Defaults to the keystore password. This setting cannot be used with
+`ssl.keystore.secure_key_password`.
+
+`ssl.keystore.secure_key_password` (<<secure-settings,Secure>>)::
+The password for the key in the keystore (`ssl.keystore.path`).
+Defaults to the keystore password. This setting cannot be used with
+`ssl.keystore.key_password`.
+
+`ssl.truststore.path`::
+The path to the keystore that contains the certificates to trust.
+Must be either a Java Keystore (jks) or a PKCS#12 file.
+`ssl.certificate_authorities` and `ssl.truststore.path` cannot be used at the
+same time.
+
+`ssl.truststore.type`::
+The type of the truststore (`ssl.truststore.path`). Must be either `jks` or
+`PKCS12`. If the keystore path ends in ".p12", ".pfx" or "pkcs12", this setting
+defaults to `PKCS12`. Otherwise, it defaults to `jks`.
+
+`ssl.truststore.password`::
+The password to the truststore (`ssl.truststore.path`). This setting cannot be
+used with `ssl.truststore.secure_password`.
+
+`ssl.truststore.secure_password` (<<secure-settings,Secure>>)::
+The password to the truststore (`ssl.truststore.path`). This setting cannot be
+used with `ssl.truststore.password`.
+
+`ssl.verification_mode`::
+One of `full` (verify the hostname and the certificate path), `certificate` (verify the
+certificate path, but not the hostname) or `none` (perform no verification).
+Defaults to `full`.
++
+See <<ssl-tls-settings,`ssl.verification_mode`>> for a more detailed explanation of these values.
+
+`ssl.supported_protocols`::
+Specifies the supported protocols for TLS/SSL. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if
+the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`.
+
+`ssl.cipher_suites`::
+Specifies the cipher suites that should be supported.
+
 [float]
 [[load-balancing]]
 ===== Load balancing and failover

+ 12 - 0
x-pack/docs/en/rest-api/security.asciidoc

@@ -76,6 +76,15 @@ native realm:
 * <<security-api-enable-user,Enable users>>
 * <<security-api-get-user,Get users>>
 
+=== OpenID Connect
+
+You can use the following APIs to authenticate users against an OpenID Connect
+authentication realm
+
+* <<security-api-oidc-prepare-authentication, Prepare an authentication request>>
+* <<security-api-oidc-authenticate, Submit an authentication response>>
+* <<security-api-oidc-logout, Logout an authenticated user>>
+
 
 include::security/authenticate.asciidoc[]
 include::security/change-password.asciidoc[]
@@ -102,3 +111,6 @@ include::security/has-privileges.asciidoc[]
 include::security/invalidate-api-keys.asciidoc[]
 include::security/invalidate-tokens.asciidoc[]
 include::security/ssl.asciidoc[]
+include::security/oidc-prepare-authentication-api.asciidoc[]
+include::security/oidc-authenticate-api.asciidoc[]
+include::security/oidc-logout-api.asciidoc[]

+ 68 - 0
x-pack/docs/en/rest-api/security/oidc-authenticate-api.asciidoc

@@ -0,0 +1,68 @@
+[role="xpack"]
+[[security-api-oidc-authenticate]]
+
+=== OpenID Connect Authenticate API
+
+Submits the response to an oAuth 2.0 authentication request for consumption from {es}. Upon successful validation, {es}
+will respond with an {es} internal Access Token and Refresh Token that can be subsequently used for authentication. This
+API endpoint basically exchanges successful OpenID Connect Authentication responses for {es} access and refresh tokens
+to be used for authentication.
+
+{es} exposes all the necessary OpenID Connect related functionality via the OpenID Connect APIs. These APIs
+are used internally by {kib} in order to provide OpenID Connect based authentication, but can also be used by other,
+custom web applications or other clients. See also
+<<security-api-oidc-prepare-authentication,OpenID Connect Prepare Authentication API>> and
+<<security-api-oidc-logout,OpenID Connect Logout API>>
+
+==== Request
+
+`POST /_security/oidc/authenticate`
+
+==== Request Body
+
+`redirect_uri`::
+The URL to which the OpenID Connect Provider redirected the User Agent in response to an authentication request, after a
+ successful authentication. This URL is expected to be provided as-is (URL encoded), taken from the body of the response
+ or as the value of a `Location` header in the response from the OpenID Connect Provider.
+
+`state`::
+String value used to maintain state between the authentication request and the response. This value needs to be the same
+as the one that was provided to the call to `/_security/oidc/prepare` earlier, or the one that was generated by {es}
+and included in the response to that call.
+
+`nonce`::
+String value used to associate a Client session with an ID Token, and to mitigate replay attacks. This value needs to be
+the same as the one that was provided to the call to `/_security/oidc/prepare` earlier, or the one that was generated by {es}
+and included in the response to that call.
+
+==== Examples
+
+The following example request exchanges the response that was returned from the OpenID Connect Provider after a successful
+authentication, for an {es} access token and refresh token to be used in subsequent requests. This example is from an
+authentication that uses the authorization code grant flow.
+
+[source,js]
+--------------------------------------------------
+POST /_security/oidc/authenticate
+{
+  "redirect_uri" : "https://oidc-kibana.elastic.co:5603/api/security/v1/oidc?code=jtI3Ntt8v3_XvcLzCFGq&state=4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I",
+  "state" : "4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I",
+  "nonce" : "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM"
+}
+--------------------------------------------------
+// CONSOLE
+// TEST[skip:These are properly tested in the OpenIDConnectIT suite]
+
+The following example output contains the access token that was generated in response, the amount of time (in
+seconds) that the token expires in, the type, and the refresh token:
+
+[source,js]
+--------------------------------------------------
+{
+  "access_token" : "dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==",
+  "type" : "Bearer",
+  "expires_in" : 1200,
+  "refresh_token": "vLBPvmAB6KvwvJZr27cS"
+}
+--------------------------------------------------
+// NOTCONSOLE

+ 53 - 0
x-pack/docs/en/rest-api/security/oidc-logout-api.asciidoc

@@ -0,0 +1,53 @@
+[role="xpack"]
+[[security-api-oidc-logout]]
+
+=== OpenID Connect Logout API
+
+Submits a request to invalidate a refresh token and an access token that was generated as a response to a call to
+`/_security/oidc/authenticate`. If the OpenID Connect authentication realm in {es} is accordingly configured, the
+response to this call will contain a URI pointing to the End Session Endpoint of the OpenID Connect Provider in
+order to perform Single Logout
+
+{es} exposes all the necessary OpenID Connect related functionality via the OpenID Connect APIs. These APIs
+are used internally by {kib} in order to provide OpenID Connect based authentication, but can also be used by other,
+custom web applications or other clients. See also <<security-api-oidc-authenticate,OpenID Connect Authenticate API>>
+and <<security-api-oidc-prepare-authentication,OpenID Connect Prepare Authentication API>>
+
+==== Request
+
+`POST /_security/oidc/logout`
+
+==== Request Body
+
+`access_token`::
+The value of the access token to be invalidated as part of the logout.
+
+`refresh_token`::
+The value of the refresh token to be invalidated as part of the logout. (Optional)
+
+
+==== Examples
+
+The following example performs logout
+
+[source,js]
+--------------------------------------------------
+POST /_security/oidc/logout
+{
+  "token" : "dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==",
+  "refresh_token": "vLBPvmAB6KvwvJZr27cS"
+}
+--------------------------------------------------
+// CONSOLE
+// TEST[skip:These are properly tested in the OpenIDConnectIT suite]
+
+The following example output of the response contains the URI pointing to the End Session Endpoint of the
+OpenID Connect Provider with all the parameters of the Logout Request, as HTTP GET parameters
+
+[source,js]
+--------------------------------------------------
+{
+  "redirect" : "https://op-provider.org/logout?id_token_hint=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c&post_logout_redirect_uri=http%3A%2F%2Foidc-kibana.elastic.co%2Floggedout&state=lGYK0EcSLjqH6pkT5EVZjC6eIW5YCGgywj2sxROO"
+}
+--------------------------------------------------
+// NOTCONSOLE

+ 128 - 0
x-pack/docs/en/rest-api/security/oidc-prepare-authentication-api.asciidoc

@@ -0,0 +1,128 @@
+[role="xpack"]
+[[security-api-oidc-prepare-authentication]]
+
+=== OpenID Connect Prepare Authentication API
+
+Creates an oAuth 2.0 authentication request as a URL string based on the configuration of the respective
+OpenID Connect authentication realm in {es}. The response of this API is a URL pointing to the Authorization Endpoint
+of the configured OpenID Connect Provider and can be used to redirect the browser of the user in order to continue
+the authentication process.
+
+{es} exposes all the necessary OpenID Connect related functionality via the OpenID Connect APIs. These APIs
+are used internally by {kib} in order to provide OpenID Connect based authentication, but can also be used by other,
+custom web applications or other clients. See also <<security-api-oidc-authenticate,OpenID Connect Authenticate API>>
+and <<security-api-oidc-logout,OpenID Connect Logout API>>
+
+==== Request
+
+`POST /_security/oidc/prepare`
+
+
+==== Request Body
+
+The following parameters can be specified in the body of the request:
+
+`realm`::
+The name of the OpenID Connect realm in {es} the configuration of which should be used in order to
+generate the authentication request. Cannot be specified when `iss` is specified.
+
+`state`::
+String value used to maintain state between the authentication request and the response, typically used
+as a Cross-Site Request Forgery mitigation. If the caller of the API doesn't provide a value, {es} will
+generate one with sufficient entropy itself and return it in the response.
+
+`nonce`::
+String value used to associate a Client session with an ID Token, and to mitigate replay attacks.
+If the caller of the API doesn't provide a value, {es} will generate one with sufficient entropy itself
+and return it in the response.
+
+`issuer`::
+In the case of a 3rd Party initiated Single Sign On, this is the Issuer Identifier for the OP that the RP is
+to send the Authentication Request to. Cannot be specified when `realm` is specified.
+
+`login_hint`::
+In the case of a 3rd Party initiated Single Sign On, a string value to be included in the authentication
+request, as the `login_hint` parameter. This parameter is not valid when `realm` is specified
+
+
+==== Examples
+
+The following example generates an authentication request for the OpenID Connect Realm `oidc1`
+
+[source,js]
+--------------------------------------------------
+POST /_security/oidc/prepare
+{
+  "realm" : "oidc1"
+}
+--------------------------------------------------
+// CONSOLE
+// TEST[skip:These are properly tested in the OpenIDConnectIT suite]
+
+The following example output of the response contains the URI pointing to the Authorization Endpoint of the
+OpenID Connect Provider with all the parameters of the Authentication Request, as HTTP GET parameters
+
+[source,js]
+--------------------------------------------------
+{
+  "redirect" : "https://op-provider.org/login?scope=openid&response_type=code&redirect_uri=http%3A%2F%2Foidc-kibana.elastic.co%3A5603%2Fkmi%2Fapi%2Fsecurity%2Fv1%2Foidc&state=4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I&nonce=WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM&client_id=0o43gasov3TxMWJOt839",
+  "state" : "4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I",
+  "nonce" : "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM"
+}
+--------------------------------------------------
+// NOTCONSOLE
+
+The following example generates an authentication request for the OpenID Connect Realm `oidc1`, where the
+values for the state and the nonce have been generated by the client
+
+[source,js]
+--------------------------------------------------
+POST /_security/oidc/prepare
+{
+  "realm" : "oidc1",
+  "state" : "lGYK0EcSLjqH6pkT5EVZjC6eIW5YCGgywj2sxROO",
+  "nonce" : "zOBXLJGUooRrbLbQk5YCcyC8AXw3iloynvluYhZ5"
+}
+--------------------------------------------------
+// CONSOLE
+// TEST[skip:These are properly tested in the OpenIDConnectIT suite]
+
+The following example output of the response contains the URI pointing to the Authorization Endpoint of the
+OpenID Connect Provider with all the parameters of the Authentication Request, as HTTP GET parameters
+
+[source,js]
+--------------------------------------------------
+{
+  "redirect" : "https://op-provider.org/login?scope=openid&response_type=code&redirect_uri=http%3A%2F%2Foidc-kibana.elastic.co%3A5603%2Fkmi%2Fapi%2Fsecurity%2Fv1%2Foidc&state=lGYK0EcSLjqH6pkT5EVZjC6eIW5YCGgywj2sxROO&nonce=zOBXLJGUooRrbLbQk5YCcyC8AXw3iloynvluYhZ5&client_id=0o43gasov3TxMWJOt839",
+  "state" : "lGYK0EcSLjqH6pkT5EVZjC6eIW5YCGgywj2sxROO",
+  "nonce" : "zOBXLJGUooRrbLbQk5YCcyC8AXw3iloynvluYhZ5"
+}
+--------------------------------------------------
+// NOTCONSOLE
+
+The following example generates an authentication request for a 3rd party initiated single sign on, specifying the
+issuer that should be used for matching the appropriate OpenID Connect Authentication realm
+
+[source,js]
+--------------------------------------------------
+POST /_security/oidc/prepare
+{
+  "issuer" : "https://op-issuer.org:8800",
+  "login_hint": "this_is_an_opaque_string"
+}
+--------------------------------------------------
+// CONSOLE
+// TEST[skip:These are properly tested in the OpenIDConnectIT suite]
+
+The following example output of the response contains the URI pointing to the Authorization Endpoint of the
+OpenID Connect Provider with all the parameters of the Authentication Request, as HTTP GET parameters
+
+[source,js]
+--------------------------------------------------
+{
+  "redirect" : "https://op-provider.org/login?scope=openid&response_type=code&redirect_uri=http%3A%2F%2Foidc-kibana.elastic.co%3A5603%2Fkmi%2Fapi%2Fsecurity%2Fv1%2Foidc&state=lGYK0EcSLjqH6pkT5EVZjC6eIW5YCGgywj2sxROO&nonce=zOBXLJGUooRrbLbQk5YCcyC8AXw3iloynvluYhZ5&client_id=0o43gasov3TxMWJOt839&login_hint=this_is_an_opaque_string",
+  "state" : "4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I",
+  "nonce" : "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM"
+}
+--------------------------------------------------
+// NOTCONSOLE