wip
This commit is contained in:
parent
428f7e0565
commit
11d5f3f767
208
zx
208
zx
@ -348,7 +348,7 @@ ensure_installed(PackageID = {Realm, Name, Version}) ->
|
||||
end.
|
||||
|
||||
|
||||
-spec ensure_installed(Realm, Name, Version) -> Result
|
||||
-spec ensure_installed(Realm, Name, Version) -> Result | no_return()
|
||||
when Realm :: realm(),
|
||||
Name :: name(),
|
||||
Version :: version(),
|
||||
@ -707,13 +707,10 @@ valid_package({Realm, Name}) ->
|
||||
{false, false} ->
|
||||
ok = log(error, "Invalid realm ~tp and package ~tp", [Realm, Name]),
|
||||
halt(1)
|
||||
end;
|
||||
valid_package(Bad) ->
|
||||
ok = log(error, "Invalid package() value: ~160tp", [Bad]),
|
||||
halt(1).
|
||||
end.
|
||||
|
||||
|
||||
-spec string_to_package(string()) -> ok | no_return().
|
||||
-spec string_to_package(string()) -> package() | no_return().
|
||||
%% @private
|
||||
%% Convert a string to a package() type if possible. If not then halt the system.
|
||||
|
||||
@ -2306,35 +2303,31 @@ create_realm(ZompConf, Realm, ExAddress, ExPort, InPort, UserName, Email) ->
|
||||
" There are no rules for this one. Any valid UTF-8 printables are legal.~n",
|
||||
ok = io:format(Instructions),
|
||||
RealName = get_input(),
|
||||
create_realm(ZompConf, Realm, ExAddress, ExPort, InPort, UserName, Email, RealName).
|
||||
|
||||
|
||||
-spec create_realm(ZompConf, Realm, ExAddress, ExPort, InPort, UserName, Email, RealName) ->
|
||||
no_return()
|
||||
when ZompConf :: [{Key :: atom(), Value :: term()}],
|
||||
Realm :: realm(),
|
||||
ExAddress :: inet:hostname() | inet:ip_address(),
|
||||
ExPort :: inet:port_number(),
|
||||
InPort :: inet:port_number(),
|
||||
UserName :: string(),
|
||||
Email :: string(),
|
||||
RealName :: string().
|
||||
|
||||
create_realm(ZompConf, Realm, ExAddress, ExPort, InPort, UserName, Email, RealName) ->
|
||||
ok = io:format("~nGenerating keys. This might take a while, so settle in...~n"),
|
||||
{ok, RealmKey, RealmPub} = generate_rsa({Realm, Realm ++ ".1.realm"}),
|
||||
{ok, PackageKey, PackagePub} = generate_rsa({Realm, Realm ++ ".1.package"}),
|
||||
{ok, SysopKey, SysopPub} = generate_rsa({Realm, UserName ++ ".1"}),
|
||||
AllKeys = [RealmKey, RealmPub, PackageKey, PackagePub, SysopKey, SysopPub],
|
||||
DangerousKeys = [PackageKey, SysopKey],
|
||||
Copy =
|
||||
fun(From) ->
|
||||
To = filename:basename(From),
|
||||
case filelib:is_file(To) of
|
||||
true ->
|
||||
M = "Whoops! Keyfile local destination ~tp exists! Aborting",
|
||||
ok = log(error, M, [To]),
|
||||
ok = log(info, "Undoing all changes..."),
|
||||
ok = lists:foreach(fun file:delete/1, AllKeys),
|
||||
halt(0);
|
||||
false ->
|
||||
{ok, _} = file:copy(From, To),
|
||||
log(info, "Copying to local directory: ~ts", [From])
|
||||
end
|
||||
end,
|
||||
Drop =
|
||||
fun(File) ->
|
||||
ok = file:delete(File),
|
||||
log(info, "Deleting ~ts", [File])
|
||||
end,
|
||||
ok = lists:foreach(Copy, AllKeys),
|
||||
ok = lists:foreach(Drop, DangerousKeys),
|
||||
ok = log(info, "Generated 16k RSA pair ~ts ~ts", [RealmKey, RealmPub]),
|
||||
ok = log(info, "Generated 16k RSA pair ~ts ~ts", [PackageKey, PackagePub]),
|
||||
ok = log(info, "Generated 16k RSA pair ~ts ~ts", [SysopKey, SysopPub]),
|
||||
|
||||
Timestamp = calendar:now_to_universal_time(erlang:timestamp()),
|
||||
|
||||
{ok, RealmPubData} = file:read_file(RealmPub),
|
||||
RealmPubRecord =
|
||||
{{Realm, filename:basename(RealmPub, ".pub.der")},
|
||||
@ -2349,25 +2342,12 @@ create_realm(ZompConf, Realm, ExAddress, ExPort, InPort, UserName, Email) ->
|
||||
{realm, Realm},
|
||||
crypto:hash(sha512, PackagePubData),
|
||||
Timestamp},
|
||||
Message =
|
||||
"~n"
|
||||
" All of the keys generated have been moved to the current directory.~n"
|
||||
"~n"
|
||||
" MAKE AND SECURELY STORE COPIES OF THESE KEYS.~n"
|
||||
"~n"
|
||||
" The private package and sysop login keys have been deleted from the "
|
||||
"key directory. These should only exist on your local system, not a prime "
|
||||
"realm server (particularly if other services are run on that machine).~n"
|
||||
" The package and sysop keys will need to be copied to the ~~/.zomp/keys/~s/~n"
|
||||
" directory on your personal or dev machine.~n",
|
||||
ok = io:format(Message, [Realm]),
|
||||
UserRecord =
|
||||
{{Realm, UserName},
|
||||
[filename:basename(SysopPub, ".pub.der")],
|
||||
Email,
|
||||
RealName},
|
||||
RealmFile = filename:join(zomp_dir(), Realm ++ ".realm"),
|
||||
RealmMeta =
|
||||
RealmSettings =
|
||||
[{realm, Realm},
|
||||
{revision, 0},
|
||||
{prime, {ExAddress, ExPort}},
|
||||
@ -2376,23 +2356,86 @@ create_realm(ZompConf, Realm, ExAddress, ExPort, InPort, UserName, Email) ->
|
||||
{sysops, [UserRecord]},
|
||||
{realm_keys, [RealmPubRecord]},
|
||||
{package_keys, [PackagePubRecord]}],
|
||||
Realms =
|
||||
case lists:keyfind(managed, 1, ZompConf) of
|
||||
{managed, M} -> [Realm | M];
|
||||
false -> [Realm]
|
||||
end,
|
||||
ZompFile = filename:join(zomp_dir(), "zomp.conf"),
|
||||
Update = fun({K, V}, ZC) -> lists:keystore(K, 1, ZC, {K, V}) end,
|
||||
NewConf =
|
||||
[{managed, Realms},
|
||||
ZompSettings =
|
||||
[{managed, [Realm]},
|
||||
{external_address, ExAddress},
|
||||
{external_port, ExPort},
|
||||
{internal_port, InPort}],
|
||||
NewZompConf = lists:foldl(Update, ZompConf, NewConf),
|
||||
ok = write_terms(RealmFile, RealmMeta),
|
||||
ok = write_terms(ZompFile, NewZompConf),
|
||||
ok = log(info, "Realm ~ts created.", [Realm]),
|
||||
create_realmfile(Realm).
|
||||
|
||||
RealmFN = Realm ++ ".realm",
|
||||
RealmConf = filename:join(zomp_dir(), RealmFN),
|
||||
ok = write_terms(RealmConf, RealmSettings),
|
||||
{ok, CWD} = file:get_cwd(),
|
||||
{ok, TempDir} = mktemp_dir("zomp"),
|
||||
ok = file:set_cwd(TempDir),
|
||||
KeyDir = filename:join("key", Realm),
|
||||
ok = filelib:ensure_dir(KeyDir),
|
||||
ok = file:make_dir(KeyDir),
|
||||
KeyCopy =
|
||||
fun(K) ->
|
||||
{ok, _} = file:copy(K, filename:join(KeyDir, filename:basename(K))),
|
||||
ok
|
||||
end,
|
||||
TarOpts = [compressed, {cwd, TempDir}],
|
||||
|
||||
ok = write_terms(RealmFN, RealmSettings),
|
||||
ok = KeyCopy(PackagePub),
|
||||
ok = KeyCopy(RealmPub),
|
||||
PublicZRF = filename:join(CWD, Realm ++ ".zrf"),
|
||||
Files = filelib:wildcard("**"),
|
||||
ok = erl_tar:create(PublicZRF, [RealmFN, "key"], TarOpts),
|
||||
|
||||
ok = KeyCopy(SysopPub),
|
||||
ok = write_terms("zomp.conf", ZompSettings),
|
||||
PrimeZRF = filename:join(CWD, Realm ++ ".zpf"),
|
||||
ok = erl_tar:create(PrimeZRF, [RealmFN, "zomp.conf", "key"], TarOpts),
|
||||
|
||||
ok = file:set_cwd(zomp_dir()),
|
||||
KeyBundle = filename:join(CWD, Realm ++ ".zkf"),
|
||||
ok = erl_tar:create(KeyBundle, [KeyDir], [compressed]),
|
||||
|
||||
ok = file:set_cwd(CWD),
|
||||
ok = rm_rf(TempDir),
|
||||
|
||||
Message =
|
||||
"============================================================================~n"
|
||||
"DONE!~n"
|
||||
"~n"
|
||||
"The realm ~ts has been created and is accessible from the current system.~n"
|
||||
"Three configuration bundles have been created in the current directory:~n"
|
||||
"~n"
|
||||
" 1. ~ts ~n"
|
||||
"This is the PRIVATE realm file you will need to install on the realm's prime~n"
|
||||
"node. It includes the your (the sysop's) public key.~n"
|
||||
"~n"
|
||||
" 2. ~ts ~n"
|
||||
"This file is the PUBLIC realm file other zomp nodes and zx users will need to~n"
|
||||
"access the realm. It does not include your (the sysop's) public key.~n"
|
||||
"~n"
|
||||
" 3. ~ts ~n"
|
||||
"This is the bundle of ALL KEYS that are defined in this realm at the moment.~n"
|
||||
"~n"
|
||||
"Now you need to make copies of these three files and back them up.~n"
|
||||
"~n"
|
||||
"On the PRIME NODE you need to run `zx add realm ~ts` and follow the prompts~n"
|
||||
"to cause it to begin serving that realm as prime. (Node restart required.)~n"
|
||||
"~n"
|
||||
"On all zx CLIENTS that want to access your new realm and on all subordinate~n"
|
||||
"MIRROR NODES the command `zx add realm ~ts` will need to be run.~n"
|
||||
"The method of public realm file distribution (~ts) is up to you.~n"
|
||||
"~n"
|
||||
"~n"
|
||||
"Public & Private key installation (if you need to recover them or perform~n"
|
||||
"sysop functions from another computer) is `zx add keybundle ~ts`.~n"
|
||||
"============================================================================~n",
|
||||
Substitutions =
|
||||
[Realm,
|
||||
PrimeZRF, PublicZRF, KeyBundle,
|
||||
PrimeZRF,
|
||||
PublicZRF, PublicZRF,
|
||||
KeyBundle],
|
||||
ok = io:format(Message, Substitutions),
|
||||
halt(0).
|
||||
|
||||
|
||||
-spec create_realmfile(realm()) -> no_return().
|
||||
@ -2451,7 +2494,7 @@ install(PackageID) ->
|
||||
{TgzFile, TgzData} = lists:keyfind(TgzFile, 1, Files),
|
||||
{"zomp.meta", MetaBin} = lists:keyfind("zomp.meta", 1, Files),
|
||||
Meta = binary_to_term(MetaBin),
|
||||
{KeyID, Signature} = maps:get(sig, 1, Meta),
|
||||
{KeyID, Signature} = maps:get(sig, Meta),
|
||||
{ok, PubKey} = loadkey(public, KeyID),
|
||||
ok = ensure_package_dirs(PackageID),
|
||||
PackageDir = filename:join("lib", PackageString),
|
||||
@ -2558,6 +2601,24 @@ receive_zrp(Socket, PackageID) ->
|
||||
end.
|
||||
|
||||
|
||||
-spec mktemp_dir(Prefix) -> Result
|
||||
when Prefix :: string(),
|
||||
Result :: {ok, TempDir :: file:filename()}
|
||||
| {error, Reason :: file:posix()}.
|
||||
|
||||
mktemp_dir(Prefix) ->
|
||||
Rand = integer_to_list(binary:decode_unsigned(crypto:strong_rand_bytes(8)), 36),
|
||||
TempPath = filename:basedir(user_cache, Prefix),
|
||||
TempDir = filename:join(TempPath, Rand),
|
||||
Result1 = filelib:ensure_dir(TempDir),
|
||||
Result2 = file:make_dir(TempDir),
|
||||
case {Result1, Result2} of
|
||||
{ok, ok} -> {ok, TempDir};
|
||||
{ok, Error} -> Error;
|
||||
{Error, _} -> Error
|
||||
end.
|
||||
|
||||
|
||||
%%% Utility functions
|
||||
|
||||
-spec read_meta() -> package_meta() | no_return().
|
||||
@ -2674,6 +2735,33 @@ installed(PackageID) ->
|
||||
filelib:is_dir(PackageDir).
|
||||
|
||||
|
||||
-spec rm_rf(file:filename()) -> ok | {error, file:posix()}.
|
||||
%% @private
|
||||
%% Recursively remove files and directories, equivalent to `rm -rf' on unix.
|
||||
|
||||
rm_rf(Path) ->
|
||||
case filelib:is_dir(Path) of
|
||||
true ->
|
||||
Pattern = filename:join(Path, "**"),
|
||||
Contents = lists:reverse(lists:sort(filelib:wildcard(Pattern))),
|
||||
ok = lists:foreach(fun rm/1, Contents),
|
||||
file:del_dir(Path);
|
||||
false ->
|
||||
file:delete(Path)
|
||||
end.
|
||||
|
||||
|
||||
-spec rm(file:filename()) -> ok | {error, file:posix()}.
|
||||
%% @private
|
||||
%% An omnibus delete helper.
|
||||
|
||||
rm(Path) ->
|
||||
case filelib:is_dir(Path) of
|
||||
true -> file:del_dir(Path);
|
||||
false -> file:delete(Path)
|
||||
end.
|
||||
|
||||
|
||||
|
||||
%%% Input argument mangling
|
||||
|
||||
@ -3225,4 +3313,4 @@ log(Level, Format, Args) ->
|
||||
warning -> "[WARNING]";
|
||||
error -> "[ERROR]"
|
||||
end,
|
||||
io:format("~p ~s: " ++ Format ++ "~n", [self(), Tag | Args]).
|
||||
io:format("~s ~p: " ++ Format ++ "~n", [Tag, self() | Args]).
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user