Skip to content

Commit

Permalink
HA alpha (#657)
Browse files Browse the repository at this point in the history
initial HA auth (oidc) support
  • Loading branch information
ekoby authored Jun 4, 2024
1 parent efcfe6e commit 53c54fe
Show file tree
Hide file tree
Showing 36 changed files with 1,791 additions and 655 deletions.
2 changes: 1 addition & 1 deletion .github/actions/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ runs:

- uses: actions/setup-go@v4
with:
go-version: '1.20.x'
go-version: '1.22.x'

- uses: lukka/[email protected]

Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ name: C/C++ CI
on:
workflow_dispatch:
pull_request:
branches: [ main ]
branches:
- main
- release-*

jobs:
build:
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ if (PROJECT_IS_TOP_LEVEL)
endif ()
endif ()

if (ziti_DEVELOPER_MODE)
if (ziti_DEVELOPER_MODE AND NOT CMAKE_CROSSCOMPILING)
ENABLE_TESTING()
add_subdirectory(tests)
endif ()
Expand Down
51 changes: 51 additions & 0 deletions inc_internal/auth_method.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2023-2024. NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ZITI_SDK_AUTH_METHOD_H
#define ZITI_SDK_AUTH_METHOD_H

#include "ziti_ctrl.h"

enum AuthenticationMethod {
LEGACY,
HA
};

typedef enum {
ZitiAuthStateUnauthenticated,
ZitiAuthStateAuthStarted,

ZitiAuthStatePartiallyAuthenticated,
ZitiAuthStateFullyAuthenticated,

ZitiAuthImpossibleToAuthenticate,
} ziti_auth_state;

typedef struct ziti_ctx *ziti_context;
typedef struct ziti_auth_method_s ziti_auth_method_t;
typedef void (*auth_state_cb)(void *ctx, ziti_auth_state, const void *data);

struct ziti_auth_method_s {
enum AuthenticationMethod kind;
int (*start)(ziti_auth_method_t *self, auth_state_cb cb, void *ctx);
int (*force_refresh)(ziti_auth_method_t *self);
int (*submit_mfa)(ziti_auth_method_t *self, const char *code);
int (*stop)(ziti_auth_method_t *self);
void (*free)(ziti_auth_method_t *self);
};

ziti_auth_method_t *new_legacy_auth(ziti_controller *ctrl);
ziti_auth_method_t *new_ha_auth(uv_loop_t *l, model_list *urls, tls_context *tls);

#endif // ZITI_SDK_AUTH_METHOD_H
3 changes: 0 additions & 3 deletions inc_internal/auth_queries.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ struct auth_queries {
extern void ziti_auth_query_init(struct ziti_ctx *ztx);
extern void ziti_auth_query_free(struct auth_queries* aq);
extern void ziti_send_event(ziti_context ztx, const ziti_event_t *e);
extern void ziti_re_auth_with_cb(ziti_context ztx, void(*cb)(ziti_api_session *, const ziti_error *, void *), void *ctx);

void ziti_auth_query_process(ziti_context ztx, void(*cb)(ziti_context ztx, int, void*));

#ifdef __cplusplus
}
Expand Down
27 changes: 27 additions & 0 deletions inc_internal/internal_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ XX(name, string, none, name, __VA_ARGS__)\
XX(hostname, string, none, hostname, __VA_ARGS__) \
XX(protocols, ziti_er_protocols, none, supportedProtocols, __VA_ARGS__)

#define ZITI_SERVICE_EDGE_ROUTERS_MODEL(XX, ...) \
XX(routers, ziti_edge_router, array, edgeRouters, __VA_ARGS__)

#define ZITI_SESSION_MODEL(XX, ...) \
XX(token, string, none, token, __VA_ARGS__)\
XX(id, string, none, id, __VA_ARGS__) \
Expand Down Expand Up @@ -184,6 +187,22 @@ XX(identity_id, string, none, identityId, __VA_ARGS__) \
XX(cert_pem, string, none, certPem, __VA_ARGS__) \
XX(fingerprint, string, none, fingerprint, __VA_ARGS__)

#define API_ADDRESS_MODEL(XX, ...) \
XX(url, string, none, url, __VA_ARGS__) \
XX(version, string, none, version, __VA_ARGS__)

#define CTRL_APIS_MODEL(XX, ...) \
XX(edge, api_address, list, edge-client, __VA_ARGS__) \
XX(oidc, api_address, list, edge-oidc, __VA_ARGS__)

#define ZITI_CONTROLLER_DETAIL(XX, ...) \
XX(id, string, none, id, __VA_ARGS__) \
XX(name, string, none, name, __VA_ARGS__) \
XX(apis, ctrl_apis, none, apiAddresses, __VA_ARGS__) \
XX(is_online, bool, none, isOnline, __VA_ARGS__) \
XX(cert_pem, string, none, certPem, __VA_ARGS__) \
XX(fingerprint, string, none, fingerprint, __VA_ARGS__)

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -196,6 +215,8 @@ DECLARE_MODEL(ziti_er_protocols, ZITI_ER_PROTOCOLS)

DECLARE_MODEL(ziti_edge_router, ZITI_EDGE_ROUTER_MODEL)

DECLARE_MODEL(ziti_service_routers, ZITI_SERVICE_EDGE_ROUTERS_MODEL)

DECLARE_MODEL(ziti_session, ZITI_SESSION_MODEL)

DECLARE_MODEL(ziti_api_session, ZITI_API_SESSION_MODEL)
Expand Down Expand Up @@ -248,6 +269,12 @@ DECLARE_MODEL(ziti_create_api_cert_req, ZITI_CREATE_API_CERT_REQ)

DECLARE_MODEL(ziti_create_api_cert_resp, ZITI_CREATE_API_CERT_RESP)

DECLARE_MODEL(api_address, API_ADDRESS_MODEL)

DECLARE_MODEL(ctrl_apis, CTRL_APIS_MODEL)

DECLARE_MODEL(ziti_controller_detail, ZITI_CONTROLLER_DETAIL)

bool ziti_has_capability(const ziti_version *v, ziti_ctrl_cap c);

#ifdef __cplusplus
Expand Down
78 changes: 78 additions & 0 deletions inc_internal/oidc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//
// Copyright NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#ifndef ZITI_SDK_OIDC_H
#define ZITI_SDK_OIDC_H

#include <ziti/model_support.h>

#include <uv.h>
#include "tlsuv/http.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct oidc_client_s oidc_client_t;
typedef void (*oidc_config_cb)(oidc_client_t *, int, const char *);
typedef void (*oidc_token_cb)(oidc_client_t *, int, const char *access_token);
typedef void (*oidc_close_cb)(oidc_client_t *);


typedef enum {
oidc_native,
oidc_external,
} oidc_auth_mode;

struct oidc_client_s {
void *data;
tlsuv_http_t http;

const char *client_id;
oidc_auth_mode mode;
oidc_config_cb config_cb;
oidc_token_cb token_cb;
oidc_close_cb close_cb;

void *config;
void *tokens;
uv_timer_t *timer;
};

// init
int oidc_client_init(uv_loop_t *loop, oidc_client_t *clt, const char *url, tls_context *tls);
int oidc_client_set_url(oidc_client_t *clt, const char* url);

int oidc_client_set_id(oidc_client_t *clt, const char *client_id);

// configure client
int oidc_client_configure(oidc_client_t *clt, oidc_config_cb);

// acquire access token and start refresh cycle
// oidc_token_cb will be called on first auth and on every refresh
int oidc_client_start(oidc_client_t *clt, oidc_token_cb);

// force token refresh ahead of normal cycle, error if called prior to oidc_client_start
int oidc_client_refresh(oidc_client_t *clt);

// close
int oidc_client_close(oidc_client_t *clt, oidc_close_cb);

#ifdef __cplusplus
};
#endif

