Init WFuzz state

This commit is contained in:
Jan Stárek
2019-10-09 13:24:01 +02:00
parent 7c3ed5ef0b
commit a5eb2a97e1
114 changed files with 6221 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
using System;
using Microsoft.OpenApi.Models;
using Models;
namespace Parser
{
public static class AttributeParser
{
public static UriAttribute ParseAttribute(OpenApiParameter parameter)
{
if (parameter.In == ParameterLocation.Path || parameter.In == ParameterLocation.Query)
{
if (parameter.Schema == null || parameter.Schema.Type == null && parameter.Schema.Format == null)
{
throw new ArgumentException("We do not know anything useful about passed URI parameter.");
}
UriAttribute attribute = new UriAttribute(parameter.Name, parameter.Required)
{
ExampleValue = ContentParser.GetStringExampleFromContent(parameter.Example, parameter.Examples) ??
ContentParser.GetSingleExample(parameter.Schema?.Example) ??
PrimitiveDataTypeExampleGenerator.GenerateExampleValueByType(parameter.Schema.Type, parameter.Schema.Format),
Type = parameter.Schema.Type,
Format = parameter.Schema.Format
};
return attribute;
}
return null;
}
}
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
namespace Parser
{
public static class ContentParser
{
public static string GetStringExampleFromContent(IOpenApiAny example, IDictionary<string, OpenApiExample> examples)
{
return GetSingleExample(example) ?? GetExampleFromExamplesDict(examples);
}
public static string GetSingleExample(IOpenApiAny example)
{
return example != null ? GetStringFromAnyType(example) : null;
}
// If there are more examples, take the first one
// To the future consider creating request for each example
static string GetExampleFromExamplesDict(IDictionary<string, OpenApiExample> examples)
{
return examples.Count > 0 ? GetSingleExample(examples.First().Value.Value) : null;
}
static string GetStringFromAnyType(IOpenApiAny value)
{
switch (value.AnyType)
{
case AnyType.Primitive:
return OpenApiAnyConvertor.GetPrimitiveValue(value);
case AnyType.Object:
case AnyType.Array:
return OpenApiAnyConvertor.GetJsonValue(value);
default:
throw new NotImplementedException("This data example type is not supported yet!");
}
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using Microsoft.OpenApi.Models;
using Models;
namespace Parser
{
public static class EndpointParser
{
public static List<Endpoint> ParseAllEndpoints(OpenApiDocument openApiDocument)
{
List<Endpoint> endpoints = new List<Endpoint>();
foreach (var path in openApiDocument.Paths)
{
endpoints.Add(ParseEndpoint(path));
}
return endpoints;
}
static Endpoint ParseEndpoint(KeyValuePair<string, OpenApiPathItem> path)
{
Endpoint endpoint = new Endpoint(path.Key);
foreach (KeyValuePair<OperationType, OpenApiOperation> operation in path.Value.Operations)
{
endpoint.Requests.Add(RequestParser.ParseRequest(operation));
}
return endpoint;
}
}
}

View File

@@ -0,0 +1,37 @@
using System.Collections.Generic;
using Microsoft.OpenApi.Models;
namespace Parser
{
public static class ExamplesParser
{
static readonly List<string> SupportedContentTypes = new List<string> { "application/json", "text/plain" };
public static string ParseExample(IDictionary<string, OpenApiMediaType> contentDict)
{
foreach (var supportedContentType in SupportedContentTypes)
{
if (contentDict.ContainsKey(supportedContentType))
return GetSpecificContentTypeExample(contentDict, supportedContentType);
}
return null;
}
static string GetSpecificContentTypeExample(IDictionary<string, OpenApiMediaType> contentDict, string contentType)
{
var content = contentDict[contentType];
return GetRealExample(content) ?? GetExampleFromSchema(content);
}
static string GetRealExample(OpenApiMediaType content)
{
return ContentParser.GetStringExampleFromContent(content.Example, content.Examples);
}
static string GetExampleFromSchema(OpenApiMediaType content)
{
return content.Schema != null ? ContentParser.GetStringExampleFromContent(content.Schema.Example, new Dictionary<string, OpenApiExample>()) : null;
}
}
}

View File

@@ -0,0 +1,68 @@
using System;
using System.Globalization;
using System.IO;
using System.Text;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Writers;
namespace Parser
{
public static class OpenApiAnyConvertor
{
public static string GetPrimitiveValue(IOpenApiAny value)
{
IOpenApiPrimitive primitive = (IOpenApiPrimitive) value;
switch (primitive.PrimitiveType)
{
case PrimitiveType.String:
OpenApiString stringValue = (OpenApiString) primitive;
return stringValue.Value;
case PrimitiveType.Boolean:
OpenApiBoolean booleanValue = (OpenApiBoolean) primitive;
return booleanValue.Value.ToString();
case PrimitiveType.Integer:
OpenApiInteger integerValue = (OpenApiInteger) primitive;
return integerValue.Value.ToString();
case PrimitiveType.Long:
OpenApiLong longValue = (OpenApiLong) primitive;
return longValue.Value.ToString();
case PrimitiveType.Float:
OpenApiFloat floatValue = (OpenApiFloat) primitive;
return floatValue.Value.ToString(CultureInfo.InvariantCulture);
case PrimitiveType.Double:
OpenApiDouble doubleValue = (OpenApiDouble) primitive;
return doubleValue.Value.ToString(CultureInfo.InvariantCulture);
case PrimitiveType.Byte:
OpenApiByte byteValue = (OpenApiByte) primitive;
return Encoding.Default.GetString(byteValue.Value);
case PrimitiveType.Binary:
OpenApiBinary binaryValue = (OpenApiBinary) primitive;
StringBuilder builder = new StringBuilder();
foreach (byte byteVal in binaryValue.Value)
{
builder.Append(Convert.ToString(byteVal, 2).PadLeft(8, '0'));
}
return builder.ToString();
case PrimitiveType.Date:
OpenApiDate dateValue = (OpenApiDate) primitive;
return dateValue.Value.ToString(CultureInfo.InvariantCulture);
case PrimitiveType.DateTime:
OpenApiDateTime dateTimeValue = (OpenApiDateTime) primitive;
return dateTimeValue.Value.ToString();
case PrimitiveType.Password:
OpenApiPassword passwordValue = (OpenApiPassword) primitive;
return passwordValue.Value;
default:
throw new NotImplementedException("This data example type is not supported yet!");
}
}
public static string GetJsonValue(IOpenApiAny value)
{
StringBuilder builder = new StringBuilder();
value.Write(new OpenApiJsonWriter(new StringWriter(builder)), OpenApiDocumentParser.Version);
return builder.ToString();
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.OpenApi;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Readers;
namespace Parser
{
public static class OpenApiDocumentParser
{
public static OpenApiSpecVersion Version;
public static OpenApiDocument ParseOpenApiDocument(string openApiDocFilePath)
{
OpenApiDocument openApiDocument;
using (FileStream stream = File.Open(openApiDocFilePath, FileMode.Open))
{
openApiDocument = new OpenApiStreamReader().Read(stream, out var diagnostic);
StoreDocumentVersion(diagnostic.SpecificationVersion);
PrintParsingErrors(diagnostic.Errors);
}
return openApiDocument;
}
static void PrintParsingErrors(IList<OpenApiError> errors)
{
foreach (var openApiError in errors)
{
Console.WriteLine("WARNING: Following parsing error occurs: " + openApiError.Message);
}
}
static void StoreDocumentVersion(OpenApiSpecVersion version)
{
Version = version;
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.1.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Models\Models.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,48 @@
using System;
using System.Text;
namespace Parser
{
// Data types for Open API 2 and OpenAPI 3 are basically the same:
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md
public static class PrimitiveDataTypeExampleGenerator
{
public static string GenerateExampleValueByType(string type, string format)
{
switch (type)
{
case "integer":
return "42";
case "number":
return "42.0";
case "boolean":
return "True";
case "string":
{
const string example = "example";
switch (format)
{
case null:
return example;
case "byte":
var plainTextBytes = Encoding.UTF8.GetBytes(example);
return Encoding.Default.GetString(plainTextBytes);
case "binary":
return "01234567";
case "date":
return "2002-10-02";
case "date-time":
return "2002-10-02T10:00:00-05:00";
case "password":
return example;
}
break;
}
}
throw new NotImplementedException("Unrecognized value data type! Check the OpenAPI documentation for new types!");
}
}
}

View File

@@ -0,0 +1,59 @@
using System.Collections.Generic;
using Microsoft.OpenApi.Models;
using Models;
namespace Parser
{
public static class RequestParser
{
public static Request ParseRequest(KeyValuePair<OperationType, OpenApiOperation> operation)
{
var request = new Request(operation.Key.ToString())
{
Summary = operation.Value.Summary,
BodyExample = GetBodyExample(operation.Value.RequestBody),
BodySchema = GetBodySchema(operation.Value.RequestBody),
UriAttributes = ParseUriAttributes(operation.Value),
Responses = ParseResponses(operation.Value)
};
return request;
}
static string GetBodyExample(OpenApiRequestBody body)
{
return body != null ? ExamplesParser.ParseExample(body.Content) : null;
}
static Dictionary<string, object> GetBodySchema(OpenApiRequestBody body)
{
return body != null ? SchemaParser.ParseSchema(body.Content) : null;
}
static List<UriAttribute> ParseUriAttributes(OpenApiOperation operation)
{
List<UriAttribute> attributes = new List<UriAttribute>();
foreach (var parameter in operation.Parameters)
{
var attribute = AttributeParser.ParseAttribute(parameter);
if (attribute != null)
{
attributes.Add(attribute);
}
}
return attributes;
}
static List<Response> ParseResponses(OpenApiOperation operation)
{
List<Response> responses = new List<Response>();
foreach (var openApiResponse in operation.Responses)
{
responses.Add(ResponseParser.ParseResponse(openApiResponse));
}
return responses;
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using Microsoft.OpenApi.Models;
using Models;
namespace Parser
{
public static class ResponseParser
{
public static Response ParseResponse(KeyValuePair<string, OpenApiResponse> openApiResponse)
{
string example = null;
if (openApiResponse.Value != null)
example = ExamplesParser.ParseExample(openApiResponse.Value.Content);
var response = new Response
{
Example = example,
StatusCode = ParseStatusCode(openApiResponse.Key)
};
return response;
}
static int ParseStatusCode(string responseKey)
{
if (responseKey == "default")
{
return -1;
}
if (!int.TryParse(responseKey, out var statusCode))
{
throw new NotImplementedException("Provided status code is not supported: " + responseKey);
}
return statusCode;
}
}
}

View File

@@ -0,0 +1,78 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.OpenApi.Models;
namespace Parser
{
public static class SchemaParser
{
public static Dictionary<string, object> ParseSchema(IDictionary<string, OpenApiMediaType> contentDict)
{
return contentDict.ContainsKey("application/json") ? ParseSchemaProperties(contentDict["application/json"].Schema) : null;
}
static Dictionary<string, object> ParseSchemaProperties(OpenApiSchema schema)
{
Dictionary<string, object> parsedSchema = new Dictionary<string, object>();
if (schema.AdditionalPropertiesAllowed && schema.AdditionalProperties != null)
{
Dictionary<string, object> nestedSchema = ParseSchemaProperties(schema.AdditionalProperties);
// Create single object with string key: "AdditionalPropertyExample1" and with nested schema as it is in documentation
// There can be multiple nested objects, but we want to reduce number of generated test cases
parsedSchema.Add("AdditionalPropertyExample1", nestedSchema);
}
if (schema.AllOf.Count > 0)
{
foreach (var openApiSchema in schema.AllOf)
{
Dictionary<string, object> nestedSchema = ParseSchemaProperties(openApiSchema);
parsedSchema = MergeTwoDictionaries(nestedSchema, parsedSchema);
}
}
if (schema.OneOf.Count > 0)
{
Dictionary<string, object> nestedSchema = ParseSchemaProperties(schema.OneOf.First());
parsedSchema = MergeTwoDictionaries(nestedSchema, parsedSchema);
}
if (schema.AnyOf.Count > 0)
{
Dictionary<string, object> nestedSchema = ParseSchemaProperties(schema.AnyOf.First());
parsedSchema = MergeTwoDictionaries(nestedSchema, parsedSchema);
}
if (schema.Properties != null && schema.Properties.Count > 0)
{
foreach (var property in schema.Properties)
{
Dictionary<string, object> nestedSchema = ParseSchemaProperties(property.Value);
parsedSchema.Add(property.Key, nestedSchema);
}
}
else if (schema.Type != null && schema.Type.ToLower() == "array")
{
parsedSchema.Add("Type", schema.Type);
Dictionary<string, object> arrayItemsSchema = ParseSchemaProperties(schema.Items);
parsedSchema.Add("ArrayItemSchema", arrayItemsSchema);
}
else if (schema.Type != "object")
{
parsedSchema.Add("Title", schema.Title);
parsedSchema.Add("Type", schema.Type);
parsedSchema.Add("Format", schema.Format);
parsedSchema.Add("Example", ContentParser.GetSingleExample(schema.Example));
}
return parsedSchema;
}
static Dictionary<string, object> MergeTwoDictionaries(Dictionary<string, object> first, Dictionary<string, object> second)
{
return new List<Dictionary<string, object>> { first, second }.SelectMany(dict => dict).ToDictionary(pair => pair.Key, pair => pair.Value);
}
}
}