Skip to content

Commit

Permalink
feat: new security and multi-tenancy (#1993)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavel910 committed Oct 26, 2021
1 parent eff4c33 commit 99ecfca
Show file tree
Hide file tree
Showing 1,184 changed files with 24,608 additions and 14,638 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/nextPush.yml
Expand Up @@ -242,7 +242,7 @@ jobs:
npx create-webiny-project@next test-project
--tag next --no-interactive
--assign-to-yarnrc '{"npmRegistryServer":"http://localhost:4873","unsafeHttpWhitelist":["localhost"]}'
--template-options '{"region":"eu-central-1"}'
--template-options '{"region":"eu-central-1","storageOperations":"ddb-es"}'
e2e-tests:
needs: [cache-keys, verdaccio-publish]
Expand Down Expand Up @@ -299,7 +299,7 @@ jobs:
npx create-webiny-project@next test-project
--tag next --no-interactive
--assign-to-yarnrc '{"npmRegistryServer":"http://localhost:4873","unsafeHttpWhitelist":["localhost"]}'
--template-options '{"region":"eu-central-1"}'
--template-options '{"region":"eu-central-1","storageOperations":"ddb-es"}'
- name: Cache project files
uses: actions/cache@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pullRequests.yml
Expand Up @@ -221,7 +221,7 @@ jobs:
npx create-webiny-project@next test-project
--tag next --no-interactive
--assign-to-yarnrc '{"npmRegistryServer":"http://localhost:4873","unsafeHttpWhitelist":["localhost"]}'
--template-options '{"region":"eu-central-1"}'
--template-options '{"region":"eu-central-1","storageOperations":"ddb-es"}'
- name: Build "api" project application
working-directory: test-project
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/v5Push.yml
Expand Up @@ -249,7 +249,7 @@ jobs:
npx create-webiny-project@next test-project
--tag next --no-interactive
--assign-to-yarnrc '{"npmRegistryServer":"http://localhost:4873","unsafeHttpWhitelist":["localhost"]}'
--template-options '{"region":"eu-central-1"}'
--template-options '{"region":"eu-central-1","storageOperations":"ddb-es"}'
e2e-tests:
needs: [cache-keys, verdaccio-publish]
Expand Down Expand Up @@ -306,7 +306,7 @@ jobs:
npx create-webiny-project@next test-project
--tag next --no-interactive
--assign-to-yarnrc '{"npmRegistryServer":"http://localhost:4873","unsafeHttpWhitelist":["localhost"]}'
--template-options '{"region":"eu-central-1"}'
--template-options '{"region":"eu-central-1","storageOperations":"ddb-es"}'
- name: Cache project files
uses: actions/cache@v2
Expand Down
328 changes: 164 additions & 164 deletions .yarn/releases/yarn-3.0.0.cjs → .yarn/releases/yarn-3.0.2.cjs 100755 → 100644

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .yarnrc.yml
Expand Up @@ -19,4 +19,4 @@ packageExtensions:
peerDependencies:
react-dom: ^16.14.0

yarnPath: .yarn/releases/yarn-3.0.0.cjs
yarnPath: .yarn/releases/yarn-3.0.2.cjs
9 changes: 7 additions & 2 deletions LICENSE
@@ -1,6 +1,11 @@
MIT License
Copyright (c) Webiny Ltd.

Copyright (c) 2018 Webiny
Portions of this software are licensed as follows:

* All content that resides under the "enterprise/" directories of this repository, is licensed under the license defined in their respective "enterprise/LICENSE" file.
* All content that resides under the "packages/" sub-directories of this repository, is licensed under the license defined in their respective "packages/*/LICENSE" file.
* All third party components incorporated into the Webiny Software are licensed under the original license provided by the owner of the applicable component.
* Content outside of the above mentioned directories or restrictions above is available under the "MIT" license as defined below.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
9 changes: 5 additions & 4 deletions api/code/graphql/package.json
Expand Up @@ -6,6 +6,8 @@
"watch": "yarn webiny run watch"
},
"dependencies": {
"@webiny/api-admin-users-cognito": "^5.16.0",
"@webiny/api-admin-users-cognito-so-ddb": "^5.16.0",
"@webiny/api-elasticsearch": "^5.16.0",
"@webiny/api-file-manager": "^5.16.0",
"@webiny/api-file-manager-ddb-es": "^5.16.0",
Expand All @@ -23,11 +25,10 @@
"@webiny/api-page-builder-so-ddb-es": "^5.16.0",
"@webiny/api-prerendering-service": "^5.16.0",
"@webiny/api-security": "^5.16.0",
"@webiny/api-security-admin-users": "^5.16.0",
"@webiny/api-security-admin-users-cognito": "^5.16.0",
"@webiny/api-security-admin-users-so-ddb": "^5.16.0",
"@webiny/api-security-cognito-authentication": "^5.16.0",
"@webiny/api-security-cognito": "^5.16.0",
"@webiny/api-security-so-ddb": "^5.16.0",
"@webiny/api-tenancy": "^5.16.0",
"@webiny/api-tenancy-so-ddb": "^5.16.0",
"@webiny/cli": "^5.16.0",
"@webiny/db-dynamodb": "^5.16.0",
"@webiny/handler": "^5.16.0",
Expand Down
15 changes: 4 additions & 11 deletions api/code/graphql/src/index.ts
Expand Up @@ -4,8 +4,6 @@ import graphqlPlugins from "@webiny/handler-graphql";
import i18nPlugins from "@webiny/api-i18n/graphql";
import i18nDynamoDbStorageOperations from "@webiny/api-i18n-ddb";
import i18nContentPlugins from "@webiny/api-i18n-content/plugins";
import adminUsersPlugins from "@webiny/api-security-admin-users";
import securityAdminUsersDynamoDbStorageOperations from "@webiny/api-security-admin-users-so-ddb";
import pageBuilderPlugins from "@webiny/api-page-builder/graphql";
import pageBuilderDynamoDbElasticsearchPlugins from "@webiny/api-page-builder-so-ddb-es";
import pageBuilderPrerenderingPlugins from "@webiny/api-page-builder/prerendering";
Expand All @@ -21,11 +19,11 @@ import fileManagerDynamoDbElasticStorageOperation from "@webiny/api-file-manager
import logsPlugins from "@webiny/handler-logs";
import fileManagerS3 from "@webiny/api-file-manager-s3";
import { createFormBuilder } from "@webiny/api-form-builder";
import securityPlugins from "./security";
import { createFormBuilderStorageOperations } from "@webiny/api-form-builder-so-ddb-es";
import headlessCmsPlugins from "@webiny/api-headless-cms/plugins";
import headlessCmsDynamoDbElasticStorageOperation from "@webiny/api-headless-cms-ddb-es";
import elasticsearchDataGzipCompression from "@webiny/api-elasticsearch/plugins/GzipCompression";
import { createFormBuilderStorageOperations } from "@webiny/api-form-builder-so-ddb-es";
import securityPlugins from "./security";

// Imports plugins created via scaffolding utilities.
import scaffoldsPlugins from "./plugins/scaffolds";
Expand All @@ -50,17 +48,14 @@ export const handler = createHandler({
elasticSearch(elasticsearchClient),
dbPlugins({
table: process.env.DB_TABLE,
driver: new DynamoDbDriver({
documentClient
})
driver: new DynamoDbDriver({ documentClient })
}),
securityPlugins(),
securityPlugins({ documentClient }),
i18nPlugins(),
i18nDynamoDbStorageOperations(),
i18nContentPlugins(),
fileManagerPlugins(),
fileManagerDynamoDbElasticStorageOperation(),
// Add File storage S3 plugin for API file manager.
fileManagerS3(),
prerenderingServicePlugins({
handlers: {
Expand All @@ -72,8 +67,6 @@ export const handler = createHandler({
}
}
}),
adminUsersPlugins(),
securityAdminUsersDynamoDbStorageOperations(),
pageBuilderPlugins(),
pageBuilderDynamoDbElasticsearchPlugins(),
pageBuilderPrerenderingPlugins(),
Expand Down
96 changes: 57 additions & 39 deletions api/code/graphql/src/security.ts
@@ -1,60 +1,75 @@
import tenancy from "@webiny/api-tenancy";
import security from "@webiny/api-security";
import personalAccessTokenAuthentication from "@webiny/api-security-admin-users/authentication/personalAccessToken";
import apiKeyAuthentication from "@webiny/api-security-admin-users/authentication/apiKey";
import userAuthorization from "@webiny/api-security-admin-users/authorization/user";
import apiKeyAuthorization from "@webiny/api-security-admin-users/authorization/apiKey";
import anonymousAuthorization from "@webiny/api-security-admin-users/authorization/anonymous";
import cognitoAuthentication from "@webiny/api-security-cognito-authentication";
import cognitoIdentityProvider from "@webiny/api-security-admin-users-cognito";
import { createTenancyContext, createTenancyGraphQL } from "@webiny/api-tenancy";
import { createStorageOperations as tenancyStorageOperations } from "@webiny/api-tenancy-so-ddb";
import { createSecurityContext, createSecurityGraphQL } from "@webiny/api-security";
import { createStorageOperations as securityStorageOperations } from "@webiny/api-security-so-ddb";
import { authenticateUsingHttpHeader } from "@webiny/api-security/plugins/authenticateUsingHttpHeader";
import apiKeyAuthentication from "@webiny/api-security/plugins/apiKeyAuthentication";
import apiKeyAuthorization from "@webiny/api-security/plugins/apiKeyAuthorization";
import groupAuthorization from "@webiny/api-security/plugins/groupAuthorization";
import parentTenantGroupAuthorization from "@webiny/api-security/plugins/parentTenantGroupAuthorization";
import cognitoAuthentication from "@webiny/api-security-cognito";
import anonymousAuthorization from "@webiny/api-security/plugins/anonymousAuthorization";
import createAdminUsersApp from "@webiny/api-admin-users-cognito";
import { syncWithCognito } from "@webiny/api-admin-users-cognito/syncWithCognito";
import { createStorageOperations as createAdminUsersStorageOperations } from "@webiny/api-admin-users-cognito-so-ddb";

export default () => [
export default ({ documentClient }) => [
/**
* Security Tenancy API (context, users, groups, tenant links).
* This will setup the complete GraphQL schema to manage users, groups, access tokens,
* and provide you with a TenancyContext to access current Tenant data and DB operations.
* Create Tenancy app in the `context`.
*/
tenancy(),
createTenancyContext({
storageOperations: tenancyStorageOperations({ documentClient })
}),

/**
* Cognito IDP plugin (hooks for User CRUD methods).
* This plugin will perform CRUD operations on Cognito when you do something with the user
* via the UI or API. It's mostly to push changes to Cognito when they happen in your app.
*
* It also extends the GraphQL schema with things like "password", which we don't handle
* natively in our security, but Cognito will handle it for us.
* Expose tenancy GraphQL schema.
*/
cognitoIdentityProvider({
region: process.env.COGNITO_REGION,
userPoolId: process.env.COGNITO_USER_POOL_ID
createTenancyGraphQL(),

/**
* Create Security app in the `context`.
*/
createSecurityContext({
storageOperations: securityStorageOperations({ documentClient })
}),

/**
* Adds a context plugin to process `security-authentication` plugins.
* NOTE: this has to be registered *after* the "tenancy" plugins
* as some of the authentication plugins rely on tenancy context.
* Expose security GraphQL schema.
*/
security(),
createSecurityGraphQL(),

/**
* Authentication plugin for Personal Access Tokens.
* PATs are directly linked to Users. We consider a token to be valid, if we manage to load
* a User who owns this particular token. The "identityType" is important, and it has to match
* the "identityType" configured in the authorization plugin later in this file.
* Create Admin Users app.
*/
personalAccessTokenAuthentication({ identityType: "admin" }),
createAdminUsersApp({
storageOperations: createAdminUsersStorageOperations({ documentClient })
}),

/**
* Authentication plugin for API Keys.
* Sync Admin Users with Cognito User Pool.
*/
syncWithCognito({
region: process.env.COGNITO_REGION,
userPoolId: process.env.COGNITO_USER_POOL_ID
}),

/**
* Perform authentication using the common "Authorization" HTTP header.
* This will fetch the value of the header, and execute the authentication process.
*/
authenticateUsingHttpHeader(),

/**
* API Key authenticator.
* API Keys are a standalone entity, and are not connected to users in any way.
* They identify a project, a 3rd party client, not the user.
* They identify a project, a 3rd party client, not a particular user.
* They are used for programmatic API access, CMS data import/export, etc.
*/
apiKeyAuthentication({ identityType: "api-key" }),

/**
* Cognito authentication plugin.
* This plugin will verify the JWT token against a provided User Pool.
* This plugin will verify the JWT token against the provided User Pool.
*/
cognitoAuthentication({
region: process.env.COGNITO_REGION,
Expand All @@ -69,11 +84,14 @@ export default () => [
apiKeyAuthorization({ identityType: "api-key" }),

/**
* Authorization plugin to load user permissions for requested tenant.
* The authorization will only be performed on identities whose "type" matches
* the provided "identityType".
* Authorization plugin to fetch permissions from a security group associated with the identity.
*/
groupAuthorization({ identityType: "admin" }),

/**
* Authorization plugin to fetch permissions from the parent tenant.
*/
userAuthorization({ identityType: "admin" }),
parentTenantGroupAuthorization({ identityType: "admin" }),

/**
* Authorization plugin to load permissions for anonymous requests.
Expand Down
20 changes: 7 additions & 13 deletions api/code/graphql/tsconfig.json
Expand Up @@ -17,6 +17,9 @@
{
"path": "../../../packages/api-security"
},
{
"path": "../../../packages/api-security-okta"
},
{
"path": "../../../packages/api-i18n-content"
},
Expand All @@ -36,13 +39,10 @@
"path": "../../../packages/api-tenancy"
},
{
"path": "../../../packages/api-security-admin-users"
},
{
"path": "../../../packages/api-security-admin-users-cognito"
"path": "../../../packages/api-admin-users-cognito"
},
{
"path": "../../../packages/api-security-admin-users-so-ddb"
"path": "../../../packages/api-admin-users-cognito-so-ddb"
},
{
"path": "../../../packages/api-headless-cms"
Expand Down Expand Up @@ -156,14 +156,8 @@
"@webiny/api-headless-cms": ["../../../packages/api-headless-cms/src"],
"@webiny/api-headless-cms-ddb-es/*": ["../../../packages/api-headless-cms-ddb-es/src/*"],
"@webiny/api-headless-cms-ddb-es": ["../../../packages/api-headless-cms-ddb-es/src"],
"@webiny/api-security-admin-users/*": ["../../../packages/api-security-admin-users/src/*"],
"@webiny/api-security-admin-users": ["../../../packages/api-security-admin-users/src"],
"@webiny/api-security-admin-users-cognito/*": [
"../../../packages/api-security-admin-users-cognito/src/*"
],
"@webiny/api-security-admin-users-cognito": [
"../../../packages/api-security-admin-users-cognito/src"
],
"@webiny/api-admin-users-cognito/*": ["../../../packages/api-admin-users-cognito/src/*"],
"@webiny/api-admin-users-cognito": ["../../../packages/api-admin-users-cognito/src"],
"@webiny/api-security-cognito-authentication": [
"../../../packages/api-security-cognito-authentication/src"
]
Expand Down
6 changes: 3 additions & 3 deletions api/code/headlessCMS/package.json
Expand Up @@ -13,10 +13,10 @@
"@webiny/api-i18n-content": "^5.16.0",
"@webiny/api-i18n-ddb": "^5.16.0",
"@webiny/api-security": "^5.16.0",
"@webiny/api-security-admin-users": "^5.16.0",
"@webiny/api-security-admin-users-so-ddb": "^5.16.0",
"@webiny/api-security-cognito-authentication": "^5.16.0",
"@webiny/api-security-cognito": "^5.16.0",
"@webiny/api-security-so-ddb": "^5.16.0",
"@webiny/api-tenancy": "^5.16.0",
"@webiny/api-tenancy-so-ddb": "^5.16.0",
"@webiny/cli": "^5.16.0",
"@webiny/db-dynamodb": "^5.16.0",
"@webiny/handler": "^5.16.0",
Expand Down
16 changes: 7 additions & 9 deletions api/code/headlessCMS/src/index.ts
Expand Up @@ -11,36 +11,34 @@ import headlessCmsPlugins from "@webiny/api-headless-cms/content";
import headlessCmsDynamoDbElasticStorageOperation from "@webiny/api-headless-cms-ddb-es";
import securityPlugins from "./security";
import logsPlugins from "@webiny/handler-logs";
import securityAdminUsersDynamoDbStorageOperations from "@webiny/api-security-admin-users-so-ddb";
import elasticsearchDataGzipCompression from "@webiny/api-elasticsearch/plugins/GzipCompression";

// Imports plugins created via scaffolding utilities.
import scaffoldsPlugins from "./plugins/scaffolds";

const debug = process.env.DEBUG === "true";

const documentClient = new DocumentClient({
convertEmptyValues: true,
region: process.env.AWS_REGION
});

export const handler = createHandler({
plugins: [
dynamoDbPlugins(),
logsPlugins(),
elasticSearch({ endpoint: `https://${process.env.ELASTIC_SEARCH_ENDPOINT}` }),
dbPlugins({
table: process.env.DB_TABLE,
driver: new DynamoDbDriver({
documentClient: new DocumentClient({
convertEmptyValues: true,
region: process.env.AWS_REGION
})
})
driver: new DynamoDbDriver({ documentClient })
}),
securityPlugins(),
securityPlugins({ documentClient }),
i18nPlugins(),
i18nDynamoDbStorageOperations(),
i18nContentPlugins(),
headlessCmsPlugins({ debug }),
headlessCmsDynamoDbElasticStorageOperation(),
scaffoldsPlugins(),
securityAdminUsersDynamoDbStorageOperations(),
elasticsearchDataGzipCompression()
],
http: { debug }
Expand Down

0 comments on commit 99ecfca

Please sign in to comment.