#endif //ZITI_SDK_OIDC_H
16 changes: 12 additions & 4 deletions inc_internal/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@ extern "C" {

typedef unsigned int uint;

#define typeof(x)

#endif

#if defined(_MSC_VER)
#define z_typeof(x) __typeof__(x)
#else
#define z_typeof(x) typeof(x)
#endif
extern const char *ziti_get_build_version(int verbose);

extern const char *ziti_git_branch();
Expand All @@ -75,7 +78,7 @@ typedef int *(*cond_error_t)(int);
#define VAL_OR_ELSE(v, def) ((v) != NULL ? (v) : (def))
#define FREE(v) do { if ((v) != NULL) { free((void*)(v)); (v) = NULL; } } while(0)
#define FIELD_OR_ELSE(obj, field, def) ((obj) ? ((obj)->field) : (def))
#define FIELD_OR_NULL(obj, field) FIELD_OR_ELSE(obj, field, (typeof((obj)->field))0)
#define FIELD_OR_NULL(obj, field) FIELD_OR_ELSE(obj, field, (z_typeof((obj)->field))0)

#define FMT(ex) _##ex##_fmt
#define COND(ex) _##ex##_cond
Expand All @@ -101,9 +104,14 @@ if (COND(ex)(ERR(ex))) { ERFILE(ex) = __FILENAME__; ERLINE(ex) = __LINE__; _##ex
}}\
for (int _##ex##_count = 0;COND(ex)(ERR(ex)) && _##ex##_count == 0; _##ex##_count++)

#define line_idx(i, l) i ## l

#define FOR(idx, arr) for (int (idx) = 0; (idx) < SIZEOF(arr) && (arr)[(idx)] != NULL; (idx)++)
#define FOR_line(el, arr, LINE) int line_idx(idx,LINE); for ( \
line_idx(idx,LINE) = 0, (el) = (arr) ? (arr)[line_idx(idx,LINE)] : NULL; \
el != NULL; \
line_idx(idx,LINE)++, (el) = (arr)[line_idx(idx,LINE)] )

