<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright The WildFly Authors
  ~ SPDX-License-Identifier: Apache-2.0
  -->

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="urn:jboss:domain:security:2.0"
           xmlns="urn:jboss:domain:security:2.0"
           elementFormDefault="qualified"
           attributeFormDefault="unqualified"
           version="3.0">

   <!-- The security subsystem root element -->
   <xs:element name="subsystem" type="security-containerType" />

   <!-- The security container configuration -->
   <xs:complexType name="security-containerType">
      <xs:annotation>
         <xs:documentation>
                <![CDATA[
                    The security subsystem, used to configure authentication and authorization.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:all>
         <xs:element name="security-management" type="securityManagementType" minOccurs="0" maxOccurs="1"/>
         <xs:element name="security-domains" type="securityDomainsType" minOccurs="0" maxOccurs="1"/>
         <xs:element name="vault" type="vaultType" minOccurs="0" maxOccurs="1"/>
         <xs:element name="elytron-integration" type="elytronIntegrationType" minOccurs="0" maxOccurs="1"/>
      </xs:all>
   </xs:complexType>

   <!-- The security management element -->
   <xs:complexType name="securityManagementType">
      <xs:annotation>
         <xs:documentation>
                <![CDATA[
                    The optional "deep-copy-subject-mode" attribute sets the copy mode of subjects done by the security
                    managers to be deep copies that makes copies of the subject principals and credentials if they are
                    cloneable. It should be set to true if subject include mutable content that can be corrupted when
                    multiple threads have the same identity and cache flushes/logout clearing the subject in one thread
                    results in subject references affecting other threads. Default value is "false".
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:attribute name="deep-copy-subject-mode" type="xs:boolean" use="optional"/>
       <xs:attribute name="initialize-jacc" type="xs:boolean" use="optional" default="true">
           <xs:annotation>
               <xs:documentation>
                   <![CDATA[
                       Indicates if this subsystem should be in charge of initializing JACC related services. This attribute can be used
                       to turn of JACC initialization from this subsystem in case Elytron is being used in parallel. In this case, JACC initialization
                       will only be performed by this subsystem. If you are using only Elytron subsystem, you can set this attribute to "false" and specify
                       a similar attribute in Elytron subsystem to enable JACC. Default value is "true".
                   ]]>
               </xs:documentation>
           </xs:annotation>
       </xs:attribute>
   </xs:complexType>

   <!-- Configuration for security domains -->
   <xs:complexType name="securityDomainsType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Configures security domains for applications.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="security-domain" type="securityDomainType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:complexType>

   <xs:complexType name="securityDomainType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Definition of a security domain.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:choice>
            <xs:element name="authentication" type="authenticationType" minOccurs="0" maxOccurs="1"/>
            <xs:element name="authentication-jaspi" type="authenticationJaspiType" minOccurs="0" maxOccurs="1"/>
         </xs:choice>
         <xs:element name="authorization" type="authorizationType" minOccurs="0" maxOccurs="1"/>
         <xs:element name="acl" type="aclType" minOccurs="0" maxOccurs="1"/>
         <xs:element name="mapping" type="mappingType" minOccurs="0" maxOccurs="1"/>
         <xs:element name="audit" type="auditType" minOccurs="0" maxOccurs="1"/>
         <xs:element name="identity-trust" type="identityTrustType" minOccurs="0" maxOccurs="1"/>
         <xs:element name="jsse" type="jsseType" minOccurs="0" maxOccurs="1"/>
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="required"/>
      <xs:attribute name="cache-type" type="xs:string" use="optional"/>
   </xs:complexType>

   <xs:complexType name="authenticationType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Authentication configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="login-module" type="loginModuleType" minOccurs="1" maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:complexType>

   <xs:complexType name="authenticationJaspiType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    JASPI authentication configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="login-module-stack" type="loginModuleStackType" maxOccurs="unbounded"/>
         <xs:element name="auth-module" type="authModuleType" maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:complexType>

   <xs:complexType name="authorizationType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Authorization configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="policy-module" type="policyModuleType" maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:complexType>

   <xs:complexType name="aclType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    ACL configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="acl-module" type="aclModuleType" maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:complexType>

   <xs:complexType name="mappingType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Mapping configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="mapping-module" type="mappingModuleType" maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:complexType>

   <xs:complexType name="auditType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Audit configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="provider-module" type="providerModuleType" maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:complexType>

   <xs:complexType name="identityTrustType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Identity trust configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="trust-module" type="trustModuleType" maxOccurs="unbounded"/>
      </xs:sequence>
   </xs:complexType>

   <xs:simpleType name="module-option-flag">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    The flag attribute controls how a login module
                    participates in the overall procedure.
                    Required - The LoginModule is required to succeed. If it
                    succeeds or fails, authentication still continues to proceed
                    down the LoginModule list.

                    Requisite - The LoginModule is required to succeed. If it succeeds,
                    authentication continues down the LoginModule list. If it fails,
                    control immediately returns to the application (authentication does not proceed
                    down the LoginModule list).

                    Sufficient - The LoginModule is  not required to succeed. If it does
                    succeed, control immediately returns to the application (authentication
                    does not proceed down the LoginModule list). If it fails,
                    authentication continues down the LoginModule list.

                    Optional - The LoginModule is not required to succeed. If it succeeds or
                    fails, authentication still continues to proceed down the
                    LoginModule list.

                    The overall authentication succeeds only if
                    all required and requisite LoginModules succeed. If a
                    sufficient LoginModule is configured and succeeds, then only
                    the required and requisite LoginModules prior to that
                    sufficient LoginModule need to have succeeded for the overall
                    authentication to succeed. If no required or requisite
                    LoginModules are configured for an application, then at least
                    one sufficient or optional LoginModule must succeed.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:restriction base="xs:token">
         <xs:enumeration value="required"/>
         <xs:enumeration value="requisite"/>
         <xs:enumeration value="sufficient"/>
         <xs:enumeration value="optional"/>
      </xs:restriction>
   </xs:simpleType>

   <xs:complexType name="loginModuleType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Login module configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="module-option" type="propertyType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="optional"/>
      <xs:attribute name="code" type="xs:string" use="required"/>
      <xs:attribute name="flag" type="module-option-flag" use="required"/>
      <xs:attribute name="module" type="xs:string" use="optional"/>
   </xs:complexType>

   <xs:complexType name="propertyType">
      <xs:attribute name="name" type="xs:string" use="required"/>
      <xs:attribute name="value" type="xs:string" use="required"/>
   </xs:complexType>

   <xs:complexType name="loginModuleStackType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Login module configuration for JASPI.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
          <xs:element name="login-module" type="loginModuleType" minOccurs="1" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="required"/>
   </xs:complexType>

   <xs:complexType name="authModuleType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Authentication module configuration for JASPI.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="module-option" type="propertyType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="optional"/>
      <xs:attribute name="code" type="xs:string" use="required"/>
      <xs:attribute name="flag" type="module-option-flag" use="optional"/>
      <xs:attribute name="login-module-stack-ref" type="xs:string" use="optional"/>
      <xs:attribute name="module" type="xs:string" use="optional"/>
   </xs:complexType>

   <xs:complexType name="policyModuleType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Authorization module configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="module-option" type="propertyType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="optional"/>
      <xs:attribute name="code" type="xs:string" use="required"/>
      <xs:attribute name="flag" type="module-option-flag" use="required"/>
      <xs:attribute name="module" type="xs:string" use="optional"/>
   </xs:complexType>

   <xs:complexType name="aclModuleType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    ACL module configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
         <xs:element name="module-option" type="propertyType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="optional"/>
      <xs:attribute name="code" type="xs:string" use="required"/>
      <xs:attribute name="flag" type="module-option-flag" use="required"/>
      <xs:attribute name="module" type="xs:string" use="optional"/>
   </xs:complexType>

   <xs:complexType name="mappingModuleType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Mapping module configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
          <xs:element name="module-option" type="propertyType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="optional"/>
      <xs:attribute name="type" type="xs:string" use="optional"/>
      <xs:attribute name="code" type="xs:string" use="required"/>
      <xs:attribute name="module" type="xs:string" use="optional"/>
   </xs:complexType>

   <xs:complexType name="providerModuleType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Audit module configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
          <xs:element name="module-option" type="propertyType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="optional"/>
      <xs:attribute name="code" type="xs:string" use="required"/>
      <xs:attribute name="module" type="xs:string" use="optional"/>
   </xs:complexType>

   <xs:complexType name="trustModuleType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Identity trust module configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
          <xs:element name="module-option" type="propertyType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="name" type="xs:string" use="optional"/>
      <xs:attribute name="code" type="xs:string" use="required"/>
      <xs:attribute name="flag" type="module-option-flag" use="required"/>
      <xs:attribute name="module" type="xs:string" use="optional"/>
   </xs:complexType>

   <xs:complexType name="jsseType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    JSSE configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
        <xs:element name="property" type="propertyType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="keystore-password" type="xs:string" use="optional"/>
      <xs:attribute name="keystore-type" type="xs:string" use="optional"/>
      <xs:attribute name="keystore-url" type="xs:string" use="optional"/>
      <xs:attribute name="keystore-provider" type="xs:string" use="optional"/>
      <xs:attribute name="keystore-provider-argument" type="xs:string" use="optional"/>
      <xs:attribute name="key-manager-factory-algorithm" type="xs:string" use="optional"/>
      <xs:attribute name="key-manager-factory-provider" type="xs:string" use="optional"/>
      <xs:attribute name="truststore-password" type="xs:string" use="optional"/>
      <xs:attribute name="truststore-type" type="xs:string" use="optional"/>
      <xs:attribute name="truststore-url" type="xs:string" use="optional"/>
      <xs:attribute name="truststore-provider" type="xs:string" use="optional"/>
      <xs:attribute name="truststore-provider-argument" type="xs:string" use="optional"/>
      <xs:attribute name="trust-manager-factory-algorithm" type="xs:string" use="optional"/>
      <xs:attribute name="trust-manager-factory-provider" type="xs:string" use="optional"/>
      <xs:attribute name="client-alias" type="xs:string" use="optional"/>
      <xs:attribute name="server-alias" type="xs:string" use="optional"/>
      <xs:attribute name="service-auth-token" type="xs:string" use="optional"/>
      <xs:attribute name="client-auth" type="xs:boolean" use="optional"/>
      <xs:attribute name="cipher-suites" type="xs:string" use="optional"/>
      <xs:attribute name="protocols" type="xs:string" use="optional"/>
   </xs:complexType>

   <xs:complexType name="vaultType">
      <xs:annotation>
         <xs:documentation>
               <![CDATA[
                    Vault Configuration.
                ]]>
         </xs:documentation>
      </xs:annotation>
      <xs:sequence>
          <xs:element name="vault-option" type="propertyType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="code" type="xs:string" use="optional"/>
   </xs:complexType>

   <!-- ELYTRON INTEGRATION SCHEMA -->
   <xs:complexType name="elytronIntegrationType">
       <xs:annotation>
           <xs:documentation>
               <![CDATA[
                    This type specifies the elements and attributes used to configure the integration of the legacy
                    security subsystem with the new security framework provided by the Elytron project.
                ]]>
           </xs:documentation>
       </xs:annotation>
       <xs:sequence>
           <xs:element name="security-realms" type="securityRealmsType" minOccurs="0" maxOccurs="1"/>
           <xs:element name="tls" type="tlsType" minOccurs="0" maxOccurs="1"/>
       </xs:sequence>
   </xs:complexType>

   <xs:complexType name="securityRealmsType">
       <xs:annotation>
           <xs:documentation>
               <![CDATA[
                   This type specifies the elements and attributes used to configure the Elytron compatible realms that
                   are to be exported by the legacy subsystem. Each realm delegates the authentication decision to a
                   legacy JAAS-based security domain.
               ]]>
           </xs:documentation>
       </xs:annotation>
       <xs:sequence>
           <xs:element name="elytron-realm" type="elytronRealmType" minOccurs="0" maxOccurs="unbounded"/>
       </xs:sequence>
   </xs:complexType>

    <xs:complexType name="elytronRealmType">
        <xs:annotation>
            <xs:documentation>
                <![CDATA[
                    The elytron-realm element allows for the configuration of Elytron-compatible realms that delegate
                    the authentication process to legacy security domains exposed by the legacy security subsystem. These
                    realms provide a bridge between the new Elytron security domains and the legacy JAAS-based security
                    domains and are meant to ease the migration process to Elytron by allowing users to start using Elytron
                    without having to immediately switch their JAAS-based login modules to the new Elytron realms.

                    The realms are exported as capabilities and can be consumed in the Elytron subsystem without requiring
                    any extra wiring between the subsystems (i.e. no dependencies to the legacy subsystem), which promotes
                    a separation that will ease the removal of the legacy subsystem in the future.

                    The export-realm element contains the following attributes:

                     * name - the name of the realm that will be exported. It must be unique and must not match any of
                     the realms already declared in the Elytron subsystem.

                     * legacy-jaas-config - the name of the legacy security domain to which the exported realm will delegate
                     the authentication decision.

                     * apply-role-mappers - if true the realm will apply any role-mappers specified in the legacy JAAS
                     security domain to the roles extracted from the authenticated Subject when creating an authorization
                     identity. If not specified this attribute defaults to true.
                ]]>
            </xs:documentation>
        </xs:annotation>
        <xs:attribute name="name" type="xs:string" use="required"/>
        <xs:attribute name="legacy-jaas-config" type="xs:string" use="required"/>
        <xs:attribute name="apply-role-mappers" type="xs:boolean" use="optional" default="true"/>
    </xs:complexType>

    <xs:complexType name="tlsType">
        <xs:annotation>
            <xs:documentation>
                <![CDATA[
                    This type specifies the elements used to configure the Elytron-compatible TLS entities that are to
                    be exported by the legacy subsystem. A legacy security domain can be used to export TLS entities such
                    as key/trust stores and key/trust managers when it has a JSSE configuration that enables the legacy
                    domain to produce these entities.
                ]]>
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="elytron-key-store" type="tlsEntityType" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element name="elytron-trust-store" type="tlsEntityType" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element name="elytron-key-manager" type="tlsEntityType" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element name="elytron-trust-manager" type="tlsEntityType" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="tlsEntityType">
        <xs:annotation>
            <xs:documentation>
                <![CDATA[
                    This type contains the attributes used to export Elytron-compatible TLS entities (key/trust stores
                    and key/trust managers).

                    The entities are exported as capabilities and can be consumed in the Elytron subsystem without requiring
                    any extra wiring between the subsystems (i.e. no dependencies to the legacy subsystem), which promotes
                    a separation that will ease the removal of the legacy subsystem in the future.

                    This type contains the following attributes:

                    * name - the name of the entity being exported. It must be unique and must not match any of the entities
                    of the same type already declared in the Elytron subsystem.

                    NOTE: the Elytron subsystem uses the same key-store element to refer to both key stores and trust stores
                    and they are both exported as the same kind of capability. So care must be taken when exporting legacy
                    key stores and trust stores as the name used must be unique across all exported key stores and trust stores.

                    * legacy-jsse-config - the name of the legacy security domain that contains a JSSE configuration that
                    is capable of producing the entity being exported. For example, if a key store is being exported then the
                    legacy-jsse-config attribute must point to a legacy domain that contains a JSSE section that configures
                    a key store.


                ]]>
            </xs:documentation>
        </xs:annotation>
        <xs:attribute name="name" type="xs:string" use="required"/>
        <xs:attribute name="legacy-jsse-config" type="xs:string" use="required"/>
    </xs:complexType>
</xs:schema>
