[[Properties_File_Based_Authentication_Migration]]
= Properties Based Authentication / Authorization

ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]

[[picketbox-based-configuration]]
== PicketBox Based Configuration

This migration example assumes a deployed web application is configured
to require authentication using FORM based authentication and is
referencing a PicketBox based security domain using the
UsersRolesLoginModule to load user information from a pair or properties
files.

[[original-configuration]]
=== Original Configuration

A security domain can be defined in the legacy security subsystem using
the following management operations: -

[source,options="nowrap"]
----
./subsystem=security/security-domain=application-security:add
./subsystem=security/security-domain=application-security/authentication=classic:add(login-modules=[{code=UsersRoles, flag=Required, module-options={usersProperties=file://${jboss.server.config.dir}/example-users.properties, rolesProperties=file://${jboss.server.config.dir}/example-roles.properties}}])
----

This would result in a security domain definition: -

[source,xml,options="nowrap"]
----
  <security-domain name="application-security">
    <authentication>
      <login-module code="UsersRoles" flag="required">
        <module-option name="usersProperties" value="file://${jboss.server.config.dir}/example-users.properties"/>
        <module-option name="rolesProperties" value="file://${jboss.server.config.dir}/example-roles.properties"/>
      </login-module>
    </authentication>
  </security-domain>
----

[[intermediate-configuration]]
=== Intermediate Configuration

It is possible to take a previously defined PicketBox security domain
and expose it as an Elytron security realm so it can be wired into a
complete Elytron based configuration, if only properties based
authentication was to be migrated it would be recommended to jump to the
fully migration configuration and avoid the unnecessary dependency on
the legacy security subsystem but for situations where that is not
immediately possible these commands illustrate an intermediate solution.

These steps assume the original configuration is already in place.

The first step is to add a mapping to an Elytron security realm within
the legacy security subsystem.

[source,options="nowrap"]
----
./subsystem=security/elytron-realm=application-security:add(legacy-jaas-config=application-security)
----

This results in the following configuration.

[source,xml,options="nowrap"]
----
  <subsystem xmlns="urn:jboss:domain:security:2.0">
    ...
    <elytron-integration>
      <security-realms>
        <elytron-realm name="application-security" legacy-jaas-config="application-security"/>
      </security-realms>
    </elytron-integration>
    ...
  </subsystem>
----

Within the Elytron subsystem a security domain can be defined which
references the exported security realm and also a http authentication
factory which supports FORM based authentication.

[source,options="nowrap"]
----
./subsystem=elytron/security-domain=application-security:add(realms=[{realm=application-security}], default-realm=application-security, permission-mapper=default-permission-mapper)
./subsystem=elytron/http-authentication-factory=application-security-http:add(http-server-mechanism-factory=global, security-domain=application-security, mechanism-configurations=[{mechanism-name=FORM}])
----

And the resulting configuration: -

[source,xml,options="nowrap"]
----
  <subsystem xmlns="urn:wildfly:elytron:1.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
    ...
    <security-domains>
      ...
      <security-domain name="application-security" default-realm="application-security" permission-mapper="default-permission-mapper">
        <realm name="application-security"/>
      </security-domain>
    </security-domains>
    ...
    <http>
      ...
      <http-authentication-factory name="application-security-http" http-server-mechanism-factory="global" security-domain="application-security">
        <mechanism-configuration>
          <mechanism mechanism-name="FORM"/>
        </mechanism-configuration>
      </http-authentication-factory>
      ...
    </http>
    ...
  </subsystem>
----

Finally configuration needs to be added to the Undertow subsystem to map
the security domain referenced by the deployment to the newly defined
http authentication factory.

[source,options="nowrap"]
----
./subsystem=undertow/application-security-domain=application-security:add(http-authentication-factory=application-security-http)
----

Which results in: -

[source,xml,options="nowrap"]
----
  <subsystem xmlns="urn:jboss:domain:undertow:4.0">
    ...
    <application-security-domains>
      <application-security-domain name="application-security" http-authentication-factory="application-security-http"/>
    </application-security-domains>
    ...
  </subsystem>
----

_Note: If the deployment was already deployed at this point the
application server should be reloaded or the deployment redeployed for
the application security domain mapping to take effect._

The following command can then be used to verify the mapping was applied
to the deployment.

[source,options="nowrap"]
----
[standalone@localhost:9990 /] ./subsystem=undertow/application-security-domain=application-security:read-resource(include-runtime=true)
{
    "outcome" => "success",
    "result" => {
        "enable-jacc" => false,
        "http-authentication-factory" => "application-security-http",
        "override-deployment-config" => false,
        "referencing-deployments" => ["HelloWorld.war"],
        "setting" => undefined
    }
}
----

The deployment being tested here is 'HelloWorld.war' and the output from
the previous command shows this deployment is referencing the mapping.

At this stage the previously defined security domain is used for it's
LoginModule configuration but this is wrapped by Elytron components
which take over authentication.

[[fully-migrated-configuration]]
=== Fully Migrated Configuration

Alternatively the configuration can be completely defined within the
Elytron subsystem, in this case it is assumed none of the previous
commands have been executed and this is started from a clean
configuration - however if the security domain definition does exist in
the legacy security subsystem that will remain completely independent.

First a new security realm can be defined within the Elytron subsystem
referencing the files referenced previously: -

[source,options="nowrap"]
----
./subsystem=elytron/properties-realm=application-properties:add(users-properties={path=example-users.properties, relative-to=jboss.server.config.dir, plain-text=true, digest-realm-name="Application Security"}, groups-properties={path=example-roles.properties, relative-to=jboss.server.config.dir}, groups-attribute=Roles)
----

As before a security domain and http authentication factory can be
defined.

[source,options="nowrap"]
----
./subsystem=elytron/security-domain=application-security:add(realms=[{realm=application-properties}], default-realm=application-properties, permission-mapper=default-permission-mapper)
./subsystem=elytron/http-authentication-factory=application-security-http:add(http-server-mechanism-factory=global, security-domain=application-security, mechanism-configurations=[{mechanism-name=FORM}])
----

This results in the following overall configuration.

[source,xml,options="nowrap"]
----
  <subsystem xmlns="urn:wildfly:elytron:1.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
    ...
    <security-domains>
      ...
      <security-domain name="application-security" default-realm="application-properties" permission-mapper="default-permission-mapper">
        <realm name="application-properties"/>
      </security-domain>
    </security-domains>
    <security-realms>
      ...
      <properties-realm name="application-properties" groups-attribute="Roles">
        <users-properties path="example-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="Application Security" plain-text="true"/>
        <groups-properties path="example-roles.properties" relative-to="jboss.server.config.dir"/>
      </properties-realm>
    </security-realms>
    ...
    <http>
      ...
      <http-authentication-factory name="application-security-http" http-server-mechanism-factory="global" security-domain="application-security">
        <mechanism-configuration>
          <mechanism mechanism-name="FORM"/>
        </mechanism-configuration>
      </http-authentication-factory>
      ...
    </http>
    ...
  </subsystem>
----

As before the application-security-domain mapping should be added to the
Undertow subsystem and the server reloaded or the deployment redeployed
as required.

[source,options="nowrap"]
----
./subsystem=undertow/application-security-domain=application-security:add(http-authentication-factory=application-security-http)
----

Which results in: -

[source,xml,options="nowrap"]
----
  <subsystem xmlns="urn:jboss:domain:undertow:4.0">
    ...
    <application-security-domains>
      <application-security-domain name="application-security" http-authentication-factory="application-security-http"/>
    </application-security-domains>
    ...
  </subsystem>
----

At this stage the authentication is the equivalent of the original
configuration however now Elytron components are used exclusively.

[[FileSystemRealm_Based_Authentication_Migration]]
== Migrating to FileSystemRealm Based Authentication

An alternative to using a legacy properties-realm in Elytron is to use
the new filesystem-realm. An Elytron filesystem-realm will use file-backed
authentication methods to secure the server. It is now easy to migrate from a
legacy properties-realm to an Elytron filesystem-realm by using the
Elytron Tool. The new Elytron Tool command, FileSystemRealmCommand, will convert
the given properties files and create an Elytron FileSystemRealm, along with a script
with the WildFly CLI commands for registering the FileSystemRealm and Security Domain
on the WildFly server. After using the tool, it will still be necessary to configure
an authentication-factory and an application-security-domain, as in the steps
above.

[[filesystem-realm-single-conversion]]
=== Single User-Roles Conversion

To convert a single user-roles properties files combination, the parameters
can be passed directly into the command:

[source, bash]
----
./bin/elytron-tool.sh filesystem-realm --users-file users.properties --roles-file roles.properties --output-location filesystem_realm_dir
----

This will then configure a filesystem-realm in filesystem_realm_dir and
will create a script converted-properties-filesystem-realm.sh in
filesystem_realm_dir with the WildFly CLI commands to register the filesystem-realm
and the security-domain, with the security-domain named
converted-properties-security-domain. To customize the filesystem-realm name
and the security-domain name, the --filesystem-realm-name and
--security-domain-name parameters can be used.

Use elytron-tool.sh filesystem-realm --help to get description of all parameters.

[[filesystem_realm_single_notes]]
==== Notes:

- The short form options, as shown in the --help option, can be used, such as
-u in place of --users-file.
- When the --summary parameter is specified, an output of operations performed
during conversion, including warnings and errors, will be shown once the
command finishes conversion.
- When the --silent parameter is specified, Elytron Tool will not give no
information output, as compared to normal operation where warnings are shown.
The --silent command will not override --summary, resulting in the ability to
hide output until the command finishes conversion.
- Elytron Tool will not configure the filesystem-realm and security-domain
within WildFly itself, it will just provide the necessary commands in the
output script file.

[[filesystem-realm-bulk-conversion]]
=== Bulk User-Roles Conversion

It is possible to convert multiple users-roles files combinations at once
by using --bulk-convert parameter with a descriptor file.

An example descriptor-file from our tests is:

[source, text]
----
users-file:/home/jucook/Documents/WildFly/Git_Projects/WildFly-Elytron/wildfly-elytron-tool/target/test-classes/filesystem-realm/users/users-5.properties
roles-file:/home/jucook/Documents/WildFly/Git_Projects/WildFly-Elytron/wildfly-elytron-tool/target/test-classes/filesystem-realm/roles/roles-5.properties
output-location:./target/test-classes/filesystem-realm/output-5-bulk
filesystem-realm-name:nameOfFileSystemRealm5
security-domain-name:nameOfSecurityDomain5

users-file:/home/jucook/Documents/WildFly/Git_Projects/WildFly-Elytron/wildfly-elytron-tool/target/test-classes/filesystem-realm/users/users-6.properties
roles-file:/home/jucook/Documents/WildFly/Git_Projects/WildFly-Elytron/wildfly-elytron-tool/target/test-classes/filesystem-realm/roles/roles-6.properties
output-location:/home/jucook/Documents/WildFly/Git_Projects/WildFly-Elytron/wildfly-elytron-tool/target/test-classes/filesystem-realm/output-6-bulk
filesystem-realm-name:nameOfFileSystemRealm6
security-domain-name:nameOfSecurityDomain6
----

Each blank line starts a new conversion operation. As with a single conversion,
the users-file, roles-file, and output-location are required parameters while
the filesystem-realm-name and security-domain-name are optional parameters.

Execute the following command to convert with the descriptor file:

[source, bash]
----
./bin/elytron-tool.sh filesystem-realm --bulk-convert descriptor-file
----

[[filesystem_realm_bulk_notes]]
==== Notes:

- For bulk conversion, only the long form option can be used, unlike the CLI
mode where both long and short form options can be used.
- The --summary and --silent parameters can be used here too. However, they
must be specified while executing the command and apply to all conversions
specified in the descriptor file.
- If the --summary parameter is used, then a summary will be provided
after each execution as opposed to after the command finishes all conversions.
- As with the single conversion, absolute or relative paths can be used for
users-file, roles-file, and output-location.
- Each execution of the command will produce a separate script in the given
output-location directory.
- Repeated output-location paths can result in an error
- If there is an error in one users-roles files combination then Elytron Tool
will report the issue, such as a missing required parameter, and continue
with the conversion of all remaining combinations.

[[legacy-security-realm]]
== Legacy Security Realm

[[original-configuration-1]]
=== Original Configuration

A legacy security realm can be defined using the following commands to
load users passwords and group information from properties files.

[source,options="nowrap"]
----
./core-service=management/security-realm=ApplicationSecurity:add
./core-service=management/security-realm=ApplicationSecurity/authentication=properties:add(relative-to=jboss.server.config.dir, path=example-users.properties, plain-text=true)
./core-service=management/security-realm=ApplicationSecurity/authorization=properties:add(relative-to=jboss.server.config.dir, path=example-roles.properties)
----

This results in the following realm definition.

[source,xml,options="nowrap"]
----
  <security-realm name="ApplicationSecurity">
    <authentication>
      <properties path="example-users.properties" relative-to="jboss.server.config.dir" plain-text="true"/>
    </authentication>
    <authorization>
      <properties path="example-roles.properties" relative-to="jboss.server.config.dir"/>
    </authorization>
  </security-realm>
----

A legacy security realm would typically be used to secure either the
management interfaces or remoting connectors.

[[migrated-configuration]]
=== Migrated Configuration

One of the motivations for adding the Elytron based security to the
application server is to allow a consistent security solution to be used
across the server, to replace the security realm the same steps as
described in the previous 'Fully Migrated' section can be followed again
up until the http-authentication-factory is defined.

A legacy security realm can also be used for SASL based authentication
so a sasl-authentication-factory should also be defined.

[source,options="nowrap"]
----
./subsystem=elytron/sasl-authentication-factory=application-security-sasl:add(sasl-server-factory=elytron, security-domain=application-security, mechanism-configurations=[{mechanism-name=PLAIN}])
----

[source,xml,options="nowrap"]
----
  <subsystem xmlns="urn:wildfly:elytron:1.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
    ...
    <sasl>
      ...
      <sasl-authentication-factory name="application-security-sasl" sasl-server-factory="elytron" security-domain="application-security">
        <mechanism-configuration>
          <mechanism mechanism-name="PLAIN"/>
        </mechanism-configuration>
      </sasl-authentication-factory>
      ...
    </sasl>
  </subsystem>
----

This can be associated with a Remoting connector to use for
authentication and the existing security realm reference cleared.

[source,options="nowrap"]
----
./subsystem=remoting/http-connector=http-remoting-connector:write-attribute(name=sasl-authentication-factory, value=application-security-sasl)
./subsystem=remoting/http-connector=http-remoting-connector:undefine-attribute(name=security-realm)
----

[source,xml,options="nowrap"]
----
  <subsystem xmlns="urn:jboss:domain:remoting:4.0">
    ...
    <http-connector name="http-remoting-connector" connector-ref="default" sasl-authentication-factory="application-security-sasl"/>
  </subsystem>
----

If this new configuration was to be used to secure the management
interfaces more suitable names should be chosen but the following
commands illustrate how to set the two authentication factories and
clear the existing security realm reference.

[source,options="nowrap"]
----
./core-service=management/management-interface=http-interface:write-attribute(name=http-authentication-factory, value=application-security-http)
./core-service=management/management-interface=http-interface:write-attribute(name=http-upgrade.sasl-authentication-factory, value=application-security-sasl)
./core-service=management/management-interface=http-interface:undefine-attribute(name=security-realm)
----

[source,xml,options="nowrap"]
----
  <management-interfaces>
    <http-interface http-authentication-factory="application-security-http">
      <http-upgrade enabled="true" sasl-authentication-factory="application-security-sasl"/>
      <socket-binding http="management-http"/>
    </http-interface>
  </management-interfaces>
----
