﻿<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="WebApplicationFirewall"
           targetNamespace="http://waher.se/Schema/WAF.xsd"
           elementFormDefault="qualified"
           xmlns="http://waher.se/Schema/WAF.xsd"
           xmlns:mstns="http://waher.se/Schema/WAF.xsd"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">

	<xs:element name="Root">
		<xs:complexType>
			<xs:choice minOccurs="0" maxOccurs="unbounded">
				<xs:group ref="Rule" minOccurs="0" maxOccurs="unbounded"/>
			</xs:choice>
			<xs:attribute name="defaultResult" type="Result" use="optional" default="Allow"/>
		</xs:complexType>
	</xs:element>

	<xs:simpleType name="Result">
		<xs:restriction base="xs:string">
			<xs:enumeration value="Allow"/>
			<xs:enumeration value="Forbid"/>
			<xs:enumeration value="NotFound"/>
			<xs:enumeration value="RateLimited"/>
			<xs:enumeration value="Ignore"/>
			<xs:enumeration value="Close"/>
		</xs:restriction>
	</xs:simpleType>

	<xs:group name="Rule">
		<xs:choice>
			<xs:element name="Allow" type="WafAction"/>
			<xs:element name="Forbid" type="WafAction"/>
			<xs:element name="NotFound" type="WafAction"/>
			<xs:element name="RateLimited" type="WafAction"/>
			<xs:element name="Ignore" type="WafAction"/>
			<xs:element name="Close" type="WafAction"/>
			<xs:element name="TemporaryRedirection" type="WafRedirection"/>
			<xs:element name="PermanentRedirection" type="WafRedirection"/>
			<xs:element name="SeeOther" type="WafRedirection"/>
			<xs:element name="UriMatch" type="WafCondition"/>
			<xs:element name="PathMatch" type="WafCondition"/>
			<xs:element name="ResourceMatch" type="WafCondition"/>
			<xs:element name="MethodMatch" type="WafCondition"/>
			<xs:element name="ContentTypeMatch" type="WafCondition"/>
			<xs:element name="ContentMatch" type="WafCondition"/>
			<xs:element name="EndpointMatch" type="WafCondition"/>
			<xs:element name="CertificateSubjectMatch" type="WafCertificateCondition"/>
			<xs:element name="CertificateIssuerMatch" type="WafCertificateCondition"/>
			<xs:element name="CertificateSerialNumberMatch" type="WafCertificateCondition"/>
			<xs:element name="HeaderMatch" type="WafNamedCondition"/>
			<xs:element name="QueryMatch" type="WafNamedCondition"/>
			<xs:element name="IsBlocked" type="WafComparison"/>
			<xs:element name="IsPermanentlyBlocked" type="WafComparison"/>
			<xs:element name="IsTemporarilyBlocked" type="WafComparison"/>
			<xs:element name="IsUnencrypted" type="WafComparison"/>
			<xs:element name="IsEncrypted">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafComparison">
							<xs:attribute name="minSecurityStrength" type="xs:positiveInteger" use="required"/>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
			<xs:element name="IsContent">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafComparison">
							<xs:attribute name="manifestFile" type="xs:string" use="required"/>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
			<xs:element name="RequestsExceeded" type="RateLimitComparison"/>
			<xs:element name="BytesExceeded" type="RateLimitComparison"/>
			<xs:element name="ConnectionsExceeded" type="RateLimitComparison"/>
			<xs:element name="ContentSizeExceeded" type="LimitComparison"/>
			<xs:element name="FromIpLocation">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafComparison">
							<xs:attribute name="country" type="xs:string" use="optional"/>
							<xs:attribute name="region" type="xs:string" use="optional"/>
							<xs:attribute name="city" type="xs:string" use="optional"/>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
			<xs:element name="FromIp">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafComparison">
							<xs:attribute name="value" type="xs:string" use="required"/>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
			<xs:element name="LogEvent">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafActionWithTags">
							<xs:attribute name="message" type="xs:string" use="required"/>
							<xs:attribute name="type" type="xs:string" use="optional" default="Informational"/>
							<xs:attribute name="level" type="xs:string" use="optional" default="Minor"/>
							<xs:attribute name="object" type="xs:string" use="optional"/>
							<xs:attribute name="actor" type="xs:string" use="optional"/>
							<xs:attribute name="eventId" type="xs:string" use="optional"/>
							<xs:attribute name="facility" type="xs:string" use="optional"/>
							<xs:attribute name="module" type="xs:string" use="optional"/>
							<xs:attribute name="stackTrace" type="xs:string" use="optional"/>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
			<xs:element name="LedgerEntry">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafActionWithTags">
							<xs:attribute name="collection" type="xs:string" use="required"/>
							<xs:attribute name="type" type="xs:string" use="required"/>
							<xs:attribute name="archivingTimeDays" type="xs:positiveInteger" use="required"/>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
			<xs:element name="AddOpenIntelligence" type="WafActionOpenIntelligence"/>
			<xs:element name="HasOpenIntelligence">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafActionOpenIntelligence">
							<xs:choice minOccurs="0" maxOccurs="unbounded">
								<xs:group ref="Rule" minOccurs="0" maxOccurs="unbounded"/>
							</xs:choice>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
			<xs:element name="Delay">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafAction">
							<xs:attribute name="seconds" type="xs:string" use="required"/>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
			<xs:element name="Call" type="WafActionReference"/>
			<xs:element name="References" type="WafActions"/>
			<xs:element name="If">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafComparison">
							<xs:attribute name="condition" type="xs:string" use="required"/>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
			<xs:element name="BlockEndpoint">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafAction">
							<xs:attribute name="reason" type="xs:string" use="required"/>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
			<xs:element name="AuditFailure" type="WafAuditAction"/>
			<xs:element name="AuditSuccess" type="WafAuditAction"/>
			<xs:element name="ClearCounter" type="WafActionWithName"/>
			<xs:element name="IncrementCounter" type="WafActionWithNameAndDelta"/>
			<xs:element name="DecrementCounter" type="WafActionWithNameAndDelta"/>
			<xs:element name="TestCounter">
				<xs:complexType>
					<xs:complexContent>
						<xs:extension base="WafActions">
							<xs:attribute name="name" type="xs:string" use="required"/>
							<xs:attribute name="delta" type="xs:string" use="optional"/>
							<xs:attribute name="above" type="xs:string" use="optional"/>
							<xs:attribute name="below" type="xs:string" use="optional"/>
						</xs:extension>
					</xs:complexContent>
				</xs:complexType>
			</xs:element>
		</xs:choice>
	</xs:group>

	<xs:simpleType name="EventType">
		<xs:restriction base="xs:string">
			<xs:enumeration value="Debug"/>
			<xs:enumeration value="Informational"/>
			<xs:enumeration value="Notice"/>
			<xs:enumeration value="Warning"/>
			<xs:enumeration value="Error"/>
			<xs:enumeration value="Critical"/>
			<xs:enumeration value="Alert"/>
			<xs:enumeration value="Emergency"/>
		</xs:restriction>
	</xs:simpleType>

	<xs:simpleType name="EventLevel">
		<xs:restriction base="xs:string">
			<xs:enumeration value="Minor"/>
			<xs:enumeration value="Medium"/>
			<xs:enumeration value="Major"/>
		</xs:restriction>
	</xs:simpleType>

	<xs:complexType name="WafAction">
		<xs:attribute name="id" type="xs:string" use="optional"/>
	</xs:complexType>

	<xs:complexType name="WafRedirection">
		<xs:complexContent>
			<xs:extension base="WafAction">
				<xs:attribute name="location" type="xs:string" use="required"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafActions">
		<xs:complexContent>
			<xs:extension base="WafAction">
				<xs:choice minOccurs="0" maxOccurs="unbounded">
					<xs:group ref="Rule" minOccurs="0" maxOccurs="unbounded"/>
				</xs:choice>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafComparison">
		<xs:complexContent>
			<xs:extension base="WafActions"/>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafCondition">
		<xs:complexContent>
			<xs:extension base="WafComparison">
				<xs:attribute name="value" type="xs:string" use="required"/>
				<xs:attribute name="mode" type="ComparisonMode" use="required"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafNamedCondition">
		<xs:complexContent>
			<xs:extension base="WafCondition">
				<xs:attribute name="name" type="xs:string" use="required"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafCertificateCondition">
		<xs:complexContent>
			<xs:extension base="WafCondition">
				<xs:attribute name="trust" type="xs:string" use="optional"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:simpleType name="ComparisonMode">
		<xs:restriction base="xs:string">
			<xs:enumeration value="ContainsRegex"/>
			<xs:enumeration value="StartsWithRegex"/>
			<xs:enumeration value="EndsWithRegex"/>
			<xs:enumeration value="ExactRegex"/>
			<xs:enumeration value="ContainsRegexIgnoreCase"/>
			<xs:enumeration value="StartsWithRegexIgnoreCase"/>
			<xs:enumeration value="EndsWithRegexIgnoreCase"/>
			<xs:enumeration value="ExactRegexIgnoreCase"/>
			<xs:enumeration value="ContainsConstant"/>
			<xs:enumeration value="StartsWithConstant"/>
			<xs:enumeration value="EndsWithConstant"/>
			<xs:enumeration value="ExactConstant"/>
			<xs:enumeration value="ContainsConstantIgnoreCase"/>
			<xs:enumeration value="StartsWithConstantIgnoreCase"/>
			<xs:enumeration value="EndsWithConstantIgnoreCase"/>
			<xs:enumeration value="ExactConstantIgnoreCase"/>
			<xs:enumeration value="Script"/>
			<xs:enumeration value="List"/>
			<xs:enumeration value="ListIgnoreCase"/>
			<xs:enumeration value="FileList"/>
			<xs:enumeration value="FileListIgnoreCase"/>
			<xs:enumeration value="DatabaseList"/>
			<xs:enumeration value="DatabaseListIgnoreCase"/>
		</xs:restriction>
	</xs:simpleType>

	<xs:complexType name="LimitComparison">
		<xs:complexContent>
			<xs:extension base="WafActions">
				<xs:attribute name="limit" type="xs:positiveInteger" use="required"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="RateLimitComparison">
		<xs:complexContent>
			<xs:extension base="LimitComparison">
				<xs:attribute name="duration" type="xs:duration" use="required"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafActionWithTags">
		<xs:complexContent>
			<xs:extension base="WafAction">
				<xs:sequence>
					<xs:element name="Tag" minOccurs="0" maxOccurs="unbounded">
						<xs:complexType>
							<xs:attribute name="name" type="xs:string" use="required"/>
							<xs:attribute name="value" type="xs:string" use="required"/>
						</xs:complexType>
					</xs:element>
				</xs:sequence>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafActionOpenIntelligence">
		<xs:complexContent>
			<xs:extension base="WafActionWithTags">
				<xs:attribute name="duration" type="xs:string" use="required"/>
				<xs:attribute name="vector" type="xs:string" use="optional"/>
				<xs:attribute name="protocol" type="xs:string" use="optional"/>
				<xs:attribute name="classification" type="xs:string" use="optional"/>
				<xs:attribute name="code" type="xs:string" use="optional"/>
				<xs:attribute name="message" type="xs:string" use="optional"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafActionReference">
		<xs:complexContent>
			<xs:extension base="WafAction">
				<xs:attribute name="reference" type="xs:string" use="required"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafAuditAction">
		<xs:complexContent>
			<xs:extension base="WafActionWithTags">
				<xs:attribute name="message" type="xs:string" use="required"/>
				<xs:attribute name="protocol" type="xs:string" use="optional"/>
				<xs:attribute name="userName" type="xs:string" use="optional"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafActionWithName">
		<xs:complexContent>
			<xs:extension base="WafAction">
				<xs:attribute name="name" type="xs:string" use="required"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="WafActionWithNameAndDelta">
		<xs:complexContent>
			<xs:extension base="WafActionWithName">
				<xs:attribute name="delta" type="xs:string" use="optional"/>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

</xs:schema>
