Skip to content

Commit 822c72b

Browse files
committed
LDAP Support - Part 1
1. ldap_client 2. support assume_role_with_web_identity Signed-off-by: jackyalbo <jacky.albo@gmail.com>
1 parent 20d8f05 commit 822c72b

10 files changed

+449
-65
lines changed

config.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ config.IAM_SERVICE_CERT_PATH = '/etc/iam-secret';
7777
config.MGMT_SERVICE_CERT_PATH = '/etc/mgmt-secret';
7878
config.EXTERNAL_DB_SERVICE_CERT_PATH = '/etc/external-db-secret';
7979

80+
/////////////////
81+
// LDAP CONFIG //
82+
/////////////////
83+
config.LDAP_CONFIG_PATH = '/etc/noobaa-server/ldap_config';
84+
8085
//////////////////
8186
// NODES CONFIG //
8287
//////////////////
@@ -1198,7 +1203,7 @@ function _get_config_root() {
11981203

11991204
/**
12001205
* go over the config object and set the relevant configurations as environment variables
1201-
*/
1206+
*/
12021207
function _set_nc_config_to_env() {
12031208
const config_to_env = ['NOOBAA_LOG_LEVEL', 'UV_THREADPOOL_SIZE', 'GPFS_DL_PATH', 'NSFS_ENABLE_DYNAMIC_SUPPLEMENTAL_GROUPS'];
12041209
for (const configuration_key of config_to_env) {

package-lock.json

+121
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
"jsonwebtoken": "9.0.2",
9898
"linux-blockutils": "0.2.0",
9999
"lodash": "4.17.21",
100+
"ldapts": "7.3.1",
100101
"mime-types": "3.0.1",
101102
"minimist": "1.2.8",
102103
"moment": "2.30.1",

src/endpoint/endpoint.js

+24-12
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ const { SemaphoreMonitor } = require('../server/bg_services/semaphore_monitor');
4343
const prom_reporting = require('../server/analytic_services/prometheus_reporting');
4444
const { PersistentLogger } = require('../util/persistent_logger');
4545
const { get_notification_logger } = require('../util/notifications_util');
46+
const ldap_client = require('../util/ldap_client').instance();
4647
const NoobaaEvent = require('../manage_nsfs/manage_nsfs_events_utils').NoobaaEvent;
4748
const cluster = /** @type {import('node:cluster').Cluster} */ (
48-
/** @type {unknown} */ (require('node:cluster'))
49+
/** @type {unknown} */
50+
(require('node:cluster'))
4951
);
5052

5153
if (process.env.NOOBAA_LOG_LEVEL) {
@@ -116,16 +118,16 @@ async function main(options = {}) {
116118
const http_metrics_port = options.http_metrics_port || config.EP_METRICS_SERVER_PORT;
117119
const https_metrics_port = options.https_metrics_port || config.EP_METRICS_SERVER_SSL_PORT;
118120
/**
119-
* Please notice that we can run the main in 2 states:
120-
* 1. Only the primary process runs the main (fork is 0 or undefined) - everything that
121-
* is implemented here would be run by this process.
122-
* 2. A primary process with multiple forks (IMPORTANT) - if there is implementation that
123-
* in only relevant to the primary process it should be implemented in
124-
* fork_utils.start_workers because the primary process returns after start_workers
125-
* and the forks will continue executing the code lines in this function
126-
* */
121+
* Please notice that we can run the main in 2 states:
122+
* 1. Only the primary process runs the main (fork is 0 or undefined) - everything that
123+
* is implemented here would be run by this process.
124+
* 2. A primary process with multiple forks (IMPORTANT) - if there is implementation that
125+
* in only relevant to the primary process it should be implemented in
126+
* fork_utils.start_workers because the primary process returns after start_workers
127+
* and the forks will continue executing the code lines in this function
128+
* */
127129
const is_workers_started_from_primary = await fork_utils.start_workers(http_metrics_port, https_metrics_port,
128-
options.nsfs_config_root, fork_count);
130+
options.nsfs_config_root, fork_count);
129131
if (is_workers_started_from_primary) return;
130132

131133
const endpoint_group_id = process.env.ENDPOINT_GROUP_ID || 'default-endpoint-group';
@@ -198,8 +200,14 @@ async function main(options = {}) {
198200
const https_port_sts = options.https_port_sts || config.ENDPOINT_SSL_STS_PORT;
199201
const https_port_iam = options.https_port_iam || config.ENDPOINT_SSL_IAM_PORT;
200202

201-
await start_endpoint_server_and_cert(SERVICES_TYPES_ENUM.S3, init_request_sdk,
202-
{ ...options, https_port: https_port_s3, http_port: http_port_s3, virtual_hosts, bucket_logger, notification_logger });
203+
await start_endpoint_server_and_cert(SERVICES_TYPES_ENUM.S3, init_request_sdk, {
204+
...options,
205+
https_port: https_port_s3,
206+
http_port: http_port_s3,
207+
virtual_hosts,
208+
bucket_logger,
209+
notification_logger
210+
});
203211
await start_endpoint_server_and_cert(SERVICES_TYPES_ENUM.STS, init_request_sdk, { https_port: https_port_sts, virtual_hosts });
204212
await start_endpoint_server_and_cert(SERVICES_TYPES_ENUM.IAM, init_request_sdk, { https_port: https_port_iam });
205213

@@ -227,6 +235,10 @@ async function main(options = {}) {
227235
object_io: object_io,
228236
}));
229237
}
238+
239+
if (ldap_client.is_ldap_configured()) {
240+
ldap_client.connect();
241+
}
230242
//noobaa started
231243
new NoobaaEvent(NoobaaEvent.NOOBAA_STARTED).create_event(undefined, undefined, undefined);
232244
// Start a monitor to send periodic endpoint reports about endpoint usage.

src/endpoint/sts/ops/sts_post_assume_role.js

+3-49
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33

44
const dbg = require('../../../util/debug_module')(__filename);
55
const { StsError } = require('../sts_errors');
6-
const jwt_utils = require('../../../util/jwt_utils');
7-
const config = require('../../../../config');
86
const { CONTENT_TYPE_APP_FORM_URLENCODED } = require('../../../util/http_utils');
97
const s3_utils = require('../../s3/s3_utils');
8+
const sts_utils = require('../../sts/sts_utils');
109

1110
/**
1211
* https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html
1312
*/
1413
async function assume_role(req) {
1514
dbg.log1('sts_post_assume_role body: ', req.body);
16-
const duration_ms = _parse_sts_duration(req.body.duration_seconds);
15+
const duration_ms = sts_utils.parse_sts_duration(req.body.duration_seconds);
1716
const duration_sec = Math.ceil(duration_ms / 1000);
1817
const expiration_time = Date.now() + duration_ms;
1918
let assumed_role;
@@ -41,7 +40,7 @@ async function assume_role(req) {
4140
AccessKeyId: access_keys.access_key.unwrap(),
4241
SecretAccessKey: access_keys.secret_key.unwrap(),
4342
Expiration: s3_utils.format_s3_xml_date(expiration_time),
44-
SessionToken: generate_session_token({
43+
SessionToken: sts_utils.generate_session_token({
4544
access_key: access_keys.access_key.unwrap(),
4645
secret_key: access_keys.secret_key.unwrap(),
4746
assumed_role_access_key: assumed_role.access_key
@@ -53,51 +52,6 @@ async function assume_role(req) {
5352
};
5453
}
5554

56-
// create and return the signed token
57-
/**
58-
* @param {Object} auth_options
59-
* @param {Number} expiry in seconds
60-
* @returns {String}
61-
*/
62-
function generate_session_token(auth_options, expiry) {
63-
dbg.log1('sts_post_assume_role.make_session_token: ', auth_options, expiry);
64-
return jwt_utils.make_auth_token(auth_options, { expiresIn: expiry });
65-
}
66-
67-
// TODO: Generalize and move to a utils file in the future
68-
/**
69-
* @param {String|undefined} duration_input duration in seconds
70-
* @returns {Number} duration in milliseconds
71-
*/
72-
function _parse_sts_duration(duration_input) {
73-
if (duration_input === undefined) {
74-
return config.STS_DEFAULT_SESSION_TOKEN_EXPIRY_MS;
75-
}
76-
77-
const duration_sec = Number(duration_input);
78-
79-
if (!Number.isInteger(duration_sec)) {
80-
throw new StsError(StsError.InvalidParameterValue);
81-
}
82-
83-
if (duration_sec < config.STS_MIN_DURATION_SECONDS) {
84-
throw new StsError(_sts_duration_validation_error(duration_input, 'greater', config.STS_MIN_DURATION_SECONDS));
85-
}
86-
if (duration_sec > config.STS_MAX_DURATION_SECONDS) {
87-
throw new StsError(_sts_duration_validation_error(duration_input, 'less', config.STS_MAX_DURATION_SECONDS));
88-
}
89-
90-
const duration_ms = duration_sec * 1000;
91-
return duration_ms;
92-
}
93-
94-
function _sts_duration_validation_error(duration_input, constraint, constraint_value) {
95-
return {
96-
...StsError.ValidationError,
97-
message: `Value ${duration_input} for durationSeconds failed to satisfy constraint: Member must have value ${constraint} than or equal to ${constraint_value}`,
98-
};
99-
}
100-
10155
module.exports = {
10256
handler: assume_role,
10357
body: {

0 commit comments

Comments
 (0)