Project: CyberArk Conjur (Provisioning / Key Management)
File: authn_status_general.md

This is a design doc for the user story that is part of the epic *As a* Conjur operator\ *I'd like to* know that an authenticator is configured correctly\ *So that* I can complete the configuration properly if it's incomplete (or remove it if it's not needed). This feature lets the person who configures an authenticator to get an immediate feedback on the configuration, before any user needs to run an authentication request. We will create a new route in `routes.rb` for `/authenticators/:authenticator/:service_id/:account/status`. This route will lead to `AuthenticateController` which will consist of a new `status` method. In this method we will call a new CommandClass `Authentication::Status`. This class's `call` method will perform the general checks that apply to all authenticators and those specific to each authenticator: The requesting user has access to the authenticator status route webservice more info in the Security section of the The authenticator is implemented The account exists although a wrong account in an `/authenticate` request will indicate a client error and not a server error, we still need to verify it exists in order to verify that the webservice exists under that account The webservice exists The authenticator is enabled in the ENV *Note:* The default authenticator (`authn`) is always healthy We will also need to audit access success & failures to this endpoint. Some authenticators need extra validation. As mentioned in the Epic, if the status check is not implemented for the authenticator we will return a 501 Not Implemented response. In the following section, we will use `authn-oidc` as an example. For each authenticator that will implement the status check, we will add: A `Status` CommandClass in the structure `Authentication::AuthnOidc::Status` (with the validations in its `call` method). A `status` method to its existing authenticator class (i.e. `Authentication::AuthnOidc::Authenticator`) which will call the new CommandClass, as follows: ``` def status Authentication::AuthnOidc::Status.new.( <input for status check> ) end ``` The `status` method above will be called from the general status check, when validating the authenticator's specific requirements. We will first verify that the `status` method exists in the `Authenticator` class, which will indicate that the status check is implemented on the given authenticator. Therefore, the `call` method of the general status check will look like the following: ``` def call validateauthenticatorexists validateauthenticatorimplementsstatuscheck . . . . validateauthenticatorrequirements end private def validateauthenticatorexists raise Err::AuthenticatorNotSupported unless authenticator end def validateauthenticatorimplementsstatuscheck unless authenticator.method_defined?(:status) raise 501 end def validateauthenticatorrequirements authenticator.status end def authenticator @authenticator =

end ``` *Note*: We check that the authenticator status check exists before we check the permissions to the status webservice as this info isn't sensitive and we can expose it. The following are the response bodies that will be returned to the user ``` { "status": "ok" } ``` ``` { "status": "error", "error": "<configuration_error>" } ``` For example, if the status check failed on `WebserviceNotFound` then the message will be `Webservice '{webservice-name}' wasn't found` (which is its built-in message) | Given | When | Then | Status | |::||--|| | A healthy authenticator | I send a request with a valid access token | I get a 200 OK response with a successful body | - [ ] | | A healthy authenticator | I send a request with an invalid access token (user is not permitted on the status webservice) | I get a 403 Forbidden response | - [ ] | | An authenticator without an implemented status check | I send a request with a valid access token | I get a 501 Not Implemented response | - [ ] | | A non-existing authenticator | I send a request with a valid access token | I get a 404 Not Found response | - [ ] | | A missing status webservice in the policy | I send a request with a valid access token | I get a 500 Internal Server Error response with an error body with the relevant error message | - [ ] | | A non-existing account name in the request | I send a request with a valid access token | I get a 500 Internal Server Error response with an error body with the relevant error message | - [ ] | | Authenticator webservice doesn't exist (wasn't loaded in the policy) | I send a request with a valid access token | I get a 500 Internal Server Error response with an error body with the relevant error message | - [ ] | | The authenticator isn't whitelisted in the ENV | I send a request with a valid access token | I get a 500 Internal Server Error response with an error body with the relevant error message | - [ ] | | Given | When | Then | Status | |::||--|| | A healthy authenticator | I send a request with a valid access token | I get a 200 OK response with a successful body | - [ ] | if `authenticator.status` (specific authenticator validation) raises an error then it propagates to the user if `authenticator.status` (specific authenticator validation) succeeds then the user gets a successful message 5 Days