-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Seed poc #1626
base: feature/seed-poc
Are you sure you want to change the base?
Seed poc #1626
Changes from 13 commits
e2cdecb
aad3252
46aa201
4c956d3
61da3d0
2cbda4b
21f06f5
a9ce68d
1be2a32
8836481
f89808e
29cc5e0
a89d173
b7b1299
ffeffdc
8d6b8d9
22d3b93
251d1d8
edfe052
e1832ca
2729dbc
edb7b50
5b45403
773760a
0c7173e
09b6d5a
ee0c527
bb9ae3a
1c00a42
a04c7a9
86d8983
e383500
5d12b6b
6b0e84e
21e0edb
e576c28
b3ec956
d40d6a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Be very careful editing this file. It is crafted to work around [this issue](https://github.com/npm/npm/issues/4479) | ||
|
||
# First ignore everything | ||
**/* | ||
|
||
# Then add back in transpiled js and ts declaration files | ||
!lib/**/*.js | ||
!lib/**/*.d.ts | ||
|
||
# Then ignore test js and ts declaration files | ||
*.test.js | ||
*.test.d.ts | ||
|
||
# This leaves us with including only js and ts declaration files of functional code |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
## API Report File for "@aws-amplify/backend-seed" | ||
|
||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). | ||
|
||
```ts | ||
|
||
// @public (undocumented) | ||
export const defineSeed: (seedFunction: SeedFunction) => void; | ||
|
||
// @public (undocumented) | ||
export type SeedFunction = () => Promise<void>; | ||
|
||
// (No @packageDocumentation comment for this package) | ||
|
||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Description | ||
|
||
Replace with a description of this package |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "../../api-extractor.base.json" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"name": "@aws-amplify/backend-seed", | ||
"version": "0.1.0", | ||
"type": "module", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"exports": { | ||
".": { | ||
"types": "./lib/index.d.ts", | ||
"import": "./lib/index.js", | ||
"require": "./lib/index.js" | ||
} | ||
}, | ||
"types": "lib/index.d.ts", | ||
"scripts": { | ||
"update:api": "api-extractor run --local" | ||
}, | ||
"license": "Apache-2.0", | ||
"dependencies": { | ||
"@aws-amplify/client-config": "^1.0.3", | ||
"@aws-amplify/platform-core": "^1.0.1", | ||
"@aws-sdk/client-cognito-identity-provider": "^3.465.0", | ||
"aws-amplify": "^6.2.0", | ||
"semver": "^7.5.4" | ||
}, | ||
"peerDependencies": { | ||
"@aws-amplify/api-graphql": "^4.1.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/** | ||
* Example usage: | ||
* const myLock = new AsyncLock(); | ||
* | ||
* async function asyncFunction() { | ||
* await myLock.acquire(); | ||
* try { | ||
* // Code that requires exclusive access to a shared resource | ||
* console.log('Accessing shared resource...'); | ||
* await someAsyncOperation(); | ||
* } finally { | ||
* myLock.release(); | ||
* } | ||
* } | ||
* | ||
* asyncFunction(); | ||
*/ | ||
// TODO this is a copy for the POC purposes. | ||
export class AsyncLock { | ||
private isLocked: boolean; | ||
private readonly queue: Array<(value?: never) => void>; | ||
|
||
/** | ||
* Creates async lock. | ||
*/ | ||
constructor(private readonly defaultTimeoutMs?: number) { | ||
this.isLocked = false; | ||
this.queue = []; | ||
} | ||
|
||
acquire = async (timeoutMs?: number): Promise<void> => { | ||
const lockPromise = new Promise<void>((resolve) => { | ||
if (!this.isLocked) { | ||
this.isLocked = true; | ||
resolve(); | ||
} else { | ||
this.queue.push(resolve); | ||
} | ||
}); | ||
timeoutMs = timeoutMs ?? this.defaultTimeoutMs; | ||
if (timeoutMs) { | ||
const timeoutPromise = new Promise<void>((resolve, reject) => | ||
setTimeout( | ||
() => | ||
reject( | ||
new Error(`Unable to acquire async lock in ${timeoutMs}ms.`) | ||
), | ||
timeoutMs | ||
) | ||
); | ||
return Promise.race<void>([lockPromise, timeoutPromise]); | ||
} | ||
return lockPromise; | ||
}; | ||
|
||
release = (): void => { | ||
const resolve = this.queue.shift(); | ||
if (resolve) { | ||
resolve(); | ||
} else { | ||
this.isLocked = false; | ||
} | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,97 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { AsyncLock } from './async_lock.js'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { AuthClient, AuthUser } from './types.js'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AdminCreateUserCommand, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CognitoIdentityProviderClient, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} from '@aws-sdk/client-cognito-identity-provider'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { randomUUID } from 'node:crypto'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { ClientConfigVersionTemplateType } from '@aws-amplify/client-config'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import * as auth from 'aws-amplify/auth'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import assert from 'assert'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { SemVer } from 'semver'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import crypto from 'node:crypto'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// TODO: this is a work around | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// it seems like as of amplify v6 , some of the code only runs in the browser ... | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// see https://github.com/aws-amplify/amplify-js/issues/12751 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (process.versions.node) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// node >= 20 now exposes crypto by default. This workaround is not needed: https://github.com/nodejs/node/pull/42083 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (new SemVer(process.versions.node).major < 20) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// @ts-expect-error altering typing for global to make compiler happy is not worth the effort assuming this is temporary workaround | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalThis.crypto = crypto; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export class DefaultAuthClient implements AuthClient { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/** | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* Asynchronous lock is used to assure that all calls to Amplify JS library are | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* made in single transaction. This is because that library maintains global state, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* for example auth session. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly lock: AsyncLock = new AsyncLock(60 * 1000); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly userPoolId: string; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly userPoolClientId: string; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly identityPoolId: string; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly allowGuestAccess: boolean | undefined; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/** | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* Creates Amplify Auth client. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
constructor( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly cognitoIdentityProviderClient: CognitoIdentityProviderClient, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
authConfig: NonNullable<ClientConfigVersionTemplateType<'1'>['auth']> | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!authConfig.identity_pool_id) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new Error('Client config must have identity pool id.'); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.userPoolId = authConfig.user_pool_id; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.userPoolClientId = authConfig.user_pool_client_id; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.identityPoolId = authConfig.identity_pool_id; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.allowGuestAccess = authConfig.unauthenticated_identities_enabled; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createUser = async ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
username: string, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
password: string | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check failure Code scanning / CodeQL Insecure randomness High
This uses a cryptographically insecure random number generated at
Math.random() Error loading related location Loading This uses a cryptographically insecure random number generated at Math.random() Error loading related location Loading
Copilot Autofix AI 3 months ago To fix the problem, we need to replace the use of
Suggested changeset
1
test-projects/seed-poc3/amplify/seed.ts
Outside changed files
Copilot is powered by AI and may make mistakes. Always verify output.
Refresh and try again.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
): Promise<AuthUser> => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await this.lock.acquire(); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.log(`creating ${username}, ${password}`); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check failure Code scanning / CodeQL Clear-text logging of sensitive information High
This logs sensitive data returned by
an access to password Error loading related location Loading
Copilot Autofix AI 3 months ago To fix the problem, we need to remove the logging of sensitive information such as passwords. Instead of logging the password, we can log a message indicating that a user is being created without including the sensitive details. This way, we maintain the ability to debug and monitor the process without exposing sensitive information.
Suggested changeset
1
packages/backend-seed/src/auth_client.ts
Copilot is powered by AI and may make mistakes. Always verify output.
Refresh and try again.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const temporaryPassword = `Test1@Temp${randomUUID().toString()}`; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await this.cognitoIdentityProviderClient.send( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new AdminCreateUserCommand({ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Username: username, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TemporaryPassword: temporaryPassword, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
UserPoolId: this.userPoolId, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MessageAction: 'SUPPRESS', | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// in case there's already signed user in the session. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await auth.signOut(); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const signInResult = await auth.signIn({ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
username, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
password: temporaryPassword, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert.strictEqual( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
signInResult.nextStep.signInStep, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'CONFIRM_SIGN_IN_WITH_NEW_PASSWORD_REQUIRED' | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await auth.confirmSignIn({ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
challengeResponse: password, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
username, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
password, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} finally { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.log(`user ${username} created`); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.lock.release(); | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { generateClientConfig } from '@aws-amplify/client-config'; | ||
import { SandboxBackendIdResolver } from './sandbox_id_resolver.js'; | ||
import { LocalNamespaceResolver } from './local_namespace_resolver.js'; | ||
import { PackageJsonReader } from '@aws-amplify/platform-core'; | ||
import { Amplify } from 'aws-amplify'; | ||
import { generateClient } from 'aws-amplify/data'; | ||
import { AuthClient, AuthUser, SeedFunction } from './types.js'; | ||
import { DefaultAuthClient } from './auth_client.js'; | ||
import { CognitoIdentityProviderClient } from '@aws-sdk/client-cognito-identity-provider'; | ||
|
||
export { AuthClient, AuthUser, SeedFunction }; | ||
|
||
const seedFunctions: Array<SeedFunction<Record<any, any>>> = []; | ||
Check failure on line 13 in packages/backend-seed/src/index.ts
|
||
|
||
export const defineSeed = <SchemaType extends Record<any, any>>( | ||
Check failure on line 15 in packages/backend-seed/src/index.ts
|
||
seedFunction: SeedFunction<SchemaType> | ||
) => { | ||
seedFunctions.push(seedFunction); | ||
}; | ||
|
||
process.once('beforeExit', async () => { | ||
const backendId = await new SandboxBackendIdResolver( | ||
new LocalNamespaceResolver(new PackageJsonReader()) | ||
).resolve(); | ||
const clientConfig = await generateClientConfig(backendId, '0'); | ||
Amplify.configure(clientConfig); | ||
const dataClient = generateClient<Record<any, any>>(); | ||
const authClient = new DefaultAuthClient( | ||
new CognitoIdentityProviderClient(), | ||
clientConfig['auth'] | ||
); | ||
try { | ||
for (const seedFunction of seedFunctions) { | ||
await seedFunction(dataClient, authClient); | ||
} | ||
} catch (e) { | ||
console.log(e); | ||
} finally { | ||
console.log('after seed functions'); | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { | ||
AmplifyUserError, | ||
PackageJsonReader, | ||
} from '@aws-amplify/platform-core'; | ||
import { EOL } from 'os'; | ||
|
||
// TODO This is copy pasted for the purpose of POC | ||
|
||
export type NamespaceResolver = { | ||
resolve: () => Promise<string>; | ||
}; | ||
|
||
/** | ||
* Reads the local app name from package.json#name in the current directory | ||
*/ | ||
export class LocalNamespaceResolver implements NamespaceResolver { | ||
/** | ||
* packageJsonReader is assigned to an instance member for testing. | ||
* resolve is bound to this so that it can be passed as a function reference | ||
*/ | ||
constructor(private readonly packageJsonReader: PackageJsonReader) {} | ||
|
||
/** | ||
* Returns the value of package.json#name from the current working directory | ||
*/ | ||
resolve = async () => { | ||
const name = this.packageJsonReader.readFromCwd().name; | ||
if (name) return name; | ||
throw new AmplifyUserError('InvalidPackageJsonError', { | ||
message: 'Cannot load name from the package.json', | ||
resolution: `Ensure you are running ampx commands in root of your project (i.e. in the parent of the 'amplify' directory).${EOL}Also ensure that your root package.json file has a "name" field.`, | ||
}); | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { userInfo as _userInfo } from 'os'; | ||
import { BackendIdentifier } from '@aws-amplify/plugin-types'; | ||
import { NamespaceResolver } from "./local_namespace_resolver.js"; | ||
|
||
// TODO This is copy pasted for the purpose of POC | ||
|
||
/** | ||
* Resolves an ID that can be used to uniquely identify sandbox environments | ||
*/ | ||
export class SandboxBackendIdResolver { | ||
/** | ||
* Initialize with an appName resolver | ||
*/ | ||
constructor( | ||
private readonly namespaceResolver: NamespaceResolver, | ||
private readonly userInfo = _userInfo | ||
) {} | ||
|
||
/** | ||
* Returns a concatenation of the resolved appName and the current username | ||
*/ | ||
resolve = async (identifier?: string): Promise<BackendIdentifier> => { | ||
const namespace = await this.namespaceResolver.resolve(); | ||
const name = identifier || this.userInfo().username; | ||
|
||
return { | ||
namespace, | ||
name, | ||
type: 'sandbox', | ||
}; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { V6Client } from '@aws-amplify/api-graphql'; | ||
|
||
// TODO is there a better way to bring in schema typings? It must come from customer project. | ||
export type SeedFunction<SchemaType extends Record<any, any>> = ( | ||
// TODO how can data client dynamically typed here? | ||
dataClient: V6Client<SchemaType>, | ||
authClient: AuthClient | ||
) => Promise<void>; | ||
|
||
export type AuthUser = { | ||
username: string; | ||
password: string; | ||
}; | ||
|
||
export type AuthClient = { | ||
createUser: (username: string, password: string) => Promise<AuthUser>; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"extends": "../../tsconfig.base.json", | ||
"compilerOptions": { "rootDir": "src", "outDir": "lib" }, | ||
"references": [{ "path": "../client-config" }, { "path": "../platform-core" }] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"entryPoints": ["src/index.ts"] | ||
} |
Check failure
Code scanning / CodeQL
Insecure randomness High
Copilot Autofix AI 3 months ago
To fix the problem, we need to replace the use of
Math.random()
with a cryptographically secure random number generator. In Node.js, we can use thecrypto
module'srandomUUID
method to generate secure random values. This method provides a cryptographically secure way to generate random UUIDs, which can be used to create secure usernames and passwords.We will update the
test-projects/seed-poc3/amplify/seed.ts
file to usecrypto.randomUUID()
instead ofMath.random()
for generating random parts of usernames and passwords.