Add Service Account Role Assignment
This commit is contained in:
parent
fead8eb47a
commit
d001f14249
|
@ -2732,7 +2732,7 @@ $projectCollections = array_merge([
|
|||
'required' => false,
|
||||
'default' => [],
|
||||
'array' => false,
|
||||
'filters' => ['json'],
|
||||
'filters' => ['json', 'encrypt'],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('resources'),
|
||||
|
|
|
@ -84,56 +84,6 @@ App::post('/v1/migrations/appwrite')
|
|||
->dynamic($migration, Response::MODEL_MIGRATION);
|
||||
});
|
||||
|
||||
App::post('/v1/migrations/firebase')
|
||||
->groups(['api', 'migrations'])
|
||||
->desc('Migrate Firebase Data (Service Account)')
|
||||
->label('scope', 'migrations.write')
|
||||
->label('event', 'migrations.create')
|
||||
->label('audits.event', 'migration.create')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'migrations')
|
||||
->label('sdk.method', 'createFirebaseMigration')
|
||||
->label('sdk.description', '/docs/references/migrations/migration-firebase.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MIGRATION)
|
||||
->param('resources', [], new ArrayList(new WhiteList(Firebase::getSupportedResources())), 'List of resources to migrate')
|
||||
->param('serviceAccount', '', new Text(65536), 'JSON of the Firebase service account credentials')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('user')
|
||||
->inject('events')
|
||||
->action(function (array $resources, string $serviceAccount, Response $response, Database $dbForProject, Document $project, Document $user, Event $events) {
|
||||
$migration = $dbForProject->createDocument('migrations', new Document([
|
||||
'$id' => ID::unique(),
|
||||
'status' => 'pending',
|
||||
'stage' => 'init',
|
||||
'source' => Firebase::getName(),
|
||||
'credentials' => [
|
||||
'serviceAccount' => $serviceAccount,
|
||||
],
|
||||
'resources' => $resources,
|
||||
'statusCounters' => '{}',
|
||||
'resourceData' => '{}',
|
||||
'errors' => [],
|
||||
]));
|
||||
|
||||
$events->setParam('migrationId', $migration->getId());
|
||||
|
||||
// Trigger Transfer
|
||||
$event = new Migration();
|
||||
$event
|
||||
->setMigration($migration)
|
||||
->setProject($project)
|
||||
->setUser($user)
|
||||
->trigger();
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
|
||||
->dynamic($migration, Response::MODEL_MIGRATION);
|
||||
});
|
||||
|
||||
App::post('/v1/migrations/firebase/oauth')
|
||||
->groups(['api', 'migrations'])
|
||||
->desc('Migrate Firebase Data (OAuth)')
|
||||
|
@ -168,8 +118,7 @@ App::post('/v1/migrations/firebase/oauth')
|
|||
Query::equal('userInternalId', [$user->getInternalId()]),
|
||||
]);
|
||||
if ($identity === false || $identity->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR); //TODO: REMOVE
|
||||
// throw new Exception(Exception::USER_IDENTITY_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_IDENTITY_NOT_FOUND);
|
||||
}
|
||||
|
||||
$accessToken = $identity->getAttribute('providerAccessToken');
|
||||
|
@ -213,7 +162,7 @@ App::post('/v1/migrations/firebase/oauth')
|
|||
'stage' => 'init',
|
||||
'source' => Firebase::getName(),
|
||||
'credentials' => [
|
||||
'serviceAccount' => $serviceAccount,
|
||||
'serviceAccount' => json_encode($serviceAccount),
|
||||
],
|
||||
'resources' => $resources,
|
||||
'statusCounters' => '{}',
|
||||
|
@ -224,7 +173,56 @@ App::post('/v1/migrations/firebase/oauth')
|
|||
$events->setParam('migrationId', $migration->getId());
|
||||
|
||||
// Trigger Transfer
|
||||
var_dump($project);
|
||||
$event = new Migration();
|
||||
$event
|
||||
->setMigration($migration)
|
||||
->setProject($project)
|
||||
->setUser($user)
|
||||
->trigger();
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
|
||||
->dynamic($migration, Response::MODEL_MIGRATION);
|
||||
});
|
||||
|
||||
App::post('/v1/migrations/firebase')
|
||||
->groups(['api', 'migrations'])
|
||||
->desc('Migrate Firebase Data (Service Account)')
|
||||
->label('scope', 'migrations.write')
|
||||
->label('event', 'migrations.create')
|
||||
->label('audits.event', 'migration.create')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
|
||||
->label('sdk.namespace', 'migrations')
|
||||
->label('sdk.method', 'createFirebaseMigration')
|
||||
->label('sdk.description', '/docs/references/migrations/migration-firebase.md')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_MIGRATION)
|
||||
->param('resources', [], new ArrayList(new WhiteList(Firebase::getSupportedResources())), 'List of resources to migrate')
|
||||
->param('serviceAccount', '', new Text(65536), 'JSON of the Firebase service account credentials')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('user')
|
||||
->inject('events')
|
||||
->action(function (array $resources, string $serviceAccount, Response $response, Database $dbForProject, Document $project, Document $user, Event $events) {
|
||||
$migration = $dbForProject->createDocument('migrations', new Document([
|
||||
'$id' => ID::unique(),
|
||||
'status' => 'pending',
|
||||
'stage' => 'init',
|
||||
'source' => Firebase::getName(),
|
||||
'credentials' => [
|
||||
'serviceAccount' => $serviceAccount,
|
||||
],
|
||||
'resources' => $resources,
|
||||
'statusCounters' => '{}',
|
||||
'resourceData' => '{}',
|
||||
'errors' => [],
|
||||
]));
|
||||
|
||||
$events->setParam('migrationId', $migration->getId());
|
||||
|
||||
// Trigger Transfer
|
||||
$event = new Migration();
|
||||
$event
|
||||
->setMigration($migration)
|
||||
|
@ -515,8 +513,7 @@ App::get('/v1/migrations/firebase/report/oauth')
|
|||
Query::equal('userInternalId', [$user->getInternalId()]),
|
||||
]);
|
||||
if ($identity === false || $identity->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR); //TODO: REMOVE
|
||||
// throw new Exception(Exception::USER_IDENTITY_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_IDENTITY_NOT_FOUND);
|
||||
}
|
||||
|
||||
$accessToken = $identity->getAttribute('providerAccessToken');
|
||||
|
@ -749,7 +746,7 @@ App::get('/v1/migrations/firebase/projects')
|
|||
Query::equal('userInternalId', [$user->getInternalId()]),
|
||||
]);
|
||||
if ($identity === false || $identity->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Not authenticated with Firebase'); //TODO: Replace with USER_IDENTITY_NOT_FOUND
|
||||
throw new Exception(Exception::USER_IDENTITY_NOT_FOUND);
|
||||
}
|
||||
|
||||
$accessToken = $identity->getAttribute('providerAccessToken');
|
||||
|
@ -766,7 +763,11 @@ App::get('/v1/migrations/firebase/projects')
|
|||
|
||||
$isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now');
|
||||
if ($isExpired) {
|
||||
$firebase->refreshTokens($refreshToken);
|
||||
try {
|
||||
$firebase->refreshTokens($refreshToken);
|
||||
} catch (\Exception $e) {
|
||||
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Failed to refresh Firebase access token');
|
||||
}
|
||||
|
||||
$accessToken = $firebase->getAccessToken('');
|
||||
$refreshToken = $firebase->getRefreshToken('');
|
||||
|
|
|
@ -5,7 +5,6 @@ use Appwrite\Messaging\Adapter\Realtime;
|
|||
use Appwrite\Permission;
|
||||
use Appwrite\Resque\Worker;
|
||||
use Appwrite\Role;
|
||||
use Appwrite\Utopia\Response\Model\Migration;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
|
@ -61,7 +60,7 @@ class MigrationsV1 extends Worker
|
|||
return;
|
||||
}
|
||||
|
||||
$this->dbForProject = $this->getProjectDB($this->args['project']['$id']);
|
||||
$this->dbForProject = $this->getProjectDB(new Document($this->args['project']));
|
||||
|
||||
$this->processMigration();
|
||||
}
|
||||
|
|
|
@ -618,6 +618,11 @@ services:
|
|||
- _APP_LOGGING_CONFIG
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||
- _APP_CONNECTIONS_DB_PROJECT
|
||||
- _APP_CONNECTIONS_DB_CONSOLE
|
||||
- _APP_CONNECTIONS_CACHE
|
||||
- _APP_CONNECTIONS_QUEUE
|
||||
- _APP_CONNECTIONS_PUBSUB
|
||||
|
||||
appwrite-maintenance:
|
||||
entrypoint: maintenance
|
||||
|
|
|
@ -87,7 +87,7 @@ class Firebase extends OAuth2
|
|||
{
|
||||
$response = $this->request(
|
||||
'POST',
|
||||
'https://github.com/login/oauth/access_token',
|
||||
'https://oauth2.googleapis.com/token',
|
||||
[],
|
||||
\http_build_query([
|
||||
'client_id' => $this->appID,
|
||||
|
@ -195,12 +195,47 @@ class Firebase extends OAuth2
|
|||
return $projects['results'];
|
||||
}
|
||||
|
||||
public function createServiceAccount(string $accessToken, string $projectID): array
|
||||
/*
|
||||
Be careful with the setIAMPolicy method, it will overwrite all existing policies
|
||||
**/
|
||||
public function assignIAMRoles(string $accessToken, string $email, string $projectId) {
|
||||
// Get IAM Roles
|
||||
$iamRoles = $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/'.$projectId.':getIamPolicy', [
|
||||
'Authorization: Bearer ' . \urlencode($accessToken),
|
||||
'Content-Type: application/json'
|
||||
]);
|
||||
|
||||
$iamRoles = \json_decode($iamRoles, true);
|
||||
|
||||
$iamRoles['bindings'][] = [
|
||||
'role' => 'roles/identitytoolkit.admin',
|
||||
'members' => [
|
||||
'serviceAccount:'.$email
|
||||
]
|
||||
];
|
||||
|
||||
$iamRoles['bindings'][] = [
|
||||
'role' => 'roles/firebase.admin',
|
||||
'members' => [
|
||||
'serviceAccount:'.$email
|
||||
]
|
||||
];
|
||||
|
||||
// Set IAM Roles
|
||||
$this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/'.$projectId.':setIamPolicy', [
|
||||
'Authorization: Bearer ' . \urlencode($accessToken),
|
||||
'Content-Type: application/json'
|
||||
], json_encode([
|
||||
'policy' => $iamRoles
|
||||
]));
|
||||
}
|
||||
|
||||
public function createServiceAccount(string $accessToken, string $projectId): array
|
||||
{
|
||||
// Create Service Account
|
||||
$response = $this->request(
|
||||
'POST',
|
||||
'https://iam.googleapis.com/v1/projects/' . $projectID . '/serviceAccounts',
|
||||
'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts',
|
||||
[
|
||||
'Authorization: Bearer ' . \urlencode($accessToken),
|
||||
'Content-Type: application/json'
|
||||
|
@ -215,10 +250,12 @@ class Firebase extends OAuth2
|
|||
|
||||
$response = json_decode($response, true);
|
||||
|
||||
$this->assignIAMRoles($accessToken, $response['email'], $projectId);
|
||||
|
||||
// Create Service Account Key
|
||||
$responseKey = $this->request(
|
||||
'POST',
|
||||
'https://iam.googleapis.com/v1/projects/' . $projectID . '/serviceAccounts/' . $response['email'] . '/keys',
|
||||
'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts/' . $response['email'] . '/keys',
|
||||
[
|
||||
'Authorization: Bearer ' . \urlencode($accessToken),
|
||||
'Content-Type: application/json'
|
||||
|
|
Loading…
Reference in a new issue