diff --git a/Makefile b/Makefile index 305e13a5..54802581 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,17 @@ CODESPELL = $(shell which codespell) SPELLCHECK = $(CODESPELL) -S _build -S doc -S .git -L applys,nd,accout,mattern,pres,fo SPELLFIX = $(SPELLCHECK) -i 3 -w +# Architecture Auto configuration +UNAME_M := $(shell uname -m) +ifeq ($(UNAME_M), x86_64) + DOCKER_PLATFORM = amd64 +else ifeq ($(UNAME_M), aarch64) + DOCKER_PLATFORM = arm64 +else ifeq ($(UNAME_M), arm64) + DOCKER_PLATFORM = arm64 +else ifeq ($(UNAME_M), armv7l) + DOCKER_PLATFORM = arm32v7 +endif .PHONY: genvars compile check test xref eunit dialyzer tar spellcheck spellfix @@ -33,6 +44,10 @@ docs: xref cp -r doc/assets/* apps/bondy/doc/assets/ cp -r doc/assets/* apps/bondy_broker_bridge/doc/assets/ +clean: node1-clean node2-clean node3-clean + ${REBAR} clean + + clean-docs: rm -rf apps/bondy/doc/* rm -f apps/bondy/doc/.build @@ -119,18 +134,28 @@ node1: ${REBAR} as node1 release ERL_DIST_PORT=27781 _build/node1/rel/bondy/bin/bondy console +node1-clean: + ${REBAR} as node1 clean + node2: ${REBAR} as node2 release ERL_DIST_PORT=27782 _build/node2/rel/bondy/bin/bondy console +node2-clean: + ${REBAR} as node2 clean + node3: ${REBAR} as node3 release ERL_DIST_PORT=27783 _build/node3/rel/bondy/bin/bondy console +node3-clean: + ${REBAR} as node3 clean edge1: ${REBAR} as edge1 release - ERL_DIST_PORT=27784 _build/edge1/rel/bondy/bin/bondy console + EDGE1_DEVICE1_PRIVKEY=4ffddd896a530ce5ee8c86b83b0d31835490a97a9cd718cb2f09c9fd31c4a7d71766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd \ + ERL_DIST_PORT=27784 \ + _build/edge1/rel/bondy/bin/bondy console run-node1: @@ -155,7 +180,7 @@ docker-build: docker rmi bondy-prod || true docker build \ --pull \ - --platform linux/amd64 \ + --platform linux/$(DOCKER_PLATFORM) \ --load \ -t "bondy-prod" \ -f deployment/Dockerfile . @@ -167,7 +192,7 @@ docker-build-alpine: docker rmi bondy-prod || true docker build \ --pull \ - --platform linux/amd64 \ + --platform linux/$(DOCKER_PLATFORM) \ --load \ -t "bondy-prod" \ -f deployment/alpine.Dockerfile . @@ -179,7 +204,7 @@ docker-build-slim: docker rmi bondy-prod || true docker build \ --pull \ - --platform linux/amd64 \ + --platform linux/$(DOCKER_PLATFORM) \ --load \ -t "bondy-prod" \ -f deployment/slim.Dockerfile . diff --git a/README.md b/README.md index 1e743268..c205997d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ ![Bondy logo](https://github.com/Leapsight/bondy/blob/develop/doc/assets/bondy_bg.png?raw=true) -![Version](https://img.shields.io/badge/version-1.0.0--beta.78-blue?style=for-the-badge)
+![Version](https://img.shields.io/badge/version-1.0.00-rc.1-blue?style=for-the-badge)
![Docker Pulls](https://img.shields.io/docker/pulls/leapsight/bondy?style=for-the-badge) ![Docker Build (master)](https://img.shields.io/github/actions/workflow/status/bondy-io/bondy/docker_image_build.yaml?&branch=master&label=docker-master&style=for-the-badge) ![Docker Build (develop)](https://img.shields.io/github/actions/workflow/status/bondy-io/bondy/docker_image_build.yaml?&branch=develop&label=docker-develop&style=for-the-badge) -![Docker Build (latest-tag)](https://img.shields.io/github/actions/workflow/status/bondy-io/bondy/docker_image_build.yaml?&tag=version-1.0.0-beta.78&label=docker-1.0.0-beta.78&style=for-the-badge) +![Docker Build (latest-tag)](https://img.shields.io/github/actions/workflow/status/bondy-io/bondy/docker_image_build.yaml?&tag=version-1.0.0-rc.1&label=docker-1.0.0-rc.1&style=for-the-badge)
![Architectures](https://img.shields.io/badge/architecture-linux%2Famd64%20%7C%20linux%2Farm64%20%7C%20macOS%2Fintel%20%7C%20macOS%2FM1-lightgrey?style=for-the-badge) @@ -134,13 +134,14 @@ leapsight/bondy:master ### Building from source #### Requirements * macOS (Intel|Apple Silicon) or Linux (amd64|arm64) -* [Erlang](https://www.erlang.org/) 24 or later -* [Rebar3](https://rebar3.readme.io/) 3.17.0 or later +* [Erlang](https://www.erlang.org/) 26.0.2 or later +* [Rebar3](https://rebar3.readme.io/) 3.22.1 or later * openssl * libssl * [Libsodium](https://github.com/jedisct1/libsodium) * libsnappy * liblz4 +* libcrypto #### Building @@ -156,7 +157,7 @@ rebar3 as prod tar Untar and copy the resulting tarball to the location where you want to install Bondy e.g. `~/tmp/bondy`. ```shell -tar -zxvf _build/prod/rel/bondy-1.0.0-beta.78.tar.qz -C ~/tmp/bondy +tar -zxvf _build/prod/rel/bondy-1.0.0-rc.1.tar.qz -C ~/tmp/bondy ``` #### Running diff --git a/apps/bondy/src/bondy.app.src b/apps/bondy/src/bondy.app.src index 8deec902..3f7e2b07 100644 --- a/apps/bondy/src/bondy.app.src +++ b/apps/bondy/src/bondy.app.src @@ -26,10 +26,10 @@ "Bondy implements the open Web Application Messaging Protocol (WAMP) " "and is written in Erlang." }, - {vsn, "1.0.0-beta.78"}, + {vsn, "1.0.0-rc.1"}, {registered, []}, %% We pass the version number in the bondy_app:start/2 arguments - {mod, {bondy_app, [{vsn, "1.0.0-beta.78"}]}}, + {mod, {bondy_app, [{vsn, "1.0.0-rc.1"}]}}, {applications,[ %% Erlang/OTP stdlib, diff --git a/apps/bondy/src/bondy_bridge_relay.erl b/apps/bondy/src/bondy_bridge_relay.erl index da438a3e..64732be8 100644 --- a/apps/bondy/src/bondy_bridge_relay.erl +++ b/apps/bondy/src/bondy_bridge_relay.erl @@ -1,5 +1,5 @@ %% ============================================================================= -%% bondy_bridge_relay_listener.erl - +%% bondy_bridge_relay.erl - %% %% Copyright (c) 2016-2023 Leapsight. All rights reserved. %% @@ -222,6 +222,28 @@ (_) -> false end }, + hostname_verification => #{ + alias => <<"hostname_verification">>, + %% We rename the prop + key => customize_hostname_check, + required => false, + datatype => {in, [ + wildcard, none, + <<"wildcard">>, <<"none">> + ]}, + validator => fun + (V) when V == <<"wildcard">>; V == wildcard -> + %% tls_options will end up having + %% #{ + %% ... + %% customize_hostname_check => [{match_fun, Match}] + %% } + Match = public_key:pkix_verify_hostname_match_fun(https), + {ok, [{match_fun, Match}]}; + (_) -> + {ok, []} + end + }, versions => #{ alias => <<"versions">>, required => true, diff --git a/apps/bondy/src/bondy_bridge_relay_client.erl b/apps/bondy/src/bondy_bridge_relay_client.erl index 40d8e99d..89a0e002 100644 --- a/apps/bondy/src/bondy_bridge_relay_client.erl +++ b/apps/bondy/src/bondy_bridge_relay_client.erl @@ -1217,8 +1217,8 @@ signer(_, #{cryptosign := #{privkey_env_var := Var}}) -> end end; -signer(_, _) -> - error(invalid_cryptosign_config). +signer(_, Conf) -> + error({invalid_cryptosign_config, Conf}). %% @private diff --git a/apps/bondy/src/bondy_system_gc.erl b/apps/bondy/src/bondy_system_gc.erl index ad88590a..55ec8718 100644 --- a/apps/bondy/src/bondy_system_gc.erl +++ b/apps/bondy/src/bondy_system_gc.erl @@ -71,6 +71,7 @@ garbage_collect() -> init([]) -> + ok = schedule_gc(), {ok, #state{}}. @@ -96,6 +97,10 @@ handle_cast(Event, State) -> {noreply, State}. +handle_info(scheduled_gc, State) -> + ok = do_gc(), + ok = schedule_gc(), + {noreply, State}; handle_info(Info, State) -> ?LOG_DEBUG(#{ @@ -123,11 +128,25 @@ code_change(_OldVsn, State, _Extra) -> %% ============================================================================= + +schedule_gc() -> + Interval = bondy_config:get(gc_interval, timer:minutes(5)), + erlang:send_after(Interval, self(), scheduled_gc), + ok. + + + do_gc() -> - L = [element(1, X) || X <- recon:proc_count(memory, 100)], + {process_count, Count} = erlang:system_info(process_count), + Ratio = bondy_config:get(gc_ratio, 0.3), + N = round(Count * Ratio), + L = [element(1, X) || X <- recon:proc_count(memory, N)], [ erlang:garbage_collect(P) || P <- L, {status, waiting} == process_info(P, status) ], + + %% We gc ourselves + erlang:garbage_collect(), ok. \ No newline at end of file diff --git a/apps/bondy/src/bondy_table_owner.erl b/apps/bondy/src/bondy_table_owner.erl index 47466a66..f714406f 100644 --- a/apps/bondy/src/bondy_table_owner.erl +++ b/apps/bondy/src/bondy_table_owner.erl @@ -222,7 +222,7 @@ handle_call({add_and_claim, Name, Opts0}, {From, _Tag}, St) -> handle_call({add_or_claim, Name, Opts0}, {From, _Tag}, St) -> case lookup(Name) of {ok, Tab} -> - ok = do_give_away(Tab, From), + true = do_give_away(Tab, From), {reply, {ok, Tab}, St}; error -> Opts1 = set_heir(Opts0), diff --git a/apps/bondy/test/bondy_ct.erl b/apps/bondy/test/bondy_ct.erl index ca1e7dc3..94870c56 100644 --- a/apps/bondy/test/bondy_ct.erl +++ b/apps/bondy/test/bondy_ct.erl @@ -20,9 +20,9 @@ -include_lib("common_test/include/ct.hrl"). -if(?OTP_RELEASE >= 25). - %% already defined by OTP + -define(TEST_SERVER, test_server). -else. - -define(CT_PEER, ct_slave). + -define(TEST_SERVER, ct_slave). -endif. -define(KERNEL_ENV, [ @@ -45,11 +45,9 @@ [{remote_gl,{fun logger_filters:remote_gl/2,stop}}, {no_domain, {fun logger_filters:domain/2,{log,undefined,[]}}}, - {domain, - {fun logger_filters:domain/2,{stop,equal,[sasl]}}}, {domain, {fun logger_filters:domain/2, - {log,super,[otp,bondy_audit]}}}], + {log,super,[otp, sasl, bondy_audit]}}}], formatter => {bondy_logger_formatter,#{ colored => true,colored_alert => "\e[0;45m", @@ -119,10 +117,15 @@ {tiered_slow_level,0}]}, {partisan, [{exchange_tick_period,60000}, - {tls_options, - [{cacertfile,"./etc/cacert.pem"}, - {keyfile,"./etc/key.pem"}, - {certfile,"./etc/cert.pem"}, + {tls_server_options, + [{cacertfile,"./etc/ssl/server/cacert.pem"}, + {keyfile,"./etc/ssl/server/key.pem"}, + {certfile,"./etc/ssl/server/keycert.pem"}, + {versions,['tlsv1.3']}]}, + {tls_client_options, + [{cacertfile,"./etc/ssl/client/cacert.pem"}, + {keyfile,"./etc/ssl/client/key.pem"}, + {certfile,"./etc/ssl/client/keycert.pem"}, {versions,['tlsv1.3']}]}, {tls,false}, {peer_service_manager,partisan_pluggable_peer_service_manager}, @@ -166,9 +169,9 @@ {config_file,"./etc/oauth2_config.json"}]}, {bridge_relay_tls, [{socket_opts, - [{cacertfile,"./etc/cacert.pem"}, - {keyfile,"./etc/key.pem"}, - {certfile,"./etc/cert.pem"}, + [{cacertfile,"./etc/ssl/server/cacert.pem"}, + {keyfile,"./etc/ssl/server/key.pem"}, + {certfile,"./etc/ssl/server/keycert.pem"}, {nodelay,true}, {keepalive,true}, {versions,['tlsv1.3']}]}, @@ -206,9 +209,9 @@ {enabled,false}]}, {wamp_tls, [{socket_opts, - [{cacertfile,"./etc/cacert.pem"}, - {keyfile,"./etc/key.pem"}, - {certfile,"./etc/cert.pem"}, + [{cacertfile,"./etc/ssl/server/cacert.pem"}, + {keyfile,"./etc/ssl/server/key.pem"}, + {certfile,"./etc/ssl/server/keycert.pem"}, {nodelay,true}, {keepalive,true}, {versions,['tlsv1.2','tlsv1.3']}]}, @@ -240,9 +243,9 @@ {wamp_serializers,[{bert,4},{erl,15}]}, {api_gateway_https, [{socket_opts, - [{cacertfile,"./etc/cacert.pem"}, - {keyfile,"./etc/key.pem"}, - {certfile,"./etc/cert.pem"}, + [{cacertfile,"./etc/ssl/server/cacert.pem"}, + {keyfile,"./etc/ssl/server/key.pem"}, + {certfile,"./etc/ssl/server/keycert.pem"}, {nodelay,true}, {keepalive,false}, {versions,['tlsv1.3']}]}, @@ -261,9 +264,9 @@ {api_gateway,[{config_file,"./etc/api_gateway_config.json"}]}, {admin_api_https, [{socket_opts, - [{cacertfile,"./etc/cacert.pem"}, - {keyfile,"./etc/key.pem"}, - {certfile,"./etc/cert.pem"}, + [{cacertfile,"./etc/ssl/server/cacert.pem"}, + {keyfile,"./etc/ssl/server/key.pem"}, + {certfile,"./etc/ssl/server/keycert.pem"}, {nodelay,true}, {keepalive,false}, {versions,['tlsv1.3']}]}, @@ -424,7 +427,7 @@ stop_bondy() -> %% ----------------------------------------------------------------------------- -%% @doc Starts a set of CT_PEER nodes as per `Config' and joins them in a +%% @doc Starts a set of TEST_SERVER nodes as per `Config' and joins them in a %% cluster. %% @end %% ----------------------------------------------------------------------------- @@ -438,7 +441,7 @@ start_cluster(_Case, _Config, _Options) -> %% ----------------------------------------------------------------------------- stop_nodes(Nodes) -> StopFun = fun({Name, _Node}) -> - case ?CT_PEER:stop(Name) of + case ?TEST_SERVER:stop(Name) of {ok, _} -> ok; {error, stop_timeout, _} -> diff --git a/apps/bondy_broker_bridge/rebar.config b/apps/bondy_broker_bridge/rebar.config index 6b11203c..27a436ba 100644 --- a/apps/bondy_broker_bridge/rebar.config +++ b/apps/bondy_broker_bridge/rebar.config @@ -10,7 +10,7 @@ }, %% Used by Kafka Bridge {brod, - {git, "https://github.com/klarna/brod.git", {tag, "3.16.1"}} + {git, "https://github.com/klarna/brod.git", {tag, "3.17.0"}} }, {hash, ".*", {git, "https://github.com/leapsight/hash", {branch, master}} diff --git a/apps/bondy_broker_bridge/src/bondy_broker_bridge.app.src b/apps/bondy_broker_bridge/src/bondy_broker_bridge.app.src index fc4bd0b1..54120c43 100644 --- a/apps/bondy_broker_bridge/src/bondy_broker_bridge.app.src +++ b/apps/bondy_broker_bridge/src/bondy_broker_bridge.app.src @@ -2,7 +2,7 @@ {description, "Bondy Broker Bridge is an application that is part of Bondy and provides a way to integrate Events with external brokers and systems." }, - {vsn, "1.0.0-beta.78"}, + {vsn, "1.0.0-rc.1"}, {registered, []}, {mod, {bondy_broker_bridge_app, []}}, {applications, [ @@ -26,4 +26,4 @@ {"Website", "https://getbondy.io"}, {"Docker", "https://hub.docker.com/r/leapsight/bondy"} ]} - ]}. +]}. diff --git a/config/dev/bondy.conf.template b/config/dev/bondy.conf.template index bcf0796d..37d0a34e 100644 --- a/config/dev/bondy.conf.template +++ b/config/dev/bondy.conf.template @@ -13,9 +13,9 @@ admin_api.https.acceptors_pool_size = 200 admin_api.https.enabled = off admin_api.https.keepalive = off admin_api.https.max_connections = 250000 -admin_api.https.cacertfile = ${BONDY_ETC_DIR}/ssl/cacert.pem -admin_api.https.certfile = ${BONDY_ETC_DIR}/ssl/cert.pem -admin_api.https.keyfile = ${BONDY_ETC_DIR}/ssl/key.pem +admin_api.https.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem +admin_api.https.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem +admin_api.https.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem admin_api.https.enabled = on api_gateway.config_file = ${BONDY_ETC_DIR}/api_spec.json api_gateway.http.acceptors_pool_size = 200 @@ -28,9 +28,9 @@ api_gateway.https.backlog = 4096 api_gateway.https.keepalive = off api_gateway.https.max_connections = 500000 api_gateway.https.nodelay = on -api_gateway.https.cacertfile = ${BONDY_ETC_DIR}/ssl/cacert.pem -api_gateway.https.certfile = ${BONDY_ETC_DIR}/ssl/cert.pem -api_gateway.https.keyfile = ${BONDY_ETC_DIR}/ssl/key.pem +api_gateway.https.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem +api_gateway.https.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem +api_gateway.https.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem api_gateway.https.enabled = on broker_bridge.config_file = ${BONDY_ETC_DIR}/broker_bridge_config.json @@ -55,10 +55,17 @@ cluster.peer_discovery.timeout = 5s cluster.peer_discovery.type = bondy_peer_discovery_static_agent cluster.peer_discovery.config.nodes.1 = bondy1@127.0.0.1 cluster.peer_discovery.config.nodes.2 = bondy2@127.0.0.1 -cluster.tls.cacertfile = ${BONDY_ETC_DIR}/ssl/cacert.pem -cluster.tls.certfile = ${BONDY_ETC_DIR}/ssl/cert.pem -cluster.tls.keyfile = ${BONDY_ETC_DIR}/ssl/key.pem cluster.tls.enabled = on +cluster.tls.server.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem +cluster.tls.server.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem +cluster.tls.server.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem +cluster.tls.server.versions = 1.2,1.3 +cluster.tls.server.verify = verify_none +cluster.tls.client.cacertfile = ${BONDY_ETC_DIR}/ssl/client/cacert.pem +cluster.tls.client.certfile = ${BONDY_ETC_DIR}/ssl/client/keycert.pem +cluster.tls.client.keyfile = ${BONDY_ETC_DIR}/ssl/client/key.pem +cluster.tls.client.versions = 1.2,1.3 +# cluster.tls.client.verify = verify_none distributed_cookie = bondy erlang.async_threads = 64 erlang.max_ports = 65536 diff --git a/config/docker/vm.args b/config/docker/vm.args index ecd24021..89d8a5ce 100644 --- a/config/docker/vm.args +++ b/config/docker/vm.args @@ -22,15 +22,25 @@ ## Connections between hidden nodes and other nodes are not transitive, they must be set up explicitly. -hidden -## Increase distribution port buffer size. -+zdbbl 32768 ## ----------------------------------------------------------------------------- -## Erlang +## Emulator Flags ## ----------------------------------------------------------------------------- +## Increase distribution port buffer size. ++zdbbl 32768 + +# Disable Speculative Scheduler Busy Waiting +# The threshold determines how long schedulers are to busy wait when running out +# of work before going to sleep. +sbwt none +# As +sbwt but affects dirty CPU schedulers. ++sbwtdcpu none + +# As +sbwt but affects dirty IO schedulers. ++sbwtdio none + ## Enable Time Correction +c true @@ -40,9 +50,6 @@ ## Max processes +P 2000000 -## Kernel polling -+K true - ## Async I/O threads +A 64 diff --git a/config/make_certs b/config/make_certs index 9b9c5e97..9953613e 100755 --- a/config/make_certs +++ b/config/make_certs @@ -18,41 +18,102 @@ %% %CopyrightEnd% %% +-record(config, {commonName, + organizationalUnitName = "Bondy", + organizationName = "Leapsight", + localityName = "London", + countryName = "UK", + emailAddress = "cert@leapsight.com", + default_bits = 2048, + v2_crls = true, + ecc_certs = false, + issuing_distribution_point = false, + crldp_crlissuer = false, + crl_port = 8000, + openssl_cmd = "openssl", + hostname = "host.example.com"}). + +%% Added for escript main([]) -> all("./_ssl/", "./_ssl"). -dn(CName) -> - #{ - commonName => CName, - organizationalUnitName => "Bondy", - organizationName => "Leapsight", - localityName => "London", - countryName => "UK", - emailAddress => "cert@leapsight.com" - }. - - -all(DataDir, Output) -> - cmd("mkdir -p " ++ Output, []), - OpenSSLCmd = "openssl", - create_rnd(DataDir, Output), % For all requests - rootCA(Output, OpenSSLCmd, "erlangCA"), - intermediateCA(Output, OpenSSLCmd, "otpCA", "erlangCA"), - endusers(Output, OpenSSLCmd, "otpCA", ["client", "server"]), - collect_certs(Output, ["erlangCA", "otpCA"], ["client", "server"]), +default_config() -> + #config{hostname = net_adm:localhost()}. + +make_config(Args) -> + make_config(Args, default_config()). + +make_config([], C) -> + C; +make_config([{organizationalUnitName, Name}|T], C) when is_list(Name) -> + make_config(T, C#config{organizationalUnitName = Name}); +make_config([{organizationName, Name}|T], C) when is_list(Name) -> + make_config(T, C#config{organizationName = Name}); +make_config([{localityName, Name}|T], C) when is_list(Name) -> + make_config(T, C#config{localityName = Name}); +make_config([{countryName, Name}|T], C) when is_list(Name) -> + make_config(T, C#config{countryName = Name}); +make_config([{emailAddress, Name}|T], C) when is_list(Name) -> + make_config(T, C#config{emailAddress = Name}); +make_config([{default_bits, Bits}|T], C) when is_integer(Bits) -> + make_config(T, C#config{default_bits = Bits}); +make_config([{v2_crls, Bool}|T], C) when is_boolean(Bool) -> + make_config(T, C#config{v2_crls = Bool}); +make_config([{crl_port, Port}|T], C) when is_integer(Port) -> + make_config(T, C#config{crl_port = Port}); +make_config([{ecc_certs, Bool}|T], C) when is_boolean(Bool) -> + make_config(T, C#config{ecc_certs = Bool}); +make_config([{issuing_distribution_point, Bool}|T], C) when is_boolean(Bool) -> + make_config(T, C#config{issuing_distribution_point = Bool}); +make_config([{crldp_crlissuer, Bool}|T], C) when is_boolean(Bool) -> + make_config(T, C#config{crldp_crlissuer = Bool}); +make_config([{openssl_cmd, Cmd}|T], C) when is_list(Cmd) -> + make_config(T, C#config{openssl_cmd = Cmd}); +make_config([{hostname, Hostname}|T], C) when is_list(Hostname) -> + make_config(T, C#config{hostname = Hostname}). + + +all([DataDir, PrivDir]) -> + all(DataDir, PrivDir). + +all(DataDir, PrivDir) -> + all(DataDir, PrivDir, #config{}). + +all(DataDir, PrivDir, C) when is_list(C) -> + all(DataDir, PrivDir, make_config(C)); +all(DataDir, PrivDir, C = #config{}) -> + ok = filelib:ensure_dir(filename:join(PrivDir, "erlangCA")), + create_rnd(DataDir, PrivDir), % For all requests + rootCA(PrivDir, "erlangCA", C), + intermediateCA(PrivDir, "otpCA", "erlangCA", C), + endusers(PrivDir, "otpCA", ["client", "server", "revoked", "undetermined", "a.server", "b.server"], C), + endusers(PrivDir, "erlangCA", ["localhost"], C), %% Create keycert files - SDir = filename:join([Output, "server"]), + SDir = filename:join([PrivDir, "server"]), SC = filename:join([SDir, "cert.pem"]), SK = filename:join([SDir, "key.pem"]), SKC = filename:join([SDir, "keycert.pem"]), append_files([SK, SC], SKC), - CDir = filename:join([Output, "client"]), + CDir = filename:join([PrivDir, "client"]), CC = filename:join([CDir, "cert.pem"]), CK = filename:join([CDir, "key.pem"]), CKC = filename:join([CDir, "keycert.pem"]), append_files([CK, CC], CKC), - remove_rnd(Output). + RDir = filename:join([PrivDir, "revoked"]), + RC = filename:join([RDir, "cert.pem"]), + RK = filename:join([RDir, "key.pem"]), + RKC = filename:join([RDir, "keycert.pem"]), + revoke(PrivDir, "otpCA", "revoked", C), + append_files([RK, RC], RKC), + MDir = filename:join([PrivDir, "undetermined"]), + MC = filename:join([MDir, "cert.pem"]), + MK = filename:join([MDir, "key.pem"]), + MKC = filename:join([MDir, "keycert.pem"]), + remove_entry(PrivDir, "otpCA", "undetermined", C), + append_files([MK, MC], MKC), + remove_rnd(PrivDir), + {ok, C}. append_files(FileNames, ResultFileName) -> {ok, ResultFile} = file:open(ResultFileName, [write]), @@ -65,111 +126,221 @@ do_append_files([F|Fs], RF) -> ok = file:write(RF, Data), do_append_files(Fs, RF). -rootCA(Root, OpenSSLCmd, Name) -> - create_ca_dir(Root, Name, ca_cnf(Name)), - DN = dn(Name), - create_self_signed_cert(Root, OpenSSLCmd, Name, req_cnf(DN)), - ok. +rootCA(Root, Name, C) -> + create_ca_dir(Root, Name, ca_cnf(Root, C#config{commonName = Name})), + create_self_signed_cert(Root, Name, req_cnf(Root, C#config{commonName = Name}), C), + file:copy(filename:join([Root, Name, "cert.pem"]), filename:join([Root, Name, "cacerts.pem"])), + gencrl(Root, Name, C). -intermediateCA(Root, OpenSSLCmd, CA, ParentCA) -> - CA = "otpCA", - create_ca_dir(Root, CA, ca_cnf(CA)), +intermediateCA(Root, CA, ParentCA, C) -> + create_ca_dir(Root, CA, ca_cnf(Root, C#config{commonName = CA})), CARoot = filename:join([Root, CA]), - DN = dn(CA), CnfFile = filename:join([CARoot, "req.cnf"]), - file:write_file(CnfFile, req_cnf(DN)), + file:write_file(CnfFile, req_cnf(Root, C#config{commonName = CA})), KeyFile = filename:join([CARoot, "private", "key.pem"]), ReqFile = filename:join([CARoot, "req.pem"]), - create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile), + create_req(Root, CnfFile, KeyFile, ReqFile, C), CertFile = filename:join([CARoot, "cert.pem"]), - sign_req(Root, OpenSSLCmd, ParentCA, "ca_cert", ReqFile, CertFile). - -endusers(Root, OpenSSLCmd, CA, Users) -> - lists:foreach(fun(User) -> enduser(Root, OpenSSLCmd, CA, User) end, Users). - -enduser(Root, OpenSSLCmd, CA, User) -> + sign_req(Root, ParentCA, "ca_cert", ReqFile, CertFile, C), + CACertsFile = filename:join(CARoot, "cacerts.pem"), + file:copy(filename:join([Root, ParentCA, "cacerts.pem"]), CACertsFile), + %% append this CA's cert to the cacerts file + {ok, Bin} = file:read_file(CertFile), + {ok, FD} = file:open(CACertsFile, [append]), + file:write(FD, ["\n", Bin]), + file:close(FD), + gencrl(Root, CA, C). + +endusers(Root, CA, Users, C) -> + [enduser(Root, CA, User, C) || User <- Users]. + +enduser(Root, CA, User, C) -> UsrRoot = filename:join([Root, User]), file:make_dir(UsrRoot), CnfFile = filename:join([UsrRoot, "req.cnf"]), - DN = dn(User), - file:write_file(CnfFile, req_cnf(DN)), + file:write_file(CnfFile, req_cnf(Root, C#config{commonName = User})), KeyFile = filename:join([UsrRoot, "key.pem"]), ReqFile = filename:join([UsrRoot, "req.pem"]), - create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile), + create_req(Root, CnfFile, KeyFile, ReqFile, C), + %create_req(Root, CnfFile, KeyFile, ReqFile), CertFileAllUsage = filename:join([UsrRoot, "cert.pem"]), - sign_req(Root, OpenSSLCmd, CA, "user_cert", ReqFile, CertFileAllUsage), + sign_req(Root, CA, "user_cert", ReqFile, CertFileAllUsage, C), CertFileDigitalSigOnly = filename:join([UsrRoot, "digital_signature_only_cert.pem"]), - sign_req(Root, OpenSSLCmd, CA, "user_cert_digital_signature_only", ReqFile, CertFileDigitalSigOnly). - -collect_certs(Root, CAs, Users) -> - Bins = lists:foldr( - fun(CA, Acc) -> - File = filename:join([Root, CA, "cert.pem"]), - {ok, Bin} = file:read_file(File), - [Bin, "\n" | Acc] - end, [], CAs), - lists:foreach( - fun(User) -> - File = filename:join([Root, User, "cacerts.pem"]), - file:write_file(File, Bins) - end, Users). + sign_req(Root, CA, "user_cert_digital_signature_only", ReqFile, CertFileDigitalSigOnly, C), + CACertsFile = filename:join(UsrRoot, "cacerts.pem"), + file:copy(filename:join([Root, CA, "cacerts.pem"]), CACertsFile), + ok. -create_self_signed_cert(Root, OpenSSLCmd, CAName, Cnf) -> +revoke(Root, CA, User, C) -> + UsrCert = filename:join([Root, User, "cert.pem"]), + CACnfFile = filename:join([Root, CA, "ca.cnf"]), + Cmd = [C#config.openssl_cmd, " ca" + " -revoke ", UsrCert, + [" -crl_reason keyCompromise" || C#config.v2_crls ], + " -config ", CACnfFile], + Env = [{"ROOTDIR", filename:absname(Root)}], + cmd(Cmd, Env), + gencrl(Root, CA, C). + +%% Remove the certificate's entry from the database. The OCSP responder +%% will consider the certificate to be unknown. +remove_entry(Root, CA, User, C) -> + Db = filename:join([Root, CA, "index.txt"]), + remove_line_with_pattern(Db, "/CN=" ++ User ++ "/"), + gencrl(Root, CA, C). + +remove_line_with_pattern(File, Pattern) -> + {ok, Bin} = file:read_file(File), + AllLines = string:lexemes(Bin, [$\n,"\r\n"]), + MaybeRemove = fun(Line, Acc) -> + case string:find(Line, Pattern) of + nomatch -> [Line|Acc]; + _ -> Acc + end + end, + RevLines = lists:foldl(MaybeRemove, [], AllLines), + Lines = lists:join("\n", lists:reverse(RevLines)), + ok = file:write_file(File, Lines). + +gencrl(Root, CA, C) -> + %% By default, the CRL is valid for a week from now. + gencrl(Root, CA, C, 24*7). + +gencrl(Root, CA, C, CrlHours) -> + CACnfFile = filename:join([Root, CA, "ca.cnf"]), + CACRLFile = filename:join([Root, CA, "crl.pem"]), + Cmd = [C#config.openssl_cmd, " ca" + " -gencrl ", + " -crlhours ", integer_to_list(CrlHours), + " -out ", CACRLFile, + " -config ", CACnfFile], + Env = [{"ROOTDIR", filename:absname(Root)}], + cmd(Cmd, Env). + +%% This function sets the number of seconds until the next CRL is due. +gencrl_sec(Root, CA, C, CrlSecs) -> + CACnfFile = filename:join([Root, CA, "ca.cnf"]), + CACRLFile = filename:join([Root, CA, "crl.pem"]), + Cmd = [C#config.openssl_cmd, " ca" + " -gencrl ", + " -crlsec ", integer_to_list(CrlSecs), + " -out ", CACRLFile, + " -config ", CACnfFile], + Env = [{"ROOTDIR", filename:absname(Root)}], + cmd(Cmd, Env). + +can_generate_expired_crls(C) -> + %% OpenSSL can generate CRLs with an expiration date in the past, + %% if we pass a negative number for -crlhours. However, LibreSSL + %% rejects this with the error "invalid argument -24: too small". + %% Let's check which one we have. + Cmd = [C#config.openssl_cmd, " ca -crlhours -24"], + Output = os:cmd(Cmd), + 0 =:= string:str(Output, "too small"). + +verify(Root, CA, User, C) -> + CAFile = filename:join([Root, User, "cacerts.pem"]), + CACRLFile = filename:join([Root, CA, "crl.pem"]), + CertFile = filename:join([Root, User, "cert.pem"]), + Cmd = [C#config.openssl_cmd, " verify" + " -CAfile ", CAFile, + " -CRLfile ", CACRLFile, %% this is undocumented, but seems to work + " -crl_check ", + CertFile], + Env = [{"ROOTDIR", filename:absname(Root)}], + try cmd(Cmd, Env) catch + exit:{eval_cmd, _, _} -> + invalid + end. + +create_self_signed_cert(Root, CAName, Cnf, C = #config{ecc_certs = true}) -> CARoot = filename:join([Root, CAName]), CnfFile = filename:join([CARoot, "req.cnf"]), file:write_file(CnfFile, Cnf), KeyFile = filename:join([CARoot, "private", "key.pem"]), CertFile = filename:join([CARoot, "cert.pem"]), - Cmd = [OpenSSLCmd, " req" - " -new" - " -x509" - " -config ", CnfFile, - " -keyout ", KeyFile, - " -out ", CertFile], - Env = [{"ROOTDIR", Root}], + Cmd = [C#config.openssl_cmd, " ecparam" + " -out ", KeyFile, + " -name secp521r1 ", + %" -name sect283k1 ", + " -genkey "], + Env = [{"ROOTDIR", filename:absname(Root)}], cmd(Cmd, Env), - fix_key_file(OpenSSLCmd, KeyFile). - -% openssl 1.0 generates key files in pkcs8 format by default and we don't handle this format -fix_key_file(OpenSSLCmd, KeyFile) -> - KeyFileTmp = KeyFile ++ ".tmp", - Cmd = [OpenSSLCmd, " rsa", - " -in ", - KeyFile, - " -out ", - KeyFileTmp], - cmd(Cmd, []), - ok = file:rename(KeyFileTmp, KeyFile). + + Cmd2 = [C#config.openssl_cmd, " req" + " -new" + " -x509" + " -config ", CnfFile, + " -key ", KeyFile, + " -outform PEM ", + " -out ", CertFile], + cmd(Cmd2, Env); +create_self_signed_cert(Root, CAName, Cnf, C) -> + CARoot = filename:join([Root, CAName]), + CnfFile = filename:join([CARoot, "req.cnf"]), + file:write_file(CnfFile, Cnf), + KeyFile = filename:join([CARoot, "private", "key.pem"]), + CertFile = filename:join([CARoot, "cert.pem"]), + Cmd = [C#config.openssl_cmd, " req" + " -new" + " -x509" + " -config ", CnfFile, + " -keyout ", KeyFile, + " -outform PEM", + " -out ", CertFile], + Env = [{"ROOTDIR", filename:absname(Root)}], + cmd(Cmd, Env). + create_ca_dir(Root, CAName, Cnf) -> CARoot = filename:join([Root, CAName]), + ok = filelib:ensure_dir(CARoot), file:make_dir(CARoot), create_dirs(CARoot, ["certs", "crl", "newcerts", "private"]), create_rnd(Root, filename:join([CAName, "private"])), create_files(CARoot, [{"serial", "01\n"}, - {"index.txt", ""}, - {"ca.cnf", Cnf}]). - -create_req(Root, OpenSSLCmd, CnfFile, KeyFile, ReqFile) -> - Cmd = [OpenSSLCmd, " req" - " -new" - " -config ", CnfFile, - " -keyout ", KeyFile, - " -out ", ReqFile], - Env = [{"ROOTDIR", Root}], + {"crlnumber", "01"}, + {"index.txt", ""}, + {"ca.cnf", Cnf}]). + +create_req(Root, CnfFile, KeyFile, ReqFile, C = #config{ecc_certs = true}) -> + Cmd = [C#config.openssl_cmd, " ecparam" + " -out ", KeyFile, + " -name secp521r1 ", + %" -name sect283k1 ", + " -genkey "], + Env = [{"ROOTDIR", filename:absname(Root)}], cmd(Cmd, Env), - fix_key_file(OpenSSLCmd, KeyFile). + Cmd2 = [C#config.openssl_cmd, " req" + " -new ", + " -key ", KeyFile, + " -outform PEM ", + " -out ", ReqFile, + " -config ", CnfFile], + cmd(Cmd2, Env); + %fix_key_file(KeyFile). +create_req(Root, CnfFile, KeyFile, ReqFile, C) -> + Cmd = [C#config.openssl_cmd, " req" + " -new" + " -config ", CnfFile, + " -outform PEM ", + " -keyout ", KeyFile, + " -out ", ReqFile], + Env = [{"ROOTDIR", filename:absname(Root)}], + cmd(Cmd, Env). + %fix_key_file(KeyFile). -sign_req(Root, OpenSSLCmd, CA, CertType, ReqFile, CertFile) -> + +sign_req(Root, CA, CertType, ReqFile, CertFile, C) -> CACnfFile = filename:join([Root, CA, "ca.cnf"]), - Cmd = [OpenSSLCmd, " ca" - " -batch" - " -notext" - " -config ", CACnfFile, - " -extensions ", CertType, - " -in ", ReqFile, - " -out ", CertFile], - Env = [{"ROOTDIR", Root}], + Cmd = [C#config.openssl_cmd, " ca" + " -batch" + " -notext" + " -config ", CACnfFile, + " -extensions ", CertType, + " -in ", ReqFile, + " -out ", CertFile], + Env = [{"ROOTDIR", filename:absname(Root)}], cmd(Cmd, Env). %% @@ -178,13 +349,13 @@ sign_req(Root, OpenSSLCmd, CA, CertType, ReqFile, CertFile) -> create_dirs(Root, Dirs) -> lists:foreach(fun(Dir) -> - file:make_dir(filename:join([Root, Dir])) end, - Dirs). + file:make_dir(filename:join([Root, Dir])) end, + Dirs). create_files(Root, NameContents) -> lists:foreach( fun({Name, Contents}) -> - file:write_file(filename:join([Root, Name]), Contents) end, + file:write_file(filename:join([Root, Name]), Contents) end, NameContents). create_rnd(FromDir, ToDir) -> @@ -199,130 +370,307 @@ remove_rnd(Dir) -> cmd(Cmd, Env) -> FCmd = lists:flatten(Cmd), Port = open_port({spawn, FCmd}, [stream, eof, exit_status, stderr_to_stdout, - {env, Env}]), - eval_cmd(Port). + {env, Env}]), + eval_cmd(Port, FCmd). -eval_cmd(Port) -> +eval_cmd(Port, Cmd) -> receive - {Port, {data, _}} -> - eval_cmd(Port); - {Port, eof} -> - ok + {Port, {data, _}} -> + eval_cmd(Port, Cmd); + {Port, eof} -> + ok end, receive - {Port, {exit_status, Status}} when Status /= 0 -> - %% io:fwrite("exit status: ~w~n", [Status]), - exit({eval_cmd, Status}) + {Port, {exit_status, 0}} -> + ok; + {Port, {exit_status, Status}} -> + exit({eval_cmd, Cmd, Status}) after 0 -> - ok + ok end. %% %% Contents of configuration files %% -req_cnf(DN) -> - #{ - commonName := CName, - organizationalUnitName := OrganizationalUnitName, - organizationName := OrganizationName, - localityName := Local, - countryName := Country, - emailAddress := Email - } = DN, - +req_cnf(Root, C) -> ["# Purpose: Configuration for requests (end users and CAs)." "\n" - "ROOTDIR = $ENV::ROOTDIR\n" + "ROOTDIR = " ++ Root ++ "\n" "\n" "[req]\n" - "input_password = secret\n" - "output_password = secret\n" - "default_bits = 1024\n" - "RANDFILE = $ROOTDIR/RAND\n" - "encrypt_key = no\n" - "default_md = sha1\n" - "#string_mask = pkix\n" - "x509_extensions = ca_ext\n" - "prompt = no\n" + "input_password = secret\n" + "output_password = secret\n" + "default_bits = ", integer_to_list(C#config.default_bits), "\n" + "RANDFILE = $ROOTDIR/RAND\n" + "encrypt_key = no\n" + "default_md = sha256\n" + "#string_mask = pkix\n" + "x509_extensions = ca_ext\n" + "prompt = no\n" "distinguished_name= name\n" "\n" "[name]\n" - "commonName = ", CName, "\n" - "organizationalUnitName = ", OrganizationalUnitName, "\n" - "organizationName = ", OrganizationName, "\n" - "localityName = ", Local, "\n" - "countryName = ", Country, "\n" - "emailAddress = ", Email, "\n" + "commonName = ", C#config.commonName, "\n" + "organizationalUnitName = ", C#config.organizationalUnitName, "\n" + "organizationName = ", C#config.organizationName, "\n" + "localityName = ", C#config.localityName, "\n" + "countryName = ", C#config.countryName, "\n" + "emailAddress = ", C#config.emailAddress, "\n" "\n" "[ca_ext]\n" - "basicConstraints = critical, CA:true\n" - "keyUsage = cRLSign, keyCertSign\n" + "basicConstraints = critical, CA:true\n" + "keyUsage = cRLSign, keyCertSign\n" "subjectKeyIdentifier = hash\n" - "subjectAltName = email:copy\n"]. + "subjectAltName = email:copy\n"]. + +ca_cnf( + Root, + #config{ + issuing_distribution_point = true, + hostname = Hostname} = C) -> + ["# Purpose: Configuration for CAs.\n" + "\n" + "ROOTDIR = " ++ Root ++ "\n" + "default_ca = ca\n" + "\n" + + "[ca]\n" + "dir = $ROOTDIR/", C#config.commonName, "\n" + "certs = $dir/certs\n" + "crl_dir = $dir/crl\n" + "database = $dir/index.txt\n" + "new_certs_dir = $dir/newcerts\n" + "certificate = $dir/cert.pem\n" + "serial = $dir/serial\n" + "crl = $dir/crl.pem\n", + ["crlnumber = $dir/crlnumber\n" || C#config.v2_crls], + "private_key = $dir/private/key.pem\n" + "RANDFILE = $dir/private/RAND\n" + "\n" + "x509_extensions = user_cert\n", + ["crl_extensions = crl_ext\n" || C#config.v2_crls], + "unique_subject = no\n" + "default_days = 3600\n" + "default_md = sha256\n" + "preserve = no\n" + "policy = policy_match\n" + "\n" + + "[policy_match]\n" + "commonName = supplied\n" + "organizationalUnitName = optional\n" + "organizationName = match\n" + "countryName = match\n" + "localityName = match\n" + "emailAddress = supplied\n" + "\n" + + "[crl_ext]\n" + "authorityKeyIdentifier=keyid:always,issuer:always\n", + ["issuingDistributionPoint=critical, @idpsec\n" || C#config.issuing_distribution_point], + "[idpsec]\n" + "fullname=URI:http://localhost:8000/",C#config.commonName,"/crl.pem\n" -ca_cnf(CA) -> + "[user_cert]\n" + "basicConstraints = CA:false\n" + "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n" + "subjectKeyIdentifier = hash\n" + "authorityKeyIdentifier = keyid,issuer:always\n" + "subjectAltName = DNS.1:" ++ Hostname ++ "\n" + "issuerAltName = issuer:copy\n" + "crlDistributionPoints=@crl_section\n" + + "[crl_section]\n" + %% intentionally invalid + "URI.1=http://localhost/",C#config.commonName,"/crl.pem\n" + "URI.2=http://localhost:",integer_to_list(C#config.crl_port),"/",C#config.commonName,"/crl.pem\n" + "\n" + + "[user_cert_digital_signature_only]\n" + "basicConstraints = CA:false\n" + "keyUsage = digitalSignature\n" + "subjectKeyIdentifier = hash\n" + "authorityKeyIdentifier = keyid,issuer:always\n" + "subjectAltName = DNS.1:" ++ Hostname ++ "\n" + "issuerAltName = issuer:copy\n" + "\n" + + "[ca_cert]\n" + "basicConstraints = critical,CA:true\n" + "keyUsage = cRLSign, keyCertSign\n" + "subjectKeyIdentifier = hash\n" + "authorityKeyIdentifier = keyid:always,issuer:always\n" + "subjectAltName = DNS.1:" ++ Hostname ++ "\n" + "issuerAltName = issuer:copy\n" + "crlDistributionPoints=@crl_section\n" + ]; + +ca_cnf( + Root, + #config{ + crldp_crlissuer = true, + hostname = Hostname} = C) -> ["# Purpose: Configuration for CAs.\n" "\n" - "ROOTDIR = $ENV::ROOTDIR\n" - "default_ca = ca\n" + "ROOTDIR = " ++ Root ++ "\n" + "default_ca = ca\n" "\n" "[ca]\n" - "dir = $ROOTDIR/", CA, "\n" - "certs = $dir/certs\n" - "crl_dir = $dir/crl\n" - "database = $dir/index.txt\n" - "new_certs_dir = $dir/newcerts\n" - "certificate = $dir/cert.pem\n" - "serial = $dir/serial\n" - "crl = $dir/crl.pem\n" - "private_key = $dir/private/key.pem\n" - "RANDFILE = $dir/private/RAND\n" + "dir = $ROOTDIR/", C#config.commonName, "\n" + "certs = $dir/certs\n" + "crl_dir = $dir/crl\n" + "database = $dir/index.txt\n" + "new_certs_dir = $dir/newcerts\n" + "certificate = $dir/cert.pem\n" + "serial = $dir/serial\n" + "crl = $dir/crl.pem\n", + ["crlnumber = $dir/crlnumber\n" || C#config.v2_crls], + "private_key = $dir/private/key.pem\n" + "RANDFILE = $dir/private/RAND\n" "\n" - "x509_extensions = user_cert\n" + "x509_extensions = user_cert\n", + ["crl_extensions = crl_ext\n" || C#config.v2_crls], "unique_subject = no\n" - "default_days = 3600\n" - "default_md = sha1\n" - "preserve = no\n" - "policy = policy_match\n" + "default_days = 3600\n" + "default_md = sha256\n" + "preserve = no\n" + "policy = policy_match\n" "\n" "[policy_match]\n" - "commonName = supplied\n" - "organizationalUnitName = optional\n" - "organizationName = match\n" - "countryName = match\n" - "localityName = match\n" - "emailAddress = supplied\n" + "commonName = supplied\n" + "organizationalUnitName = optional\n" + "organizationName = match\n" + "countryName = match\n" + "localityName = match\n" + "emailAddress = supplied\n" "\n" + "[crl_ext]\n" + "authorityKeyIdentifier=keyid:always,issuer:always\n", + "[user_cert]\n" - "basicConstraints = CA:false\n" - "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n" + "basicConstraints = CA:false\n" + "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n" + "subjectKeyIdentifier = hash\n" + "authorityKeyIdentifier = keyid,issuer:always\n" + "subjectAltName = DNS.1:" ++ Hostname ++ "\n" + "issuerAltName = issuer:copy\n" + "crlDistributionPoints=crl_section\n" + + "[crl_section]\n" + "fullname=URI:http://localhost/",C#config.commonName,"/crl.pem\n" + "CRLissuer=dirName:issuer_sect\n" + + "[issuer_sect]\n" + "C=UK\n" + "O=Organisation\n" + "CN=Some Name\n" + + "[user_cert_digital_signature_only]\n" + "basicConstraints = CA:false\n" + "keyUsage = digitalSignature\n" "subjectKeyIdentifier = hash\n" "authorityKeyIdentifier = keyid,issuer:always\n" - "subjectAltName = email:copy\n" - "issuerAltName = issuer:copy\n" + "subjectAltName = DNS.1:" ++ Hostname ++ "\n" + "issuerAltName = issuer:copy\n" + "\n" + + "[ca_cert]\n" + "basicConstraints = critical,CA:true\n" + "keyUsage = cRLSign, keyCertSign\n" + "subjectKeyIdentifier = hash\n" + "authorityKeyIdentifier = keyid:always,issuer:always\n" + "subjectAltName = email:copy\n" + "issuerAltName = issuer:copy\n" + ]; + +ca_cnf( + Root, + #config{ + issuing_distribution_point = false, + hostname = Hostname + } = C) -> + ["# Purpose: Configuration for CAs.\n" + "\n" + "ROOTDIR = " ++ Root ++ "\n" + "default_ca = ca\n" + "\n" + + "[ca]\n" + "dir = $ROOTDIR/", C#config.commonName, "\n" + "certs = $dir/certs\n" + "crl_dir = $dir/crl\n" + "database = $dir/index.txt\n" + "new_certs_dir = $dir/newcerts\n" + "certificate = $dir/cert.pem\n" + "serial = $dir/serial\n" + "crl = $dir/crl.pem\n", + ["crlnumber = $dir/crlnumber\n" || C#config.v2_crls], + "private_key = $dir/private/key.pem\n" + "RANDFILE = $dir/private/RAND\n" + "\n" + "x509_extensions = user_cert\n", + ["crl_extensions = crl_ext\n" || C#config.v2_crls], + "unique_subject = no\n" + "default_days = 3600\n" + "default_md = sha256\n" + "preserve = no\n" + "policy = policy_match\n" "\n" + "[policy_match]\n" + "commonName = supplied\n" + "organizationalUnitName = optional\n" + "organizationName = match\n" + "countryName = match\n" + "localityName = match\n" + "emailAddress = supplied\n" + "\n" + + "[crl_ext]\n" + "authorityKeyIdentifier=keyid:always,issuer:always\n", + %["issuingDistributionPoint=critical, @idpsec\n" || C#config.issuing_distribution_point], + + %"[idpsec]\n" + %"fullname=URI:http://localhost:8000/",C#config.commonName,"/crl.pem\n" + + "[user_cert]\n" + "basicConstraints = CA:false\n" + "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n" + "subjectKeyIdentifier = hash\n" + "authorityKeyIdentifier = keyid,issuer:always\n" + "subjectAltName = DNS.1:" ++ Hostname ++ "\n" + "issuerAltName = issuer:copy\n" + %"crlDistributionPoints=@crl_section\n" + + %%"[crl_section]\n" + %% intentionally invalid + %%"URI.1=http://localhost/",C#config.commonName,"/crl.pem\n" + %%"URI.2=http://localhost:",integer_to_list(C#config.crl_port),"/",C#config.commonName,"/crl.pem\n" + %%"\n" + "[user_cert_digital_signature_only]\n" - "basicConstraints = CA:false\n" - "keyUsage = digitalSignature\n" + "basicConstraints = CA:false\n" + "keyUsage = digitalSignature\n" "subjectKeyIdentifier = hash\n" "authorityKeyIdentifier = keyid,issuer:always\n" - "subjectAltName = email:copy\n" - "issuerAltName = issuer:copy\n" + "subjectAltName = DNS.1:" ++ Hostname ++ "\n" + "issuerAltName = issuer:copy\n" "\n" "[ca_cert]\n" - "basicConstraints = critical,CA:true\n" - "keyUsage = cRLSign, keyCertSign\n" + "basicConstraints = critical,CA:true\n" + "keyUsage = cRLSign, keyCertSign\n" "subjectKeyIdentifier = hash\n" "authorityKeyIdentifier = keyid:always,issuer:always\n" - "subjectAltName = email:copy\n" - "issuerAltName = issuer:copy\n"]. + "subjectAltName = email:copy\n" + "issuerAltName = issuer:copy\n" + %"crlDistributionPoints=@crl_section\n" + ]. \ No newline at end of file diff --git a/config/test/edge_1_bondy.conf.template b/config/test/edge_1_bondy.conf.template index b0edd305..ed4cf50a 100644 --- a/config/test/edge_1_bondy.conf.template +++ b/config/test/edge_1_bondy.conf.template @@ -37,17 +37,17 @@ api_gateway.https.nodelay = on api_gateway.https.port = 19083 # broker_bridge.config_file = ${BONDY_ETC_DIR}/broker_bridge_config.json -broker_bridge.kafka.clients.default.allow_topic_auto_creation = on -broker_bridge.kafka.clients.default.auto_start_producers = on -broker_bridge.kafka.clients.default.endpoints = [{"127.0.0.1", 9092}] -broker_bridge.kafka.clients.default.max_metadata_sock_retry = 5 -broker_bridge.kafka.clients.default.producer.partition_restart_delay_seconds = 2s -broker_bridge.kafka.clients.default.producer.required_acks = 1 -broker_bridge.kafka.clients.default.producer.topic_restart_delay_seconds = 10s -broker_bridge.kafka.clients.default.reconnect_cool_down_seconds = 10s -broker_bridge.kafka.clients.default.restart_delay_seconds = 10s -broker_bridge.kafka.enabled = off -broker_bridge.kafka.topics.wamp_events = com.leapsight.wamp.events +# broker_bridge.kafka.clients.default.allow_topic_auto_creation = on +# broker_bridge.kafka.clients.default.auto_start_producers = on +# broker_bridge.kafka.clients.default.endpoints = [{"127.0.0.1", 9092}] +# broker_bridge.kafka.clients.default.max_metadata_sock_retry = 5 +# broker_bridge.kafka.clients.default.producer.partition_restart_delay_seconds = 2s +# broker_bridge.kafka.clients.default.producer.required_acks = 1 +# broker_bridge.kafka.clients.default.producer.topic_restart_delay_seconds = 10s +# broker_bridge.kafka.clients.default.reconnect_cool_down_seconds = 10s +# broker_bridge.kafka.clients.default.restart_delay_seconds = 10s +# broker_bridge.kafka.enabled = off +# broker_bridge.kafka.topics.wamp_events = com.leapsight.wamp.events cluster.parallelism = 1 cluster.peer_port = 19086 @@ -96,10 +96,10 @@ wamp.tcp.port = 19082 wamp.tls.enabled = off # wamp.tls.acceptors_pool_size = 200 # wamp.tls.backlog = 1024 -# wamp.tls.cacertfile = ${BONDY_ETC_DIR}/cacert.pem -# wamp.tls.certfile = ${BONDY_ETC_DIR}/cert.pem +# wamp.tls.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem +# wamp.tls.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem # wamp.tls.keepalive = on -# wamp.tls.keyfile = ${BONDY_ETC_DIR}/key.pem +# wamp.tls.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem # wamp.tls.max_connections = 100000 # wamp.tls.nodelay = on # wamp.tls.port = 19085 @@ -108,18 +108,21 @@ wamp.tls.enabled = off wamp.websocket.compression_enabled = on -# bridge.edge = on -# bridge.edge.transport = tls -# bridge.edge.timeout = 5s -# bridge.edge.reconnect = on -# bridge.edge.reconnect.max_retries = 10 - - -# bridge.edge.endpoint = 127.0.0.1:18093 -# bridge.edge.realm.1.uri = com.leapsight.test -# bridge.edge.realm.1.authid = device1 -# bridge.edge.realm.1.cryptosign.pubkey = 1766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd -# bridge.edge.realm.1.cryptosign.privkey_env_var = EDGE1_DEVICE1_PRIVKEY +bridge.edge = on +bridge.edge.endpoint = 127.0.0.1:18093 +bridge.edge.transport = tls +bridge.edge.timeout = 5s +bridge.edge.reconnect = on +bridge.edge.reconnect.max_retries = 10 +bridge.edge.tls.cacertfile = ${BONDY_ETC_DIR}/ssl/client/cacert.pem +bridge.edge.tls.certfile = ${BONDY_ETC_DIR}/ssl/client/keycert.pem +bridge.edge.tls.keyfile = ${BONDY_ETC_DIR}/ssl/client/key.pem +bridge.edge.tls.versions = 1.2,1.3 +bridge.edge.tls.verify = verify_none +bridge.edge.realm.1.uri = com.leapsight.test +bridge.edge.realm.1.authid = device1 +bridge.edge.realm.1.cryptosign.pubkey = 1766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd +bridge.edge.realm.1.cryptosign.privkey_env_var = EDGE1_DEVICE1_PRIVKEY # bridge.edge.realm.1.procedure.1 = com.example.add exact out # bridge.edge.realm.1.procedure.2 = com.example.mult exact out # bridge.edge.realm.1.topic.1 = com.example. prefix out diff --git a/config/test/node_1_bondy.conf.template b/config/test/node_1_bondy.conf.template index 8f671a76..ca1886e2 100644 --- a/config/test/node_1_bondy.conf.template +++ b/config/test/node_1_bondy.conf.template @@ -23,7 +23,7 @@ admin_api.https.keepalive = off admin_api.https.max_connections = 250000 admin_api.https.backlog = 18084 admin_api.https.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem -admin_api.https.certfile = ${BONDY_ETC_DIR}/ssl/server/cert.pem +admin_api.https.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem admin_api.https.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem api_gateway.config_file = ${BONDY_ETC_DIR}/api_gateway_config.json @@ -42,7 +42,7 @@ api_gateway.https.keepalive = off api_gateway.https.max_connections = 500000 api_gateway.https.nodelay = on api_gateway.https.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem -api_gateway.https.certfile = ${BONDY_ETC_DIR}/ssl/server/cert.pem +api_gateway.https.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem api_gateway.https.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem broker_bridge.config_file = ${BONDY_ETC_DIR}/broker_bridge_config.json @@ -71,13 +71,15 @@ cluster.peer_discovery.timeout = 5s # cluster.peer_discovery.config.nodes.1 = bondy1@127.0.0.1:18086 cluster.tls.enabled = on cluster.tls.server.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem -cluster.tls.server.certfile = ${BONDY_ETC_DIR}/ssl/server/cert.pem +cluster.tls.server.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem cluster.tls.server.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem cluster.tls.server.versions = 1.2,1.3 -# cluster.tls.client.cacertfile = ${BONDY_ETC_DIR}/ssl/client/cacert.pem -# cluster.tls.client.certfile = ${BONDY_ETC_DIR}/ssl/client/cert.pem -# cluster.tls.client.keyfile = ${BONDY_ETC_DIR}/ssl/client/key.pem -# cluster.tls.client.versions = 1.2,1.3 +cluster.tls.server.verify = verify_none +cluster.tls.client.cacertfile = ${BONDY_ETC_DIR}/ssl/client/cacert.pem +cluster.tls.client.certfile = ${BONDY_ETC_DIR}/ssl/client/keycert.pem +cluster.tls.client.keyfile = ${BONDY_ETC_DIR}/ssl/client/key.pem +cluster.tls.client.versions = 1.2,1.3 +cluster.tls.client.verify = verify_none erlang.async_threads = 64 erlang.max_ports = 65536 @@ -118,7 +120,7 @@ wamp.tls.port = 18085 wamp.tls.acceptors_pool_size = 200 wamp.tls.backlog = 1024 wamp.tls.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem -wamp.tls.certfile = ${BONDY_ETC_DIR}/ssl/server/cert.pem +wamp.tls.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem wamp.tls.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem wamp.tls.keepalive = on wamp.tls.max_connections = 100000 @@ -134,6 +136,6 @@ bridge.listener.tcp.port = 18092 bridge.listener.tls = on bridge.listener.tls.port = 18093 bridge.listener.tls.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem -bridge.listener.tls.certfile = ${BONDY_ETC_DIR}/ssl/server/cert.pem +bridge.listener.tls.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem bridge.listener.tls.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem bridge.listener.tls.idle_timeout = 30s \ No newline at end of file diff --git a/config/test/node_2_bondy.conf.template b/config/test/node_2_bondy.conf.template index dccc7e0a..e677ba31 100644 --- a/config/test/node_2_bondy.conf.template +++ b/config/test/node_2_bondy.conf.template @@ -59,13 +59,15 @@ cluster.peer_discovery.type = bondy_peer_discovery_static_agent cluster.peer_discovery.config.nodes.1 = bondy1@127.0.0.1:18086 cluster.tls.enabled = on cluster.tls.server.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem -cluster.tls.server.certfile = ${BONDY_ETC_DIR}/ssl/server/cert.pem +cluster.tls.server.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem cluster.tls.server.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem cluster.tls.server.versions = 1.2,1.3 +cluster.tls.server.verify = verify_none cluster.tls.client.cacertfile = ${BONDY_ETC_DIR}/ssl/client/cacert.pem -cluster.tls.client.certfile = ${BONDY_ETC_DIR}/ssl/client/cert.pem +cluster.tls.client.certfile = ${BONDY_ETC_DIR}/ssl/client/keycert.pem cluster.tls.client.keyfile = ${BONDY_ETC_DIR}/ssl/client/key.pem cluster.tls.client.versions = 1.2,1.3 +cluster.tls.client.verify = verify_none erlang.async_threads = 64 erlang.max_ports = 65536 diff --git a/config/test/node_3_bondy.conf.template b/config/test/node_3_bondy.conf.template index 456fe97c..a93df17d 100644 --- a/config/test/node_3_bondy.conf.template +++ b/config/test/node_3_bondy.conf.template @@ -59,13 +59,15 @@ cluster.peer_discovery.type = bondy_peer_discovery_static_agent cluster.peer_discovery.config.nodes.1 = bondy1@127.0.0.1:18086 cluster.tls.enabled = on cluster.tls.server.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem -cluster.tls.server.certfile = ${BONDY_ETC_DIR}/ssl/server/cert.pem +cluster.tls.server.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem cluster.tls.server.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem cluster.tls.server.versions = 1.2,1.3 +cluster.tls.server.verify = verify_none cluster.tls.client.cacertfile = ${BONDY_ETC_DIR}/ssl/client/cacert.pem -cluster.tls.client.certfile = ${BONDY_ETC_DIR}/ssl/client/cert.pem +cluster.tls.client.certfile = ${BONDY_ETC_DIR}/ssl/client/keycert.pem cluster.tls.client.keyfile = ${BONDY_ETC_DIR}/ssl/client/key.pem cluster.tls.client.versions = 1.2,1.3 +cluster.tls.client.verify = verify_none erlang.async_threads = 64 erlang.max_ports = 65536 @@ -101,8 +103,9 @@ wamp.tcp.nodelay = on wamp.tcp.port = 18282 wamp.tls.acceptors_pool_size = 200 wamp.tls.backlog = 1024 -wamp.tls.cacertfile = ${BONDY_ETC_DIR}/cacert.pem -wamp.tls.certfile = ${BONDY_ETC_DIR}/cert.pem +wamp.tls.cacertfile = ${BONDY_ETC_DIR}/ssl/server/cacert.pem +wamp.tls.certfile = ${BONDY_ETC_DIR}/ssl/server/keycert.pem +wamp.tls.keyfile = ${BONDY_ETC_DIR}/ssl/server/key.pem wamp.tls.enabled = off wamp.tls.keepalive = on wamp.tls.keyfile = ${BONDY_ETC_DIR}/key.pem diff --git a/deployment/Dockerfile b/deployment/Dockerfile index 81edf1e7..82701529 100644 --- a/deployment/Dockerfile +++ b/deployment/Dockerfile @@ -4,7 +4,7 @@ # Build stage 1 # =========================================================================== -FROM erlang:24 AS builder +FROM erlang:26 AS builder # Install build dependencies RUN --mount=type=cache,id=apt,sharing=locked,target=/var/cache/apt apt-get update && \ @@ -69,7 +69,7 @@ ENV HOME "/bondy" RUN apt-get update \ && apt-get -y install \ sudo bash procps iproute2 net-tools curl jq nano \ - openssl libsodium-dev libsnappy-dev \ + openssl libsodium-dev libsnappy-dev\ && rm -rf /var/lib/apt/lists/* \ && groupadd -g 1000 -r bondy \ && useradd -u 1000 -r -g bondy -d /bondy -s /bin/bash -c "bondy" bondy \ diff --git a/deployment/alpine.Dockerfile b/deployment/alpine.Dockerfile index 48da9122..1d9148b1 100644 --- a/deployment/alpine.Dockerfile +++ b/deployment/alpine.Dockerfile @@ -4,7 +4,7 @@ # Build stage 1 # =========================================================================== -FROM erlang:24-alpine AS builder +FROM erlang:26-alpine AS builder # Install build dependencies RUN --mount=type=cache,id=apk,sharing=locked,target=/var/cache/apk \ @@ -28,7 +28,7 @@ RUN rebar3 as docker tar && \ # Build stage 2 # =========================================================================== -FROM alpine:3.16 as runner +FROM alpine:3.18.3 as runner # We define defaults # We assume you have DNS. Erlang will take the FQDN and generate diff --git a/rebar.config b/rebar.config index 9aca3d97..b8e7f440 100644 --- a/rebar.config +++ b/rebar.config @@ -1,4 +1,4 @@ -{minimum_otp_vsn, "R24"}. +{minimum_otp_vsn, "R26.0.2"}. {erl_opts, [ % warn_export_all, @@ -26,19 +26,19 @@ %% Crypto %% ------------------------------------------------------------------------- {jose, - {git, "https://github.com/potatosalad/erlang-jose.git", {tag, "1.11.2"}} + {git, "https://github.com/potatosalad/erlang-jose.git", {tag, "1.11.6"}} }, {pbkdf2, {git, "https://github.com/leapsight-oss/erlang-pbkdf2.git", {branch, "master"}} }, - {stringprep, "1.0.27"}, + {stringprep, "1.0.29"}, {enacl, "1.2.1"}, %% ------------------------------------------------------------------------- %% Web Server|client %% ------------------------------------------------------------------------- %% Used to implement WebSockets, API Gateway, HTTP Admin API %% and /metrics endpoint - {cowboy, "2.9.0"}, + {cowboy, "2.10.0"}, %% Used by API Gateway to implement forward action to %% downstream HTTP services hackney, @@ -46,7 +46,21 @@ %% ------------------------------------------------------------------------- %% Utils %% ------------------------------------------------------------------------- - {uuid, "2.0.4", {pkg, uuid_erl}}, + {uuid, "2.0.6", {pkg, uuid_erl}}, + {app_config, + {git, "https://github.com/leapsight/app_config.git", {tag, "1.1.1"}} + }, + {leap, { + git, + "https://gitlab.com/leapsight/leap.git", + {branch, "master"} + }}, + %% Leapsight utility library + {utils, { + git, + "https://github.com/leapsight/utils.git", + {tag, "1.3.7"} + }}, lrw, %% ------------------------------------------------------------------------- %% Concurrency|Load|Traffic Management @@ -63,11 +77,11 @@ %% Instrumentation/Debugging %% ------------------------------------------------------------------------- bear, - {observer_cli, "1.7.2"}, + {observer_cli, "1.7.4"}, %% Exposes metrics to Promethues - {prometheus, "4.8.1"}, + {prometheus, "4.10.0"}, {prometheus_cowboy, "0.1.8"}, - {telemetry, "1.0.0"}, + {telemetry, "1.2.1"}, {riak_sysmon, {git, "https://github.com/Leapsight/riak_sysmon.git", {tag, "2.2.0"}} }, @@ -88,7 +102,7 @@ {partisan, { git, "http://github.com/lasp-lang/partisan.git", - {tag, "v5.0.0-rc.4"} + {tag, "v5.0.0-rc.7"} }}, %% The embedded database using Partisan, Plumtree and dvvsets. %% Stores data in ets and leveldb, also performs active anti-entropy @@ -96,7 +110,7 @@ {plum_db, { git, "https://github.com/Leapsight/plum_db.git", - {tag, "1.0.7"} + {tag, "1.0.11"} }}, %% A partial implementation of an Adaptive Radix Trie. %% We use it to store the procedure and topic tries. @@ -111,18 +125,6 @@ git, "https://gitlab.com/leapsight/mops.git", {branch, "master"} - }}, - %% Leapsight utility library implementing relational algebra - {leap, { - git, - "https://gitlab.com/leapsight/leap.git", - {branch, "master"} - }}, - %% Leapsight utility library - {utils, { - git, - "https://gitlab.com/leapsight/utils.git", - {tag, "1.3.5"} }} ]}. @@ -134,7 +136,7 @@ {relx, [ - {release, {bondy, "1.0.0-beta.78"},[ + {release, {bondy, "1.0.0-rc.1"},[ %% Erlang/OTP crypto, inets, @@ -338,8 +340,8 @@ "{{platform_etc_dir}}/ssl/server/cacert.pem" }, {copy, - "config/_ssl/server/cert.pem", - "{{platform_etc_dir}}/ssl/server/cert.pem" + "config/_ssl/server/keycert.pem", + "{{platform_etc_dir}}/ssl/server/keycert.pem" }, {copy, "config/_ssl/server/key.pem", @@ -350,8 +352,8 @@ "{{platform_etc_dir}}/ssl/client/cacert.pem" }, {copy, - "config/_ssl/client/cert.pem", - "{{platform_etc_dir}}/ssl/client/cert.pem" + "config/_ssl/client/keycert.pem", + "{{platform_etc_dir}}/ssl/client/keycert.pem" }, {copy, "config/_ssl/client/key.pem", @@ -392,8 +394,8 @@ "{{platform_etc_dir}}/ssl/server/cacert.pem" }, {copy, - "config/_ssl/server/cert.pem", - "{{platform_etc_dir}}/ssl/server/cert.pem" + "config/_ssl/server/keycert.pem", + "{{platform_etc_dir}}/ssl/server/keycert.pem" }, {copy, "config/_ssl/server/key.pem", @@ -404,8 +406,8 @@ "{{platform_etc_dir}}/ssl/client/cacert.pem" }, {copy, - "config/_ssl/client/cert.pem", - "{{platform_etc_dir}}/ssl/client/cert.pem" + "config/_ssl/client/keycert.pem", + "{{platform_etc_dir}}/ssl/client/keycert.pem" }, {copy, "config/_ssl/client/key.pem", @@ -449,8 +451,8 @@ "{{platform_etc_dir}}/ssl/server/cacert.pem" }, {copy, - "config/_ssl/server/cert.pem", - "{{platform_etc_dir}}/ssl/server/cert.pem" + "config/_ssl/server/keycert.pem", + "{{platform_etc_dir}}/ssl/server/keycert.pem" }, {copy, "config/_ssl/server/key.pem", @@ -461,8 +463,8 @@ "{{platform_etc_dir}}/ssl/client/cacert.pem" }, {copy, - "config/_ssl/client/cert.pem", - "{{platform_etc_dir}}/ssl/client/cert.pem" + "config/_ssl/client/keycert.pem", + "{{platform_etc_dir}}/ssl/client/keycert.pem" }, {copy, "config/_ssl/client/key.pem", @@ -506,8 +508,8 @@ "{{platform_etc_dir}}/ssl/server/cacert.pem" }, {copy, - "config/_ssl/server/cert.pem", - "{{platform_etc_dir}}/ssl/server/cert.pem" + "config/_ssl/server/keycert.pem", + "{{platform_etc_dir}}/ssl/server/keycert.pem" }, {copy, "config/_ssl/server/key.pem", @@ -518,8 +520,8 @@ "{{platform_etc_dir}}/ssl/client/cacert.pem" }, {copy, - "config/_ssl/client/cert.pem", - "{{platform_etc_dir}}/ssl/client/cert.pem" + "config/_ssl/client/keycert.pem", + "{{platform_etc_dir}}/ssl/client/keycert.pem" }, {copy, "config/_ssl/client/key.pem", @@ -565,6 +567,30 @@ {template, "config/test/sys.config", "releases/{{release_version}}/sys.config" + }, + {copy, + "config/_ssl/server/cacerts.pem", + "{{platform_etc_dir}}/ssl/server/cacert.pem" + }, + {copy, + "config/_ssl/server/keycert.pem", + "{{platform_etc_dir}}/ssl/server/keycert.pem" + }, + {copy, + "config/_ssl/server/key.pem", + "{{platform_etc_dir}}/ssl/server/key.pem" + }, + {copy, + "config/_ssl/client/cacerts.pem", + "{{platform_etc_dir}}/ssl/client/cacert.pem" + }, + {copy, + "config/_ssl/client/keycert.pem", + "{{platform_etc_dir}}/ssl/client/keycert.pem" + }, + {copy, + "config/_ssl/client/key.pem", + "{{platform_etc_dir}}/ssl/client/key.pem" } ]} ]} @@ -843,11 +869,12 @@ "releases/{{release_version}}/schema/", "etc/generated/user_defined.config" }, - { - "{{deps_dir}}/eleveldb/priv", - "releases/{{release_version}}/schema/", - "etc/generated/user_defined.config" - }, + %% Incorporated in plum_db + %% { + %% "{{deps_dir}}/eleveldb/priv", + %% "releases/{{release_version}}/schema/", + %% "etc/generated/user_defined.config" + %% }, { "{{deps_dir}}/plum_db/priv", "releases/{{release_version}}/schema/", diff --git a/rebar.lock b/rebar.lock index a8e7428f..f16da1db 100644 --- a/rebar.lock +++ b/rebar.lock @@ -2,9 +2,9 @@ [{<<"accept">>,{pkg,<<"accept">>,<<"0.3.5">>},2}, {<<"acceptor_pool">>,{pkg,<<"acceptor_pool">>,<<"1.0.0">>},1}, {<<"app_config">>, - {git,"https://gitlab.com/leapsight/app_config.git", - {ref,"e6a4dc99c0c9f17a6d4d865e40aefc409986f849"}}, - 1}, + {git,"https://github.com/leapsight/app_config.git", + {ref,"01fa09bf6b7cac41b13a15552b6a9cc132acdaf4"}}, + 0}, {<<"art">>, {git,"https://gitlab.com/leapsight/art.git", {ref,"35f8db5c877def1b4916791dce9a7858dc94dd33"}}, @@ -19,11 +19,11 @@ {<<"bert">>,{pkg,<<"bert">>,<<"0.1.0">>},0}, {<<"brod">>, {git,"https://github.com/klarna/brod.git", - {ref,"5d9f189623070f4927cb88af563552695b305fce"}}, + {ref,"6966f0244b87904363cb8053ac0364ff281411d9"}}, 0}, - {<<"certifi">>,{pkg,<<"certifi">>,<<"2.9.0">>},1}, - {<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.9.0">>},0}, - {<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.11.0">>},1}, + {<<"certifi">>,{pkg,<<"certifi">>,<<"2.12.0">>},1}, + {<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.10.0">>},0}, + {<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.12.1">>},1}, {<<"crc32cer">>,{pkg,<<"crc32cer">>,<<"0.1.8">>},2}, {<<"eini">>,{pkg,<<"eini">>,<<"1.2.9">>},1}, {<<"eleveldb">>, @@ -35,9 +35,9 @@ {ref,"b62e070111e635e739628254eab8db2835631d28"}}, 0}, {<<"enacl">>,{pkg,<<"enacl">>,<<"1.2.1">>},0}, - {<<"erlcloud">>,{pkg,<<"erlcloud">>,<<"3.6.1">>},0}, + {<<"erlcloud">>,{pkg,<<"erlcloud">>,<<"3.7.3">>},0}, {<<"gproc">>,{pkg,<<"gproc">>,<<"0.9.0">>},1}, - {<<"hackney">>,{pkg,<<"hackney">>,<<"1.18.1">>},0}, + {<<"hackney">>,{pkg,<<"hackney">>,<<"1.19.1">>},0}, {<<"hash">>, {git,"https://github.com/leapsight/hash", {ref,"dfbcc9ee089626f84068a1dcee3b1753a716871e"}}, @@ -50,7 +50,7 @@ 0}, {<<"jsone">>,{pkg,<<"jsone">>,<<"1.6.1">>},1}, {<<"jsx">>,{pkg,<<"jsx">>,<<"2.11.0">>},1}, - {<<"kafka_protocol">>,{pkg,<<"kafka_protocol">>,<<"4.0.1">>},1}, + {<<"kafka_protocol">>,{pkg,<<"kafka_protocol">>,<<"4.1.3">>},1}, {<<"key_value">>, {git,"https://gitlab.com/leapsight/key_value.git", {ref,"414fb19cd067b368666ceb5a2a63f1f24109562b"}}, @@ -66,6 +66,10 @@ {<<"lhttpc">>,{pkg,<<"lhttpc">>,<<"1.6.2">>},1}, {<<"logger_colorful">>,{pkg,<<"logger_colorful">>,<<"0.1.0">>},0}, {<<"lrw">>,{pkg,<<"lrw">>,<<"2.0.1">>},0}, + {<<"maps_utils">>, + {git,"https://github.com/Leapsight/maps_utils.git", + {ref,"afa2da62e0e691ce33d1008cc424c994fff339bf"}}, + 1}, {<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},1}, {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.2.0">>},1}, {<<"mops">>, @@ -73,16 +77,16 @@ {ref,"3955142d3720dc5b7a481e28124a2c5421dcd078"}}, 0}, {<<"msgpack">>,{pkg,<<"msgpack">>,<<"0.7.0">>},0}, - {<<"observer_cli">>,{pkg,<<"observer_cli">>,<<"1.7.2">>},0}, + {<<"observer_cli">>,{pkg,<<"observer_cli">>,<<"1.7.4">>},0}, {<<"opentelemetry_api">>,{pkg,<<"opentelemetry_api">>,<<"1.2.1">>},1}, {<<"opentelemetry_semantic_conventions">>, {pkg,<<"opentelemetry_semantic_conventions">>,<<"0.2.0">>}, 2}, - {<<"p1_utils">>,{pkg,<<"p1_utils">>,<<"1.0.23">>},1}, + {<<"p1_utils">>,{pkg,<<"p1_utils">>,<<"1.0.25">>},1}, {<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.4.1">>},0}, {<<"partisan">>, {git,"http://github.com/lasp-lang/partisan.git", - {ref,"bcccdfc0a5b126344dda0ca9b7871e8225f7ad23"}}, + {ref,"095d732cf9dd50e908c9c907a3481b2ac9b46a94"}}, 0}, {<<"pbkdf2">>, {git,"https://github.com/leapsight-oss/erlang-pbkdf2.git", @@ -90,15 +94,15 @@ 0}, {<<"plum_db">>, {git,"https://github.com/Leapsight/plum_db.git", - {ref,"0353f25f074a1f6f25ead0143a59a4ba7cd36b2b"}}, + {ref,"6dc8819140d3502c2c24841d03f1362b584e397c"}}, 0}, - {<<"prometheus">>,{pkg,<<"prometheus">>,<<"4.8.1">>},0}, + {<<"prometheus">>,{pkg,<<"prometheus">>,<<"4.10.0">>},0}, {<<"prometheus_cowboy">>,{pkg,<<"prometheus_cowboy">>,<<"0.1.8">>},0}, {<<"prometheus_httpd">>,{pkg,<<"prometheus_httpd">>,<<"2.1.11">>},1}, {<<"quantile_estimator">>,{pkg,<<"quantile_estimator">>,<<"0.2.1">>},1}, - {<<"quickrand">>,{pkg,<<"quickrand">>,<<"2.0.4">>},1}, + {<<"quickrand">>,{pkg,<<"quickrand">>,<<"2.0.6">>},1}, {<<"ranch">>,{pkg,<<"ranch">>,<<"1.8.0">>},1}, - {<<"recon">>,{pkg,<<"recon">>,<<"2.5.2">>},1}, + {<<"recon">>,{pkg,<<"recon">>,<<"2.5.4">>},1}, {<<"riak_sysmon">>, {git,"https://github.com/Leapsight/riak_sysmon.git", {ref,"726df1f4c31108bb9366fb767b480f286e51f7fc"}}, @@ -106,11 +110,10 @@ {<<"setup">>,{pkg,<<"setup">>,<<"2.1.0">>},1}, {<<"sext">>,{pkg,<<"sext">>,<<"1.8.0">>},1}, {<<"sidejob">>,{pkg,<<"sidejob">>,<<"2.1.0">>},0}, - {<<"snappyer">>,{pkg,<<"snappyer">>,<<"1.2.8">>},1}, - {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.6">>},1}, - {<<"stringprep">>,{pkg,<<"stringprep">>,<<"1.0.27">>},0}, - {<<"supervisor3">>,{pkg,<<"supervisor3">>,<<"1.1.11">>},1}, - {<<"telemetry">>,{pkg,<<"telemetry">>,<<"1.0.0">>},0}, + {<<"snappyer">>,{pkg,<<"snappyer">>,<<"1.2.9">>},1}, + {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.7">>},1}, + {<<"stringprep">>,{pkg,<<"stringprep">>,<<"1.0.29">>},0}, + {<<"telemetry">>,{pkg,<<"telemetry">>,<<"1.2.1">>},0}, {<<"tuplespace">>, {git,"https://gitlab.com/leapsight/tuplespace.git", {ref,"d5e540dc2e1d3a4b75dbf3841de99d4547e118ff"}}, @@ -118,10 +121,10 @@ {<<"types">>,{pkg,<<"types">>,<<"0.1.8">>},1}, {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},1}, {<<"utils">>, - {git,"https://gitlab.com/leapsight/utils.git", - {ref,"881e59760358bf22979d6ef1fcd96fc476c8b3ca"}}, + {git,"https://github.com/leapsight/utils.git", + {ref,"641bd36d997970d355a700009bbaa6b84f0bd987"}}, 0}, - {<<"uuid">>,{pkg,<<"uuid_erl">>,<<"2.0.4">>},0}, + {<<"uuid">>,{pkg,<<"uuid_erl">>,<<"2.0.6">>},0}, {<<"wamp">>, {git,"https://github.com/Leapsight/wamp.git", {ref,"73c97fd06c5905d492d252d01bbd73cebe4ae337"}}, @@ -134,49 +137,48 @@ {<<"base16">>, <<"283644E2B21BD5915ACB7178BED7851FB07C6E5749B8FAD68A53C501092176D9">>}, {<<"bear">>, <<"430419C1126B477686CDE843E88BA0F2C7DC5CDF0881C677500074F704339A99">>}, {<<"bert">>, <<"A87D6693515070A9B287C1043CB7E5B2406BE0357685022764BFBD2609703555">>}, - {<<"certifi">>, <<"6F2A475689DD47F19FB74334859D460A2DC4E3252A3324BD2111B8F0429E7E21">>}, - {<<"cowboy">>, <<"865DD8B6607E14CF03282E10E934023A1BD8BE6F6BACF921A7E2A96D800CD452">>}, - {<<"cowlib">>, <<"0B9FF9C346629256C42EBE1EEB769A83C6CB771A6EE5960BD110AB0B9B872063">>}, + {<<"certifi">>, <<"2D1CCA2EC95F59643862AF91F001478C9863C2AC9CB6E2F89780BFD8DE987329">>}, + {<<"cowboy">>, <<"FF9FFEFF91DAE4AE270DD975642997AFE2A1179D94B1887863E43F681A203E26">>}, + {<<"cowlib">>, <<"A9FA9A625F1D2025FE6B462CB865881329B5CAFF8F1854D1CBC9F9533F00E1E1">>}, {<<"crc32cer">>, <<"C6C2275C5FB60A95F4935D414F30B50EE9CFED494081C9B36EBB02EDFC2F48DB">>}, {<<"eini">>, <<"FCC3CBD49BBDD9A1D9735C7365DAFFCD84481CCE81E6CB80537883AA44AC4895">>}, {<<"enacl">>, <<"7776480B9B3D42A51D66DBBCBF17FA3D79285B3D2ADCB4D5B5BD0B70F0EF1949">>}, - {<<"erlcloud">>, <<"51B9045F96FE67A8823D384A163269403A30CD1CAD8C47EEEFF7026F17B16912">>}, + {<<"erlcloud">>, <<"31F8A89C391B003350C832BDA550EC93E813889D2A3533915435A56B0ACCA844">>}, {<<"gproc">>, <<"853CCB7805E9ADA25D227A157BA966F7B34508F386A3E7E21992B1B484230699">>}, - {<<"hackney">>, <<"F48BF88F521F2A229FC7BAE88CF4F85ADC9CD9BCF23B5DC8EB6A1788C662C4F6">>}, + {<<"hackney">>, <<"59DE4716E985DD2B5CBD4954FA1AE187E2B610A9C4520FFCB0B1653C3D6E5559">>}, {<<"idna">>, <<"8A63070E9F7D0C62EB9D9FCB360A7DE382448200FBBD1B106CC96D3D8099DF8D">>}, {<<"jobs">>, <<"329C024A889249EA8262D0EF70BC7A498B7C96DA95977EBD026B13B069FB0E13">>}, {<<"jsone">>, <<"7EA1098FE004C4127320FE0E3CF6A951B01F82039FEAA56C322DC7E34DD59762">>}, {<<"jsx">>, <<"08154624050333919B4AC1B789667D5F4DB166DC50E190C4D778D1587F102EE0">>}, - {<<"kafka_protocol">>, <<"FC696880C73483C8B032C4BB60F2873046035C7824E1EDCB924CFCE643CF23DD">>}, + {<<"kafka_protocol">>, <<"362D85A898D4148A43DBABB10A30BB2D6FF32BA0097EB06981D11B34E2E0A9CD">>}, {<<"lhttpc">>, <<"044F16F0018C7AA7E945E9E9406C7F6035E0B8BC08BF77B00C78CE260E1071E3">>}, {<<"logger_colorful">>, <<"548A7F21C7F2F6713CD2E1A7B1323B2AD712E11AE5913D2FB05BE6F34B799081">>}, {<<"lrw">>, <<"E5BCA6EFD184C03451FF416D3B8FA250BFE867E02B705AF530A0E61CE7B5B32A">>}, {<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>}, {<<"mimerl">>, <<"67E2D3F571088D5CFD3E550C383094B47159F3EEE8FFA08E64106CDF5E981BE3">>}, {<<"msgpack">>, <<"128AE0A2227C7E7A2847C0F0F73551C268464F8C1EE96BFFB920BC0A5712B295">>}, - {<<"observer_cli">>, <<"1679C65D70049389195FDD9E5FE00F995946935D1DCC6357E514CA1AF136E238">>}, + {<<"observer_cli">>, <<"3C1BFB6D91BF68F6A3D15F46AE20DA0F7740D363EE5BC041191CE8722A6C4FAE">>}, {<<"opentelemetry_api">>, <<"7B69ED4F40025C005DE0B74FCE8C0549625D59CB4DF12D15C32FE6DC5076FF42">>}, {<<"opentelemetry_semantic_conventions">>, <<"B67FE459C2938FCAB341CB0951C44860C62347C005ACE1B50F8402576F241435">>}, - {<<"p1_utils">>, <<"7F94466ADA69BD982EA7BB80FBCA18E7053E7D0B82C9D9E37621FA508587069B">>}, + {<<"p1_utils">>, <<"2D39B5015A567BBD2CC7033EEB93A7C60D8C84EFE1EF69A3473FAA07FA268187">>}, {<<"parse_trans">>, <<"6E6AA8167CB44CC8F39441D05193BE6E6F4E7C2946CB2759F015F8C56B76E5FF">>}, - {<<"prometheus">>, <<"FA76B152555273739C14B06F09F485CF6D5D301FE4E9D31B7FF803D26025D7A0">>}, + {<<"prometheus">>, <<"792ADBF0130FF61B5FA8826F013772AF24B6E57B984445C8D602C8A0355704A1">>}, {<<"prometheus_cowboy">>, <<"CFCE0BC7B668C5096639084FCD873826E6220EA714BF60A716F5BD080EF2A99C">>}, {<<"prometheus_httpd">>, <<"F616ED9B85B536B195D94104063025A91F904A4CFC20255363F49A197D96C896">>}, {<<"quantile_estimator">>, <<"EF50A361F11B5F26B5F16D0696E46A9E4661756492C981F7B2229EF42FF1CD15">>}, - {<<"quickrand">>, <<"168CA3A8466A26912B8C3A1D6AA58975E1BB49E5C7AFB4998B80F6B90F910490">>}, + {<<"quickrand">>, <<"37E49398D614534F2861633F8E1155828676DF31ED90872616E4A526E6B9CF38">>}, {<<"ranch">>, <<"8C7A100A139FD57F17327B6413E4167AC559FBC04CA7448E9BE9057311597A1D">>}, - {<<"recon">>, <<"CBA53FA8DB83AD968C9A652E09C3ED7DDCC4DA434F27C3EAA9CA47FFB2B1FF03">>}, + {<<"recon">>, <<"05DD52A119EE4059FA9DAA1AB7CE81BC7A8161A2F12E9D42E9D551FFD2BA901C">>}, {<<"setup">>, <<"05F69185A5EB71474C9BC6BA892565651EC7507791F85632B7B914DBFE130510">>}, {<<"sext">>, <<"90A95B889F5C781B70BBCF44278B763148E313C376B60D87CE664CB1C1DD29B5">>}, {<<"sidejob">>, <<"5D6A7C9C620778CB1908E46B552D767DF2ED4D77070BB7B5B8773D4FF18D1D37">>}, - {<<"snappyer">>, <<"201CE9067A33C71A6A5087C0C3A49A010B17112D461E6DF696C722DCB6D0934A">>}, - {<<"ssl_verify_fun">>, <<"CF344F5692C82D2CD7554F5EC8FD961548D4FD09E7D22F5B62482E5AEAEBD4B0">>}, - {<<"stringprep">>, <<"02808C7024BC6285CA6A8A67E7ADDFC16F35DDA55551A582C5181D8EA960E890">>}, - {<<"supervisor3">>, <<"D81CDEC31D102FDE407423E1D05B569572850DEEBED86B951D5233C387CBA80B">>}, - {<<"telemetry">>, <<"0F453A102CDF13D506B7C0AB158324C337C41F1CC7548F0BC0E130BBF0AE9452">>}, + {<<"snappyer">>, <<"9CC58470798648CE34C662CA0AA6DAAE31367667714C9A543384430A3586E5D3">>}, + {<<"ssl_verify_fun">>, <<"354C321CF377240C7B8716899E182CE4890C5938111A1296ADD3EC74CF1715DF">>}, + {<<"stringprep">>, <<"02F23E8C3A219A3DFE40A22E908BECE3A2F68AF0FF599EA8A7B714ECB21E62EE">>}, + {<<"telemetry">>, <<"68FDFE8D8F05A8428483A97D7AAB2F268AAFF24B49E0F599FAA091F1D4E7F61C">>}, {<<"types">>, <<"5782B67231E8C174FE2835395E71E669FE0121076779D2A09F1C0D58EE0E2F13">>}, {<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>}, - {<<"uuid">>, <<"77C3E3EE1E1701A2856CE945846D7CEB71931C60633A305D0B0FEAE03B2B3B5C">>}]}, + {<<"uuid">>, <<"8767AAE0D93A0EFD062B5B30BB21188E121721C683200E164445065C08C2100A">>}]}, {pkg_hash_ext,[ {<<"accept">>, <<"11B18C220BCC2EAB63B5470C038EF10EB6783BCB1FCDB11AA4137DEFA5AC1BB8">>}, {<<"acceptor_pool">>, <<"0CBCD83FDC8B9AD2EEE2067EF8B91A14858A5883CB7CD800E6FCD5803E158788">>}, @@ -184,47 +186,46 @@ {<<"base16">>, <<"02AFD0827E61A7B07093873E063575CA3A2B07520567C7F8CEC7C5D42F052D76">>}, {<<"bear">>, <<"157B67901ADF84FF0DA6EAE035CA1292A0AC18AA55148154D8C582B2C68959DB">>}, {<<"bert">>, <<"2A561521EC3529B248658A3E2D3D4BFE6729B0AB8291C701BF15EF413EDA1506">>}, - {<<"certifi">>, <<"266DA46BDB06D6C6D35FDE799BCB28D36D985D424AD7C08B5BB48F5B5CDD4641">>}, - {<<"cowboy">>, <<"2C729F934B4E1AA149AFF882F57C6372C15399A20D54F65C8D67BEF583021BDE">>}, - {<<"cowlib">>, <<"2B3E9DA0B21C4565751A6D4901C20D1B4CC25CBB7FD50D91D2AB6DD287BC86A9">>}, + {<<"certifi">>, <<"EE68D85DF22E554040CDB4BE100F33873AC6051387BAF6A8F6CE82272340FF1C">>}, + {<<"cowboy">>, <<"3AFDCCB7183CC6F143CB14D3CF51FA00E53DB9EC80CDCD525482F5E99BC41D6B">>}, + {<<"cowlib">>, <<"163B73F6367A7341B33C794C4E88E7DBFE6498AC42DCD69EF44C5BC5507C8DB0">>}, {<<"crc32cer">>, <<"251499085482920DEB6C9B7AADABF9FB4C432F96ADD97AB42AEE4501E5B6F591">>}, {<<"eini">>, <<"DA64AE8DB7C2F502E6F20CDF44CD3D9BE364412B87FF49FEBF282540F673DFCB">>}, {<<"enacl">>, <<"67BBBEDDD2564DC899A3DCBC3765CD6AD71629134F1E500A50EC071F0F75E552">>}, - {<<"erlcloud">>, <<"9881E84692CF49435B7773CD91F71D8A6435532CCC30F3D2F6485036D9A93B2F">>}, + {<<"erlcloud">>, <<"112B6E9B1C78FA4CD8E189681F2249E6E8C133D5AAB746ACFECBFA40B18E42DA">>}, {<<"gproc">>, <<"587E8AF698CCD3504CF4BA8D90F893EDE2B0F58CABB8A916E2BF9321DE3CF10B">>}, - {<<"hackney">>, <<"A4ECDAFF44297E9B5894AE499E9A070EA1888C84AFDD1FD9B7B2BC384950128E">>}, + {<<"hackney">>, <<"8AA08234BDEFC269995C63C2282CF3CD0E36FEBE3A6BFAB11B610572FDD1CAD0">>}, {<<"idna">>, <<"92376EB7894412ED19AC475E4A86F7B413C1B9FBB5BD16DCCD57934157944CEA">>}, {<<"jobs">>, <<"09D486146BD32897726BB1F63DD95D1EB7F6F5A4C21C38CA58AB1646E8229724">>}, {<<"jsone">>, <<"A6C1DF6081DF742068D2ED747A4FE8A7740C56421B53E02BC9D4907DD3502922">>}, {<<"jsx">>, <<"EED26A0D04D217F9EECEFFFB89714452556CF90EB38F290A27A4D45B9988F8C0">>}, - {<<"kafka_protocol">>, <<"687BFD9989998EC8FBBC3ED50D1239A6C07A7DC15B52914AD477413B89ECB621">>}, + {<<"kafka_protocol">>, <<"28CF73001270D972524DD0FAD4A59074F4441219F9CF237AD808A2AC1EC97487">>}, {<<"lhttpc">>, <<"76B5FA6149D1E10D4B1FBC4EBD51D371DB19C1AB9F0A9ECF5B526440DF064E97">>}, {<<"logger_colorful">>, <<"D2A11586B2311FF2CC4B2C38835FE8C8768D2087AE9BF7D9EA80C8C33E92689D">>}, {<<"lrw">>, <<"B81D24DE6248EA2509279C992F7B675B110EE166A63F4B2FAB97652446CAD611">>}, {<<"metrics">>, <<"69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16">>}, {<<"mimerl">>, <<"F278585650AA581986264638EBF698F8BB19DF297F66AD91B18910DFC6E19323">>}, {<<"msgpack">>, <<"4649353DA003E6F438D105E4B1E0F17757F6F5EC8687A6F30875FF3AC4CE2A51">>}, - {<<"observer_cli">>, <<"A1D280C112BB5443F09B63041D6C5DDA39B40829DB40B24FDF208E1B86DAB353">>}, + {<<"observer_cli">>, <<"50DE6D95D814F447458BD5D72666A74624EDDB0EF98BDCEE61A0153AAE0865FF">>}, {<<"opentelemetry_api">>, <<"6D7A27B7CAD2AD69A09CABF6670514CAFCEC717C8441BEB5C96322BAC3D05350">>}, {<<"opentelemetry_semantic_conventions">>, <<"D61FA1F5639EE8668D74B527E6806E0503EFC55A42DB7B5F39939D84C07D6895">>}, - {<<"p1_utils">>, <<"47F21618694EEEE5006AF1C88731AD86B757161E7823C29B6F73921B571C8502">>}, + {<<"p1_utils">>, <<"9219214428F2C6E5D3187FF8EB9A8783695C2427420BE9A259840E07ADA32847">>}, {<<"parse_trans">>, <<"620A406CE75DADA827B82E453C19CF06776BE266F5A67CFF34E1EF2CBB60E49A">>}, - {<<"prometheus">>, <<"6EDFBE928D271C7F657A6F2C46258738086584BD6CAE4A000B8B9A6009BA23A5">>}, + {<<"prometheus">>, <<"2A99BB6DCE85E238C7236FDE6B0064F9834DC420DDBD962AAC4EA2A3C3D59384">>}, {<<"prometheus_cowboy">>, <<"BA286BECA9302618418892D37BCD5DC669A6CC001F4EB6D6AF85FF81F3F4F34C">>}, {<<"prometheus_httpd">>, <<"0BBE831452CFDF9588538EB2F570B26F30C348ADAE5E95A7D87F35A5910BCF92">>}, {<<"quantile_estimator">>, <<"282A8A323CA2A845C9E6F787D166348F776C1D4A41EDE63046D72D422E3DA946">>}, - {<<"quickrand">>, <<"4CB18E9304CF28E054E8DC6E151D1AC7F174E6FE31D5C1A07F71279B92A90800">>}, + {<<"quickrand">>, <<"86A03C7FC96B9C6B9FA6BEF5FCEB773E359C772EE3814BE60B8EB44B54F99140">>}, {<<"ranch">>, <<"49FBCFD3682FAB1F5D109351B61257676DA1A2FDBE295904176D5E521A2DDFE5">>}, - {<<"recon">>, <<"2C7523C8DEE91DFF41F6B3D63CBA2BD49EB6D2FE5BF1EEC0DF7F87EB5E230E1C">>}, + {<<"recon">>, <<"E9AB01AC7FC8572E41EB59385EFEB3FB0FF5BF02103816535BACAEDF327D0263">>}, {<<"setup">>, <<"EFD072578F0CF85BEA96CAAFFC7ADB0992398272522660A136E10567377071C5">>}, {<<"sext">>, <<"BC6016CB8690BAF677EACACFE6E7CADFEC8DC7E286CBBED762F6CD55B0678E73">>}, {<<"sidejob">>, <<"6DC3DAC041C8C07C64401ECD22684730DA1497F5F14377B3CA9C5B2B9A135181">>}, - {<<"snappyer">>, <<"35518E79A28548B56D8FD6AEE2F565F12F51C2D3D053F9CFA817C83BE88C4F3D">>}, - {<<"ssl_verify_fun">>, <<"BDB0D2471F453C88FF3908E7686F86F9BE327D065CC1EC16FA4540197EA04680">>}, - {<<"stringprep">>, <<"A5967B1144CA8002A58A03D16DD109FBD0BCDB82616CEAD2F983944314AF6A00">>}, - {<<"supervisor3">>, <<"E6C2DEDBCABCBA24995A218ACA12DB5E208B80D3252692B22EF0F1A266104B50">>}, - {<<"telemetry">>, <<"73BC09FA59B4A0284EFB4624335583C528E07EC9AE76ACA96EA0673850AEC57A">>}, + {<<"snappyer">>, <<"18D00CA218AE613416E6EECAFE1078DB86342A66F86277BD45C95F05BF1C8B29">>}, + {<<"ssl_verify_fun">>, <<"FE4C190E8F37401D30167C8C405EDA19469F34577987C76DDE613E838BBC67F8">>}, + {<<"stringprep">>, <<"928EBA304C3006EB1512110EBD7B87DB163B00859A09375A1E4466152C6C462A">>}, + {<<"telemetry">>, <<"DAD9CE9D8EFFC621708F99EAC538EF1CBE05D6A874DD741DE2E689C47FEAFED5">>}, {<<"types">>, <<"04285239F4954C5EDE56F78ED7778EDE24E3F2E997F7B16402A167AF0CC2658A">>}, {<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>}, - {<<"uuid">>, <<"7A4CCD1C151D9B88B4383FA802BCCF9BCB3754B7F53D7CAA164D51A14A6652E4">>}]} + {<<"uuid">>, <<"1D54D5DE4CC66317D882F62347A21655601E84CCCE913E80AADE202CDB3A8C65">>}]} ]. diff --git a/schema/bondy.schema b/schema/bondy.schema index 270a68db..d9145fc1 100644 --- a/schema/bondy.schema +++ b/schema/bondy.schema @@ -668,14 +668,14 @@ hidden ]}. -%% The Cowboy acceptors_pool_size for the Admin API https listener +%% The Cowboy acceptors_pool_size for the Admin API http listener {mapping, "admin_api.http.acceptors_pool_size", "bondy.admin_api_http.acceptors_pool_size", [ {datatype, integer}, {validators, ["pos_integer"]}, {default, 200} ]}. -%% The Cowboy max number of connections for the Admin API https listener +%% The Cowboy max number of connections for the Admin API http listener {mapping, "admin_api.http.max_connections", "bondy.admin_api_http.max_connections", [ {datatype, integer}, {validators, ["pos_integer"]}, @@ -1891,14 +1891,12 @@ %% The time the agent will wait to initiate the next join attempt. For this to %% take effect cluster.peer_discovery.automatic_join needs to be on. -{mapping, "cluster.peer_discovery.join_retry_interval", "bondy.peer_discovery.join_retry_interval", [ +{mapping, "cluster.peer_discovery.join_retry_interval", + "bondy.peer_discovery.join_retry_interval", [ {default, "5s"}, {datatype, {duration, ms}} ]}. - - - %% The name of a module implementing the bondy_peer_discovery_agent behaviour. %% At the moment Bondy provides only the `bondy_peer_discovery_dns_agent', which %% ssumes that all Bondy nodes are deployed using a common base name e.g. bondy, @@ -1960,6 +1958,28 @@ end}. {datatype, flag} ]}. +%% @doc If the `off' value is provided, it does nothing and the configuration +%% will use any value provided by cluster.tls.server.cacertfile. +%% If the `on' value is provided tries to load the trusted CA certificates +%% provided by the OS. If no cacerts could be loaded it disables the option and +%% revers to cluster.tls.server.cacertfile. +%% If a DER-encoded trusted certificates string is provided it overrides option +%% cluster.tls.server.cacertfile. +{mapping, "cluster.tls.server.cacerts", "partisan.tls_server_options.cacerts", [ + {default, false}, + {datatype, [flag, string]} +]}. + +%% @doc Defaults to verify_none as additional options are needed to be able to +%% perform the certificate verification. A warning will be emitted unless +%% verify_none is explicitly configured. Usually the applications will want to +%% configure verify_peer together with an appropriate cacert or cacertfile +%% option. +{mapping, "cluster.tls.server.verify", "partisan.tls_server_options.verify", [ + {datatype, {enum, [verify_peer, verify_none]}}, + {default, verify_none} +]}. + %% @doc Default cert location for cluster TLS connection {mapping, "cluster.tls.server.certfile", "partisan.tls_server_options.certfile", [ {datatype, file}, @@ -1985,11 +2005,24 @@ end}. {default, "1.3"} ]}. -{mapping, "cluster.tls.server.verify", "partisan.tls_server_options.verify", [ + + +{mapping, "cluster.tls.client.verify", "partisan.tls_client_options.verify", [ {datatype, {enum, [verify_peer, verify_none]}}, {default, verify_none} ]}. +%% @doc If the `off' value is provided, it does nothing and the configuration +%% will use any value provided by cluster.tls.client.cacertfile. +%% If the `on' value is provided tries to load the trusted CA certificates +%% provided by the OS. If no cacerts could be loaded it disables the option and +%% revers to cluster.tls.client.cacertfile. +%% If a DER-encoded trusted certificates string is provided it overrides option +%% cluster.tls.client.cacertfile. +{mapping, "cluster.tls.client.cacerts", "partisan.tls_client_options.cacerts", [ + {default, false}, + {datatype, [flag, string]} +]}. %% @doc Default cert location for cluster TLS connection {mapping, "cluster.tls.client.certfile", "partisan.tls_client_options.certfile", [ @@ -2016,11 +2049,6 @@ end}. {default, "1.3"} ]}. -{mapping, "cluster.tls.client.verify", "partisan.tls_client_options.verify", [ - {datatype, {enum, [verify_peer, verify_none]}}, - {default, verify_none} -]}. - {translation, "partisan.tls_server_options.versions", fun(Conf) -> diff --git a/schema/bondy_bridge_relay.schema b/schema/bondy_bridge_relay.schema index 4d40a3cc..3c5c8145 100644 --- a/schema/bondy_bridge_relay.schema +++ b/schema/bondy_bridge_relay.schema @@ -58,6 +58,13 @@ {commented, "{{platform_etc_dir}}/client/cacert.pem"} ]}. + +{mapping, "bridge.$name.tls.hostname_verification", + "bondy.bridges", [ + {datatype, {enum, [wildcard, none]}}, + {default, wildcard} +]}. + %% @doc A comma separate list of TLS protocol versions that will be supported %% At the moment Bondy only supports versions 1.2 and 1.3 {mapping, "bridge.$name.tls.versions", "bondy.bridges", [ @@ -478,6 +485,7 @@ when KeyStr == <<"cacertfile">>; KeyStr == <<"certfile">>; KeyStr == <<"keyfile">>; + KeyStr == <<"hostname_verification">>; KeyStr == <<"verify">> -> Key = binary_to_atom(KeyStr), Put([Name, tls_opts, Key], Value, Acc); @@ -931,7 +939,7 @@ end}. %% with the edge.tls config variable, for example: {mapping, "bridge.listener.tls.certfile", "bondy.bridge_relay_tls.tls_opts.certfile", [ {datatype, file}, - {default, "{{platform_etc_dir}}/cert.pem"} + {default, "{{platform_etc_dir}}/keycert.pem"} ]}. %% @doc Default key location for https can be overridden with the diff --git a/schema/logger.schema b/schema/logger.schema index eae09a5b..6004156b 100644 --- a/schema/logger.schema +++ b/schema/logger.schema @@ -8,7 +8,6 @@ ]}} ]}. - %% ============================================================================= %% DEFAULT HANDLER %% ============================================================================= @@ -263,12 +262,17 @@ %% and print them to a dedicated handler. %% %% The value is a comma separated string which con contain one or more of the -%% following elements: "otp", "sasl" and "bondy_audit" +%% following elements: "otp", "ssl" and "bondy_audit" {mapping, "log.handlers.default.filter_domains", "kernel.logger", [ {default, "otp, bondy_audit"}, {datatype, string} ]}. +{mapping, "log.handlers.default.allow_progress_reports", "kernel.logger", [ + {default, off}, + {datatype, flag} +]}. + %% When formatting maps limit their depth to a value. If -1 is provided, this %% option is disabled. {mapping, "log.handlers.default.formatter.map_depth", "kernel.logger", [ @@ -599,6 +603,11 @@ {datatype, string} ]}. +{mapping, "log.handlers.$id.allow_progress_reports", "kernel.logger", [ + {default, off}, + {datatype, flag} +]}. + %% When formatting maps limit their depth to a value. If -1 is provided, this %% option is disabled. {mapping, "log.handlers.$id.formatter.map_depth", "kernel.logger", [ @@ -775,35 +784,60 @@ end, %% Filters - AllDomains = sets:from_list([otp, sasl, bondy_audit]), + AllDomains = sets:from_list([otp, ssl, bondy_audit]), ConfDomains = cuttlefish:conf_get( HandlerPrefix ++ ["filter_domains"], HandlersConf ), + AllowProgressReports = cuttlefish:conf_get( + HandlerPrefix ++ ["allow_progress_reports"], HandlersConf + ), + ProgressAction = + case AllowProgressReports of + true -> log; + false -> stop + end, + LogDomains = sets:from_list([ list_to_existing_atom(string:strip(X, both)) || X <- string:tokens(ConfDomains, ",") ]), StopDomains = sets:subtract(AllDomains, LogDomains), + DomainFilter = fun + (Action, _, D) when D == otp; D == sasl -> + { + fun logger_filters:domain/2, + {Action, equal, [otp, sasl]} + }; + (Action, Rel, D) -> + { + fun logger_filters:domain/2, + {Action, equal, [D]} + } + end, + LogFilters = [ + {D, + DomainFilter(log, sub, D) + } || D <- sets:to_list(LogDomains) + ], + StopFilters = [ + {D, + DomainFilter(stop, super, D) + } || D <- sets:to_list(StopDomains) + ], Filters = [ + {progress, + {fun logger_filters:progress/2, ProgressAction} + }, {remote_gl, {fun logger_filters:remote_gl/2, stop} }, {no_domain, {fun logger_filters:domain/2, {log, undefined, []}} - }, - {domain, - { - fun logger_filters:domain/2, - {stop, equal, sets:to_list(StopDomains)}} - }, - {domain, - { - fun logger_filters:domain/2, - {log, super, sets:to_list(LogDomains)}} - } + } | LogFilters ++ StopFilters ], + %% Formatter FormatConf = cuttlefish_variable:filter_by_prefix( HandlerPrefix ++ ["formatter"], CuttleConf