Skip to content
This repository was archived by the owner on Feb 2, 2022. It is now read-only.

Commit add2963

Browse files
stishkinstas
andauthored
Ability to add SSL certificates (#125)
- only works with RESTler at this point Co-authored-by: stas <statis@microsoft.com>
1 parent 4339967 commit add2963

10 files changed

Lines changed: 236 additions & 101 deletions

File tree

cli/raft-tools/libs/node-js/raft.js

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const fs = require('fs');
4+
const path = require('path');
45
const url = require('url');
56
const { exec } = require('child_process');
67

@@ -106,6 +107,7 @@ function getAuthHeader(callback) {
106107
callback(new Error("More than one authentication method is specified: " + config.authenticationMethod), null);
107108
} else {
108109
const authMethod = authMethods[0];
110+
console.log("Authentication Method: " + authMethod);
109111
switch (authMethod.toLowerCase()) {
110112
case 'msal':
111113
const msalDirectory = toolDirectory + "/../../auth/node-js/msal";
@@ -123,11 +125,11 @@ function getAuthHeader(callback) {
123125
);
124126
break;
125127
case 'txttoken':
126-
callback(null, process.env['RAFT_' + config.authenticationmethod.txttoken] || process.env[config.authenticationmethod.txttoken] );
128+
callback(null, process.env['RAFT_' + config.authenticationMethod[authMethod]] || process.env[config.authenticationMethod[authMethod]] );
127129
break;
128130
case 'commandline':
129-
exec(config.authenticationmethod.commandline, (error, result) => {
130-
callback(erorr, result);
131+
exec(config.authenticationMethod[authMethod], (error, result) => {
132+
callback(error, result);
131133
}
132134
);
133135
break;
@@ -139,6 +141,40 @@ function getAuthHeader(callback) {
139141
}
140142
}
141143

144+
function installCertificates(callback) {
145+
if (!config.targetConfiguration || !config.targetConfiguration.certificates) {
146+
callback(null, null);
147+
} else {
148+
fs.readdir(config.targetConfiguration.certificates, function(err, files) {
149+
if (err) {
150+
callback(err, null);
151+
}
152+
else {
153+
files.forEach(function(file) {
154+
console.log("File: " + file);
155+
if (path.extname(file) === '.crt') {
156+
const copySrc = config.targetConfiguration.certificates + "/" + file;
157+
const copyDest = "/usr/local/share/ca-certificates/" + file;
158+
console.log("CopySrc: " + copySrc + " CopyDest: " + copyDest);
159+
fs.copyFileSync(copySrc, copyDest);
160+
}
161+
});
162+
console.log("Updating certificates");
163+
exec("update-ca-certificates --fresh", (error, _) => {
164+
if (error) {
165+
console.log("Failed to update certificates: " + error);
166+
callback(error, null);
167+
} else {
168+
callback(null, null);
169+
}
170+
}
171+
);
172+
}
173+
});
174+
}
175+
}
176+
177+
exports.installCertificates = installCertificates;
142178
exports.workDirectory = workDirectory;
143179
exports.config = config;
144180
exports.RaftUtils = RaftUtils;

cli/raft-tools/libs/python3/raft.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,27 @@
55
import time
66
import io
77
import importlib
8+
import shutil
9+
import glob
810

911
from urllib.parse import urlparse
1012
from contextlib import redirect_stdout
1113

14+
def install_certificates():
15+
work_directory = os.environ['RAFT_WORK_DIRECTORY']
16+
run_directory = os.environ['RAFT_TOOL_RUN_DIRECTORY']
17+
with open(os.path.join(work_directory, "task-config.json"), 'r') as task_config:
18+
config = json.load(task_config)
19+
if config.get("targetConfiguration") and config.get("targetConfiguration").get("certificates"):
20+
certificates = config["targetConfiguration"]["certificates"]
21+
files = glob.iglob(os.path.join(certificates, "*.crt"))
22+
for f in files:
23+
if os.path.isfile(f):
24+
print(f"Copying file {f}")
25+
shutil.copy(f, "/usr/local/share/ca-certificates/")
26+
subprocess.check_call(["update-ca-certificates", "--fresh"])
27+
28+
1229
def auth_token(init):
1330
work_directory = os.environ['RAFT_WORK_DIRECTORY']
1431
run_directory = os.environ['RAFT_TOOL_RUN_DIRECTORY']

cli/raft-tools/tools/Dredd/config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"container" : "apiaryio/dredd:stable",
33
"shell" : "/bin/sh",
44
"run" : {
5-
"shellArguments" : ["-c", "sleep $RAFT_STARTUP_DELAY; npm install $RAFT_TOOL_RUN_DIRECTORY; node $RAFT_TOOL_RUN_DIRECTORY/index.js"]
5+
"shellArguments" : ["-c", "sleep $RAFT_STARTUP_DELAY; apk add ca-certificates; npm install $RAFT_TOOL_RUN_DIRECTORY; node $RAFT_TOOL_RUN_DIRECTORY/index.js"]
66
},
77
"idle" : {
88
"shellArguments" : ["-c", "echo DebugMode; while true; do sleep 100000; done;"]

cli/raft-tools/tools/Dredd/index.js

Lines changed: 104 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -10,117 +10,127 @@ const raftUtils = new raft.RaftUtils("Dredd");
1010

1111
raftUtils.reportStatusCreated();
1212

13-
raft.getAuthHeader((error, result) => {
13+
raft.installCertificates((error, result) => {
1414
if (error) {
1515
console.error(error);
1616
raftUtils.logException(error);
1717
raftUtils.reportStatusError(error).then( () => {
1818
raftUtils.flush();
1919
});
2020
} else {
21+
raft.getAuthHeader((error, result) => {
22+
if (error) {
23+
console.error(error);
24+
raftUtils.logException(error);
25+
raftUtils.reportStatusError(error).then( () => {
26+
raftUtils.flush();
27+
});
28+
} else {
2129

22-
let headers = [];
23-
if (result) {
24-
headers = ["Authorization: " + result];
25-
}
26-
var Dredd = require('dredd');
27-
const EventEmitter = require('events');
28-
let eventEmitter = new EventEmitter();
29-
console.log(raftUtils.config);
30-
31-
let configuration = {
32-
init: false,
33-
endpoint: raft.config.targetConfiguration.endpoint, // your URL to API endpoint the tests will run against
34-
path: [], // Required Array if Strings; filepaths to API description documents, can use glob wildcards
35-
'dry-run': false, // Boolean, do not run any real HTTP transaction
36-
names: false, // Boolean, Print Transaction names and finish, similar to dry-run
37-
loglevel: 'debug', // String, logging level (debug, warning, error, silent)
38-
only: [], // Array of Strings, run only transaction that match these names
39-
header: headers, // Array of Strings, these strings are then added as headers (key:value) to every transaction
40-
user: null, // String, Basic Auth credentials in the form username:password
41-
hookfiles: [], // Array of Strings, filepaths to files containing hooks (can use glob wildcards)
42-
reporter: ['markdown', 'html'], // Array of possible reporters, see folder lib/reporters
43-
output: [raft.workDirectory + '/report.md', raft.workDirectory + '/report.html'], // Array of Strings, filepaths to files used for output of file-based reporters
44-
'inline-errors': false, // Boolean, If failures/errors are display immediately in Dredd run
45-
require: null, // String, When using nodejs hooks, require the given module before executing hooks
46-
color: true,
47-
emitter: eventEmitter, // listen to test progress, your own instance of EventEmitter
48-
path: raft.config.targetConfiguration.apiSpecifications
49-
}
50-
var dredd = new Dredd(configuration);
30+
let headers = [];
31+
if (result) {
32+
headers = ["Authorization: " + result];
33+
}
34+
var Dredd = require('dredd');
35+
const EventEmitter = require('events');
36+
let eventEmitter = new EventEmitter();
37+
console.log(raftUtils.config);
5138

52-
//This is very ugly hack to address:
53-
//https://github.com/apiaryio/dredd/issues/1873
54-
dredd.prepareAPIdescriptions1 = dredd.prepareAPIdescriptions;
55-
dredd.prepareAPIdescriptions = function(callback) {
56-
dredd.prepareAPIdescriptions1((error, apiDescriptions) => {
57-
if (apiDescriptions) {
58-
apiDescriptions
59-
.map((apiDescription) => apiDescription.annotations.map((annotation) => {
60-
if (annotation.type === 'error') {
61-
let bugDetails = {...annotation.origin};
62-
bugDetails['name'] = annotation.name;
63-
bugDetails['message'] = annotation.message;
64-
raftUtils.reportBug(bugDetails);
65-
annotation.type = 'warning';
66-
}
67-
annotation;
68-
})
69-
);
39+
let configuration = {
40+
init: false,
41+
endpoint: raft.config.targetConfiguration.endpoint, // your URL to API endpoint the tests will run against
42+
path: [], // Required Array if Strings; filepaths to API description documents, can use glob wildcards
43+
'dry-run': false, // Boolean, do not run any real HTTP transaction
44+
names: false, // Boolean, Print Transaction names and finish, similar to dry-run
45+
loglevel: 'debug', // String, logging level (debug, warning, error, silent)
46+
only: [], // Array of Strings, run only transaction that match these names
47+
header: headers, // Array of Strings, these strings are then added as headers (key:value) to every transaction
48+
user: null, // String, Basic Auth credentials in the form username:password
49+
hookfiles: [], // Array of Strings, filepaths to files containing hooks (can use glob wildcards)
50+
reporter: ['markdown', 'html'], // Array of possible reporters, see folder lib/reporters
51+
output: [raft.workDirectory + '/report.md', raft.workDirectory + '/report.html'], // Array of Strings, filepaths to files used for output of file-based reporters
52+
'inline-errors': false, // Boolean, If failures/errors are display immediately in Dredd run
53+
require: null, // String, When using nodejs hooks, require the given module before executing hooks
54+
color: true,
55+
emitter: eventEmitter, // listen to test progress, your own instance of EventEmitter
56+
path: raft.config.targetConfiguration.apiSpecifications
7057
}
71-
callback(error, apiDescriptions);
72-
});
73-
};
58+
var dredd = new Dredd(configuration);
7459

75-
eventEmitter.on('start', (e, callback) => {
76-
e.map((event) => {
77-
raftUtils.reportStatusRunning(
78-
{
79-
location : event.location,
80-
numberOfRequests : event.transactions.length
60+
//This is very ugly hack to address:
61+
//https://github.com/apiaryio/dredd/issues/1873
62+
dredd.prepareAPIdescriptions1 = dredd.prepareAPIdescriptions;
63+
dredd.prepareAPIdescriptions = function(callback) {
64+
dredd.prepareAPIdescriptions1((error, apiDescriptions) => {
65+
if (apiDescriptions) {
66+
apiDescriptions
67+
.map((apiDescription) => apiDescription.annotations.map((annotation) => {
68+
if (annotation.type === 'error') {
69+
let bugDetails = {...annotation.origin};
70+
bugDetails['name'] = annotation.name;
71+
bugDetails['message'] = annotation.message;
72+
raftUtils.reportBug(bugDetails);
73+
annotation.type = 'warning';
74+
}
75+
annotation;
76+
})
77+
);
8178
}
82-
);
83-
})
84-
callback();
85-
}
86-
);
79+
callback(error, apiDescriptions);
80+
});
81+
};
8782

88-
eventEmitter.on('end', (callback) => {
89-
//raftUtils.reportStatusRunning(runDetails);
90-
callback();
91-
}
92-
);
93-
94-
eventEmitter.on('test pass', (test) => {
95-
//raftUtils.reportStatusRunning(runDetails);
96-
});
83+
eventEmitter.on('start', (e, callback) => {
84+
e.map((event) => {
85+
raftUtils.reportStatusRunning(
86+
{
87+
location : event.location,
88+
numberOfRequests : event.transactions.length
89+
}
90+
);
91+
})
92+
callback();
93+
}
94+
);
9795

98-
eventEmitter.on('test fail', (test) => {
99-
let bugDetails = {...test.origin};
100-
bugDetails['name'] = test.title;
101-
bugDetails['message'] = test.message;
102-
raftUtils.reportBug(bugDetails);
103-
//raftUtils.reportStatusRunning(runDetails);
104-
});
96+
eventEmitter.on('end', (callback) => {
97+
//raftUtils.reportStatusRunning(runDetails);
98+
callback();
99+
}
100+
);
105101

106-
dredd.run(function (err, stats) {
107-
// err is present if anything went wrong
108-
// otherwise stats is an object with useful statistics
109-
if (err) {
110-
console.error(err);
111-
raftUtils.logException(err);
112-
let details = {
113-
'message' : err.message
114-
}
115-
raftUtils.reportStatusError(details).then( () => {
116-
raftUtils.flush();
102+
eventEmitter.on('test pass', (test) => {
103+
//raftUtils.reportStatusRunning(runDetails);
117104
});
118-
} else {
119-
console.log(stats);
120-
raftUtils.reportStatusCompleted(stats).then( () => {
121-
raftUtils.flush();
105+
106+
eventEmitter.on('test fail', (test) => {
107+
let bugDetails = {...test.origin};
108+
bugDetails['name'] = test.title;
109+
bugDetails['message'] = test.message;
110+
raftUtils.reportBug(bugDetails);
111+
//raftUtils.reportStatusRunning(runDetails);
122112
});
113+
114+
dredd.run(function (err, stats) {
115+
// err is present if anything went wrong
116+
// otherwise stats is an object with useful statistics
117+
if (err) {
118+
console.error(err);
119+
raftUtils.logException(err);
120+
let details = {
121+
'message' : err.message
122+
}
123+
raftUtils.reportStatusError(details).then( () => {
124+
raftUtils.flush();
125+
});
126+
} else {
127+
console.log(stats);
128+
raftUtils.reportStatusCompleted(stats).then( () => {
129+
raftUtils.flush();
130+
});
131+
}
132+
});
123133
}
124-
});
134+
})
125135
}
126136
})

cli/raft-tools/tools/Schemathesis/run.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", os.path.join(raft_libs_dir, "requirements.txt")])
1515
raft.auth_token(True)
1616
else:
17+
raft.install_certificates()
1718
token = raft.auth_token(False)
1819

1920
work_directory = os.environ['RAFT_WORK_DIRECTORY']

cli/raft-tools/tools/ZAP/scan.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,14 @@ def run_zap(target_index, targets_total, host, target, token):
6060
pass
6161

6262
try:
63-
raftUtils.log_trace("Starting ZAP")
6463
details = {"targetIndex": target_index, "numberOfTargets" : targets_total, "target": target}
64+
print(f"Starting ZAP target: {target} host_config: {host_config}")
65+
66+
if os.path.exists(target):
67+
shutil.copy(target, '/zap/wrk/swagger.json')
68+
target='swagger.json'
69+
70+
raftUtils.log_trace(f"Starting ZAP")
6571
raftUtils.report_status_running(details)
6672
status_reporter = StatusReporter(details)
6773
logger = logging.getLogger()
@@ -122,4 +128,4 @@ def run(target_index, targets_total, host, target, token):
122128
host = args[i+1]
123129
i=i+1
124130

125-
run(target_index, targets_total, host, target, token)
131+
run(target_index, targets_total, host, target, token)

src/APIService/ApiService/DTOs.fs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ module DTOs =
4141
/// </summary>
4242
Endpoint : System.Uri
4343

44+
/// <summary>
45+
/// Paths to folders containing certificates to add to trusted certificate store. Certificates must have .crt extension.
46+
/// These certificates are used for SSL authentication.
47+
/// </summary>
48+
Certificates : string array
49+
4450
/// <summary>
4551
/// List of OpenApi/swagger specifications locations for the job run. Can be URL or file path.
4652
/// </summary>

0 commit comments

Comments
 (0)