Merge branch 'heads/main' into daniel/k8s-auth-gateway

This commit is contained in:
Daniel Hougaard
2025-05-14 14:26:05 +04:00
330 changed files with 15686 additions and 6256 deletions
@@ -16,5 +16,6 @@ export enum AppConnection {
Auth0 = "auth0",
HCVault = "hashicorp-vault",
LDAP = "ldap",
TeamCity = "teamcity"
TeamCity = "teamcity",
OCI = "oci"
}
@@ -0,0 +1,2 @@
export * from "./queries";
export * from "./types";
@@ -0,0 +1,108 @@
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { appConnectionKeys } from "../queries";
import {
TListOCIVaultKeys,
TListOCIVaults,
TOCICompartment,
TOCIVault,
TOCIVaultKey
} from "./types";
const ociConnectionKeys = {
all: [...appConnectionKeys.all, "oci"] as const,
listCompartments: (connectionId: string) =>
[...ociConnectionKeys.all, "compartments", connectionId] as const,
listVaults: (connectionId: string, compartmentOcid: string) =>
[...ociConnectionKeys.all, "vaults", connectionId, compartmentOcid] as const,
listVaultKeys: (connectionId: string, compartmentOcid: string, vaultOcid: string) =>
[...ociConnectionKeys.all, "keys", connectionId, compartmentOcid, vaultOcid] as const
};
export const useOCIConnectionListCompartments = (
connectionId: string,
options?: Omit<
UseQueryOptions<
TOCICompartment[],
unknown,
TOCICompartment[],
ReturnType<typeof ociConnectionKeys.listCompartments>
>,
"queryKey" | "queryFn"
>
) => {
return useQuery({
queryKey: ociConnectionKeys.listCompartments(connectionId),
queryFn: async () => {
const { data } = await apiRequest.get<TOCICompartment[]>(
`/api/v1/app-connections/oci/${connectionId}/compartments`
);
return data;
},
...options
});
};
export const useOCIConnectionListVaults = (
{ connectionId, compartmentOcid }: TListOCIVaults,
options?: Omit<
UseQueryOptions<
TOCIVault[],
unknown,
TOCIVault[],
ReturnType<typeof ociConnectionKeys.listVaults>
>,
"queryKey" | "queryFn"
>
) => {
return useQuery({
queryKey: ociConnectionKeys.listVaults(connectionId, compartmentOcid),
queryFn: async () => {
const { data } = await apiRequest.get<TOCIVault[]>(
`/api/v1/app-connections/oci/${connectionId}/vaults`,
{
params: {
compartmentOcid
}
}
);
return data;
},
...options
});
};
export const useOCIConnectionListVaultKeys = (
{ connectionId, compartmentOcid, vaultOcid }: TListOCIVaultKeys,
options?: Omit<
UseQueryOptions<
TOCIVaultKey[],
unknown,
TOCIVaultKey[],
ReturnType<typeof ociConnectionKeys.listVaultKeys>
>,
"queryKey" | "queryFn"
>
) => {
return useQuery({
queryKey: ociConnectionKeys.listVaultKeys(connectionId, compartmentOcid, vaultOcid),
queryFn: async () => {
const { data } = await apiRequest.get<TOCIVaultKey[]>(
`/api/v1/app-connections/oci/${connectionId}/vault-keys`,
{
params: {
compartmentOcid,
vaultOcid
}
}
);
return data;
},
...options
});
};
@@ -0,0 +1,27 @@
// Response types
export type TOCICompartment = {
id: string;
name: string;
};
export type TOCIVault = {
id: string;
displayName: string;
};
export type TOCIVaultKey = {
id: string;
displayName: string;
};
// Param types
export type TListOCIVaults = {
connectionId: string;
compartmentOcid: string;
};
export type TListOCIVaultKeys = {
connectionId: string;
compartmentOcid: string;
vaultOcid: string;
};
@@ -84,6 +84,10 @@ export type TTeamCityConnectionOption = TAppConnectionOptionBase & {
app: AppConnection.TeamCity;
};
export type TOCIConnectionOption = TAppConnectionOptionBase & {
app: AppConnection.OCI;
};
export type TAppConnectionOption =
| TAwsConnectionOption
| TGitHubConnectionOption
@@ -101,7 +105,8 @@ export type TAppConnectionOption =
| TWindmillConnectionOption
| TAuth0ConnectionOption
| THCVaultConnectionOption
| TTeamCityConnectionOption;
| TTeamCityConnectionOption
| TOCIConnectionOption;
export type TAppConnectionOptionMap = {
[AppConnection.AWS]: TAwsConnectionOption;
@@ -122,4 +127,5 @@ export type TAppConnectionOptionMap = {
[AppConnection.HCVault]: THCVaultConnectionOption;
[AppConnection.LDAP]: TLdapConnectionOption;
[AppConnection.TeamCity]: TTeamCityConnectionOption;
[AppConnection.OCI]: TOCIConnectionOption;
};
@@ -13,6 +13,7 @@ import { THCVaultConnection } from "./hc-vault-connection";
import { THumanitecConnection } from "./humanitec-connection";
import { TLdapConnection } from "./ldap-connection";
import { TMsSqlConnection } from "./mssql-connection";
import { TOCIConnection } from "./oci-connection";
import { TPostgresConnection } from "./postgres-connection";
import { TTeamCityConnection } from "./teamcity-connection";
import { TTerraformCloudConnection } from "./terraform-cloud-connection";
@@ -32,6 +33,7 @@ export * from "./hc-vault-connection";
export * from "./humanitec-connection";
export * from "./ldap-connection";
export * from "./mssql-connection";
export * from "./oci-connection";
export * from "./postgres-connection";
export * from "./teamcity-connection";
export * from "./terraform-cloud-connection";
@@ -56,7 +58,8 @@ export type TAppConnection =
| TAuth0Connection
| THCVaultConnection
| TLdapConnection
| TTeamCityConnection;
| TTeamCityConnection
| TOCIConnection;
export type TAvailableAppConnection = Pick<TAppConnection, "name" | "id">;
@@ -102,4 +105,5 @@ export type TAppConnectionMap = {
[AppConnection.HCVault]: THCVaultConnection;
[AppConnection.LDAP]: TLdapConnection;
[AppConnection.TeamCity]: TTeamCityConnection;
[AppConnection.OCI]: TOCIConnection;
};
@@ -0,0 +1,17 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { TRootAppConnection } from "@app/hooks/api/appConnections/types/root-connection";
export enum OCIConnectionMethod {
AccessKey = "access-key"
}
export type TOCIConnection = TRootAppConnection & { app: AppConnection.OCI } & {
method: OCIConnectionMethod.AccessKey;
credentials: {
userOcid: string;
tenancyOcid: string;
region: string;
fingerprint: string;
privateKey: string;
};
};
@@ -2,6 +2,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { pkiSubscriberKeys } from "../pkiSubscriber/queries";
import { workspaceKeys } from "../workspace";
import { TCertificate, TDeleteCertDTO, TRevokeCertDTO } from "./types";
@@ -42,6 +43,9 @@ export const useRevokeCert = () => {
queryClient.invalidateQueries({
queryKey: workspaceKeys.forWorkspaceCertificates(projectSlug)
});
queryClient.invalidateQueries({
queryKey: pkiSubscriberKeys.allPkiSubscriberCertificates()
});
}
});
};
+1
View File
@@ -27,6 +27,7 @@ export * from "./orgAdmin";
export * from "./organization";
export * from "./pkiAlerts";
export * from "./pkiCollections";
export * from "./pkiSubscriber";
export * from "./projectUserAdditionalPrivilege";
export * from "./rateLimit";
export * from "./roles";
@@ -0,0 +1,20 @@
export enum PkiSubscriberStatus {
ACTIVE = "active",
DISABLED = "disabled"
}
export const pkiSubscriberStatusToNameMap: { [K in PkiSubscriberStatus]: string } = {
[PkiSubscriberStatus.ACTIVE]: "Active",
[PkiSubscriberStatus.DISABLED]: "Disabled"
};
export const getPkiSubscriberStatusBadgeVariant = (status: PkiSubscriberStatus) => {
switch (status) {
case PkiSubscriberStatus.ACTIVE:
return "success";
case PkiSubscriberStatus.DISABLED:
return "danger";
default:
return "primary";
}
};
@@ -0,0 +1,7 @@
export {
useCreatePkiSubscriber,
useDeletePkiSubscriber,
useIssuePkiSubscriberCert,
useUpdatePkiSubscriber
} from "./mutations";
export { useGetPkiSubscriber, useGetPkiSubscriberCertificates } from "./queries";
@@ -0,0 +1,110 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { TCreateCertificateResponse } from "../ca/types";
import { workspaceKeys } from "../workspace/query-keys";
import { pkiSubscriberKeys } from "./queries";
import {
TCreatePkiSubscriberDTO,
TDeletePkiSubscriberDTO,
TIssuePkiSubscriberCertDTO,
TPkiSubscriber,
TUpdatePkiSubscriberDTO
} from "./types";
export const useCreatePkiSubscriber = () => {
const queryClient = useQueryClient();
return useMutation<TPkiSubscriber, object, TCreatePkiSubscriberDTO>({
mutationFn: async (body) => {
const { data: subscriber } = await apiRequest.post("/api/v1/pki/subscribers", body);
return subscriber;
},
onSuccess: ({ projectId, name }) => {
queryClient.invalidateQueries({
queryKey: workspaceKeys.getWorkspacePkiSubscribers(projectId)
});
queryClient.invalidateQueries({
queryKey: pkiSubscriberKeys.getPkiSubscriber({
subscriberName: name,
projectId
})
});
}
});
};
export const useUpdatePkiSubscriber = () => {
const queryClient = useQueryClient();
return useMutation<TPkiSubscriber, object, TUpdatePkiSubscriberDTO>({
mutationFn: async ({ subscriberName, ...body }) => {
const { data: subscriber } = await apiRequest.patch(
`/api/v1/pki/subscribers/${subscriberName}`,
body
);
return subscriber;
},
onSuccess: ({ projectId, name }) => {
queryClient.invalidateQueries({
queryKey: workspaceKeys.getWorkspacePkiSubscribers(projectId)
});
queryClient.invalidateQueries({
queryKey: pkiSubscriberKeys.getPkiSubscriber({
subscriberName: name,
projectId
})
});
}
});
};
export const useDeletePkiSubscriber = () => {
const queryClient = useQueryClient();
return useMutation<TPkiSubscriber, object, TDeletePkiSubscriberDTO>({
mutationFn: async ({ subscriberName, projectId }) => {
const { data: subscriber } = await apiRequest.delete(
`/api/v1/pki/subscribers/${subscriberName}`,
{
data: {
projectId
}
}
);
return subscriber;
},
onSuccess: ({ name, projectId }) => {
queryClient.invalidateQueries({
queryKey: workspaceKeys.getWorkspacePkiSubscribers(projectId)
});
queryClient.invalidateQueries({
queryKey: pkiSubscriberKeys.getPkiSubscriber({
subscriberName: name,
projectId
})
});
}
});
};
export const useIssuePkiSubscriberCert = () => {
const queryClient = useQueryClient();
return useMutation<TCreateCertificateResponse, object, TIssuePkiSubscriberCertDTO>({
mutationFn: async ({ subscriberName, projectId }) => {
const { data } = await apiRequest.post(
`/api/v1/pki/subscribers/${subscriberName}/issue-certificate`,
{
projectId
}
);
return data;
},
onSuccess: (_, { subscriberName, projectId }) => {
queryClient.invalidateQueries({
queryKey: pkiSubscriberKeys.forPkiSubscriberCertificates({
subscriberName,
projectId
})
});
}
});
};
@@ -0,0 +1,102 @@
import { useQuery } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { TCertificate } from "../certificates/types";
import { TPkiSubscriber } from "./types";
export const pkiSubscriberKeys = {
getPkiSubscriber: ({
subscriberName,
projectId
}: {
subscriberName: string;
projectId: string;
}) => [{ subscriberName, projectId }, "pki-subscriber"] as const,
allPkiSubscriberCertificates: () => ["pki-subscriber-certificates"] as const,
forPkiSubscriberCertificates: ({
subscriberName,
projectId
}: {
subscriberName: string;
projectId: string;
}) => [...pkiSubscriberKeys.allPkiSubscriberCertificates(), subscriberName, projectId] as const,
specificPkiSubscriberCertificates: ({
subscriberName,
projectId,
offset,
limit
}: {
subscriberName: string;
projectId: string;
offset: number;
limit: number;
}) =>
[
...pkiSubscriberKeys.forPkiSubscriberCertificates({ subscriberName, projectId }),
{ offset, limit, projectId }
] as const
};
export const useGetPkiSubscriber = ({
subscriberName,
projectId
}: {
subscriberName: string;
projectId: string;
}) => {
return useQuery({
queryKey: pkiSubscriberKeys.getPkiSubscriber({ subscriberName, projectId }),
queryFn: async () => {
const { data: pkiSubscriber } = await apiRequest.get<TPkiSubscriber>(
`/api/v1/pki/subscribers/${subscriberName}`,
{
params: {
projectId
}
}
);
return pkiSubscriber;
},
enabled: Boolean(subscriberName) && Boolean(projectId)
});
};
export const useGetPkiSubscriberCertificates = ({
subscriberName,
projectId,
offset,
limit
}: {
subscriberName: string;
projectId: string;
offset: number;
limit: number;
}) => {
return useQuery({
queryKey: pkiSubscriberKeys.specificPkiSubscriberCertificates({
subscriberName,
projectId,
offset,
limit
}),
queryFn: async () => {
const params = new URLSearchParams({
offset: String(offset),
limit: String(limit),
projectId
});
const {
data: { certificates, totalCount }
} = await apiRequest.get<{ certificates: TCertificate[]; totalCount: number }>(
`/api/v1/pki/subscribers/${subscriberName}/certificates`,
{
params
}
);
return { certificates, totalCount };
},
enabled: Boolean(subscriberName) && Boolean(projectId)
});
};
@@ -0,0 +1,53 @@
import { CertExtendedKeyUsage, CertKeyUsage } from "../certificates/enums";
export enum PkiSubscriberStatus {
ACTIVE = "active",
DISABLED = "disabled"
}
export type TPkiSubscriber = {
id: string;
projectId: string;
caId: string;
name: string;
commonName: string;
status: PkiSubscriberStatus;
ttl: string;
subjectAlternativeNames: string[];
keyUsages: CertKeyUsage[];
extendedKeyUsages: CertExtendedKeyUsage[];
};
export type TCreatePkiSubscriberDTO = {
projectId: string;
caId: string;
name: string;
commonName: string;
ttl: string;
subjectAlternativeNames: string[];
keyUsages: CertKeyUsage[];
extendedKeyUsages: CertExtendedKeyUsage[];
};
export type TUpdatePkiSubscriberDTO = {
subscriberName: string;
projectId: string;
caId?: string;
name?: string;
commonName?: string;
status?: PkiSubscriberStatus;
ttl?: string;
subjectAlternativeNames?: string[];
keyUsages?: CertKeyUsage[];
extendedKeyUsages?: CertExtendedKeyUsage[];
};
export type TDeletePkiSubscriberDTO = {
subscriberName: string;
projectId: string;
};
export type TIssuePkiSubscriberCertDTO = {
subscriberName: string;
projectId: string;
};
+2 -2
View File
@@ -19,7 +19,7 @@ export type TProjectRole = {
id: string;
createdAt: string;
updatedAt: string;
description?: string;
description?: string | null;
permissions: TProjectPermission[];
};
@@ -76,7 +76,7 @@ export type TDeleteOrgRoleDTO = {
export type TCreateProjectRoleDTO = {
projectId: string;
name: string;
description?: string;
description?: string | null;
slug: string;
permissions: TProjectPermission[];
};
+2 -1
View File
@@ -12,7 +12,8 @@ export enum SecretSync {
Vercel = "vercel",
Windmill = "windmill",
HCVault = "hashicorp-vault",
TeamCity = "teamcity"
TeamCity = "teamcity",
OCIVault = "oci-vault"
}
export enum SecretSyncStatus {
@@ -11,6 +11,7 @@ import { TGcpSync } from "./gcp-sync";
import { TGitHubSync } from "./github-sync";
import { THCVaultSync } from "./hc-vault-sync";
import { THumanitecSync } from "./humanitec-sync";
import { TOCIVaultSync } from "./oci-vault-sync";
import { TTeamCitySync } from "./teamcity-sync";
import { TTerraformCloudSync } from "./terraform-cloud-sync";
import { TVercelSync } from "./vercel-sync";
@@ -36,7 +37,8 @@ export type TSecretSync =
| TVercelSync
| TWindmillSync
| THCVaultSync
| TTeamCitySync;
| TTeamCitySync
| TOCIVaultSync;
export type TListSecretSyncs = { secretSyncs: TSecretSync[] };
@@ -0,0 +1,17 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync";
export type TOCIVaultSync = TRootSecretSync & {
destination: SecretSync.OCIVault;
destinationConfig: {
compartmentOcid: string;
vaultOcid: string;
keyOcid: string;
};
connection: {
app: AppConnection.OCI;
name: string;
id: string;
};
};
+1
View File
@@ -21,6 +21,7 @@ export type TSshHost = {
hostCertTtl: string;
loginMappings: TLoginMapping[];
};
export type TCreateSshHostDTO = {
projectId: string;
hostname: string;
@@ -35,6 +35,7 @@ export {
useListWorkspaceGroups,
useListWorkspacePkiAlerts,
useListWorkspacePkiCollections,
useListWorkspacePkiSubscribers,
useListWorkspaceSshCas,
useListWorkspaceSshCertificates,
useListWorkspaceSshCertificateTemplates,
@@ -14,6 +14,7 @@ import { IntegrationAuth } from "../integrationAuth/types";
import { TIntegration } from "../integrations/types";
import { TPkiAlert } from "../pkiAlerts/types";
import { TPkiCollection } from "../pkiCollections/types";
import { TPkiSubscriber } from "../pkiSubscriber/types";
import { EncryptedSecret } from "../secrets/types";
import { TSshCertificate, TSshCertificateAuthority } from "../sshCa/types";
import { TSshCertificateTemplate } from "../sshCertificateTemplates/types";
@@ -874,6 +875,21 @@ export const useListWorkspaceSshHosts = (projectId: string) => {
});
};
export const useListWorkspacePkiSubscribers = (projectId: string) => {
return useQuery({
queryKey: workspaceKeys.getWorkspacePkiSubscribers(projectId),
queryFn: async () => {
const {
data: { subscribers }
} = await apiRequest.get<{ subscribers: TPkiSubscriber[] }>(
`/api/v2/workspace/${projectId}/pki-subscribers`
);
return subscribers;
},
enabled: Boolean(projectId)
});
};
export const useListWorkspaceSshHostGroups = (projectId: string) => {
return useQuery({
queryKey: workspaceKeys.getWorkspaceSshHostGroups(projectId),
@@ -54,6 +54,8 @@ export const workspaceKeys = {
}) => [...workspaceKeys.forWorkspaceCertificates(slug), { offset, limit }] as const,
getWorkspacePkiAlerts: (workspaceId: string) =>
[{ workspaceId }, "workspace-pki-alerts"] as const,
getWorkspacePkiSubscribers: (projectId: string) =>
[{ projectId }, "workspace-pki-subscribers"] as const,
getWorkspacePkiCollections: (workspaceId: string) =>
[{ workspaceId }, "workspace-pki-collections"] as const,
getWorkspaceCertificateTemplates: (workspaceId: string) =>