#define FOR(el, arr) FOR_line(el, arr, __LINE__)


#define container_of(ptr, type, member) ((type *) ((char*)(ptr) - offsetof(type, member)))
Expand Down
14 changes: 13 additions & 1 deletion inc_internal/ziti_ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ extern const char* const PC_ENDPOINT_STATE_TYPE;

typedef void (*ziti_ctrl_redirect_cb)(const char *new_address, void *ctx);

typedef void (*ctrl_version_cb)(const ziti_version *, const ziti_error *, void *);

typedef void(*routers_cb)(ziti_service_routers *srv_routers, const ziti_error *, void *);

typedef struct ziti_controller_s {
uv_loop_t *loop;
tlsuv_http_t *client;
Expand All @@ -42,6 +46,9 @@ typedef struct ziti_controller_s {
unsigned int page_size;

ziti_version version;
ctrl_version_cb version_cb;
void *version_cb_ctx;
void *version_req;

bool has_token;
char *instance_id;
Expand All @@ -64,11 +71,14 @@ int ziti_ctrl_close(ziti_controller *ctrl);

void ziti_ctrl_clear_api_session(ziti_controller *ctrl);

void ziti_ctrl_get_version(ziti_controller *ctrl, void (*ver_cb)(ziti_version *, const ziti_error *, void *), void *ctx);
void ziti_ctrl_get_version(ziti_controller *ctrl, ctrl_version_cb cb, void *ctx);

void ziti_ctrl_login(ziti_controller *ctrl, model_list *cfg_types, void (*cb)(ziti_api_session *, const ziti_error *, void *),
void *ctx);

void ziti_ctrl_list_controllers(ziti_controller *ctrl,
void (*cb)(ziti_controller_detail_array, const ziti_error*, void *ctx), void *ctx);

void ziti_ctrl_current_api_session(ziti_controller *ctrl, void(*cb)(ziti_api_session *, const ziti_error *, void *), void *ctx);

void ziti_ctrl_create_api_certificate(ziti_controller *ctrl, const char *csr_pem, void(*cb)(ziti_create_api_cert_resp *, const ziti_error *, void *), void *ctx);
Expand All @@ -89,6 +99,8 @@ void ziti_ctrl_get_services(ziti_controller *ctrl, void (*srv_cb)(ziti_service_a
void ziti_ctrl_get_service(ziti_controller *ctrl, const char *service_name,
void (*srv_cb)(ziti_service *, const ziti_error *, void *), void *ctx);

void ziti_ctrl_list_service_routers(ziti_controller *ctrl, const ziti_service *srv, routers_cb, void *ctx);

void ziti_ctrl_create_session(
ziti_controller *ctrl, const char *service_id, ziti_session_type type,
void (*cb)(ziti_session *, const ziti_error *, void *), void *ctx);
Expand Down
18 changes: 11 additions & 7 deletions inc_internal/zt_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "edge_protocol.h"
#include "posture.h"
#include "authenticators.h"
#include "auth_method.h"

#include <sodium.h>

Expand Down Expand Up @@ -183,7 +184,8 @@ struct ziti_conn {
ziti_listen_cb listen_cb;
ziti_client_cb client_cb;

ziti_session *session;
ziti_edge_router_array routers;
char *token;
model_map bindings;
model_map children;
uv_timer_t *timer;
Expand Down Expand Up @@ -256,23 +258,26 @@ struct ziti_ctx {
ziti_config config;
ziti_options opts;
ziti_controller ctrl;
model_list controllers;
uint32_t id;

model_map ctrl_details;

tlsuv_private_key_t sessionKey;
char *sessionCsr;
tls_cert sessionCert;
tls_context *tlsCtx;

bool closing;
bool enabled;
bool logout;
int ctrl_status;

bool active_session_request;
ziti_api_session *api_session;
uv_timeval64_t api_session_expires_at;
ziti_api_session_state api_session_state;
ziti_auth_method_t *auth_method;
ziti_auth_state auth_state;
// HA access_token(JWT) or legacy ziti_api_session.token
char *session_token;

uv_timeval64_t session_received_at;
ziti_identity_data *identity_data;

bool services_loaded;
Expand All @@ -286,7 +291,6 @@ struct ziti_ctx {

char *last_update;

uv_timer_t *api_session_timer;
uv_timer_t *service_refresh_timer;
uv_prepare_t *prepper;

Expand Down
2 changes: 1 addition & 1 deletion includes/ziti/ziti_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ struct ziti_service_event {
* `ziti_mfa_auth(...)`
*/
struct ziti_mfa_auth_event {
ziti_auth_query_mfa *auth_query_mfa;
const ziti_auth_query_mfa *auth_query_mfa;
};

/**
Expand Down
1 change: 1 addition & 0 deletions includes/ziti/ziti_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ XX(ca, string, none, ca, __VA_ARGS__)

#define ZITI_CONFIG_MODEL(XX, ...) \
XX(controller_url, string, none, ztAPI, __VA_ARGS__) \
XX(controllers, string, list, ztAPIs, __VA_ARGS__) \
XX(id, ziti_id_cfg, none, id, __VA_ARGS__) \
XX(cfg_source, string, none, , __VA_ARGS__)

Expand Down
3 changes: 3 additions & 0 deletions library/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,11 @@ SET(ZITI_SRC_FILES
authenticators.c
crypto.c
bind.c
oidc.c
proto/edge_client.pb-c.c
proto/google/protobuf/timestamp.pb-c.c
legacy_auth.c
ha_auth.c
util/future.c
)

Expand Down
Loading

0 comments on commit 53c54fe

Please sign in to comment.