Skip to content

Commit 0778529

Browse files
committed
Initial commit
0 parents  commit 0778529

File tree

11 files changed

+1323
-0
lines changed

11 files changed

+1323
-0
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Detectify API examples
2+
3+
This repository contains basic examples for using the Detectify API to manage scans and retrieve scan results. Full documentation for the API [can be found here][api-docs].
4+
5+
Examples are provided for the following languages:
6+
7+
- [C#](./c-sharp/)
8+
- [Java](./java/)
9+
- [Node](./node/)
10+
- [PHP](./php/)
11+
- [Python](./python/)
12+
- [Ruby](./ruby/)
13+
14+
[api-docs]:https://developer.detectify.com/

c-sharp/detectify.cs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Net.Http;
5+
using System.Security.Cryptography;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace DetectifyExample
10+
{
11+
internal class Program
12+
{
13+
public static async Task Main(string[] args)
14+
{
15+
// Detectify keys
16+
var apiKey = "d4bf676ee6146557cbf0f28fe6cbc290";
17+
var secretKey = "SGVsbG8sIHdvcmxkISBJIGFtIGEgdGVhcG90IQ==";
18+
19+
// Token for the scan profile
20+
var scanProfile = "5605b488634efe810dff4276e28ca7f9";
21+
22+
// Create the API client
23+
var detectify = new Detectify(apiKey, secretKey);
24+
25+
// Start a scan
26+
bool started = await detectify.StartScanAsync(scanProfile);
27+
if (started)
28+
{
29+
// Show scan status if scan successfully started
30+
await detectify.ScanStatusAsync(scanProfile);
31+
}
32+
}
33+
}
34+
35+
public class Detectify
36+
{
37+
/// <summary>
38+
/// Detectify API endpoint, without a trailing slash.
39+
/// </summary>
40+
private const string Endpoint = "https://api.detectify.com/rest/v2";
41+
42+
private string ApiKey { get; }
43+
private string SecretKey { get; }
44+
45+
public Detectify(string apiKey, string secretKey)
46+
{
47+
ApiKey = apiKey;
48+
SecretKey = secretKey;
49+
}
50+
51+
52+
/// <summary>
53+
/// Create the headers used to sign an API request.
54+
/// </summary>
55+
/// <param name="method">The method used for the call, in uppercase.</param>
56+
/// <param name="path">The path of the request, ie `/v2/domains/`.</param>
57+
/// <param name="timestamp">The timestamp used when creating the signature.</param>
58+
/// <param name="body">The body used for requests that require a provided payload. Must be null or an empty string if the request has no body.</param>
59+
/// <returns>Returns a dictionary of signature headers to use with an API call.</returns>
60+
private Dictionary<string, string> MakeHeaders(string method, string path,
61+
DateTime timestamp, string body)
62+
{
63+
// Signature timestamp is in Unix epoch format
64+
var epoch = (long) (timestamp - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds;
65+
66+
// Calculate signature hash
67+
var signatureValue = $"{method};{path};{ApiKey};{epoch};{body}";
68+
var signatureBytes = new HMACSHA256(Convert.FromBase64String(SecretKey))
69+
.ComputeHash(Encoding.Default.GetBytes(signatureValue));
70+
var signature = Convert.ToBase64String(signatureBytes);
71+
72+
return new Dictionary<string, string>
73+
{
74+
["X-Detectify-Key"] = ApiKey,
75+
["X-Detectify-Signature"] = signature,
76+
["X-Detectify-Timestamp"] = epoch.ToString()
77+
};
78+
}
79+
80+
/// <summary>
81+
/// Start a scan for a given scan profile.
82+
/// </summary>
83+
/// <param name="scanProfile">The scan profile to start a scan on.</param>
84+
/// <returns>Returns true if a scan was started, false if not.</returns>
85+
public async Task<bool> StartScanAsync(string scanProfile)
86+
{
87+
var path = $"/scans/{scanProfile}/";
88+
var url = $"{Endpoint}{path}";
89+
var timestamp = DateTime.UtcNow;
90+
91+
// Create Detectify headers
92+
var headers = MakeHeaders("POST", path, timestamp, null);
93+
94+
using (var client = new HttpClient())
95+
{
96+
// Add Detectify headers to request
97+
headers.ToList().ForEach(h => client.DefaultRequestHeaders.Add(h.Key, h.Value));
98+
99+
var response = await client.PostAsync(url, null);
100+
101+
switch ((int) response.StatusCode)
102+
{
103+
case 202:
104+
Console.WriteLine("Scan start request accepted");
105+
return true;
106+
case 400:
107+
Console.WriteLine("Invalid scan profile token");
108+
return false;
109+
case 401:
110+
Console.WriteLine("Missing/invalid API key or message signature, or invalid timestamp");
111+
return false;
112+
case 403:
113+
Console.WriteLine("The API key cannot access this functionality");
114+
return false;
115+
case 404:
116+
Console.WriteLine(
117+
"The specified scan profile does not exist or the API cannot access the profile");
118+
return false;
119+
case 409:
120+
Console.WriteLine("A scan is already running on the specified profile");
121+
return false;
122+
case 423:
123+
Console.WriteLine("The domain is not verified");
124+
return false;
125+
case 500:
126+
case 503:
127+
Console.WriteLine("An error occurred while processing the request");
128+
return false;
129+
default:
130+
Console.WriteLine($"API returned unhandled status code: {(int) response.StatusCode}");
131+
return false;
132+
}
133+
}
134+
}
135+
136+
/// <summary>
137+
/// Retrieves the status of a currently running scan for a given scan profile.
138+
/// </summary>
139+
/// <param name="scanProfile">The scan profile token to check scan status for.</param>
140+
public async Task ScanStatusAsync(string scanProfile)
141+
{
142+
var path = $"/scans/{scanProfile}/";
143+
var url = $"{Endpoint}{path}";
144+
var timestamp = DateTime.UtcNow;
145+
146+
// Create Detectify headers
147+
var headers = MakeHeaders("GET", path, timestamp, null);
148+
149+
using (var client = new HttpClient())
150+
{
151+
// Add Detectify headers to request
152+
headers.ToList().ForEach(h => client.DefaultRequestHeaders.Add(h.Key, h.Value));
153+
154+
var response = await client.GetAsync(url);
155+
156+
switch ((int) response.StatusCode)
157+
{
158+
case 200:
159+
Console.WriteLine(await response.Content.ReadAsStringAsync());
160+
break;
161+
case 400:
162+
Console.WriteLine("Invalid scan profile token");
163+
break;
164+
case 401:
165+
Console.WriteLine("Missing/invalid API key or message signature, or invalid timestamp");
166+
break;
167+
case 403:
168+
Console.WriteLine("The API key cannot access this functionality");
169+
break;
170+
case 404:
171+
Console.WriteLine(
172+
"No scan running for the specified profile, or the specified scan profile does not exist, or the API cannot access the profile");
173+
break;
174+
case 500:
175+
case 503:
176+
Console.WriteLine("An error occurred while processing the request");
177+
break;
178+
default:
179+
Console.WriteLine($"API returned unhandled status code: {(int) response.StatusCode}");
180+
break;
181+
}
182+
}
183+
}
184+
}
185+
}

0 commit comments

Comments
 (0)