Merge pull request #1644 from akhilmhdh/chore/aws-ssm-api

AWS SSM integration api documentation
This commit is contained in:
Maidul Islam
2024-04-02 09:22:50 -07:00
committed by GitHub
13 changed files with 329 additions and 72 deletions

View File

@ -479,3 +479,74 @@ export const PROJECT_USER_ADDITIONAL_PRIVILEGE = {
projectMembershipId: "Project membership id of user"
}
};
export const INTEGRATION_AUTH = {
GET: {
integrationAuthId: "The id of integration authentication object."
},
DELETE: {
integration: "The slug of the integration to be unauthorized.",
projectId: "The ID of the project to delete the integration auth from."
},
DELETE_BY_ID: {
integrationAuthId: "The id of integration authentication object to delete."
},
CREATE_ACCESS_TOKEN: {
workspaceId: "The ID of the project to create the integration auth for.",
integration: "The slug of integration for the auth object.",
accessId: "The unique authorized access id of the external integration provider.",
accessToken: "The unique authorized access token of the external integration provider.",
url: "",
namespace: "",
refreshToken: "The refresh token for integration authorization."
},
LIST_AUTHORIZATION: {
workspaceId: "The ID of the project to list integration auths for."
}
};
export const INTEGRATION = {
CREATE: {
integrationAuthId: "The ID of the integration auth object to link with integration.",
app: "The name of the external integration providers app entity that you want to sync secrets with. Used in Netlify, GitHub, Vercel integrations.",
isActive: "Whether the integration should be active or disabled.",
appId:
"The ID of the external integration providers app entity that you want to sync secrets with. Used in Netlify, GitHub, Vercel integrations.",
secretPath: "The path of the secrets to sync secrets from.",
sourceEnvironment: "The environment to sync secret from.",
targetEnvironment:
"The target environment of the integration provider. Used in cloudflare pages, TeamCity, Gitlab integrations.",
targetEnvironmentId:
"The target environment id of the integration provider. Used in cloudflare pages, teamcity, gitlab integrations.",
targetService:
"The service based grouping identifier of the external provider. Used in Terraform cloud, Checkly, Railway and NorthFlank",
targetServiceId:
"The service based grouping identifier ID of the external provider. Used in Terraform cloud, Checkly, Railway and NorthFlank",
owner: "External integration providers service entity owner. Used in Github.",
path: "Path to save the synced secrets. Used by Gitlab, AWS Parameter Store, Vault",
region: "AWS region to sync secrets to.",
scope: "Scope of the provider. Used by Github, Qovery",
metadata: {
secretPrefix: "The prefix for the saved secret. Used by GCP",
secretSuffix: "The suffix for the saved secret. Used by GCP",
initialSyncBehavoir: "Type of syncing behavoir with the integration",
shouldAutoRedeploy: "Used by Render to trigger auto deploy",
secretGCPLabel: "The label for the GCP secrets"
}
},
UPDATE: {
integrationId: "The ID of the integration object.",
app: "The name of the external integration providers app entity that you want to sync secrets with. Used in Netlify, GitHub, Vercel integrations.",
appId:
"The ID of the external integration providers app entity that you want to sync secrets with. Used in Netlify, GitHub, Vercel integrations.",
isActive: "Whether the integration should be active or disabled.",
secretPath: "The path of the secrets to sync secrets from.",
owner: "External integration providers service entity owner. Used in Github.",
targetEnvironment:
"The target environment of the integration provider. Used in cloudflare pages, TeamCity, Gitlab integrations.",
environment: "The environment to sync secrets from."
},
DELETE: {
integrationId: "The ID of the integration object."
}
};

View File

