3232#include " dim.h"
3333#include " keyring/keyring_file.h"
3434#include " keyring/master_key_file.h"
35+ #include " mysql/harness/filesystem.h"
3536#include " random_generator.h"
3637
3738/*
@@ -96,40 +97,53 @@ static std::pair<std::string, std::string> get_master_key(
9697 if (e.code () != std::errc::no_such_file_or_directory || !create_if_needed) {
9798 throw ;
9899 }
99- }
100100
101- std::string master_key;
102- // get the key for the keyring from the master key file, decrypting it with
103- // the scramble
104- if (!master_scramble.empty ()) {
105- try {
106- // look up for the master_key for this given keyring file
107- master_key = mkf.get (keyring_file_path, master_scramble);
108- } catch (const std::out_of_range &) {
109- // missing key will be handled further down
110- }
101+ return {};
111102 }
112103
104+ // look up for the master_key for this given keyring file
105+ std::string master_key =
106+ mkf.get (mysql_harness::Path (keyring_file_path).real_path ().str (),
107+ master_scramble);
108+
109+ // if there is no master key for the "read-path' based keyring path, try to
110+ // lookup via the path itself.
113111 if (master_key.empty ()) {
114- if (!create_if_needed)
115- throw std::runtime_error (" Master key for keyring at '" +
116- keyring_file_path + " ' could not be read" );
117- // if the master key doesn't exist anywhere yet, generate one and store it
118- mysql_harness::RandomGeneratorInterface &rg =
119- mysql_harness::DIM::instance ().get_RandomGenerator ();
120- master_key = rg.generate_strong_password (kKeyLength );
121- // scramble to encrypt the master key with, which should be stored in the
122- // keyring
112+ master_key = mkf.get (keyring_file_path, master_scramble);
113+ }
114+
115+ return {master_key, master_scramble};
116+ }
117+
118+ static std::pair<std::string, std::string> create_initial_keyring_pair (
119+ MasterKeyFile &mkf, const std::string &keyring_file_path,
120+ std::string master_scramble) {
121+ // if the master key doesn't exist anywhere yet, generate one and store it
122+ mysql_harness::RandomGeneratorInterface &rg =
123+ mysql_harness::DIM::instance ().get_RandomGenerator ();
124+ std::string master_key = rg.generate_strong_password (kKeyLength );
125+
126+ // scramble to encrypt the master key with, which should be stored in the
127+ // keyring
128+ if (master_scramble.empty ()) {
123129 master_scramble = rg.generate_strong_password (kKeyLength );
124- mkf.add (keyring_file_path, master_key, master_scramble);
130+
131+ KeyringFile kf;
132+ kf.set_header (master_scramble);
133+ kf.save (keyring_file_path, master_key);
125134 }
126- return std::make_pair (master_key, master_scramble);
135+
136+ // use the real-path to store/lookup the keyring
137+ mkf.add (mysql_harness::Path (keyring_file_path).real_path ().str (), master_key,
138+ master_scramble);
139+
140+ mkf.save ();
141+
142+ return {master_key, master_scramble};
127143}
128144
129145bool init_keyring (const std::string &keyring_file_path,
130146 const std::string &master_key_path, bool create_if_needed) {
131- std::string master_key;
132- std::string master_scramble;
133147 MasterKeyFile mkf (master_key_path);
134148
135149 try {
@@ -142,30 +156,40 @@ bool init_keyring(const std::string &keyring_file_path,
142156 }
143157
144158 // throws std::runtime_error (anything else?)
145- std::tie ( master_key, master_scramble) =
159+ auto [ master_key, master_scramble] =
146160 get_master_key (mkf, keyring_file_path, create_if_needed);
147161
148- bool existed =
149- init_keyring_with_key (keyring_file_path, master_key, create_if_needed);
150- if (create_if_needed && !existed) {
151- g_keyring->set_header (master_scramble);
152- flush_keyring ();
162+ // if there is a master-scramble, the
163+ const bool keyring_existed{!master_scramble.empty ()};
164+
165+ if (master_key.empty ()) {
166+ if (!create_if_needed) {
167+ throw std::runtime_error (" Master key for keyring at '" +
168+ keyring_file_path + " ' could not be read" );
169+ }
170+
153171 try {
154- mkf.save ();
172+ std::tie (master_key, master_scramble) =
173+ create_initial_keyring_pair (mkf, keyring_file_path, master_scramble);
155174 } catch (const std::system_error &e) {
156175 throw std::system_error (
157176 e.code (), " Unable to save master key to " + master_key_path);
158177 }
159178 }
160- return existed;
179+
180+ // load the keyring.
181+ init_keyring_with_key (keyring_file_path, master_key, false );
182+
183+ return keyring_existed;
161184}
162185
163186bool init_keyring_with_key (const std::string &keyring_file_path,
164187 const std::string &master_key,
165188 bool create_if_needed) {
166189 if (g_keyring) throw std::logic_error (" Keyring already initialized" );
167190 bool existed = false ;
168- std::unique_ptr<KeyringFile> key_store (new KeyringFile ());
191+
192+ auto key_store = std::make_unique<KeyringFile>();
169193 try {
170194 key_store->load (keyring_file_path, master_key);
171195 existed = true ;
0 commit comments