Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
36a54f9
Redo 8.7.1 (#3469)
AdamL-Microsoft Aug 30, 2023
cad8e0e
Support custom ado fields that mark work items as duplicate (#3467)
kananb Aug 30, 2023
4d0e007
Update readme with archive message (#3408)
mgreisen Aug 31, 2023
762aecd
Bump tokio from 1.30.0 to 1.32.0 in /src/proxy-manager (#3425)
dependabot[bot] Aug 31, 2023
702f9f4
Bump tokio from 1.30.0 to 1.32.0 in /src/agent (#3424)
dependabot[bot] Aug 31, 2023
ef3ef00
Remove unnecessary method argument (#3473)
kananb Sep 1, 2023
4fbe92a
Bump elsa from 1.8.1 to 1.9.0 in /src/agent (#3411)
dependabot[bot] Sep 4, 2023
954e3dc
Bump tempfile from 3.7.1 to 3.8.0 in /src/agent (#3437)
dependabot[bot] Sep 5, 2023
30e90ac
Bump tempfile from 3.7.1 to 3.8.0 in /src/proxy-manager (#3436)
dependabot[bot] Sep 5, 2023
0610a62
Updating requirements.txt to accept >= onefuzztypes. (#3477)
nharper285 Sep 5, 2023
56788f7
Bump notify from 6.0.1 to 6.1.1 in /src/agent (#3435)
dependabot[bot] Sep 5, 2023
d355ecb
Bump azure_* crates (#3478)
Porges Sep 5, 2023
ad55d3b
Release 8.8.0 (#3466)
AdamL-Microsoft Sep 6, 2023
d624d38
Bump clap from 4.3.21 to 4.4.2 in /src/agent (#3484)
dependabot[bot] Sep 6, 2023
519c92f
Bump gimli from 0.27.3 to 0.28.0 in /src/agent (#3414)
dependabot[bot] Sep 6, 2023
7f9fbbe
Bump clap from 4.3.21 to 4.4.2 in /src/proxy-manager (#3474)
dependabot[bot] Sep 6, 2023
7789df1
Bump winreg from 0.50.0 to 0.51.0 in /src/agent (#3434)
dependabot[bot] Sep 6, 2023
e15acaf
Starting integration tests (#3438)
tevoinea Sep 7, 2023
96c39da
Fix sed checks for CLI versioning (#3486)
nharper285 Sep 7, 2023
6033ed1
Bump bytes from 1.4.0 to 1.5.0 in /src/agent (#3488)
dependabot[bot] Sep 10, 2023
1f04adb
Improve area/iteration path validation (#3489)
kananb Sep 11, 2023
e3b3617
Improve handling of unexpected breakpoints (#3493)
tevoinea Sep 13, 2023
68026da
Update azure_* crates (#3503)
Porges Sep 13, 2023
e2f38ce
Fuzz coverage recording (#3322)
tevoinea Sep 14, 2023
a2e0974
Reporting coverage on task start up (#3502)
nharper285 Sep 14, 2023
9bf5785
Remove feature flag from heartbeat metrics. (#3505)
nharper285 Sep 14, 2023
15603fb
Update archive notice. (#3507)
mgreisen Sep 15, 2023
fa259dd
Add onefuzz service version to job created events (#3504)
kananb Sep 20, 2023
bbe79e3
Tevoinea/add version checking in local tasks (#3517)
tevoinea Sep 21, 2023
80fe109
Create directories if they don't exist in the template (#3522)
tevoinea Sep 21, 2023
1cee562
Support for retention policies on containers (#3501)
Porges Sep 26, 2023
b67d86e
Bump rayon from 1.7.0 to 1.8.0 in /src/agent (#3520)
dependabot[bot] Sep 26, 2023
ecb2d32
Bump insta from 1.31.0 to 1.32.0 in /src/agent (#3521)
dependabot[bot] Sep 26, 2023
7bcc41c
Disable `repro` and `debug` VM CLI commands. (#3494)
nharper285 Sep 27, 2023
9132e11
Make modules case insenstive on windows (#3527)
tevoinea Sep 28, 2023
88faa81
Update windows interceptor list (#3528)
tevoinea Sep 28, 2023
88cae50
Template creation command (#3531)
tevoinea Sep 28, 2023
e10d8ea
Terminate process on timeout in windows for the coverage task (#3529)
chkeita Sep 29, 2023
7b79dd6
Ignore regression update when the work item is in some states (#3532)
chkeita Oct 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,24 @@ jobs:
key: ${{env.ACTIONS_CACHE_KEY_DATE}} # additional key for cache-busting
workspaces: src/agent
- name: Linux Prereqs
if: runner.os == 'Linux' && steps.cache-agent-artifacts.outputs.cache-hit != 'true'
if: runner.os == 'Linux'
run: |
sudo apt-get -y update
sudo apt-get -y install libssl-dev libunwind-dev build-essential pkg-config
sudo apt-get -y install libssl-dev libunwind-dev build-essential pkg-config clang
- name: Clone onefuzz-samples
run: git clone https://github.com/microsoft/onefuzz-samples
- name: Prepare for agent integration tests
shell: bash
working-directory: ./onefuzz-samples/examples/simple-libfuzzer
run: |
make
mkdir -p ../../../src/agent/onefuzz-task/tests/targets/simple
cp fuzz.exe ../../../src/agent/onefuzz-task/tests/targets/simple/fuzz.exe
cp *.pdb ../../../src/agent/onefuzz-task/tests/targets/simple/ 2>/dev/null || :
- name: Install Rust Prereqs
if: steps.rust-build-cache.outputs.cache-hit != 'true' && steps.cache-agent-artifacts.outputs.cache-hit != 'true'
shell: bash
run: src/ci/rust-prereqs.sh
- run: src/ci/agent.sh
if: steps.cache-agent-artifacts.outputs.cache-hit != 'true'
shell: bash
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
Expand All @@ -115,7 +123,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: 3.7
python-version: "3.10"
- name: lint
shell: bash
run: src/ci/check-check-pr.sh
Expand All @@ -129,7 +137,7 @@ jobs:
shell: bash
- uses: actions/setup-python@v4
with:
python-version: 3.7
python-version: "3.10"
- uses: actions/download-artifact@v3
with:
name: artifact-onefuzztypes
Expand Down Expand Up @@ -182,7 +190,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: 3.8
python-version: "3.10"
- name: lint
shell: bash
run: |
Expand All @@ -200,7 +208,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: 3.8
python-version: "3.10"
- name: lint
shell: bash
run: |
Expand All @@ -216,7 +224,7 @@ jobs:
- run: src/ci/set-versions.sh
- uses: actions/setup-python@v4
with:
python-version: 3.7
python-version: "3.10"
- run: src/ci/onefuzztypes.sh
- uses: actions/upload-artifact@v3
with:
Expand Down Expand Up @@ -473,7 +481,7 @@ jobs:
path: artifacts
- uses: actions/setup-python@v4
with:
python-version: 3.7
python-version: "3.10"
- name: Lint
shell: bash
run: |
Expand Down
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 8.8.0

### Added

* Agent: Added Mariner Linux support for agent VMs [#3306](https://github.com/microsoft/onefuzz/pull/3306)
* Service: Added support for custom ado fields that mark work items as duplicate [#3467](https://github.com/microsoft/onefuzz/pull/3467)
* Service: Permanently store OneFuzz job result data - # crashing input, # regression crashing input, etc. - in Azure storage [#3380](https://github.com/microsoft/onefuzz/pull/3380), [#3439](https://github.com/microsoft/onefuzz/pull/3439)
* Service: Added validation for Iteration/AreaPath on notifications when a job is submitted with a notification config and for `onefuzz debug notification test_template` [#3386](https://github.com/microsoft/onefuzz/pull/3386)

### Changed

* Agent: Updated libfuzzer-fuzz basic template to include required args and make it match cli [#3429](https://github.com/microsoft/onefuzz/pull/3429)
* Agent: Downgraded some debug logs from warn to debug [#3450](https://github.com/microsoft/onefuzz/pull/3450)
* CLI: Removed CLI commands from the local fuzzing tasks as they can now be described via yaml template [#3428](https://github.com/microsoft/onefuzz/pull/3428)
* Service: AutoScale table entries are now deleted on VMSS shutdown [#3455](https://github.com/microsoft/onefuzz/pull/3455)

### Fixed

* Agent: Fixed local path generation [#3432](https://github.com/microsoft/onefuzz/pull/3432), [#3460](https://github.com/microsoft/onefuzz/pull/3460)

## 8.7.1

### Fixed

* Service: Removed deprecated Azure retention policy setting that was causing scaleset deployment errors [#3452](https://github.com/microsoft/onefuzz/pull/3452)

## 8.7.0

### Added
Expand Down
2 changes: 1 addition & 1 deletion CURRENT_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8.7.0
8.8.0
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# <img src="docs/onefuzz_text.svg" height="120" alt="OneFuzz" />

# :exclamation: IMPORTANT NOTICE :exclamation:

**_August 31, 2023_**.

**_Since September 2020 when OneFuzz was first open sourced, we’ve been on a journey to create a best-in-class orchestrator for running fuzzers, driving security and quality into our products._**


**_Initially launched by a small group in MSR, OneFuzz has now become a significant internal platform within Microsoft. As such, we are regretfully archiving the project to focus our attention on becoming a more deeply integrated service within the company. Unfortunately, we aren’t a large enough team to live in both the open-source world and the internal Microsoft world with its own unique set of requirements._**

**_Our current plan is to archive the project in the next few months. That means we’ll still be making updates for a little while. Of course, even after it’s archived, you’ll still be able to fork it and make the changes you need. Once we’ve decided on a specific date for archiving, we’ll update this readme._**

**_Thanks for taking the journey with us._**

**_The OneFuzz team._**

---
**_Update: September 15 2023:_**
**_Our current target to archive the project is September 30th, 2023._**

---

[![Onefuzz build status](https://github.com/microsoft/onefuzz/workflows/Build/badge.svg?branch=main)](https://github.com/microsoft/onefuzz/actions/workflows/ci.yml?query=branch%3Amain)

## A self-hosted Fuzzing-As-A-Service platform
Expand Down
4 changes: 4 additions & 0 deletions contrib/onefuzz-job-azure-devops-pipeline/ado-work-items.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
"System.AreaPath": "OneFuzz-Ado-Integration",
"System.Title": "{{report.task_id}}"
},
"ado_duplicate_fields": {
"System.Reason": "My custom value that means a work item is a duplicate",
"Custom.Work.Item.Field": "My custom value that means a work item is a duplicate"
},
"on_duplicate": {
"increment": [],
"comment": "DUP {{report.input_sha256}} <br> Repro Command: <br> <pre> {{ repro_cmd }} </pre> ",
Expand Down
7 changes: 7 additions & 0 deletions docs/notifications/ado.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ clickable, make it a link.
"System.Title": "{{ report.crash_site }} - {{ report.executable }}",
"Microsoft.VSTS.TCM.ReproSteps": "This is my call stack: <ul> {{ for item in report.call_stack }} <li> {{ item }} </li> {{ end }} </ul>"
},
"ado_duplicate_fields": {
"System.Reason": "My custom value that means a work item is a duplicate",
"Custom.Work.Item.Field": "My custom value that means a work item is a duplicate"
// note: the fields and values below are checked by default and don't need to be specified
// "System.Reason": "Duplicate"
// "Microsoft.VSTS.Common.ResolvedReason": "Duplicate"
},
"comment": "This is my comment. {{ report.input_sha256 }} {{ input_url }} <br> <pre>{{ repro_cmd }}</pre>",
"unique_fields": ["System.Title", "System.AreaPath"],
"on_duplicate": {
Expand Down
8 changes: 8 additions & 0 deletions docs/webhook_events.md
Original file line number Diff line number Diff line change
Expand Up @@ -2033,6 +2033,10 @@ If webhook is set to have Event Grid message format then the payload will look a
},
"original_crash_test_result": {
"$ref": "#/definitions/CrashTestResult"
},
"report_url": {
"title": "Report Url",
"type": "string"
}
},
"required": [
Expand Down Expand Up @@ -6427,6 +6431,10 @@ If webhook is set to have Event Grid message format then the payload will look a
},
"original_crash_test_result": {
"$ref": "#/definitions/CrashTestResult"
},
"report_url": {
"title": "Report Url",
"type": "string"
}
},
"required": [
Expand Down
1 change: 1 addition & 0 deletions src/ApiService/ApiService/FeatureFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ public static class FeatureFlagConstants {
public const string EnableBlobRetentionPolicy = "EnableBlobRetentionPolicy";
public const string EnableDryRunBlobRetention = "EnableDryRunBlobRetention";
public const string EnableWorkItemCreation = "EnableWorkItemCreation";
public const string EnableContainerRetentionPolicies = "EnableContainerRetentionPolicies";
}
2 changes: 1 addition & 1 deletion src/ApiService/ApiService/Functions/Jobs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ private async Task<HttpResponseData> Post(HttpRequestData req, FunctionContext c
"job");
}

await _context.Events.SendEvent(new EventJobCreated(job.JobId, job.Config, job.UserInfo));
await _context.Events.SendEvent(new EventJobCreated(job.JobId, job.Config, job.UserInfo, _context.ServiceConfiguration.OneFuzzVersion));
return await RequestHandling.Ok(req, JobResponse.ForJob(job, taskInfo: null));
}

Expand Down
68 changes: 52 additions & 16 deletions src/ApiService/ApiService/Functions/QueueFileChanges.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Azure.Core;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -54,14 +55,16 @@ public async Async.Task Run(
return;
}

var storageAccount = new ResourceIdentifier(topicElement.GetString()!);

try {
// Setting isLastRetryAttempt to false will rethrow any exceptions
// With the intention that the azure functions runtime will handle requeing
// the message for us. The difference is for the poison queue, we're handling the
// requeuing ourselves because azure functions doesn't support retry policies
// for queue based functions.

var result = await FileAdded(fileChangeEvent, isLastRetryAttempt: false);
var result = await FileAdded(storageAccount, fileChangeEvent, isLastRetryAttempt: false);
if (!result.IsOk && result.ErrorV.Code == ErrorCode.ADO_WORKITEM_PROCESSING_DISABLED) {
await RequeueMessage(msg, TimeSpan.FromDays(1));
}
Expand All @@ -71,16 +74,47 @@ public async Async.Task Run(
}
}

private async Async.Task<OneFuzzResultVoid> FileAdded(JsonDocument fileChangeEvent, bool isLastRetryAttempt) {
private async Async.Task<OneFuzzResultVoid> FileAdded(ResourceIdentifier storageAccount, JsonDocument fileChangeEvent, bool isLastRetryAttempt) {
var data = fileChangeEvent.RootElement.GetProperty("data");
var url = data.GetProperty("url").GetString()!;
var parts = url.Split("/").Skip(3).ToList();

var container = parts[0];
var container = Container.Parse(parts[0]);
var path = string.Join('/', parts.Skip(1));

_log.LogInformation("file added : {Container} - {Path}", container, path);
return await _notificationOperations.NewFiles(Container.Parse(container), path, isLastRetryAttempt);
_log.LogInformation("file added : {Container} - {Path}", container.String, path);

var (_, result) = await (
ApplyRetentionPolicy(storageAccount, container, path),
_notificationOperations.NewFiles(container, path, isLastRetryAttempt));

return result;
}

private async Async.Task<bool> ApplyRetentionPolicy(ResourceIdentifier storageAccount, Container container, string path) {
if (await _context.FeatureManagerSnapshot.IsEnabledAsync(FeatureFlagConstants.EnableContainerRetentionPolicies)) {
// default retention period can be applied to the container
// if one exists, we will set the expiry date on the newly-created blob, if it doesn't already have one
var account = await _storage.GetBlobServiceClientForAccount(storageAccount);
var containerClient = account.GetBlobContainerClient(container.String);
var containerProps = await containerClient.GetPropertiesAsync();
var retentionPeriod = RetentionPolicyUtils.GetContainerRetentionPeriodFromMetadata(containerProps.Value.Metadata);
if (!retentionPeriod.IsOk) {
_log.LogError("invalid retention period: {Error}", retentionPeriod.ErrorV);
} else if (retentionPeriod.OkV is TimeSpan period) {
var blobClient = containerClient.GetBlobClient(path);
var tags = (await blobClient.GetTagsAsync()).Value.Tags;
var expiryDate = DateTime.UtcNow + period;
var tag = RetentionPolicyUtils.CreateExpiryDateTag(DateOnly.FromDateTime(expiryDate));
if (tags.TryAdd(tag.Key, tag.Value)) {
_ = await blobClient.SetTagsAsync(tags);
_log.LogInformation("applied container retention policy ({Policy}) to {Path}", period, path);
return true;
}
}
}

return false;
}

private async Async.Task RequeueMessage(string msg, TimeSpan? visibilityTimeout = null) {
Expand All @@ -94,20 +128,22 @@ private async Async.Task RequeueMessage(string msg, TimeSpan? visibilityTimeout
newCustomDequeueCount = json["data"]!["customDequeueCount"]!.GetValue<int>();
}

var queueName = QueueFileChangesQueueName;
if (newCustomDequeueCount > MAX_DEQUEUE_COUNT) {
_log.LogWarning("Message retried more than {MAX_DEQUEUE_COUNT} times with no success: {msg}", MAX_DEQUEUE_COUNT, msg);
queueName = QueueFileChangesPoisonQueueName;
await _context.Queue.QueueObject(
QueueFileChangesPoisonQueueName,
json,
StorageType.Config)
.IgnoreResult();
} else {
json!["data"]!["customDequeueCount"] = newCustomDequeueCount + 1;
await _context.Queue.QueueObject(
QueueFileChangesQueueName,
json,
StorageType.Config,
visibilityTimeout ?? CalculateExponentialBackoff(newCustomDequeueCount))
.IgnoreResult();
}

json!["data"]!["customDequeueCount"] = newCustomDequeueCount + 1;

await _context.Queue.QueueObject(
queueName,
json,
StorageType.Config,
visibilityTimeout ?? CalculateExponentialBackoff(newCustomDequeueCount))
.IgnoreResult();
}

// Possible return values:
Expand Down
5 changes: 2 additions & 3 deletions src/ApiService/ApiService/Functions/QueueNodeHeartbeat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ public async Async.Task Run([QueueTrigger("node-heartbeat", Connection = "AzureW
var nodeHeartbeatEvent = new EventNodeHeartbeat(node.MachineId, node.ScalesetId, node.PoolName, node.State);
// TODO: do we still send event if we fail do update the table ?
await events.SendEvent(nodeHeartbeatEvent);
if (await _context.FeatureManagerSnapshot.IsEnabledAsync(FeatureFlagConstants.EnableCustomMetricTelemetry)) {
metrics.SendMetric(1, nodeHeartbeatEvent);
}
metrics.SendMetric(1, nodeHeartbeatEvent);


}
}
5 changes: 2 additions & 3 deletions src/ApiService/ApiService/Functions/QueueTaskHeartbeat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ public async Async.Task Run([QueueTrigger("task-heartbeat", Connection = "AzureW

var taskHeartBeatEvent = new EventTaskHeartbeat(newTask.JobId, newTask.TaskId, job.Config.Project, job.Config.Name, newTask.State, newTask.Config);
await _events.SendEvent(taskHeartBeatEvent);
if (await _context.FeatureManagerSnapshot.IsEnabledAsync(FeatureFlagConstants.EnableCustomMetricTelemetry)) {
_metrics.SendMetric(1, taskHeartBeatEvent);
}
_metrics.SendMetric(1, taskHeartBeatEvent);

}
}
2 changes: 2 additions & 0 deletions src/ApiService/ApiService/OneFuzzTypes/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public enum ErrorCode {
ADO_VALIDATION_MISSING_PAT_SCOPES = 492,
ADO_WORKITEM_PROCESSING_DISABLED = 494,
ADO_VALIDATION_INVALID_PATH = 495,
ADO_VALIDATION_INVALID_PROJECT = 496,
INVALID_RETENTION_PERIOD = 497,
// NB: if you update this enum, also update enums.py
}

Expand Down
3 changes: 2 additions & 1 deletion src/ApiService/ApiService/OneFuzzTypes/Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ TaskConfig Config
public record EventJobCreated(
Guid JobId,
JobConfig Config,
StoredUserInfo? UserInfo
StoredUserInfo? UserInfo,
string OneFuzzVersion
) : BaseEvent();


Expand Down
7 changes: 5 additions & 2 deletions src/ApiService/ApiService/OneFuzzTypes/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,8 @@ public record ADODuplicateTemplate(
Dictionary<string, string> SetState,
Dictionary<string, string> AdoFields,
string? Comment = null,
List<Dictionary<string, string>>? Unless = null
List<Dictionary<string, string>>? Unless = null,
List<string>? RegressionIgnoreStates = null
);

public record AdoTemplate(
Expand All @@ -689,6 +690,7 @@ public record AdoTemplate(
List<string> UniqueFields,
Dictionary<string, string> AdoFields,
ADODuplicateTemplate OnDuplicate,
Dictionary<string, string>? AdoDuplicateFields = null,
string? Comment = null
) : NotificationTemplate {
public async Task<OneFuzzResultVoid> Validate() {
Expand All @@ -704,8 +706,9 @@ public record RenderedAdoTemplate(
List<string> UniqueFields,
Dictionary<string, string> AdoFields,
ADODuplicateTemplate OnDuplicate,
Dictionary<string, string>? AdoDuplicateFields = null,
string? Comment = null
) : AdoTemplate(BaseUrl, AuthToken, Project, Type, UniqueFields, AdoFields, OnDuplicate, Comment);
) : AdoTemplate(BaseUrl, AuthToken, Project, Type, UniqueFields, AdoFields, OnDuplicate, AdoDuplicateFields, Comment) { }

public record TeamsTemplate(SecretData<string> Url) : NotificationTemplate {
public Task<OneFuzzResultVoid> Validate() {
Expand Down
Loading