@ -1,6 +1,7 @@
import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { INTEGRATION_AUTH } from "@app/lib/api-docs";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -10,8 +11,14 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
server.route({
url: "/integration-options",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "List of integrations available.",
security: [
{
bearerAuth: []
}
],
response: {
200: z.object({
integrationOptions: z
@ -38,10 +45,16 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
server.route({
url: "/:integrationAuthId",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Get details of an integration authorization by auth object id.",
security: [
{
bearerAuth: []
}
],
params: z.object({
integrationAuthId: z.string().trim()
integrationAuthId: z.string().trim().describe(INTEGRATION_AUTH.GET.integrationAuthId)
}),
response: {
200: z.object({
@ -64,11 +77,17 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
server.route({
url: "/",
method: "DELETE",
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Remove all integration's auth object from the project.",
security: [
{
bearerAuth: []
}
],
querystring: z.object({
integration: z.string().trim(),
projectId: z.string().trim()
integration: z.string().trim().describe(INTEGRATION_AUTH.DELETE.integration),
projectId: z.string().trim().describe(INTEGRATION_AUTH.DELETE.projectId)
}),
response: {
200: z.object({
@ -104,10 +123,16 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
server.route({
url: "/:integrationAuthId",
method: "DELETE",
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Remove an integration auth object by object id.",
security: [
{
bearerAuth: []
}
],
params: z.object({
integrationAuthId: z.string().trim()
integrationAuthId: z.string().trim().describe(INTEGRATION_AUTH.DELETE_BY_ID.integrationAuthId)
}),
response: {
200: z.object({
@ -183,16 +208,22 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
server.route({
url: "/access-token",
method: "POST",
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Create the integration authentication object required for syncing secrets.",
security: [
{
bearerAuth: []
}
],
body: z.object({
workspaceId: z.string().trim(),
integration: z.string().trim(),
accessId: z.string().trim().optional(),
accessToken: z.string().trim().optional(),
url: z.string().url().trim().optional(),
namespace: z.string().trim().optional(),
refreshToken: z.string().trim().optional()
workspaceId: z.string().trim().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.workspaceId),
integration: z.string().trim().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.integration),
accessId: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.accessId),
accessToken: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.accessToken),
url: z.string().url().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.url),
namespace: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.namespace),
refreshToken: z.string().trim().optional().describe(INTEGRATION_AUTH.CREATE_ACCESS_TOKEN.refreshToken)
}),
response: {
200: z.object({

View File

@ -2,6 +2,7 @@ import { z } from "zod";
import { IntegrationsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { INTEGRATION } from "@app/lib/api-docs";
import { removeTrailingSlash, shake } from "@app/lib/fn";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -13,33 +14,45 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
url: "/",
method: "POST",
schema: {
description: "Create an integration to sync secrets.",
security: [
{
bearerAuth: []
}
],
body: z.object({
integrationAuthId: z.string().trim(),
app: z.string().trim().optional(),
isActive: z.boolean(),
appId: z.string().trim().optional(),
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
sourceEnvironment: z.string().trim(),
targetEnvironment: z.string().trim().optional(),
targetEnvironmentId: z.string().trim().optional(),
targetService: z.string().trim().optional(),
targetServiceId: z.string().trim().optional(),
owner: z.string().trim().optional(),
path: z.string().trim().optional(),
region: z.string().trim().optional(),
scope: z.string().trim().optional(),
integrationAuthId: z.string().trim().describe(INTEGRATION.CREATE.integrationAuthId),
app: z.string().trim().optional().describe(INTEGRATION.CREATE.app),
isActive: z.boolean().describe(INTEGRATION.CREATE.isActive).default(true),
appId: z.string().trim().optional().describe(INTEGRATION.CREATE.appId),
secretPath: z
.string()
.trim()
.default("/")
.transform(removeTrailingSlash)
.describe(INTEGRATION.CREATE.secretPath),
sourceEnvironment: z.string().trim().describe(INTEGRATION.CREATE.sourceEnvironment),
targetEnvironment: z.string().trim().optional().describe(INTEGRATION.CREATE.targetEnvironment),
targetEnvironmentId: z.string().trim().optional().describe(INTEGRATION.CREATE.targetEnvironmentId),
targetService: z.string().trim().optional().describe(INTEGRATION.CREATE.targetService),
targetServiceId: z.string().trim().optional().describe(INTEGRATION.CREATE.targetServiceId),
owner: z.string().trim().optional().describe(INTEGRATION.CREATE.owner),
path: z.string().trim().optional().describe(INTEGRATION.CREATE.path),
region: z.string().trim().optional().describe(INTEGRATION.CREATE.region),
scope: z.string().trim().optional().describe(INTEGRATION.CREATE.scope),
metadata: z
.object({
secretPrefix: z.string().optional(),
secretSuffix: z.string().optional(),
initialSyncBehavior: z.string().optional(),
shouldAutoRedeploy: z.boolean().optional(),
secretPrefix: z.string().optional().describe(INTEGRATION.CREATE.metadata.secretPrefix),
secretSuffix: z.string().optional().describe(INTEGRATION.CREATE.metadata.secretSuffix),
initialSyncBehavior: z.string().optional().describe(INTEGRATION.CREATE.metadata.initialSyncBehavoir),
shouldAutoRedeploy: z.boolean().optional().describe(INTEGRATION.CREATE.metadata.shouldAutoRedeploy),
secretGCPLabel: z
.object({
labelName: z.string(),
labelValue: z.string()
})
.optional()
.describe(INTEGRATION.CREATE.metadata.secretGCPLabel)
})
.optional()
}),
@ -49,7 +62,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const { integration, integrationAuth } = await server.services.integration.createIntegration({
actorId: req.permission.id,
@ -102,17 +115,28 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
url: "/:integrationId",
method: "PATCH",
schema: {
description: "Update an integration by integration id",
security: [
{
bearerAuth: []
}
],
params: z.object({
integrationId: z.string().trim()
integrationId: z.string().trim().describe(INTEGRATION.UPDATE.integrationId)
}),
body: z.object({
app: z.string().trim(),
appId: z.string().trim(),
isActive: z.boolean(),
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
targetEnvironment: z.string().trim(),
owner: z.string().trim(),
environment: z.string().trim()
app: z.string().trim().describe(INTEGRATION.UPDATE.app),
appId: z.string().trim().describe(INTEGRATION.UPDATE.appId),
isActive: z.boolean().describe(INTEGRATION.UPDATE.isActive),
secretPath: z
.string()
.trim()
.default("/")
.transform(removeTrailingSlash)
.describe(INTEGRATION.UPDATE.secretPath),
targetEnvironment: z.string().trim().describe(INTEGRATION.UPDATE.targetEnvironment),
owner: z.string().trim().describe(INTEGRATION.UPDATE.owner),
environment: z.string().trim().describe(INTEGRATION.UPDATE.environment)
}),
response: {
200: z.object({
@ -120,7 +144,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const integration = await server.services.integration.updateIntegration({
actorId: req.permission.id,
@ -138,8 +162,14 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
url: "/:integrationId",
method: "DELETE",
schema: {
description: "Remove an integration using the integration object ID",
security: [
{
bearerAuth: []
}
],
params: z.object({
integrationId: z.string().trim()
integrationId: z.string().trim().describe(INTEGRATION.DELETE.integrationId)
}),
response: {
200: z.object({
@ -147,7 +177,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const integration = await server.services.integration.deleteIntegration({
actorId: req.permission.id,

View File

@ -7,7 +7,7 @@ import {
UserEncryptionKeysSchema,
UsersSchema
} from "@app/db/schemas";
import { PROJECTS } from "@app/lib/api-docs";
import { INTEGRATION_AUTH, PROJECTS } from "@app/lib/api-docs";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { ProjectFilterType } from "@app/services/project/project-types";
@ -332,8 +332,14 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
url: "/:workspaceId/authorizations",
method: "GET",
schema: {
description: "List integration auth objects for a workspace.",
security: [
{
bearerAuth: []
}
],
params: z.object({
workspaceId: z.string().trim()
workspaceId: z.string().trim().describe(INTEGRATION_AUTH.LIST_AUTHORIZATION.workspaceId)
}),
response: {
200: z.object({
@ -341,7 +347,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const authorizations = await server.services.integrationAuth.listIntegrationAuthByProjectId({
actorId: req.permission.id,

View File

@ -0,0 +1,32 @@
---
title: "Create Auth"
openapi: "POST /api/v1/integration-auth/access-token"
---
## Integration Authentication Parameters
The integration authentication endpoint is generic and can be used for all native integrations.
For specific integration parameters for a given service, please review the respective documentation below.
<Tabs>
<Tab title="AWS Secrets manager">
<ParamField body="integration" type="string" initialValue="aws-secret-manager" required>
This value must be **aws-secret-manager**.
</ParamField>
<ParamField body="workspaceId" type="string" required>
Infisical project id for the integration.
</ParamField>
<ParamField body="accessId" type="string" required>
The AWS IAM User Access ID.
</ParamField>
<ParamField body="accessToken" type="string" required>
The AWS IAM User Access Secret Key.
</ParamField>
</Tab>
<Tab title="GCP Secrets manager">
Coming Soon
</Tab>
<Tab title="Heroku">
Coming Soon
</Tab>
</Tabs>

View File

@ -0,0 +1,40 @@
---
title: "Create"
openapi: "POST /api/v1/integration"
---
## Integration Parameters
The integration creation endpoint is generic and can be used for all native integrations.
For specific integration parameters for a given service, please review the respective documentation below.
<Tabs>
<Tab title="AWS Secrets manager">
<ParamField body="integrationAuthId" type="string" required>
The ID of the integration auth object for authentication with AWS.
Refer [Create Integration Auth](./create-auth) for more info
</ParamField>
<ParamField body="isActive" type="boolean">
Whether the integration should be active or inactive
</ParamField>
<ParamField body="app" type="string" required>
The secret name used when saving secret in AWS SSM. Used for naming and can be arbitrary.
</ParamField>
<ParamField body="region" type="string" required>
The AWS region of the SSM. Example: `us-east-1`
</ParamField>
<ParamField body="sourceEnvironment" type="string" required>
The Infisical environment slug from where secrets will be synced from. Example: `dev`
</ParamField>
<ParamField body="secretPath" type="string" required>
The Infisical folder path from where secrets will be synced from. Example: `/some/path`. The root of the environment is `/`.
</ParamField>
</Tab>
<Tab title="GCP Secrets manager">
Coming Soon
</Tab>
<Tab title="Heroku">
Coming Soon
</Tab>
</Tabs>

View File

@ -0,0 +1,4 @@
---
title: "Delete Auth By ID"
openapi: "DELETE /api/v1/integration-auth/{integrationAuthId}"
---

View File

@ -0,0 +1,4 @@
---
title: "Delete Auth"
openapi: "DELETE /api/v1/integration-auth"
---

View File

@ -0,0 +1,4 @@
---
title: "Delete"
openapi: "DELETE /api/v1/integration/{integrationId}"
---

View File

@ -0,0 +1,4 @@
---
title: "Get Auth By ID"
openapi: "GET /api/v1/integration-auth/{integrationAuthId}"
---

View File

@ -0,0 +1,4 @@
---
title: "List Auth"
openapi: "GET /api/v1/workspace/{workspaceId}/authorizations"
---

View File

@ -0,0 +1,4 @@
---
title: "Update"
openapi: "PATCH /api/v1/integration/{integrationId}"
---

View File

@ -1,6 +1,6 @@
{
"name": "Infisical",
"openapi": "https://app.infisical.com/api/docs/json",
"openapi": "http://localhost:8080/api/docs/json",
"logo": {
"dark": "/logo/dark.svg",
"light": "/logo/light.svg",
@ -32,7 +32,10 @@
"thumbsRating": true
},
"api": {
"baseUrl": ["https://app.infisical.com", "http://localhost:8080"]
"baseUrl": [
"https://app.infisical.com",
"http://localhost:8080"
]
},
"topbarLinks": [
{
@ -279,7 +282,7 @@
"integrations/cloud/azure-key-vault",
"integrations/cloud/gcp-secret-manager",
{
"group": "Cloudflare",
"group": "Cloudflare",
"pages": [
"integrations/cloud/cloudflare-pages",
"integrations/cloud/cloudflare-workers"
@ -356,14 +359,16 @@
},
{
"group": "Build Tool Integrations",
"pages": ["integrations/build-tools/gradle"]
"pages": [
"integrations/build-tools/gradle"
]
},
{
"group": "",
"pages": [
"sdks/overview"
]
},
},
{
"group": "SDK's",
"pages": [
@ -494,13 +499,30 @@
"api-reference/endpoints/secret-imports/delete"
]
},
{
"group": "Integrations",
"pages": [
"api-reference/endpoints/integrations/create-auth",
"api-reference/endpoints/integrations/list-auth",
"api-reference/endpoints/integrations/find-auth",
"api-reference/endpoints/integrations/delete-auth",
"api-reference/endpoints/integrations/delete-auth-by-id",
"api-reference/endpoints/integrations/create",
"api-reference/endpoints/integrations/update",
"api-reference/endpoints/integrations/delete"
]
},
{
"group": "Service Tokens",
"pages": ["api-reference/endpoints/service-tokens/get"]
"pages": [
"api-reference/endpoints/service-tokens/get"
]
},
{
"group": "Audit Logs",
"pages": ["api-reference/endpoints/audit-logs/export-audit-log"]
"pages": [
"api-reference/endpoints/audit-logs/export-audit-log"
]
}
]
},
@ -516,21 +538,22 @@
},
{
"group": "",
"pages": ["changelog/overview"]
"pages": [
"changelog/overview"
]
},
{
"group": "Contributing",
"pages": [
{
"group": "Getting Started",
"pages": [
"contributing/getting-started/overview",
"contributing/getting-started/code-of-conduct",
"contributing/getting-started/pull-requests",
"contributing/getting-started/faq"
]
},
{
"group": "Getting Started",
"pages": [
"contributing/getting-started/overview",
"contributing/getting-started/code-of-conduct",
"contributing/getting-started/pull-requests",
"contributing/getting-started/faq"
]
},
{
"group": "Contributing to platform",
"pages": [
@ -540,11 +563,11 @@
]
},
{
"group": "Contributing to SDK",
"pages": [
"contributing/sdk/developing"
]
}
"group": "Contributing to SDK",
"pages": [
"contributing/sdk/developing"
]
}
]
}
],