/** * Authenticate an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * * @return mixed */ public function handle(Request $request, Closure $next) { $_token = $request->input('access-token'); $_clientId = $request->input('client-id'); // Remove these arguments $request->offsetUnset('client-id'); $request->offsetUnset('access-token'); // Just plain ol' bad... if (empty($_token) || empty($_clientId)) { $this->error('bad request: no token or client-id present'); return ErrorPacket::create(Response::HTTP_BAD_REQUEST); } try { $_key = AppKey::byClientId($_clientId)->firstOrFail(); $this->setSigningCredentials($_clientId, $_key->client_secret); } catch (\Exception $_ex) { $this->error('forbidden: invalid "client-id" [' . $_clientId . ']'); return ErrorPacket::create(Response::HTTP_FORBIDDEN, 'Invalid "client-id"'); } if (!$this->verifySignature($_token, $_clientId, $_key->client_secret)) { $this->error('bad request: signature verification fail'); return ErrorPacket::create(Response::HTTP_BAD_REQUEST); } try { $_owner = $this->_locateOwner($_key->owner_id, $_key->owner_type_nbr); } catch (ModelNotFoundException $_ex) { $this->error('unauthorized: invalid "user" assigned to akt#' . $_key->id); return ErrorPacket::create(Response::HTTP_UNAUTHORIZED); } $request->setUserResolver(function () use($_owner) { return $_owner; }); //$this->debug('token validated for client "' . $_clientId . '"'); return parent::handle($request, $next); }
/** * Handle a request * * @param ManifestJob $command * * * @return bool * @throws \Exception */ public function handle(ManifestJob $command) { \Log::debug('[dfe:manifest] begin'); if ($command->showManifest()) { $_manifest = ClusterManifest::createFromFile(base_path() . DIRECTORY_SEPARATOR . ConsoleDefaults::CLUSTER_MANIFEST_FILE); $_result = !$_manifest->existed() ? ErrorPacket::create() : SuccessPacket::make($_manifest->toArray()); // And then show it... if ($_manifest->existed()) { \Log::debug(' * Manifest found: ' . print_r($_manifest->all(), true)); } else { \Log::info(' * No manifest file found. Nothing to show.'); } } else { try { $_key = $command->noKeys() ? false : AppKey::createKey($command->getOwnerId(), $command->getOwnerType()); if ($_key) { $command->getOutput()->getVerbosity() == OutputInterface::VERBOSITY_VERBOSE && $command->getOutput()->writeln(' - generated client-id and secret: ' . $_key->client_id); } if ($command->createManifest()) { // Create a new manifest... $_manifest = ClusterManifest::make(base_path(), ['cluster-id' => config('dfe.cluster-id'), 'default-domain' => config('provisioning.default-domain'), 'signature-method' => config('dfe.signature-method'), 'storage-root' => config('provisioning.storage-root'), 'console-api-url' => config('dfe.security.console-api-url'), 'console-api-key' => config('dfe.security.console-api-key'), 'client-id' => !$_key ? null : $_key->client_id, 'client-secret' => !$_key ? null : $_key->client_secret]); $command->setResult($_result = SuccessPacket::make($_manifest->toArray(), Response::HTTP_CREATED)); } } catch (\Exception $_ex) { $command->setResult($_result = ErrorPacket::create(Response::HTTP_BAD_REQUEST)); } } \Log::debug('[dfe:manifest] end'); return $command; }
/** @inheritdoc */ public static function boot() { parent::boot(); // Ensure user is active upon creation static::creating(function (ServiceUser $model) { $model->active_ind = true; }); static::created(function (ServiceUser $model) { AppKey::createKeyForEntity($model, OwnerTypes::SERVICE_USER); }); }
/** * Create a new user instance after a valid registration. * * @param array $data * * @return User */ public function create(array $data) { return \DB::transaction(function () use($data) { $_user = User::create(['first_name_text' => $data['first_name_text'], 'last_name_text' => $data['last_name_text'], 'email_addr_text' => $data['email_addr_text'], 'nickname_text' => $data['nickname_text'], 'password_text' => bcrypt($data['password_text'])]); $_appKey = AppKey::create(array('key_class_text' => AppKeyClasses::USER, 'owner_id' => $_user->id, 'owner_type_nbr' => OwnerTypes::USER, 'server_secret' => config('dfe.security.console-api-key'))); // Update the user with the key info and activate $_user->api_token_text = $_appKey->client_id; $_user->active_ind = 1; $_user->save(); return $_user; }); }
/** * Validates a client key pair and generates a signature for verification. * * @param string $clientId * @param string $clientSecret * * @return $this */ protected function setSigningCredentials($clientId, $clientSecret) { $_key = AppKey::byClientId($clientId)->first(); if (empty($_key) || $clientSecret != $_key->client_secret) { throw new \InvalidArgumentException('Invalid credentials.'); } // Looks good $this->vsClientId = $_key->client_id; $this->vsClientSecret = $_key->client_secret; $this->vsSignature = $this->generateSignature(); return $this; }
/** * Handle a request * * @param RegisterJob $command * * @return mixed * @throws \Exception */ public function handle(RegisterJob $command) { $_key = config('dfe.security.console-api-key'); try { $_owner = $command->getOwnerInfo(); // Generate the key $_key = AppKey::createKey($_owner->id, $_owner->type, ['server_secret' => $_key]); $this->debug('[dfe:register] Successfully created app key "' . $_key->client_id . '"'); $_result = SuccessPacket::make($_key->toArray(), Response::HTTP_CREATED); } catch (\Exception $_ex) { $this->error('[dfe:register] Exception while creating key: ' . $_ex->getMessage()); $_result = ErrorPacket::create(Response::HTTP_BAD_REQUEST, $_ex); } $command->publishResult($command->getJobId(), $_result); return $_result; }
/** * Handle the command * * @return mixed */ public function fire() { parent::fire(); $_command = new RegisterJob($this->argument('owner-id'), strtolower($this->argument('owner-type'))); \Queue::push($_command); $_result = $_command->getResult(); if (empty($_result) || null === ($_id = IfSet::getDeep($_result, 'success', 'id'))) { $this->error('Results not found for request. Please try again.'); return 1; } try { /** @type AppKey $_key */ $_key = AppKey::findOrFail($_id); } catch (ModelNotFoundException $_ex) { $this->error('The key has been misplaced. Please try again.'); return 2; } $this->writeln('<info>Key pair id "' . $_id . '" created. Please keep secure.</info>'); $this->writeln(' <comment>client_id</comment>: <info>' . $_key->client_id . '</info>'); $this->writeln('<comment>client_secret</comment>: <info>' . $_key->client_secret . '</info>'); return 0; }
/** * Handle the command * * @return mixed */ public function fire() { parent::fire(); $this->config = config('commands.setup'); // 1. Make sure it's a clean install if (0 != ServiceUser::count()) { if ($this->option('force')) { $this->writeln('system has users. <comment>--force</comment> override in place.'); $this->_backupServiceUsers(); } else { $this->writeln('system has users. use --force to override.', 'error'); return 1; } } // 1.5 Generate an API secret and stick it in config for AppKey \Config::set('dfe.security.console-api-key', $_apiSecret = $this->option('api-secret') ?: $this->_generateApiSecret()); // 2. Create initial admin user try { // Delete all users /** @noinspection PhpUndefinedMethodInspection */ DB::table('service_user_t')->delete(); // Add our new user $_user = ServiceUser::create(['first_name_text' => 'System', 'last_name_text' => 'Administrator', 'nickname_text' => 'Admin', 'email_addr_text' => $this->argument('admin-email'), 'password_text' => \Hash::make($this->option('admin-password')), 'active_ind' => 1]); if (empty($_user)) { throw new \Exception('Invalid response from user::create'); } $this->writeln('user <comment>' . $this->argument('admin-email') . '</comment> created.', 'info'); // Register if (false === License::registerAdmin($_user)) { $this->writeln('Error while registering installation'); } } catch (\Exception $_ex) { $this->writeln('Error while creating admin user: '******'error'); return 1; } // 2. Check permissions and required directories $_paths = config('commands.setup.required-directories', []); foreach ($_paths as $_path) { if (!Disk::ensurePath($_path)) { $this->writeln('Unable to create directory: ' . $_path, 'error'); } } // 3. Create console and dashboard API key sets $_consoleKey = AppKey::createKey(0, OwnerTypes::CONSOLE, ['server_secret' => $_apiSecret]); $_dashboardKey = AppKey::createKey(0, OwnerTypes::DASHBOARD, ['server_secret' => $_apiSecret]); // 4. Generate .dfe.cluster.json file ClusterManifest::make(base_path('database/dfe'), ['cluster-id' => config('dfe.cluster-id'), 'default-domain' => config('provisioning.default-domain'), 'signature-method' => config('dfe.signature-method'), 'storage-root' => config('provisioning.storage-root'), 'console-api-url' => config('dfe.security.console-api-url'), 'console-api-key' => $_apiSecret, 'client-id' => $_dashboardKey->client_id, 'client-secret' => $_dashboardKey->client_secret]); // 5. Make a console environment $config = <<<INI DFE_CONSOLE_API_KEY={$_apiSecret} DFE_CONSOLE_API_CLIENT_ID={$_consoleKey->client_id} DFE_CONSOLE_API_CLIENT_SECRET={$_consoleKey->client_secret} INI; $this->_writeFile('console.env', $config); // 6. Make a dashboard config file... $config = <<<INI DFE_CONSOLE_API_KEY={$_apiSecret} DFE_CONSOLE_API_CLIENT_ID={$_dashboardKey->client_id} DFE_CONSOLE_API_CLIENT_SECRET={$_dashboardKey->client_secret} INI; return $this->_writeFile('dashboard.env', $config); }
/** * * @param int $ownerId * @param int $ownerType * * @return AppKey */ protected static function findAppKey($ownerId, $ownerType) { return AppKey::mine($ownerId, $ownerType); }
/** * @param Instance $instance * @param bool $object If true, the Metadata object is returned instead of the array * * @return array|\DreamFactory\Enterprise\Common\Support\Metadata */ public static function makeMetadata(Instance $instance, $object = false) { if (null === ($_key = AppKey::mine($instance->id, OwnerTypes::INSTANCE))) { // Create an instance key $_key = AppKey::create(['key_class_text' => AppKeyClasses::INSTANCE, 'owner_id' => $instance->id, 'owner_type_nbr' => OwnerTypes::INSTANCE, 'server_secret' => config('dfe.security.console-api-key')]); if (null === $_key) { throw new \RuntimeException('Instance is unlicensed.'); } } $_cluster = static::_lookupCluster($instance->cluster_id); $_md = new Metadata(array_merge(static::$metadataTemplate, ['storage-map' => InstanceStorage::buildStorageMap($instance->user->storage_id_text), 'env' => static::buildEnvironmentMetadata($instance, $_cluster, $_key), 'db' => static::buildDatabaseMetadata($instance), 'paths' => static::buildPathMetadata($instance), 'audit' => static::buildAuditMetadata($instance), 'limits' => static::buildLimitsMetadata($instance)]), $instance->instance_name_text . '.json', $instance->getOwnerPrivateStorageMount()); return $object ? $_md : $_md->toArray(); }
/** * @param ProvisionServiceRequest $request * * @return array * @throws ProvisioningException */ protected function provisionInstance($request) { $_storagePath = null; // Pull the request apart $_instance = $request->getInstance(); $_name = $this->sanitizeInstanceName($_instance->instance_name_text); $this->info('[provisioning] instance "' . $_name . '" begin'); $_storageProvisioner = $request->getStorageProvisioner(); $this->setPrivatePath($_privatePath = $_storageProvisioner->getPrivatePath()); $this->setOwnerPrivatePath($_ownerPrivatePath = $_storageProvisioner->getOwnerPrivatePath()); // 1. Provision the database if (false === ($_dbConfig = Provision::getDatabaseProvisioner($_instance->guest_location_nbr)->provision($request))) { throw new ProvisioningException('[provisioning] error during database provisioning.'); } // 2. Generate an app key for the instance AppKey::create(['key_class_text' => AppKeyClasses::INSTANCE, 'owner_id' => $_instance->id, 'owner_type_nbr' => OwnerTypes::INSTANCE, 'server_secret' => config('dfe.security.console-api-key')]); // 3. Update the instance with new provision info try { $_instance->fill(['guest_location_nbr' => GuestLocations::DFE_CLUSTER, 'instance_id_text' => $_name, 'instance_name_text' => $_name, 'db_host_text' => $_dbConfig['host'], 'db_port_nbr' => $_dbConfig['port'], 'db_name_text' => $_dbConfig['database'], 'db_user_text' => $_dbConfig['username'], 'db_password_text' => $_dbConfig['password'], 'ready_state_nbr' => InstanceStates::ADMIN_REQUIRED, 'state_nbr' => ProvisionStates::PROVISIONED, 'platform_state_nbr' => OperationalStates::NOT_ACTIVATED, 'start_date' => $_instance->freshTimestamp(), 'end_date' => null, 'terminate_date' => null, 'provision_ind' => true, 'deprovision_ind' => false]); // Create the guest row... $_host = $this->getFullyQualifiedDomainName($_name); /** @noinspection PhpUndefinedMethodInspection */ DB::transaction(function () use($_instance, $_host) { /** Add guest data if there is a guest record */ $_instance->guest && $_instance->guest->fill(['base_image_text' => config('provisioning.base-image', ConsoleDefaults::DFE_CLUSTER_BASE_IMAGE), 'vendor_state_nbr' => ProvisionStates::PROVISIONED, 'vendor_state_text' => 'running', 'public_host_text' => $_host])->save(); // Save the instance $_instance->save(); }); } catch (\Exception $_ex) { throw new \RuntimeException('[provisioning:instance] error updating instance data: ' . $_ex->getMessage()); } // Fire off a "provisioned" event... \Event::fire('dfe.provisioned', [$this, $request, $_instance->getMetadata()]); $this->info('[provisioning:instance] instance "' . $_name . '" provisioned'); return $_instance->getMetadata(); }
/** * Standardized user creation method * * @param \Illuminate\Http\Request $request * @param bool $validate If false, no validation is done. * * @return \DreamFactory\Enterprise\Common\Packets\ErrorPacket|\DreamFactory\Enterprise\Common\Packets\SuccessPacket */ public static function register(Request $request, $validate = true) { $_email = $request->input('email', $request->input('email_addr_text')); $_first = $request->input('firstname', $request->input('first_name_text')); $_last = $request->input('lastname', $request->input('last_name_text')); $_password = $request->input('password', $request->input('password_text')); $_nickname = $request->input('nickname', $request->input('nickname_text', $_first)); $_company = $request->input('company', $request->input('company_name_text')); $_phone = $request->input('phone', $request->input('phone_text')); if ($validate) { if (empty($_email) || empty($_password) || empty($_first) || empty($_last)) { /** @noinspection PhpUndefinedMethodInspection */ Log::error('missing required fields from partner post', ['payload' => $request->input()]); throw new \InvalidArgumentException('Missing required fields'); } if (false === filter_var($_email, FILTER_VALIDATE_EMAIL)) { /** @noinspection PhpUndefinedMethodInspection */ Log::error('invalid email address "' . $_email . '"', ['payload' => $request->input()]); throw new \InvalidArgumentException('Email address invalid'); } } // See if we know this cat... if (null !== ($_user = User::byEmail($_email)->first())) { // Existing user found, don't add to database... $_values = $_user->toArray(); unset($_values['password_text'], $_values['external_password_text']); /** @noinspection PhpUndefinedMethodInspection */ Log::info('existing user attempting registration through api', ['user' => $_values]); return $_user; } // Create a user account try { /** @type User $_user */ /** @noinspection PhpUndefinedMethodInspection */ $_user = DB::transaction(function () use($request, $_first, $_last, $_email, $_password, $_nickname, $_phone, $_company) { /** @noinspection PhpUndefinedMethodInspection */ $_user = User::create(['first_name_text' => $_first, 'last_name_text' => $_last, 'email_addr_text' => $_email, 'nickname_text' => $_nickname, 'password_text' => Hash::make($_password), 'phone_text' => $_phone, 'company_name_text' => $_company]); if (null === ($_appKey = AppKey::mine($_user->id, OwnerTypes::USER))) { $_appKey = AppKey::create(['key_class_text' => AppKeyClasses::USER, 'owner_id' => $_user->id, 'owner_type_nbr' => OwnerTypes::USER, 'server_secret' => config('dfe.security.console-api-key')]); } // Update the user with the key info and activate $_user->api_token_text = $_appKey->client_id; $_user->active_ind = 1; $_user->save(); return $_user; }); $_values = $_user->toArray(); unset($_values['password_text'], $_values['external_password_text']); /** @noinspection PhpUndefinedMethodInspection */ Log::info('new user registered', ['user' => $_values]); return $validate ? SuccessPacket::create($_user, Response::HTTP_CREATED) : $_user; } catch (\Exception $_ex) { if (false !== ($_pos = stripos($_message = $_ex->getMessage(), ' (sql: '))) { $_message = substr($_message, 0, $_pos); } /** @noinspection PhpUndefinedMethodInspection */ Log::error('database error creating user from ops-resource post: ' . $_message); return $validate ? ErrorPacket::create(null, Response::HTTP_INTERNAL_SERVER_ERROR, $_message) : null; } }