API provider oauth client ids are now separate from the provider package

This commit is contained in:
Matt Aitken
2023-01-14 15:11:13 +00:00
parent 30d6d544c1
commit d6164d601e
7 changed files with 148 additions and 108 deletions
+15 -17
View File
@@ -26,26 +26,24 @@ cd packages/internal-cli
2. Run the script
```bash
pnpm run cli
pnpm run cli <path_to_your_provider_json_file>
```
# Example provider JSON file
```json
{
"github": {
"client_id": "<github client id>"
},
"slack": {
"client_id": "<slack client id>"
}
}
```
# Options
## Environment
`-e` or `--environment`
| Option | Description | Default |
| ------------- | --------------------------- | ------- |
| `development` | The development environment | x |
| `production` | The production environment | |
Example:
```bash
pnpm run cli -e production
```
## Pizzly host
`-p` or `--pizzlyhost`
@@ -56,7 +54,7 @@ Pass the base url for Pizzly, defaults to `http://localhost:3004`.
`-s` or `--pizzlysecretkey`
Pass the secret key for Pizzly, defaults to undefined which will work locally in the default configuration.
Pass the secret key for Pizzly, defaults to undefined which will work locally in the default configuration. In production you will want to set a Pizzly secret key, see their docs for details.
## AWS profile
+117 -74
View File
@@ -10,25 +10,61 @@ import {
} from "@aws-sdk/client-secrets-manager";
import fetch from "node-fetch";
const providersSchema = z.record(
z.string(),
z.object({
client_id: z.string(),
})
);
const program = new Command();
program
.command("update")
.description("Update the catalog")
.option("-e, --environment <environment>", "The environment to update")
.argument(
"<integration_file_path>",
"The file path to the integration file. Probably ../../apps/webapp/integrations.yml"
)
.option("-p, --pizzlyhost <pizzly_host>", "Pizzly host")
.option("-s, --pizzlysecretkey <pizzly_secret_key>", "Pizzly secret key")
.option("-a, --awsprofile <aws_profile>", "AWS profile name")
.action(
async (options: {
environment?: string;
pizzlyhost?: string;
pizzlysecretkey?: string;
awsprofile?: string;
}) => {
const environment = options.environment ?? "development";
const pizzly_host = options.pizzlyhost ?? "http://localhost:3004";
async (
integration_file_path: string,
options: {
pizzlyhost?: string;
pizzlysecretkey?: string;
awsprofile?: string;
}
) => {
if (!integration_file_path) {
console.error(
"Missing integration file path.",
`You need to pass in the path to a JSON file which has this format:
{
"github": {
"client_id": "<your_client_id>"
}
}
`
);
return;
}
const file = fs.readFileSync(integration_file_path, "utf8");
const json = JSON.parse(file);
const result = providersSchema.safeParse(json);
if (!result.success) {
console.error(
`Integration file ${integration_file_path} is in the wrong file format`,
result.error.format()
);
return;
}
const authProviders = result.data;
const pizzly_host = options.pizzlyhost ?? "http://localhost:3004";
const providers = getProviders(true);
const client = new SecretsManagerClient({
@@ -36,74 +72,81 @@ program
credentials: fromIni({ profile: options.awsprofile ?? "default" }),
});
const promises = providers.map(async (integration) => {
if (integration.authentication.type !== "oauth")
return Promise.resolve();
const promises = Object.entries(authProviders).map(
async ([service, authentication]) => {
const environmentClientId = authentication.client_id;
const environmentClientId =
integration.authentication.environments[environment!]?.client_id;
if (!environmentClientId) {
console.log(`No client id for ${integration.slug} in ${environment}`);
console.log("Skipping…");
return Promise.resolve();
}
const secretId = `integrations/${integration.slug}/${environmentClientId}`;
try {
console.log(`Finding secret for id: ${secretId}`);
const response = await client.send(
new GetSecretValueCommand({
SecretId: secretId,
VersionStage: "AWSCURRENT", // VersionStage defaults to AWSCURRENT if unspecified
})
);
const secretData = response.SecretString;
invariant(secretData, `Secret data is missing: ${secretId}`);
const secretObject = JSON.parse(secretData);
const { client_secret } = z
.object({
client_secret: z.string(),
})
.parse(secretObject);
console.log(`Found secret for id: ${secretId}`);
const hasExistingConfig = await hasConfig(
pizzly_host,
integration.slug,
options.pizzlysecretkey
);
if (hasExistingConfig) {
const response = await updateConfig(
pizzly_host,
integration.slug,
environmentClientId,
client_secret,
integration.authentication.scopes,
options.pizzlysecretkey
);
console.log(`Updated config for ${integration.slug}`);
} else {
const response = await createConfig(
pizzly_host,
integration.slug,
environmentClientId,
client_secret,
integration.authentication.scopes,
options.pizzlysecretkey
);
console.log(`Created config for ${integration.slug}`);
if (!environmentClientId) {
console.log(`No client id for ${service}`);
console.log("Skipping…");
return Promise.resolve();
}
const provider = providers.find((p) => p.slug === service);
if (provider?.authentication.type !== "oauth") {
console.log(
`The provider ${service} is the wrong type ${provider?.authentication.type}. Must be oauth`
);
console.log("Skipping…");
return Promise.resolve();
}
const secretId = `integrations/${service}/${environmentClientId}`;
try {
console.log(`Finding secret for id: ${secretId}`);
const response = await client.send(
new GetSecretValueCommand({
SecretId: secretId,
VersionStage: "AWSCURRENT", // VersionStage defaults to AWSCURRENT if unspecified
})
);
const secretData = response.SecretString;
invariant(secretData, `Secret data is missing: ${secretId}`);
const secretObject = JSON.parse(secretData);
const { client_secret } = z
.object({
client_secret: z.string(),
})
.parse(secretObject);
console.log(`Found secret for id: ${secretId}`);
const hasExistingConfig = await hasConfig(
pizzly_host,
service,
options.pizzlysecretkey
);
if (hasExistingConfig) {
const response = await updateConfig(
pizzly_host,
service,
environmentClientId,
client_secret,
provider.authentication.scopes,
options.pizzlysecretkey
);
console.log(`Updated config for ${service}`);
} else {
const response = await createConfig(
pizzly_host,
service,
environmentClientId,
client_secret,
provider.authentication.scopes,
options.pizzlysecretkey
);
console.log(`Created config for ${service}`);
}
} catch (error) {
// For a list of exceptions thrown, see
// https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
throw error;
}
} catch (error) {
// For a list of exceptions thrown, see
// https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
throw error;
}
});
);
await Promise.all(promises);
console.log(`Added ${promises.length} secrets`);
@@ -8,14 +8,6 @@ export const github = {
authentication: {
type: "oauth",
scopes: ["repo"],
environments: {
development: {
client_id: "cd763219ce4005e58c00",
},
production: {
client_id: "98922f3fbb27485bae70",
},
},
},
schemas,
};
@@ -8,14 +8,6 @@ export const slack = {
authentication: {
type: "oauth",
scopes: ["channels:read", "channels:join", "chat:write"],
environments: {
development: {
client_id: "276370297397.4579145654276",
},
production: {
client_id: "276370297397.4639924595715",
},
},
},
schemas,
};
-1
View File
@@ -12,7 +12,6 @@ export type Provider = {
export type OAuthAuthentication = {
type: "oauth";
scopes: string[];
environments: Record<string, { client_id: string }>;
};
export type APIKeyAuthentication = {
+8
View File
@@ -0,0 +1,8 @@
{
"github": {
"client_id": "cd763219ce4005e58c00"
},
"slack": {
"client_id": "276370297397.4579145654276"
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"github": {
"client_id": "98922f3fbb27485bae70"
},
"slack": {
"client_id": "276370297397.4639924595715"
}
}