summaryrefslogtreecommitdiff
path: root/jstests/client_encrypt/lib/mock_kms.js
blob: a7f34c3731222c12e2f646554f2c66983eb2b65c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/**
 * Starts a mock KMS Server to test
 * FLE encryption and decryption.
 */

// These faults must match the list of faults in kms_http_server.py, see the
// SUPPORTED_FAULT_TYPES list in kms_http_server.py
const FAULT_ENCRYPT = "fault_encrypt";
const FAULT_ENCRYPT_CORRECT_FORMAT = "fault_encrypt_correct_format";
const FAULT_ENCRYPT_WRONG_FIELDS = "fault_encrypt_wrong_fields";
const FAULT_ENCRYPT_BAD_BASE64 = "fault_encrypt_bad_base64";
const FAULT_DECRYPT = "fault_decrypt";
const FAULT_DECRYPT_CORRECT_FORMAT = "fault_decrypt_correct_format";
const FAULT_DECRYPT_WRONG_KEY = "fault_decrypt_wrong_key";

const DISABLE_FAULTS = "disable_faults";
const ENABLE_FAULTS = "enable_faults";

class MockKMSServer {
    /**
    * Create a new webserver.
    *
    * @param {string} fault_type
    * @param {bool} disableFaultsOnStartup optionally disable fault on startup
    */
    constructor(fault_type, disableFaultsOnStartup) {
        this.python = "python3";
        this.disableFaultsOnStartup = disableFaultsOnStartup || false;
        this.fault_type = fault_type;

        if (_isWindows()) {
            this.python = "python.exe";
        }

        print("Using python interpreter: " + this.python);

        this.ca_file = "jstests/libs/ca.pem";
        this.server_cert_file = "jstests/libs/server.pem";
        this.web_server_py = "jstests/client_encrypt/lib/kms_http_server.py";
        this.control_py = "jstests/client_encrypt/lib/kms_http_control.py";
        this.port = -1;
    }

    /**
     * Start a web server
     */
    start() {
        this.port = allocatePort();
        print("Mock Web server is listening on port: " + this.port);

        let args = [
            this.python,
            "-u",
            this.web_server_py,
            "--port=" + this.port,
            "--ca_file=" + this.ca_file,
            "--cert_file=" + this.server_cert_file
        ];
        if (this.fault_type) {
            args.push("--fault=" + this.fault_type);
            if (this.disableFaultsOnStartup) {
                args.push("--disable-faults");
            }
        }

        this.pid = _startMongoProgram({args: args});
        assert(checkProgram(this.pid));

        assert.soon(function() {
            return rawMongoProgramOutput().search("Mock KMS Web Server Listening") !== -1;
        });
        sleep(1000);
        print("Mock KMS Server successfully started");
    }

    _runCommand(cmd) {
        let ret = 0;
        if (_isWindows()) {
            ret = runProgram('cmd.exe', '/c', cmd);
        } else {
            ret = runProgram('/bin/sh', '-c', cmd);
        }

        assert.eq(ret, 0);
    }

    /**
     * Query the HTTP server.
     *
     * @param {string} query type
     *
     * @return {object} Object representation of JSON from the server.
     */
    query(query) {
        const out_file = "out_" + this.port + ".txt";
        const python_command = this.python + " -u " + this.control_py + " --port=" + this.port +
            " --ca_file=" + this.ca_file + " --query=" + query + " > " + out_file;

        this._runCommand(python_command);

        const result = cat(out_file);

        try {
            return JSON.parse(result);
        } catch (e) {
            jsTestLog("Failed to parse: " + result + "\n" + result);
            throw e;
        }
    }

    /**
     * Control the HTTP server.
     *
     * @param {string} query type
     */
    control(query) {
        const python_command = this.python + " -u " + this.control_py + " --port=" + this.port +
            " --ca_file=" + this.ca_file + " --query=" + query;

        this._runCommand(python_command);
    }

    /**
     * Disable Faults
     */
    disableFaults() {
        this.control(DISABLE_FAULTS);
    }

    /**
     * Enable Faults
     */
    enableFaults() {
        this.control(ENABLE_FAULTS);
    }

    /**
     * Query the stats page for the HTTP server.
     *
     * @return {object} Object representation of JSON from the server.
     */
    queryStats() {
        return this.query("stats");
    }

    /**
     * Get the URL.
     *
     * @return {string} url of http server
     */
    getURL() {
        return "https://localhost:" + this.port;
    }

    /**
     * Stop the web server
     */
    stop() {
        stopMongoProgramByPid(this.pid);
    }
}