Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/actions/rust/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ runs:
shell: bash
if: runner.os == 'Linux'
run: |
sudo apt update -qq
sudo apt update
# snappy is required by rust rocksdb
sudo apt install -qq --yes clang llvm libsnappy-dev
sudo update-alternatives --set cc /usr/bin/clang
4 changes: 2 additions & 2 deletions packages/dashmate/src/ssl/zerossl/cancelCertificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import requestApi from './requestApi.js';
* @return {Promise<Certificate>}
*/
export default async function cancelCertificate(apiKey, id) {
const url = `https://api.zerossl.com/certificates/${id}/cancel?access_key=${apiKey}`;
const url = `https://api.zerossl.com/certificates/${id}/cancel`;

const requestOptions = {
method: 'POST',
Expand All @@ -18,5 +18,5 @@ export default async function cancelCertificate(apiKey, id) {
},
};

return requestApi(url, requestOptions);
return requestApi(apiKey, url, requestOptions);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default async function createZeroSSLCertificate(
certificate_csr: csr,
});

const url = `https://api.zerossl.com/certificates?access_key=${apiKey}`;
const url = 'https://api.zerossl.com/certificates';

const requestOptions = {
method: 'POST',
Expand All @@ -32,7 +32,7 @@ export default async function createZeroSSLCertificate(
},
};

const data = await requestApi(url, requestOptions);
const data = await requestApi(apiKey, url, requestOptions);

return new Certificate(data);
}
4 changes: 2 additions & 2 deletions packages/dashmate/src/ssl/zerossl/downloadCertificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
import requestApi from './requestApi.js';

export default async function downloadCertificate(id, apiKey) {
const url = `https://api.zerossl.com/certificates/${id}/download/return?access_key=${apiKey}`;
const url = `https://api.zerossl.com/certificates/${id}/download/return`;

const requestOptions = {
method: 'GET',
headers: { },
};

const data = await requestApi(url, requestOptions);
const data = await requestApi(apiKey, url, requestOptions);

return `${data['certificate.crt']}\n${data['ca_bundle.crt']}`;
}
4 changes: 2 additions & 2 deletions packages/dashmate/src/ssl/zerossl/getCertificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import requestApi from './requestApi.js';
* @return {Promise<Certificate>}
*/
export default async function getCertificate(apiKey, id) {
const url = `https://api.zerossl.com/certificates/${id}?access_key=${apiKey}`;
const url = `https://api.zerossl.com/certificates/${id}`;

const requestOptions = {
method: 'GET',
headers: { },
};

const data = await requestApi(url, requestOptions);
const data = await requestApi(apiKey, url, requestOptions);

return new Certificate(data);
}
4 changes: 2 additions & 2 deletions packages/dashmate/src/ssl/zerossl/listCertificates.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default async function listCertificates(
page = 1,
search = undefined,
) {
let url = `https://api.zerossl.com/certificates?access_key=${apiKey}&limit=1000&page=${page}`;
let url = `https://api.zerossl.com/certificates?limit=1000&page=${page}`;

if (statuses.length > 0) {
url += `&statuses=${statuses.join(',')}`;
Expand All @@ -34,7 +34,7 @@ export default async function listCertificates(
headers: {},
};

const data = await requestApi(url, requestOptions);
const data = await requestApi(apiKey, url, requestOptions);

return data.results.map((certificateData) => new Certificate(certificateData));
}
86 changes: 80 additions & 6 deletions packages/dashmate/src/ssl/zerossl/requestApi.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,96 @@
import errorDescriptions from './errors/errorDescriptions.js';

const INVALID_API_KEY_MESSAGE = 'Invalid ZeroSSL API key';
const INVALID_API_RESPONSE_MESSAGE = 'Invalid ZeroSSL API response';
const REDACTED_VALUE = '[REDACTED]';

/**
* Redact the API key from a parsed ZeroSSL error without mutating the response.
*
* @param {*} value
* @param {string} apiKey
* @returns {*}
*/
function redactApiKey(value, apiKey) {
if (typeof value === 'string') {
return value.replaceAll(apiKey, REDACTED_VALUE);
}

if (Array.isArray(value)) {
return value.map((item) => redactApiKey(item, apiKey));
}

if (value !== null && typeof value === 'object') {
return Object.fromEntries(
Object.entries(value).map(([key, item]) => [
redactApiKey(key, apiKey),
redactApiKey(item, apiKey),
]),
);
}

return value;
}

/**
* Build headers with one canonical ZeroSSL authorization value.
*
* @param {string} apiKey
* @param {HeadersInit} sourceHeaders
* @returns {Headers}
*/
function createHeaders(apiKey, sourceHeaders) {
if (typeof apiKey !== 'string' || apiKey.length === 0 || apiKey.trim() !== apiKey) {
throw new Error(INVALID_API_KEY_MESSAGE);
}

const authorization = `ApiKey ${apiKey}`;

try {
const headers = new Headers(sourceHeaders);
headers.set('Authorization', authorization);

if (headers.get('Authorization') !== authorization) {
throw new Error(INVALID_API_KEY_MESSAGE);
}

return headers;
} catch {
throw new Error(INVALID_API_KEY_MESSAGE);
}
}

/**
* Request the ZeroSSL API
*
* @param {string} apiKey
* @param {string} url
* @param {Object} options
* @returns {Promise<Object>}
*/
export default async function requestApi(url, options) {
const response = await fetch(url, options);
const data = await response.json();
export default async function requestApi(apiKey, url, options) {
const headers = createHeaders(apiKey, options.headers);
const requestOptions = {
...options,
headers,
};

const response = await fetch(url, requestOptions);

let data;
try {
data = await response.json();
} catch {
throw new Error(INVALID_API_RESPONSE_MESSAGE);
}

if (data.error) {
const errorMessage = errorDescriptions[data.error.code];
const sanitizedError = redactApiKey(data.error, apiKey);
const errorMessage = errorDescriptions[sanitizedError.code];

const error = new Error(errorMessage || data.error.type);
const error = new Error(errorMessage || sanitizedError.type);

Object.assign(error, data.error);
Object.assign(error, sanitizedError);

throw error;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/dashmate/src/ssl/zerossl/revokeCertificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default async function revokeCertificate(
apiKey,
id,
) {
const url = `https://api.zerossl.com/certificates/${id}/revoke?access_key=${apiKey}`;
const url = `https://api.zerossl.com/certificates/${id}/revoke`;

const requestOptions = {
method: 'POST',
Expand All @@ -21,5 +21,5 @@ export default async function revokeCertificate(
},
};

return requestApi(url, requestOptions);
return requestApi(apiKey, url, requestOptions);
}
4 changes: 2 additions & 2 deletions packages/dashmate/src/ssl/zerossl/verifyDomain.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default async function verifyDomain(id, apiKey) {
validation_method: 'HTTP_CSR_HASH',
});

const url = `https://api.zerossl.com/certificates/${id}/challenges?access_key=${apiKey}`;
const url = `https://api.zerossl.com/certificates/${id}/challenges`;

const requestOptions = {
method: 'POST',
Expand All @@ -24,5 +24,5 @@ export default async function verifyDomain(id, apiKey) {
},
};

return requestApi(url, requestOptions);
return requestApi(apiKey, url, requestOptions);
}
Loading
Loading