diff --git a/backend/spec.json b/backend/spec.json index 83cd44f9e..adb8af411 100644 --- a/backend/spec.json +++ b/backend/spec.json @@ -18,17 +18,68 @@ "paths": { "/api/v1/identities/": { "post": { - "description": "", + "summary": "Create identity", + "description": "Create identity", "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identity": { + "$ref": "#/components/schemas/Identity" + } + }, + "description": "Details of the created identity" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of entity to create", + "example": "development" + }, + "organizationId": { + "type": "string", + "description": "ID of organization where to create identity", + "example": "dev-environment" + }, + "role": { + "type": "string", + "description": "Role to assume for organization membership", + "example": "no-access" + } + }, + "required": [ + "name", + "organizationId", + "role" + ] + } + } } } } }, "/api/v1/identities/{identityId}": { "patch": { - "description": "", + "summary": "Update identity", + "description": "Update identity", "parameters": [ { "name": "identityId", @@ -36,17 +87,58 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of identity to update" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identity": { + "$ref": "#/components/schemas/Identity" + } + }, + "description": "Details of the updated identity" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of entity to update to", + "example": "development" + }, + "role": { + "type": "string", + "description": "Role to update to for organization membership", + "example": "no-access" + } + } + } + } } } }, "delete": { - "description": "", + "summary": "Delete identity", + "description": "Delete identity", "parameters": [ { "name": "identityId", @@ -54,14 +146,33 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of identity" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identity": { + "$ref": "#/components/schemas/Identity" + } + }, + "description": "Details of the deleted identity" + } + } + } } - } + }, + "security": [ + { + "bearerAuth": [] + } + ] } }, "/api/v1/secret/{secretId}/secret-versions": { @@ -1222,17 +1333,57 @@ }, "/api/v1/auth/token/renew": { "post": { - "description": "", + "summary": "Renew access token", + "description": "Renew access token", "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "accessToken": { + "type": "string", + "description": "(Same) Access token after successful renewal" + }, + "expiresIn": { + "type": "number", + "description": "TTL of access token in seconds" + }, + "tokenType": { + "type": "string", + "description": "Type of access token (e.g. Bearer)" + } + }, + "description": "Access token and its details" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "accessToken": { + "type": "string", + "description": "Access token to renew", + "example": "..." + } + } + } + } } } } }, "/api/v1/auth/universal-auth/login": { "post": { - "description": "", + "summary": "Login with Universal Auth", + "description": "Login with Universal Auth", "parameters": [ { "name": "user-agent", @@ -1244,14 +1395,58 @@ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "accessToken": { + "type": "string", + "description": "Access token issued after successful login" + }, + "expiresIn": { + "type": "number", + "description": "TTL of access token in seconds" + }, + "tokenType": { + "type": "string", + "description": "Type of access token (e.g. Bearer)" + } + }, + "description": "Access token and its details" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientId": { + "type": "string", + "description": "Client ID for identity to login with Universal Auth", + "example": "..." + }, + "clientSecret": { + "type": "string", + "description": "Client Secret for identity to login with Universal Auth", + "example": "..." + } + } + } + } } } } }, "/api/v1/auth/universal-auth/identities/{identityId}": { "post": { - "description": "", + "summary": "Attach Universal Auth configuration onto identity", + "description": "Attach Universal Auth configuration onto identity", "parameters": [ { "name": "identityId", @@ -1259,20 +1454,109 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of identity to attach Universal Auth onto" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityUniversalAuth": { + "$ref": "#/components/schemas/IdentityUniversalAuth" + } + }, + "description": "Details of attached Universal Auth" + } + } + } }, "400": { "description": "Bad Request" } + }, + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientSecretTrustedIps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipAddress": { + "type": "string", + "description": "IP address to trust", + "default": "0.0.0.0/0" + } + } + }, + "description": "List of IPs or CIDR ranges that the Client Secret can be used from together with the Client ID to get back an access token. By default, Client Secrets are given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", + "example": "...", + "default": [ + { + "ipAddress": "0.0.0.0/0" + } + ] + }, + "accessTokenTTL": { + "type": "number", + "description": "The incremental lifetime for an acccess token in seconds; a value of 0 implies an infinite incremental lifetime.", + "example": "...", + "default": 100 + }, + "accessTokenMaxTTL": { + "type": "number", + "description": "The maximum lifetime for an acccess token in seconds; a value of 0 implies an infinite maximum lifetime.", + "example": "...", + "default": 2592000 + }, + "accessTokenNumUsesLimit": { + "type": "number", + "description": "The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses.", + "example": "...", + "default": 0 + }, + "accessTokenTrustedIps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipAddress": { + "type": "string", + "description": "IP address to trust", + "default": "0.0.0.0/0" + } + } + }, + "description": "List of IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", + "example": "...", + "default": [ + { + "ipAddress": "0.0.0.0/0" + } + ] + } + } + } + } + } } }, "patch": { - "description": "", + "summary": "Update Universal Auth configuration on identity", + "description": "Update Universal Auth configuration on identity", "parameters": [ { "name": "identityId", @@ -1280,20 +1564,94 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of identity to update Universal Auth on" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityUniversalAuth": { + "$ref": "#/components/schemas/IdentityUniversalAuth" + } + }, + "description": "Details of updated Universal Auth" + } + } + } }, "400": { "description": "Bad Request" } + }, + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientSecretTrustedIps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipAddress": { + "type": "string", + "description": "IP address to trust" + } + } + }, + "description": "List of IPs or CIDR ranges that the Client Secret can be used from together with the Client ID to get back an access token. By default, Client Secrets are given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", + "example": "..." + }, + "accessTokenTTL": { + "type": "number", + "description": "The incremental lifetime for an acccess token in seconds; a value of 0 implies an infinite incremental lifetime.", + "example": "..." + }, + "accessTokenMaxTTL": { + "type": "number", + "description": "The maximum lifetime for an acccess token in seconds; a value of 0 implies an infinite maximum lifetime.", + "example": "..." + }, + "accessTokenNumUsesLimit": { + "type": "number", + "description": "The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses.", + "example": "..." + }, + "accessTokenTrustedIps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipAddress": { + "type": "string", + "description": "IP address to trust" + } + } + }, + "description": "List of IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", + "example": "..." + } + } + } + } + } } }, "get": { - "description": "", + "summary": "Retrieve Universal Auth configuration on identity", + "description": "Retrieve Universal Auth configuration on identity", "parameters": [ { "name": "identityId", @@ -1301,19 +1659,39 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of identity to retrieve Universal Auth on" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityUniversalAuth": { + "$ref": "#/components/schemas/IdentityUniversalAuth" + } + }, + "description": "Details of retrieved Universal Auth" + } + } + } } - } + }, + "security": [ + { + "bearerAuth": [] + } + ] } }, "/api/v1/auth/universal-auth/identities/{identityId}/client-secrets": { "post": { - "description": "", + "summary": "Create Universal Auth Client Secret for identity", + "description": "Create Universal Auth Client Secret for identity", "parameters": [ { "name": "identityId", @@ -1321,17 +1699,69 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of identity to create Universal Auth Client Secret for" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientSecret": { + "type": "string", + "description": "The created Client Secret" + }, + "clientSecretData": { + "$ref": "#/components/schemas/IdentityUniversalAuthClientSecretData" + } + }, + "description": "Details of the created Client Secret" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "A description for the Client Secret to create.", + "example": "..." + }, + "ttl": { + "type": "number", + "description": "The time-to-live for the Client Secret to create. By default, the TTL will be set to 0 which implies that the Client Secret will never expire; a value of 0 implies an infinite lifetime.", + "example": "...", + "default": 0 + }, + "numUsesLimit": { + "type": "number", + "description": "The maximum number of times that the Client Secret can be used together with the Client ID to get back an access token; a value of 0 implies infinite number of uses.", + "example": "...", + "default": 0 + } + } + } + } } } }, "get": { - "description": "", + "summary": "List Universal Auth Client Secrets for identity", + "description": "List Universal Auth Client Secrets for identity", "parameters": [ { "name": "identityId", @@ -1339,19 +1769,42 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of identity for which to get Client Secrets for" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientSecretData": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IdentityUniversalAuthClientSecretData" + } + } + }, + "description": "Details of the Client Secrets" + } + } + } } - } + }, + "security": [ + { + "bearerAuth": [] + } + ] } }, "/api/v1/auth/universal-auth/identities/{identityId}/client-secrets/{clientSecretId}/revoke": { "post": { - "description": "", + "summary": "Revoke Universal Auth Client Secret for identity", + "description": "Revoke Universal Auth Client Secret for identity", "parameters": [ { "name": "identityId", @@ -1359,7 +1812,8 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of identity under which Client Secret was issued for" }, { "name": "clientSecretId", @@ -1367,14 +1821,33 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of Client Secret to revoke" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientSecretData": { + "$ref": "#/components/schemas/IdentityUniversalAuthClientSecretData" + } + }, + "description": "Details of the revoked Client Secret" + } + } + } } - } + }, + "security": [ + { + "bearerAuth": [] + } + ] } }, "/api/v1/admin/config": { @@ -4526,7 +4999,8 @@ }, "/api/v2/organizations/{organizationId}/identity-memberships": { "get": { - "description": "", + "summary": "Return organization identity memberships", + "description": "Return organization identity memberships", "parameters": [ { "name": "organizationId", @@ -4534,14 +5008,36 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of organization" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityMemberships": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IdentityMembershipOrg" + }, + "description": "Identity memberships of organization" + } + } + } + } + } } - } + }, + "security": [ + { + "bearerAuth": [] + } + ] } }, "/api/v2/workspace/{workspaceId}/memberships": { @@ -5122,7 +5618,7 @@ "properties": { "role": { "type": "string", - "description": "Role of membership - either admin or member" + "description": "Role to update to for project membership" } } } @@ -5227,7 +5723,8 @@ } }, "patch": { - "description": "", + "summary": "Update project identity membership", + "description": "Update project identity membership", "parameters": [ { "name": "workspaceId", @@ -5235,7 +5732,8 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of project" }, { "name": "identityId", @@ -5243,17 +5741,53 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of identity whose membership to update in project" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityMembership": { + "$ref": "#/components/schemas/IdentityMembership", + "description": "Updated identity membership" + } + } + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "role": { + "type": "string", + "description": "Role to update to for identity project membership" + } + } + } + } } } }, "delete": { - "description": "", + "summary": "Delete project identity membership", + "description": "Delete project identity membership", "parameters": [ { "name": "workspaceId", @@ -5261,7 +5795,8 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of project" }, { "name": "identityId", @@ -5269,19 +5804,39 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of identity whose membership to delete in project" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityMembership": { + "$ref": "#/components/schemas/IdentityMembership", + "description": "Deleted identity membership" + } + } + } + } + } } - } + }, + "security": [ + { + "bearerAuth": [] + } + ] } }, "/api/v2/workspace/{workspaceId}/identity-memberships": { "get": { - "description": "", + "summary": "Return project identity memberships", + "description": "Return project identity memberships", "parameters": [ { "name": "workspaceId", @@ -5289,14 +5844,36 @@ "required": true, "schema": { "type": "string" - } + }, + "description": "ID of project" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityMemberships": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IdentityMembership" + }, + "description": "Identity memberships of project" + } + } + } + } + } } - } + }, + "security": [ + { + "bearerAuth": [] + } + ] } }, "/api/v2/secret/batch-create/workspace/{workspaceId}/environment/{environment}": { @@ -6562,6 +7139,137 @@ } } }, + "Identity": { + "type": "object", + "properties": { + "_id": { + "type": "string", + "example": "" + }, + "name": { + "type": "string", + "example": "Machine 1" + }, + "authMethod": { + "type": "string", + "example": "universal-auth" + } + } + }, + "IdentityUniversalAuth": { + "type": "object", + "properties": { + "_id": { + "type": "string", + "example": "" + }, + "identity": { + "type": "string", + "example": "" + }, + "clientId": { + "type": "string", + "example": "..." + }, + "clientSecretTrustedIps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipAddress": { + "type": "string", + "example": "0.0.0.0" + }, + "type": { + "type": "string", + "example": "ipv4" + }, + "prefix": { + "type": "string", + "example": "0" + } + } + } + }, + "accessTokenTTL": { + "type": "number", + "example": 7200 + }, + "accessTokenMaxTTL": { + "type": "number", + "example": 2592000 + }, + "accessTokenNumUsesLimit": { + "type": "number", + "example": 0 + }, + "accessTokenTrustedIps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ipAddress": { + "type": "string", + "example": "0.0.0.0" + }, + "type": { + "type": "string", + "example": "ipv4" + }, + "prefix": { + "type": "string", + "example": "0" + } + } + } + } + } + }, + "IdentityUniversalAuthClientSecretData": { + "type": "object", + "properties": { + "_id": { + "type": "string", + "example": "" + }, + "identityUniversalAuth": { + "type": "string", + "example": "" + }, + "isClientSecretRevoked": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string", + "example": "" + }, + "clientSecretPrefix": { + "type": "string", + "example": "abc" + }, + "clientSecretNumUses": { + "type": "number", + "example": 0 + }, + "clientSecretNumUsesLimit": { + "type": "number", + "example": 0 + }, + "clientSecretTTL": { + "type": "number", + "example": 0 + }, + "createdAt": { + "type": "string", + "example": "2023-01-13T14:16:12.210Z" + }, + "updatedAt": { + "type": "string", + "example": "2023-01-13T14:16:12.210Z" + } + } + }, "Membership": { "type": "object", "properties": { @@ -6658,6 +7366,70 @@ } } }, + "IdentityMembership": { + "type": "object", + "properties": { + "identity": { + "type": "object", + "properties": { + "_id": { + "type": "string", + "example": "" + }, + "name": { + "type": "string", + "example": "Machine 1" + }, + "authMethod": { + "type": "string", + "example": "universal-auth" + } + } + }, + "workspace": { + "type": "string", + "example": "" + }, + "role": { + "type": "string", + "example": "member" + } + } + }, + "IdentityMembershipOrg": { + "type": "object", + "properties": { + "identity": { + "type": "object", + "properties": { + "_id": { + "type": "string", + "example": "" + }, + "name": { + "type": "string", + "example": "Machine 1" + }, + "authMethod": { + "type": "string", + "example": "universal-auth" + } + } + }, + "organization": { + "type": "string", + "example": "" + }, + "role": { + "type": "string", + "example": "member" + }, + "status": { + "type": "string", + "example": "accepted" + } + } + }, "Organization": { "type": "object", "properties": { diff --git a/backend/src/controllers/v1/universalAuthController.ts b/backend/src/controllers/v1/universalAuthController.ts index e22c4e686..498a96c0e 100644 --- a/backend/src/controllers/v1/universalAuthController.ts +++ b/backend/src/controllers/v1/universalAuthController.ts @@ -60,6 +60,52 @@ const packageUniversalAuthClientSecretData = (identityUniversalAuthClientSecret: * @param res */ export const renewAccessToken = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Renew access token' + #swagger.description = 'Renew access token' + + #swagger.requestBody = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "accessToken": { + "type": "string", + "description": "Access token to renew", + "example": "..." + } + } + } + } + } + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "accessToken": { + "type": "string", + "description": "(Same) Access token after successful renewal" + }, + "expiresIn": { + "type": "number", + "description": "TTL of access token in seconds" + }, + "tokenType": { + "type": "string", + "description": "Type of access token (e.g. Bearer)" + } + }, + "description": "Access token and its details" + } + } + } + } + */ const { body: { accessToken @@ -152,6 +198,57 @@ export const renewAccessToken = async (req: Request, res: Response) => { * @param res */ export const loginIdentityUniversalAuth = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Login with Universal Auth' + #swagger.description = 'Login with Universal Auth' + + #swagger.requestBody = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientId": { + "type": "string", + "description": "Client ID for identity to login with Universal Auth", + "example": "..." + }, + "clientSecret": { + "type": "string", + "description": "Client Secret for identity to login with Universal Auth", + "example": "..." + } + } + } + } + } + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "accessToken": { + "type": "string", + "description": "Access token issued after successful login" + }, + "expiresIn": { + "type": "number", + "description": "TTL of access token in seconds" + }, + "tokenType": { + "type": "string", + "description": "Type of access token (e.g. Bearer)" + } + }, + "description": "Access token and its details" + } + } + } + } + */ const { body: { clientId, @@ -304,7 +401,105 @@ export const loginIdentityUniversalAuth = async (req: Request, res: Response) => }); } -export const addIdentityUniversalAuth = async (req: Request, res: Response) => { +/** + * Attach identity universal auth method onto identity with id [identityId] + * @param req + * @param res + */ +export const attachIdentityUniversalAuth = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Attach Universal Auth configuration onto identity' + #swagger.description = 'Attach Universal Auth configuration onto identity' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['identityId'] = { + "description": "ID of identity to attach Universal Auth onto", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.requestBody = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientSecretTrustedIps": { + type: "array", + items: { + type: "object", + "properties": { + "ipAddress": { + type: "string", + description: "IP address to trust", + default: "0.0.0.0/0" + } + } + }, + "description": "List of IPs or CIDR ranges that the Client Secret can be used from together with the Client ID to get back an access token. By default, Client Secrets are given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", + "example": "...", + "default": [{ ipAddress: "0.0.0.0/0" }] + }, + "accessTokenTTL": { + "type": "number", + "description": "The incremental lifetime for an acccess token in seconds; a value of 0 implies an infinite incremental lifetime.", + "example": "...", + "default": 100 + }, + "accessTokenMaxTTL": { + "type": "number", + "description": "The maximum lifetime for an acccess token in seconds; a value of 0 implies an infinite maximum lifetime.", + "example": "...", + "default": 2592000 + }, + "accessTokenNumUsesLimit": { + "type": "number", + "description": "The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses.", + "example": "...", + "default": 0 + }, + "accessTokenTrustedIps": { + type: "array", + items: { + type: "object", + "properties": { + "ipAddress": { + type: "string", + description: "IP address to trust", + default: "0.0.0.0/0" + } + } + }, + "description": "List of IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", + "example": "...", + "default": [{ ipAddress: "0.0.0.0/0" }] + } + } + } + } + } + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityUniversalAuth": { + $ref: '#/definitions/IdentityUniversalAuth' + } + }, + "description": "Details of attached Universal Auth" + } + } + } + } + */ const { params: { identityId }, body: { @@ -415,7 +610,98 @@ export const addIdentityUniversalAuth = async (req: Request, res: Response) => { }); } +/** + * Update identity universal auth method on identity with id [identityId] + * @param req + * @param res + */ export const updateIdentityUniversalAuth = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Update Universal Auth configuration on identity' + #swagger.description = 'Update Universal Auth configuration on identity' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['identityId'] = { + "description": "ID of identity to update Universal Auth on", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.requestBody = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientSecretTrustedIps": { + type: "array", + items: { + type: "object", + "properties": { + "ipAddress": { + type: "string", + description: "IP address to trust" + } + } + }, + "description": "List of IPs or CIDR ranges that the Client Secret can be used from together with the Client ID to get back an access token. By default, Client Secrets are given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", + "example": "...", + }, + "accessTokenTTL": { + "type": "number", + "description": "The incremental lifetime for an acccess token in seconds; a value of 0 implies an infinite incremental lifetime.", + "example": "...", + }, + "accessTokenMaxTTL": { + "type": "number", + "description": "The maximum lifetime for an acccess token in seconds; a value of 0 implies an infinite maximum lifetime.", + "example": "...", + }, + "accessTokenNumUsesLimit": { + "type": "number", + "description": "The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses.", + "example": "...", + }, + "accessTokenTrustedIps": { + type: "array", + items: { + type: "object", + "properties": { + "ipAddress": { + type: "string", + description: "IP address to trust" + } + } + }, + "description": "List of IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0 entry representing all possible IPv4 addresses.", + "example": "...", + } + } + } + } + } + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityUniversalAuth": { + $ref: '#/definitions/IdentityUniversalAuth' + } + }, + "description": "Details of updated Universal Auth" + } + } + } + } + */ const { params: { identityId }, body: { @@ -527,7 +813,43 @@ export const updateIdentityUniversalAuth = async (req: Request, res: Response) = }); } +/** + * Return identity universal auth method on identity with id [identityId] + * @param req + * @param res + */ export const getIdentityUniversalAuth = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Retrieve Universal Auth configuration on identity' + #swagger.description = 'Retrieve Universal Auth configuration on identity' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['identityId'] = { + "description": "ID of identity to retrieve Universal Auth on", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityUniversalAuth": { + $ref: '#/definitions/IdentityUniversalAuth' + } + }, + "description": "Details of retrieved Universal Auth" + } + } + } + } + */ const { params: { identityId } } = await validateRequest(reqValidator.GetUniversalAuthForIdentityV1, req); @@ -578,7 +900,77 @@ export const getIdentityUniversalAuth = async (req: Request, res: Response) => { }); } + +/** + * Create client secret for identity universal auth method on identity with id [identityId] + * @param req + * @param res + */ export const createUniversalAuthClientSecret = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Create Universal Auth Client Secret for identity' + #swagger.description = 'Create Universal Auth Client Secret for identity' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['identityId'] = { + "description": "ID of identity to create Universal Auth Client Secret for", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.requestBody = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "A description for the Client Secret to create.", + "example": "..." + }, + "ttl": { + "type": "number", + "description": "The time-to-live for the Client Secret to create. By default, the TTL will be set to 0 which implies that the Client Secret will never expire; a value of 0 implies an infinite lifetime.", + "example": "...", + "default": 0 + }, + "numUsesLimit": { + "type": "number", + "description": "The maximum number of times that the Client Secret can be used together with the Client ID to get back an access token; a value of 0 implies infinite number of uses.", + "example": "...", + "default": 0 + } + } + } + } + } + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientSecret": { + "type": "string", + "description": "The created Client Secret" + }, + "clientSecretData": { + $ref: '#/definitions/IdentityUniversalAuthClientSecretData' + } + }, + "description": "Details of the created Client Secret" + } + } + } + } + */ const { params: { identityId }, body: { @@ -661,7 +1053,46 @@ export const createUniversalAuthClientSecret = async (req: Request, res: Respons }); } -export const getUniversalAuthClientSecrets = async (req: Request, res: Response) => { +/** + * Return list of client secret details for identity universal auth method on identity with id [identityId] + * @param req + * @param res + */ +export const getUniversalAuthClientSecretsDetails = async (req: Request, res: Response) => { + /* + #swagger.summary = 'List Universal Auth Client Secrets for identity' + #swagger.description = 'List Universal Auth Client Secrets for identity' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['identityId'] = { + "description": "ID of identity for which to get Client Secrets for", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientSecretData": { + type: "array", + items: { + $ref: '#/definitions/IdentityUniversalAuthClientSecretData' + } + } + }, + "description": "Details of the Client Secrets" + } + } + } + } + */ const { params: { identityId } } = await validateRequest(reqValidator.GetUniversalAuthClientSecretsV1, req); @@ -721,7 +1152,50 @@ export const getUniversalAuthClientSecrets = async (req: Request, res: Response) }); } +/** + * Revoke client secret for identity universal auth method on identity with id [identityId] + * @param req + * @param res + */ export const revokeUniversalAuthClientSecret = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Revoke Universal Auth Client Secret for identity' + #swagger.description = 'Revoke Universal Auth Client Secret for identity' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['identityId'] = { + "description": "ID of identity under which Client Secret was issued for", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.parameters['clientSecretId'] = { + "description": "ID of Client Secret to revoke", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "clientSecretData": { + $ref: '#/definitions/IdentityUniversalAuthClientSecretData' + } + }, + "description": "Details of the revoked Client Secret" + } + } + } + } + */ const { params: { identityId, clientSecretId } } = await validateRequest(reqValidator.RevokeUniversalAuthClientSecretV1, req); diff --git a/backend/src/controllers/v2/organizationsController.ts b/backend/src/controllers/v2/organizationsController.ts index 26f08267c..f939f9072 100644 --- a/backend/src/controllers/v2/organizationsController.ts +++ b/backend/src/controllers/v2/organizationsController.ts @@ -428,6 +428,40 @@ export const deleteOrganizationById = async (req: Request, res: Response) => { * @returns */ export const getOrganizationIdentityMemberships = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Return organization identity memberships' + #swagger.description = 'Return organization identity memberships' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['organizationId'] = { + "description": "ID of organization", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityMemberships": { + "type": "array", + "items": { + $ref: "#/components/schemas/IdentityMembershipOrg" + }, + "description": "Identity memberships of organization" + } + } + } + } + } + } + */ const { params: { organizationId } } = await validateRequest(reqValidator.GetOrgIdentityMembershipsV2, req); diff --git a/backend/src/controllers/v2/workspaceController.ts b/backend/src/controllers/v2/workspaceController.ts index 8f23d1d74..780a3c1f3 100644 --- a/backend/src/controllers/v2/workspaceController.ts +++ b/backend/src/controllers/v2/workspaceController.ts @@ -342,7 +342,7 @@ export const updateWorkspaceMembership = async (req: Request, res: Response) => "properties": { "role": { "type": "string", - "description": "Role of membership - either admin or member", + "description": "Role to update to for project membership", } } } @@ -598,6 +598,59 @@ export const toggleAutoCapitalization = async (req: Request, res: Response) => { * @param res */ export const updateIdentityWorkspaceRole = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Update project identity membership' + #swagger.description = 'Update project identity membership' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['workspaceId'] = { + "description": "ID of project", + "required": true, + "type": "string" + } + + #swagger.parameters['identityId'] = { + "description": "ID of identity whose membership to update in project", + "required": true, + "type": "string" + } + + #swagger.requestBody = { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "role": { + "type": "string", + "description": "Role to update to for identity project membership", + } + } + } + } + } + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityMembership": { + $ref: "#/components/schemas/IdentityMembership", + "description": "Updated identity membership" + } + } + } + } + } + } + */ const { params: { workspaceId, identityId }, body: { @@ -679,12 +732,48 @@ export const toggleAutoCapitalization = async (req: Request, res: Response) => { } /** - * Delete identity with id [identityId] to workspace + * Delete identity with id [identityId] from workspace * with id [workspaceId] * @param req * @param res */ export const deleteIdentityFromWorkspace = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Delete project identity membership' + #swagger.description = 'Delete project identity membership' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['workspaceId'] = { + "description": "ID of project", + "required": true, + "type": "string" + } + + #swagger.parameters['identityId'] = { + "description": "ID of identity whose membership to delete in project", + "required": true, + "type": "string" + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityMembership": { + $ref: "#/components/schemas/IdentityMembership", + "description": "Deleted identity membership" + } + } + } + } + } + } + */ const { params: { workspaceId, identityId } } = await validateRequest(reqValidator.DeleteIdentityFromWorkspaceV2, req); @@ -736,6 +825,40 @@ export const toggleAutoCapitalization = async (req: Request, res: Response) => { * @returns */ export const getWorkspaceIdentityMemberships = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Return project identity memberships' + #swagger.description = 'Return project identity memberships' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['workspaceId'] = { + "description": "ID of project", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identityMemberships": { + "type": "array", + "items": { + $ref: "#/components/schemas/IdentityMembership" + }, + "description": "Identity memberships of project" + } + } + } + } + } + } + */ const { params: { workspaceId } } = await validateRequest(reqValidator.GetWorkspaceIdentityMembersV2, req); diff --git a/backend/src/ee/controllers/v1/identitiesController.ts b/backend/src/ee/controllers/v1/identitiesController.ts index c4e88f7c2..179beeda3 100644 --- a/backend/src/ee/controllers/v1/identitiesController.ts +++ b/backend/src/ee/controllers/v1/identitiesController.ts @@ -42,6 +42,58 @@ import { ForbiddenError } from "@casl/ability"; * @returns */ export const createIdentity = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Create identity' + #swagger.description = 'Create identity' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.requestBody = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of entity to create", + "example": "development" + }, + "organizationId": { + "type": "string", + "description": "ID of organization where to create identity", + "example": "dev-environment" + }, + "role": { + "type": "string", + "description": "Role to assume for organization membership", + "example": "no-access" + } + }, + "required": ["name", "organizationId", "role"] + } + } + } + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identity": { + $ref: '#/definitions/Identity' + } + }, + "description": "Details of the created identity" + } + } + } + } + */ const { body: { name, @@ -120,6 +172,59 @@ export const createIdentity = async (req: Request, res: Response) => { * @returns */ export const updateIdentity = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Update identity' + #swagger.description = 'Update identity' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['identityId'] = { + "description": "ID of identity to update", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.requestBody = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of entity to update to", + "example": "development" + }, + "role": { + "type": "string", + "description": "Role to update to for organization membership", + "example": "no-access" + } + } + } + } + } + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identity": { + $ref: '#/definitions/Identity' + } + }, + "description": "Details of the updated identity" + } + } + } + } + */ const { params: { identityId }, body: { @@ -242,6 +347,37 @@ export const createIdentity = async (req: Request, res: Response) => { * @returns */ export const deleteIdentity = async (req: Request, res: Response) => { + /* + #swagger.summary = 'Delete identity' + #swagger.description = 'Delete identity' + + #swagger.security = [{ + "bearerAuth": [] + }] + + #swagger.parameters['identityId'] = { + "description": "ID of identity", + "required": true, + "type": "string", + "in": "path" + } + + #swagger.responses[200] = { + content: { + "application/json": { + "schema": { + "type": "object", + "properties": { + "identity": { + $ref: '#/definitions/Identity' + } + }, + "description": "Details of the deleted identity" + } + } + } + } + */ const { params: { identityId } } = await validateRequest(reqValidator.DeleteIdentityV1, req); diff --git a/backend/src/routes/v1/universalAuth.ts b/backend/src/routes/v1/universalAuth.ts index d232f0ee8..b9d180040 100644 --- a/backend/src/routes/v1/universalAuth.ts +++ b/backend/src/routes/v1/universalAuth.ts @@ -18,15 +18,15 @@ router.post( router.post( "/universal-auth/identities/:identityId", requireAuth({ - acceptedAuthModes: [AuthMode.JWT] + acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] }), - universalAuthController.addIdentityUniversalAuth + universalAuthController.attachIdentityUniversalAuth ); router.patch( "/universal-auth/identities/:identityId", requireAuth({ - acceptedAuthModes: [AuthMode.JWT] + acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] }), universalAuthController.updateIdentityUniversalAuth ); @@ -34,7 +34,7 @@ router.patch( router.get( "/universal-auth/identities/:identityId", requireAuth({ - acceptedAuthModes: [AuthMode.JWT] + acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] }), universalAuthController.getIdentityUniversalAuth ); @@ -42,7 +42,7 @@ router.get( router.post( "/universal-auth/identities/:identityId/client-secrets", requireAuth({ - acceptedAuthModes: [AuthMode.JWT] + acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] }), universalAuthController.createUniversalAuthClientSecret ); @@ -50,15 +50,15 @@ router.post( router.get( "/universal-auth/identities/:identityId/client-secrets", requireAuth({ - acceptedAuthModes: [AuthMode.JWT] + acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] }), - universalAuthController.getUniversalAuthClientSecrets + universalAuthController.getUniversalAuthClientSecretsDetails ); router.post( "/universal-auth/identities/:identityId/client-secrets/:clientSecretId/revoke", requireAuth({ - acceptedAuthModes: [AuthMode.JWT] + acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] }), universalAuthController.revokeUniversalAuthClientSecret ); diff --git a/backend/src/routes/v2/workspace.ts b/backend/src/routes/v2/workspace.ts index 5dde7541f..f45c38f0c 100644 --- a/backend/src/routes/v2/workspace.ts +++ b/backend/src/routes/v2/workspace.ts @@ -96,7 +96,7 @@ router.patch( router.post( "/:workspaceId/identity-memberships/:identityId", requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] + acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] }), workspaceController.addIdentityToWorkspace ); @@ -104,7 +104,7 @@ router.post( router.patch( "/:workspaceId/identity-memberships/:identityId", requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] + acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] }), workspaceController.updateIdentityWorkspaceRole ); @@ -112,7 +112,7 @@ router.patch( router.delete( "/:workspaceId/identity-memberships/:identityId", requireAuth({ - acceptedAuthModes: [AuthMode.JWT, AuthMode.API_KEY] + acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] }), workspaceController.deleteIdentityFromWorkspace ); @@ -120,7 +120,7 @@ router.delete( router.get( "/:workspaceId/identity-memberships", requireAuth({ - acceptedAuthModes: [AuthMode.JWT] + acceptedAuthModes: [AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN] }), workspaceController.getWorkspaceIdentityMemberships ); diff --git a/backend/src/validation/auth.ts b/backend/src/validation/auth.ts index 84fea54b6..31f707875 100644 --- a/backend/src/validation/auth.ts +++ b/backend/src/validation/auth.ts @@ -117,7 +117,7 @@ export const AddUniversalAuthToIdentityV1 = z.object({ .min(1) .default([{ ipAddress: "0.0.0.0/0" }]), accessTokenTTL: z.number().int().min(0).default(7200), - accessTokenMaxTTL: z.number().int().min(0).default(0), + accessTokenMaxTTL: z.number().int().min(0).default(2592000), accessTokenNumUsesLimit: z.number().int().min(0).default(0) }) }); @@ -143,7 +143,7 @@ export const UpdateUniversalAuthToIdentityV1 = z.object({ .optional(), accessTokenTTL: z.number().int().min(0).optional(), accessTokenNumUsesLimit: z.number().int().min(0).optional(), - accessTokenMaxTTL: z.number().int().min(0).default(0), + accessTokenMaxTTL: z.number().int().min(0).optional(), }), }); diff --git a/backend/swagger/index.ts b/backend/swagger/index.ts index 9bd934b1e..6f3a426fb 100644 --- a/backend/swagger/index.ts +++ b/backend/swagger/index.ts @@ -52,6 +52,41 @@ const generateOpenAPISpec = async () => { updatedAt: "2023-01-13T14:16:12.210Z", createdAt: "2023-01-13T14:16:12.210Z" }, + Identity: { + _id: "", + name: "Machine 1", + authMethod: "universal-auth" + }, + IdentityUniversalAuth: { + _id: "", + identity: "", + clientId: "...", + clientSecretTrustedIps: [{ + ipAddress: "0.0.0.0", + type: "ipv4", + prefix: "0" + }], + accessTokenTTL: 7200, + accessTokenMaxTTL: 2592000, + accessTokenNumUsesLimit: 0, + accessTokenTrustedIps: [{ + ipAddress: "0.0.0.0", + type: "ipv4", + prefix: "0" + }] + }, + IdentityUniversalAuthClientSecretData: { + _id: "", + identityUniversalAuth: "", + isClientSecretRevoked: false, + description: "", + clientSecretPrefix: "abc", + clientSecretNumUses: 0, + clientSecretNumUsesLimit: 0, + clientSecretTTL: 0, + createdAt: "2023-01-13T14:16:12.210Z", + updatedAt: "2023-01-13T14:16:12.210Z" + }, Membership: { user: { _id: "", @@ -79,6 +114,25 @@ const generateOpenAPISpec = async () => { role: "owner", status: "accepted" }, + IdentityMembership: { + identity: { + _id: "", + name: "Machine 1", + authMethod: "universal-auth" + }, + workspace: "", + role: "member" + }, + IdentityMembershipOrg: { + identity: { + _id: "", + name: "Machine 1", + authMethod: "universal-auth" + }, + organization: "", + role: "member", + status: "accepted" + }, Organization: { _id: "", name: "Acme Corp.", diff --git a/docs/api-reference/endpoints/environments/create.mdx b/docs/api-reference/endpoints/environments/create.mdx index 826dcce3d..2527c613d 100644 --- a/docs/api-reference/endpoints/environments/create.mdx +++ b/docs/api-reference/endpoints/environments/create.mdx @@ -1,4 +1,4 @@ --- title: "Create" -openapi: "POST /api/v1/workspace/{workspaceId}/environments" +openapi: "POST /api/v2/workspace/{workspaceId}/environments" --- diff --git a/docs/api-reference/endpoints/identities/create.mdx b/docs/api-reference/endpoints/identities/create.mdx new file mode 100644 index 000000000..05a11521f --- /dev/null +++ b/docs/api-reference/endpoints/identities/create.mdx @@ -0,0 +1,4 @@ +--- +title: "Create" +openapi: "POST /api/v1/identities/" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/identities/delete.mdx b/docs/api-reference/endpoints/identities/delete.mdx new file mode 100644 index 000000000..07e79dfe9 --- /dev/null +++ b/docs/api-reference/endpoints/identities/delete.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete" +openapi: "DELETE /api/v1/identities/{identityId}" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/identities/update.mdx b/docs/api-reference/endpoints/identities/update.mdx new file mode 100644 index 000000000..c0940467b --- /dev/null +++ b/docs/api-reference/endpoints/identities/update.mdx @@ -0,0 +1,4 @@ +--- +title: "Update" +openapi: "PATCH /api/v1/identities/{identityId}" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/organizations/delete-membership.mdx b/docs/api-reference/endpoints/organizations/delete-membership.mdx index d9862e854..ee9ab77d5 100644 --- a/docs/api-reference/endpoints/organizations/delete-membership.mdx +++ b/docs/api-reference/endpoints/organizations/delete-membership.mdx @@ -1,4 +1,4 @@ --- -title: "Delete Membership" +title: "Delete User Membership" openapi: "DELETE /api/v2/organizations/{organizationId}/memberships/{membershipId}" --- diff --git a/docs/api-reference/endpoints/organizations/list-identity-memberships.mdx b/docs/api-reference/endpoints/organizations/list-identity-memberships.mdx new file mode 100644 index 000000000..1929a4b59 --- /dev/null +++ b/docs/api-reference/endpoints/organizations/list-identity-memberships.mdx @@ -0,0 +1,4 @@ +--- +title: "List Identity Memberships" +openapi: "GET /api/v2/organizations/{organizationId}/identity-memberships" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/organizations/memberships.mdx b/docs/api-reference/endpoints/organizations/memberships.mdx index b4b6f3d33..12f60ff7b 100644 --- a/docs/api-reference/endpoints/organizations/memberships.mdx +++ b/docs/api-reference/endpoints/organizations/memberships.mdx @@ -1,4 +1,4 @@ --- -title: "Get Memberships" +title: "Get User Memberships" openapi: "GET /api/v2/organizations/{organizationId}/memberships" --- diff --git a/docs/api-reference/endpoints/organizations/update-membership.mdx b/docs/api-reference/endpoints/organizations/update-membership.mdx index 1654d59c2..bf6af2de8 100644 --- a/docs/api-reference/endpoints/organizations/update-membership.mdx +++ b/docs/api-reference/endpoints/organizations/update-membership.mdx @@ -1,4 +1,4 @@ --- -title: "Update Membership" +title: "Update User Membership" openapi: "PATCH /api/v2/organizations/{organizationId}/memberships/{membershipId}" --- diff --git a/docs/api-reference/endpoints/universal-auth/attach.mdx b/docs/api-reference/endpoints/universal-auth/attach.mdx new file mode 100644 index 000000000..cf2fb6264 --- /dev/null +++ b/docs/api-reference/endpoints/universal-auth/attach.mdx @@ -0,0 +1,4 @@ +--- +title: "Attach" +openapi: "POST /api/v1/auth/universal-auth/identities/{identityId}" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/universal-auth/create-client-secret.mdx b/docs/api-reference/endpoints/universal-auth/create-client-secret.mdx new file mode 100644 index 000000000..b93760697 --- /dev/null +++ b/docs/api-reference/endpoints/universal-auth/create-client-secret.mdx @@ -0,0 +1,4 @@ +--- +title: "Create Client Secret" +openapi: "POST /api/v1/auth/universal-auth/identities/{identityId}/client-secrets" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/universal-auth/list-client-secrets.mdx b/docs/api-reference/endpoints/universal-auth/list-client-secrets.mdx new file mode 100644 index 000000000..165604d06 --- /dev/null +++ b/docs/api-reference/endpoints/universal-auth/list-client-secrets.mdx @@ -0,0 +1,4 @@ +--- +title: "List Client Secrets" +openapi: "GET /api/v1/auth/universal-auth/identities/{identityId}/client-secrets" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/universal-auth/login.mdx b/docs/api-reference/endpoints/universal-auth/login.mdx new file mode 100644 index 000000000..a1617a53c --- /dev/null +++ b/docs/api-reference/endpoints/universal-auth/login.mdx @@ -0,0 +1,4 @@ +--- +title: "Login" +openapi: "POST /api/v1/auth/universal-auth/login" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/universal-auth/renew-access-token.mdx b/docs/api-reference/endpoints/universal-auth/renew-access-token.mdx new file mode 100644 index 000000000..3079fc08c --- /dev/null +++ b/docs/api-reference/endpoints/universal-auth/renew-access-token.mdx @@ -0,0 +1,4 @@ +--- +title: "Renew Access Token" +openapi: "POST /api/v1/auth/token/renew" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/universal-auth/retrieve.mdx b/docs/api-reference/endpoints/universal-auth/retrieve.mdx new file mode 100644 index 000000000..a26f59706 --- /dev/null +++ b/docs/api-reference/endpoints/universal-auth/retrieve.mdx @@ -0,0 +1,4 @@ +--- +title: "Retrieve" +openapi: "GET /api/v1/auth/universal-auth/identities/{identityId}" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/universal-auth/revoke-client-secret.mdx b/docs/api-reference/endpoints/universal-auth/revoke-client-secret.mdx new file mode 100644 index 000000000..5344d796f --- /dev/null +++ b/docs/api-reference/endpoints/universal-auth/revoke-client-secret.mdx @@ -0,0 +1,4 @@ +--- +title: "Revoke Client Secret" +openapi: "POST /api/v1/auth/universal-auth/identities/{identityId}/client-secrets/{clientSecretId}/revoke" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/universal-auth/update.mdx b/docs/api-reference/endpoints/universal-auth/update.mdx new file mode 100644 index 000000000..2d33de15a --- /dev/null +++ b/docs/api-reference/endpoints/universal-auth/update.mdx @@ -0,0 +1,4 @@ +--- +title: "Update" +openapi: "PATCH /api/v1/auth/universal-auth/identities/{identityId}" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/workspaces/delete-identity-membership.mdx b/docs/api-reference/endpoints/workspaces/delete-identity-membership.mdx new file mode 100644 index 000000000..4621f9b50 --- /dev/null +++ b/docs/api-reference/endpoints/workspaces/delete-identity-membership.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete Identity Membership" +openapi: "DELETE /api/v2/workspace/{workspaceId}/identity-memberships/{identityId}" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/workspaces/delete-membership.mdx b/docs/api-reference/endpoints/workspaces/delete-membership.mdx index 826eafa83..e93b2415b 100644 --- a/docs/api-reference/endpoints/workspaces/delete-membership.mdx +++ b/docs/api-reference/endpoints/workspaces/delete-membership.mdx @@ -1,4 +1,4 @@ --- -title: "Delete Membership" +title: "Delete User Membership" openapi: "DELETE /api/v2/workspace/{workspaceId}/memberships/{membershipId}" --- diff --git a/docs/api-reference/endpoints/workspaces/list-identity-memberships.mdx b/docs/api-reference/endpoints/workspaces/list-identity-memberships.mdx new file mode 100644 index 000000000..45297efff --- /dev/null +++ b/docs/api-reference/endpoints/workspaces/list-identity-memberships.mdx @@ -0,0 +1,4 @@ +--- +title: "List Identity Memberships" +openapi: "GET /api/v2/workspace/{workspaceId}/identity-memberships" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/workspaces/memberships.mdx b/docs/api-reference/endpoints/workspaces/memberships.mdx index 38b86d616..386c8a089 100644 --- a/docs/api-reference/endpoints/workspaces/memberships.mdx +++ b/docs/api-reference/endpoints/workspaces/memberships.mdx @@ -1,4 +1,4 @@ --- -title: "Get Memberships" +title: "Get User Memberships" openapi: "GET /api/v2/workspace/{workspaceId}/memberships" --- diff --git a/docs/api-reference/endpoints/workspaces/update-identity-membership.mdx b/docs/api-reference/endpoints/workspaces/update-identity-membership.mdx new file mode 100644 index 000000000..398c7bc81 --- /dev/null +++ b/docs/api-reference/endpoints/workspaces/update-identity-membership.mdx @@ -0,0 +1,4 @@ +--- +title: "Update Identity Membership" +openapi: "PATCH /api/v2/workspace/{workspaceId}/identity-memberships/{identityId}" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/workspaces/update-membership.mdx b/docs/api-reference/endpoints/workspaces/update-membership.mdx index 367793847..f0ef15412 100644 --- a/docs/api-reference/endpoints/workspaces/update-membership.mdx +++ b/docs/api-reference/endpoints/workspaces/update-membership.mdx @@ -1,4 +1,4 @@ --- -title: "Update Membership" +title: "Update User Membership" openapi: "PATCH /api/v2/workspace/{workspaceId}/memberships/{membershipId}" --- diff --git a/docs/api-reference/overview/examples/e2ee-enabled.mdx b/docs/api-reference/overview/examples/e2ee-enabled.mdx index ad9ff59cd..1de9c2290 100644 --- a/docs/api-reference/overview/examples/e2ee-enabled.mdx +++ b/docs/api-reference/overview/examples/e2ee-enabled.mdx @@ -3,7 +3,7 @@ title: "E2EE Enabled" --- - E2EE enabled mode only works with Service Tokens and cannot be used with [Identities](/documentation/platform/identities/overview). + E2EE enabled mode only works with [Service Tokens](/documentation/platform/token) and cannot be used with [Identities](/documentation/platform/identities/overview). Using Infisical's API to read/write secrets with E2EE enabled allows you to create, update, and retrieve secrets diff --git a/docs/documentation/platform/identities/universal-auth.mdx b/docs/documentation/platform/identities/universal-auth.mdx index c53114f6a..92c595418 100644 --- a/docs/documentation/platform/identities/universal-auth.mdx +++ b/docs/documentation/platform/identities/universal-auth.mdx @@ -42,7 +42,7 @@ using the Universal Auth authentication method. Here's some more guidance on each field: - Access Token TTL (default is `7200`): The incremental lifetime for an acccess token in seconds; a value of `0` implies an infinite incremental lifetime. - - Access Token Max TTL (default is `7200`): The maximum lifetime for an acccess token in seconds; a value of `0` implies an infinite maximum lifetime. + - Access Token Max TTL (default is `2592000`): The maximum lifetime for an acccess token in seconds; a value of `0` implies an infinite maximum lifetime. - Access Token Max Number of Uses (default is `0`): The maximum number of times that an access token can be used; a value of `0` implies infinite number of uses. - Client Secret Trusted IPs: The IPs or CIDR ranges that the **Client Secret** can be used from together with the **Client ID** to get back an access token. By default, **Client Secrets** are given the `0.0.0.0/0` entry representing all possible IPv4 addresses. - Access Token Trusted IPs: The IPs or CIDR ranges that access tokens can be used from. By default, each token is given the `0.0.0.0/0` entry representing all possible IPv4 addresses. diff --git a/docs/mint.json b/docs/mint.json index f9804b502..2cfacf1bd 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -336,12 +336,34 @@ "api-reference/endpoints/users/my-organizations" ] }, + { + "group": "Identities", + "pages": [ + "api-reference/endpoints/identities/create", + "api-reference/endpoints/identities/update", + "api-reference/endpoints/identities/delete" + ] + }, + { + "group": "Universal Auth", + "pages": [ + "api-reference/endpoints/universal-auth/login", + "api-reference/endpoints/universal-auth/attach", + "api-reference/endpoints/universal-auth/retrieve", + "api-reference/endpoints/universal-auth/update", + "api-reference/endpoints/universal-auth/create-client-secret", + "api-reference/endpoints/universal-auth/list-client-secrets", + "api-reference/endpoints/universal-auth/revoke-client-secret", + "api-reference/endpoints/universal-auth/renew-access-token" + ] + }, { "group": "Organizations", "pages": [ "api-reference/endpoints/organizations/memberships", "api-reference/endpoints/organizations/update-membership", "api-reference/endpoints/organizations/delete-membership", + "api-reference/endpoints/organizations/list-identity-memberships", "api-reference/endpoints/organizations/workspaces" ] }, @@ -351,6 +373,9 @@ "api-reference/endpoints/workspaces/memberships", "api-reference/endpoints/workspaces/update-membership", "api-reference/endpoints/workspaces/delete-membership", + "api-reference/endpoints/workspaces/list-identity-memberships", + "api-reference/endpoints/workspaces/update-identity-membership", + "api-reference/endpoints/workspaces/delete-identity-membership", "api-reference/endpoints/workspaces/workspace-key", "api-reference/endpoints/workspaces/secret-snapshots", "api-reference/endpoints/workspaces/rollback-snapshot" diff --git a/docs/spec.yaml b/docs/spec.yaml index 0d29a0b35..a0a2dc13f 100644 --- a/docs/spec.yaml +++ b/docs/spec.yaml @@ -11,33 +11,104 @@ servers: paths: /api/v1/identities/: post: - description: '' + summary: Create identity + description: Create identity responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + identity: + $ref: '#/components/schemas/Identity' + description: Details of the created identity + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Name of entity to create + example: development + organizationId: + type: string + description: ID of organization where to create identity + example: dev-environment + role: + type: string + description: Role to assume for organization membership + example: no-access + required: + - name + - organizationId + - role /api/v1/identities/{identityId}: patch: - description: '' + summary: Update identity + description: Update identity parameters: - name: identityId in: path required: true schema: type: string + description: ID of identity to update responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + identity: + $ref: '#/components/schemas/Identity' + description: Details of the updated identity + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Name of entity to update to + example: development + role: + type: string + description: Role to update to for organization membership + example: no-access delete: - description: '' + summary: Delete identity + description: Delete identity parameters: - name: identityId in: path required: true schema: type: string + description: ID of identity responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + identity: + $ref: '#/components/schemas/Identity' + description: Details of the deleted identity + security: + - bearerAuth: [] /api/v1/secret/{secretId}/secret-versions: get: summary: Return secret versions @@ -757,13 +828,40 @@ paths: description: OK /api/v1/auth/token/renew: post: - description: '' + summary: Renew access token + description: Renew access token responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + accessToken: + type: string + description: (Same) Access token after successful renewal + expiresIn: + type: number + description: TTL of access token in seconds + tokenType: + type: string + description: Type of access token (e.g. Bearer) + description: Access token and its details + requestBody: + content: + application/json: + schema: + type: object + properties: + accessToken: + type: string + description: Access token to renew + example: ... /api/v1/auth/universal-auth/login: post: - description: '' + summary: Login with Universal Auth + description: Login with Universal Auth parameters: - name: user-agent in: header @@ -772,84 +870,330 @@ paths: responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + accessToken: + type: string + description: Access token issued after successful login + expiresIn: + type: number + description: TTL of access token in seconds + tokenType: + type: string + description: Type of access token (e.g. Bearer) + description: Access token and its details + requestBody: + content: + application/json: + schema: + type: object + properties: + clientId: + type: string + description: Client ID for identity to login with Universal Auth + example: ... + clientSecret: + type: string + description: Client Secret for identity to login with Universal Auth + example: ... /api/v1/auth/universal-auth/identities/{identityId}: post: - description: '' + summary: Attach Universal Auth configuration onto identity + description: Attach Universal Auth configuration onto identity parameters: - name: identityId in: path required: true schema: type: string + description: ID of identity to attach Universal Auth onto responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + identityUniversalAuth: + $ref: '#/components/schemas/IdentityUniversalAuth' + description: Details of attached Universal Auth '400': description: Bad Request + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + clientSecretTrustedIps: + type: array + items: + type: object + properties: + ipAddress: + type: string + description: IP address to trust + default: 0.0.0.0/0 + description: >- + List of IPs or CIDR ranges that the Client Secret can be + used from together with the Client ID to get back an access + token. By default, Client Secrets are given the 0.0.0.0/0 + entry representing all possible IPv4 addresses. + example: ... + default: + - ipAddress: 0.0.0.0/0 + accessTokenTTL: + type: number + description: >- + The incremental lifetime for an acccess token in seconds; a + value of 0 implies an infinite incremental lifetime. + example: ... + default: 100 + accessTokenMaxTTL: + type: number + description: >- + The maximum lifetime for an acccess token in seconds; a + value of 0 implies an infinite maximum lifetime. + example: ... + default: 2592000 + accessTokenNumUsesLimit: + type: number + description: >- + The maximum number of times that an access token can be + used; a value of 0 implies infinite number of uses. + example: ... + default: 0 + accessTokenTrustedIps: + type: array + items: + type: object + properties: + ipAddress: + type: string + description: IP address to trust + default: 0.0.0.0/0 + description: >- + List of IPs or CIDR ranges that access tokens can be used + from. By default, each token is given the 0.0.0.0/0 entry + representing all possible IPv4 addresses. + example: ... + default: + - ipAddress: 0.0.0.0/0 patch: - description: '' + summary: Update Universal Auth configuration on identity + description: Update Universal Auth configuration on identity parameters: - name: identityId in: path required: true schema: type: string + description: ID of identity to update Universal Auth on responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + identityUniversalAuth: + $ref: '#/components/schemas/IdentityUniversalAuth' + description: Details of updated Universal Auth '400': description: Bad Request + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + clientSecretTrustedIps: + type: array + items: + type: object + properties: + ipAddress: + type: string + description: IP address to trust + description: >- + List of IPs or CIDR ranges that the Client Secret can be + used from together with the Client ID to get back an access + token. By default, Client Secrets are given the 0.0.0.0/0 + entry representing all possible IPv4 addresses. + example: ... + accessTokenTTL: + type: number + description: >- + The incremental lifetime for an acccess token in seconds; a + value of 0 implies an infinite incremental lifetime. + example: ... + accessTokenMaxTTL: + type: number + description: >- + The maximum lifetime for an acccess token in seconds; a + value of 0 implies an infinite maximum lifetime. + example: ... + accessTokenNumUsesLimit: + type: number + description: >- + The maximum number of times that an access token can be + used; a value of 0 implies infinite number of uses. + example: ... + accessTokenTrustedIps: + type: array + items: + type: object + properties: + ipAddress: + type: string + description: IP address to trust + description: >- + List of IPs or CIDR ranges that access tokens can be used + from. By default, each token is given the 0.0.0.0/0 entry + representing all possible IPv4 addresses. + example: ... get: - description: '' + summary: Retrieve Universal Auth configuration on identity + description: Retrieve Universal Auth configuration on identity parameters: - name: identityId in: path required: true schema: type: string + description: ID of identity to retrieve Universal Auth on responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + identityUniversalAuth: + $ref: '#/components/schemas/IdentityUniversalAuth' + description: Details of retrieved Universal Auth + security: + - bearerAuth: [] /api/v1/auth/universal-auth/identities/{identityId}/client-secrets: post: - description: '' + summary: Create Universal Auth Client Secret for identity + description: Create Universal Auth Client Secret for identity parameters: - name: identityId in: path required: true schema: type: string + description: ID of identity to create Universal Auth Client Secret for responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + clientSecret: + type: string + description: The created Client Secret + clientSecretData: + $ref: '#/components/schemas/IdentityUniversalAuthClientSecretData' + description: Details of the created Client Secret + security: + - bearerAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + description: + type: string + description: A description for the Client Secret to create. + example: ... + ttl: + type: number + description: >- + The time-to-live for the Client Secret to create. By + default, the TTL will be set to 0 which implies that the + Client Secret will never expire; a value of 0 implies an + infinite lifetime. + example: ... + default: 0 + numUsesLimit: + type: number + description: >- + The maximum number of times that the Client Secret can be + used together with the Client ID to get back an access + token; a value of 0 implies infinite number of uses. + example: ... + default: 0 get: - description: '' + summary: List Universal Auth Client Secrets for identity + description: List Universal Auth Client Secrets for identity parameters: - name: identityId in: path required: true schema: type: string + description: ID of identity for which to get Client Secrets for responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + clientSecretData: + type: array + items: + $ref: >- + #/components/schemas/IdentityUniversalAuthClientSecretData + description: Details of the Client Secrets + security: + - bearerAuth: [] /api/v1/auth/universal-auth/identities/{identityId}/client-secrets/{clientSecretId}/revoke: post: - description: '' + summary: Revoke Universal Auth Client Secret for identity + description: Revoke Universal Auth Client Secret for identity parameters: - name: identityId in: path required: true schema: type: string + description: ID of identity under which Client Secret was issued for - name: clientSecretId in: path required: true schema: type: string + description: ID of Client Secret to revoke responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + clientSecretData: + $ref: '#/components/schemas/IdentityUniversalAuthClientSecretData' + description: Details of the revoked Client Secret + security: + - bearerAuth: [] /api/v1/admin/config: get: description: '' @@ -2809,16 +3153,30 @@ paths: description: OK /api/v2/organizations/{organizationId}/identity-memberships: get: - description: '' + summary: Return organization identity memberships + description: Return organization identity memberships parameters: - name: organizationId in: path required: true schema: type: string + description: ID of organization responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + identityMemberships: + type: array + items: + $ref: '#/components/schemas/IdentityMembershipOrg' + description: Identity memberships of organization + security: + - bearerAuth: [] /api/v2/workspace/{workspaceId}/memberships: post: description: '' @@ -3190,7 +3548,7 @@ paths: properties: role: type: string - description: Role of membership - either admin or member + description: Role to update to for project membership delete: summary: Delete project user membership description: Delete project user membership @@ -3251,49 +3609,99 @@ paths: '200': description: OK patch: - description: '' + summary: Update project identity membership + description: Update project identity membership parameters: - name: workspaceId in: path required: true schema: type: string + description: ID of project - name: identityId in: path required: true schema: type: string + description: ID of identity whose membership to update in project responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + identityMembership: + $ref: '#/components/schemas/IdentityMembership' + description: Updated identity membership + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + role: + type: string + description: Role to update to for identity project membership delete: - description: '' + summary: Delete project identity membership + description: Delete project identity membership parameters: - name: workspaceId in: path required: true schema: type: string + description: ID of project - name: identityId in: path required: true schema: type: string + description: ID of identity whose membership to delete in project responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + identityMembership: + $ref: '#/components/schemas/IdentityMembership' + description: Deleted identity membership + security: + - bearerAuth: [] /api/v2/workspace/{workspaceId}/identity-memberships: get: - description: '' + summary: Return project identity memberships + description: Return project identity memberships parameters: - name: workspaceId in: path required: true schema: type: string + description: ID of project responses: '200': description: OK + content: + application/json: + schema: + type: object + properties: + identityMemberships: + type: array + items: + $ref: '#/components/schemas/IdentityMembership' + description: Identity memberships of project + security: + - bearerAuth: [] /api/v2/secret/batch-create/workspace/{workspaceId}/environment/{environment}: post: description: '' @@ -4092,6 +4500,100 @@ components: createdAt: type: string example: '2023-01-13T14:16:12.210Z' + Identity: + type: object + properties: + _id: + type: string + example: '' + name: + type: string + example: Machine 1 + authMethod: + type: string + example: universal-auth + IdentityUniversalAuth: + type: object + properties: + _id: + type: string + example: '' + identity: + type: string + example: '' + clientId: + type: string + example: ... + clientSecretTrustedIps: + type: array + items: + type: object + properties: + ipAddress: + type: string + example: 0.0.0.0 + type: + type: string + example: ipv4 + prefix: + type: string + example: '0' + accessTokenTTL: + type: number + example: 7200 + accessTokenMaxTTL: + type: number + example: 2592000 + accessTokenNumUsesLimit: + type: number + example: 0 + accessTokenTrustedIps: + type: array + items: + type: object + properties: + ipAddress: + type: string + example: 0.0.0.0 + type: + type: string + example: ipv4 + prefix: + type: string + example: '0' + IdentityUniversalAuthClientSecretData: + type: object + properties: + _id: + type: string + example: '' + identityUniversalAuth: + type: string + example: '' + isClientSecretRevoked: + type: boolean + example: false + description: + type: string + example: '' + clientSecretPrefix: + type: string + example: abc + clientSecretNumUses: + type: number + example: 0 + clientSecretNumUsesLimit: + type: number + example: 0 + clientSecretTTL: + type: number + example: 0 + createdAt: + type: string + example: '2023-01-13T14:16:12.210Z' + updatedAt: + type: string + example: '2023-01-13T14:16:12.210Z' Membership: type: object properties: @@ -4161,6 +4663,51 @@ components: status: type: string example: accepted + IdentityMembership: + type: object + properties: + identity: + type: object + properties: + _id: + type: string + example: '' + name: + type: string + example: Machine 1 + authMethod: + type: string + example: universal-auth + workspace: + type: string + example: '' + role: + type: string + example: member + IdentityMembershipOrg: + type: object + properties: + identity: + type: object + properties: + _id: + type: string + example: '' + name: + type: string + example: Machine 1 + authMethod: + type: string + example: universal-auth + organization: + type: string + example: '' + role: + type: string + example: member + status: + type: string + example: accepted Organization: type: object properties: