mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-10 18:29:07 +00:00
add tenancy OCID requirement
This commit is contained in:
@@ -16,6 +16,7 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||||
t.string("type").notNullable();
|
t.string("type").notNullable();
|
||||||
|
|
||||||
|
t.string("tenancyOcid").notNullable();
|
||||||
t.string("allowedUsernames").notNullable();
|
t.string("allowedUsernames").notNullable();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export const IdentityOciAuthsSchema = z.object({
|
|||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
identityId: z.string().uuid(),
|
identityId: z.string().uuid(),
|
||||||
type: z.string(),
|
type: z.string(),
|
||||||
|
tenancyOcid: z.string(),
|
||||||
allowedUsernames: z.string()
|
allowedUsernames: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1021,6 +1021,7 @@ interface AddIdentityOciAuthEvent {
|
|||||||
type: EventType.ADD_IDENTITY_OCI_AUTH;
|
type: EventType.ADD_IDENTITY_OCI_AUTH;
|
||||||
metadata: {
|
metadata: {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
|
tenancyOcid: string;
|
||||||
allowedUsernames: string;
|
allowedUsernames: string;
|
||||||
accessTokenTTL: number;
|
accessTokenTTL: number;
|
||||||
accessTokenMaxTTL: number;
|
accessTokenMaxTTL: number;
|
||||||
@@ -1040,6 +1041,7 @@ interface UpdateIdentityOciAuthEvent {
|
|||||||
type: EventType.UPDATE_IDENTITY_OCI_AUTH;
|
type: EventType.UPDATE_IDENTITY_OCI_AUTH;
|
||||||
metadata: {
|
metadata: {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
|
tenancyOcid?: string;
|
||||||
allowedUsernames?: string;
|
allowedUsernames?: string;
|
||||||
accessTokenTTL?: number;
|
accessTokenTTL?: number;
|
||||||
accessTokenMaxTTL?: number;
|
accessTokenMaxTTL?: number;
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ export const OCI_AUTH = {
|
|||||||
},
|
},
|
||||||
ATTACH: {
|
ATTACH: {
|
||||||
identityId: "The ID of the identity to attach the configuration onto.",
|
identityId: "The ID of the identity to attach the configuration onto.",
|
||||||
|
tenancyOcid: "The OCID of your tenancy.",
|
||||||
allowedUsernames:
|
allowedUsernames:
|
||||||
"The comma-separated list of trusted OCI account usernames that are allowed to authenticate with Infisical.",
|
"The comma-separated list of trusted OCI account usernames that are allowed to authenticate with Infisical.",
|
||||||
accessTokenTTL: "The lifetime for an access token in seconds.",
|
accessTokenTTL: "The lifetime for an access token in seconds.",
|
||||||
@@ -288,6 +289,7 @@ export const OCI_AUTH = {
|
|||||||
},
|
},
|
||||||
UPDATE: {
|
UPDATE: {
|
||||||
identityId: "The ID of the identity to update the auth method for.",
|
identityId: "The ID of the identity to update the auth method for.",
|
||||||
|
tenancyOcid: "The OCID of your tenancy.",
|
||||||
allowedUsernames:
|
allowedUsernames:
|
||||||
"The comma-separated list of trusted OCI account usernames that are allowed to authenticate with Infisical.",
|
"The comma-separated list of trusted OCI account usernames that are allowed to authenticate with Infisical.",
|
||||||
accessTokenTTL: "The new lifetime for an access token in seconds.",
|
accessTokenTTL: "The new lifetime for an access token in seconds.",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
|||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
import { TIdentityTrustedIp } from "@app/services/identity/identity-types";
|
import { TIdentityTrustedIp } from "@app/services/identity/identity-types";
|
||||||
import { validateUsernames } from "@app/services/identity-oci-auth/identity-oci-auth-validators";
|
import { validateTenancy, validateUsernames } from "@app/services/identity-oci-auth/identity-oci-auth-validators";
|
||||||
import { isSuperAdmin } from "@app/services/super-admin/super-admin-fns";
|
import { isSuperAdmin } from "@app/services/super-admin/super-admin-fns";
|
||||||
|
|
||||||
export const registerIdentityOciAuthRouter = async (server: FastifyZodProvider) => {
|
export const registerIdentityOciAuthRouter = async (server: FastifyZodProvider) => {
|
||||||
@@ -88,6 +88,7 @@ export const registerIdentityOciAuthRouter = async (server: FastifyZodProvider)
|
|||||||
}),
|
}),
|
||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
|
tenancyOcid: validateTenancy.describe(OCI_AUTH.ATTACH.tenancyOcid),
|
||||||
allowedUsernames: validateUsernames.describe(OCI_AUTH.ATTACH.allowedUsernames),
|
allowedUsernames: validateUsernames.describe(OCI_AUTH.ATTACH.allowedUsernames),
|
||||||
accessTokenTrustedIps: z
|
accessTokenTrustedIps: z
|
||||||
.object({
|
.object({
|
||||||
@@ -141,6 +142,7 @@ export const registerIdentityOciAuthRouter = async (server: FastifyZodProvider)
|
|||||||
type: EventType.ADD_IDENTITY_OCI_AUTH,
|
type: EventType.ADD_IDENTITY_OCI_AUTH,
|
||||||
metadata: {
|
metadata: {
|
||||||
identityId: identityOciAuth.identityId,
|
identityId: identityOciAuth.identityId,
|
||||||
|
tenancyOcid: identityOciAuth.tenancyOcid,
|
||||||
allowedUsernames: identityOciAuth.allowedUsernames,
|
allowedUsernames: identityOciAuth.allowedUsernames,
|
||||||
accessTokenTTL: identityOciAuth.accessTokenTTL,
|
accessTokenTTL: identityOciAuth.accessTokenTTL,
|
||||||
accessTokenMaxTTL: identityOciAuth.accessTokenMaxTTL,
|
accessTokenMaxTTL: identityOciAuth.accessTokenMaxTTL,
|
||||||
@@ -175,6 +177,7 @@ export const registerIdentityOciAuthRouter = async (server: FastifyZodProvider)
|
|||||||
}),
|
}),
|
||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
|
tenancyOcid: validateTenancy.describe(OCI_AUTH.UPDATE.tenancyOcid),
|
||||||
allowedUsernames: validateUsernames.describe(OCI_AUTH.UPDATE.allowedUsernames),
|
allowedUsernames: validateUsernames.describe(OCI_AUTH.UPDATE.allowedUsernames),
|
||||||
accessTokenTrustedIps: z
|
accessTokenTrustedIps: z
|
||||||
.object({
|
.object({
|
||||||
@@ -221,6 +224,7 @@ export const registerIdentityOciAuthRouter = async (server: FastifyZodProvider)
|
|||||||
type: EventType.UPDATE_IDENTITY_OCI_AUTH,
|
type: EventType.UPDATE_IDENTITY_OCI_AUTH,
|
||||||
metadata: {
|
metadata: {
|
||||||
identityId: identityOciAuth.identityId,
|
identityId: identityOciAuth.identityId,
|
||||||
|
tenancyOcid: identityOciAuth.tenancyOcid,
|
||||||
allowedUsernames: identityOciAuth.allowedUsernames,
|
allowedUsernames: identityOciAuth.allowedUsernames,
|
||||||
accessTokenTTL: identityOciAuth.accessTokenTTL,
|
accessTokenTTL: identityOciAuth.accessTokenTTL,
|
||||||
accessTokenMaxTTL: identityOciAuth.accessTokenMaxTTL,
|
accessTokenMaxTTL: identityOciAuth.accessTokenMaxTTL,
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ export const identityOciAuthServiceFactory = ({
|
|||||||
headers
|
headers
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (data.compartmentId !== identityOciAuth.tenancyOcid) {
|
||||||
|
throw new UnauthorizedError({
|
||||||
|
message: "Access denied: OCI account isn't part of tenancy."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (identityOciAuth.allowedUsernames) {
|
if (identityOciAuth.allowedUsernames) {
|
||||||
const isAccountAllowed = identityOciAuth.allowedUsernames.split(",").some((name) => name.trim() === data.name);
|
const isAccountAllowed = identityOciAuth.allowedUsernames.split(",").some((name) => name.trim() === data.name);
|
||||||
|
|
||||||
@@ -121,6 +127,7 @@ export const identityOciAuthServiceFactory = ({
|
|||||||
|
|
||||||
const attachOciAuth = async ({
|
const attachOciAuth = async ({
|
||||||
identityId,
|
identityId,
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames,
|
allowedUsernames,
|
||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
@@ -179,6 +186,7 @@ export const identityOciAuthServiceFactory = ({
|
|||||||
{
|
{
|
||||||
identityId: identityMembershipOrg.identityId,
|
identityId: identityMembershipOrg.identityId,
|
||||||
type: "iam",
|
type: "iam",
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames,
|
allowedUsernames,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
@@ -194,6 +202,7 @@ export const identityOciAuthServiceFactory = ({
|
|||||||
|
|
||||||
const updateOciAuth = async ({
|
const updateOciAuth = async ({
|
||||||
identityId,
|
identityId,
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames,
|
allowedUsernames,
|
||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
@@ -250,6 +259,7 @@ export const identityOciAuthServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const updatedOciAuth = await identityOciAuthDAL.updateById(identityOciAuth.id, {
|
const updatedOciAuth = await identityOciAuthDAL.updateById(identityOciAuth.id, {
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames,
|
allowedUsernames,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type TLoginOciAuthDTO = {
|
|||||||
|
|
||||||
export type TAttachOciAuthDTO = {
|
export type TAttachOciAuthDTO = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
|
tenancyOcid: string;
|
||||||
allowedUsernames: string;
|
allowedUsernames: string;
|
||||||
accessTokenTTL: number;
|
accessTokenTTL: number;
|
||||||
accessTokenMaxTTL: number;
|
accessTokenMaxTTL: number;
|
||||||
@@ -22,6 +23,7 @@ export type TAttachOciAuthDTO = {
|
|||||||
|
|
||||||
export type TUpdateOciAuthDTO = {
|
export type TUpdateOciAuthDTO = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
|
tenancyOcid?: string;
|
||||||
allowedUsernames?: string;
|
allowedUsernames?: string;
|
||||||
accessTokenTTL?: number;
|
accessTokenTTL?: number;
|
||||||
accessTokenMaxTTL?: number;
|
accessTokenMaxTTL?: number;
|
||||||
|
|||||||
@@ -19,3 +19,12 @@ export const validateUsernames = z
|
|||||||
message: "One or more usernames are invalid"
|
message: "One or more usernames are invalid"
|
||||||
})
|
})
|
||||||
.transform((arr) => arr.join(", "));
|
.transform((arr) => arr.join(", "));
|
||||||
|
|
||||||
|
export const validateTenancy = z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1, "Tenancy OCID cannot be empty.")
|
||||||
|
.refine(
|
||||||
|
(val) => new RE2("^ocid1\\.tenancy\\.oc1\\..+$").test(val),
|
||||||
|
"Invalid Tenancy OCID format. Must start with ocid1.tenancy.oc1."
|
||||||
|
);
|
||||||
|
|||||||
@@ -461,6 +461,7 @@ export const useAddIdentityOciAuth = () => {
|
|||||||
return useMutation<IdentityOciAuth, object, AddIdentityOciAuthDTO>({
|
return useMutation<IdentityOciAuth, object, AddIdentityOciAuthDTO>({
|
||||||
mutationFn: async ({
|
mutationFn: async ({
|
||||||
identityId,
|
identityId,
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames,
|
allowedUsernames,
|
||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
@@ -472,6 +473,7 @@ export const useAddIdentityOciAuth = () => {
|
|||||||
} = await apiRequest.post<{ identityOciAuth: IdentityOciAuth }>(
|
} = await apiRequest.post<{ identityOciAuth: IdentityOciAuth }>(
|
||||||
`/api/v1/auth/oci-auth/identities/${identityId}`,
|
`/api/v1/auth/oci-auth/identities/${identityId}`,
|
||||||
{
|
{
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames,
|
allowedUsernames,
|
||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
@@ -497,6 +499,7 @@ export const useUpdateIdentityOciAuth = () => {
|
|||||||
return useMutation<IdentityOciAuth, object, UpdateIdentityOciAuthDTO>({
|
return useMutation<IdentityOciAuth, object, UpdateIdentityOciAuthDTO>({
|
||||||
mutationFn: async ({
|
mutationFn: async ({
|
||||||
identityId,
|
identityId,
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames,
|
allowedUsernames,
|
||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
@@ -508,6 +511,7 @@ export const useUpdateIdentityOciAuth = () => {
|
|||||||
} = await apiRequest.patch<{ identityOciAuth: IdentityOciAuth }>(
|
} = await apiRequest.patch<{ identityOciAuth: IdentityOciAuth }>(
|
||||||
`/api/v1/auth/oci-auth/identities/${identityId}`,
|
`/api/v1/auth/oci-auth/identities/${identityId}`,
|
||||||
{
|
{
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames,
|
allowedUsernames,
|
||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ export type DeleteIdentityAwsAuthDTO = {
|
|||||||
export type IdentityOciAuth = {
|
export type IdentityOciAuth = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
type: "iam";
|
type: "iam";
|
||||||
|
tenancyOcid: string;
|
||||||
allowedUsernames: string;
|
allowedUsernames: string;
|
||||||
accessTokenTTL: number;
|
accessTokenTTL: number;
|
||||||
accessTokenMaxTTL: number;
|
accessTokenMaxTTL: number;
|
||||||
@@ -303,6 +304,7 @@ export type IdentityOciAuth = {
|
|||||||
export type AddIdentityOciAuthDTO = {
|
export type AddIdentityOciAuthDTO = {
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
identityId: string;
|
identityId: string;
|
||||||
|
tenancyOcid: string;
|
||||||
allowedUsernames: string;
|
allowedUsernames: string;
|
||||||
accessTokenTTL: number;
|
accessTokenTTL: number;
|
||||||
accessTokenMaxTTL: number;
|
accessTokenMaxTTL: number;
|
||||||
@@ -315,6 +317,7 @@ export type AddIdentityOciAuthDTO = {
|
|||||||
export type UpdateIdentityOciAuthDTO = {
|
export type UpdateIdentityOciAuthDTO = {
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
identityId: string;
|
identityId: string;
|
||||||
|
tenancyOcid?: string;
|
||||||
allowedUsernames?: string;
|
allowedUsernames?: string;
|
||||||
accessTokenTTL?: number;
|
accessTokenTTL?: number;
|
||||||
accessTokenMaxTTL?: number;
|
accessTokenMaxTTL?: number;
|
||||||
|
|||||||
+17
@@ -29,6 +29,7 @@ import { IdentityFormTab } from "./types";
|
|||||||
|
|
||||||
const schema = z
|
const schema = z
|
||||||
.object({
|
.object({
|
||||||
|
tenancyOcid: z.string().trim().min(1, "Tenancy OCID is required."),
|
||||||
allowedUsernames: z.string(),
|
allowedUsernames: z.string(),
|
||||||
accessTokenTTL: z
|
accessTokenTTL: z
|
||||||
.string()
|
.string()
|
||||||
@@ -90,6 +91,7 @@ export const IdentityOciAuthForm = ({
|
|||||||
} = useForm<FormData>({
|
} = useForm<FormData>({
|
||||||
resolver: zodResolver(schema),
|
resolver: zodResolver(schema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
|
tenancyOcid: "",
|
||||||
allowedUsernames: "",
|
allowedUsernames: "",
|
||||||
accessTokenTTL: "2592000",
|
accessTokenTTL: "2592000",
|
||||||
accessTokenMaxTTL: "2592000",
|
accessTokenMaxTTL: "2592000",
|
||||||
@@ -107,6 +109,7 @@ export const IdentityOciAuthForm = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
reset({
|
reset({
|
||||||
|
tenancyOcid: data.tenancyOcid,
|
||||||
allowedUsernames: data.allowedUsernames,
|
allowedUsernames: data.allowedUsernames,
|
||||||
accessTokenTTL: String(data.accessTokenTTL),
|
accessTokenTTL: String(data.accessTokenTTL),
|
||||||
accessTokenMaxTTL: String(data.accessTokenMaxTTL),
|
accessTokenMaxTTL: String(data.accessTokenMaxTTL),
|
||||||
@@ -121,6 +124,7 @@ export const IdentityOciAuthForm = ({
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
reset({
|
reset({
|
||||||
|
tenancyOcid: "",
|
||||||
allowedUsernames: "",
|
allowedUsernames: "",
|
||||||
accessTokenTTL: "2592000",
|
accessTokenTTL: "2592000",
|
||||||
accessTokenMaxTTL: "2592000",
|
accessTokenMaxTTL: "2592000",
|
||||||
@@ -131,6 +135,7 @@ export const IdentityOciAuthForm = ({
|
|||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const onFormSubmit = async ({
|
const onFormSubmit = async ({
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames,
|
allowedUsernames,
|
||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
@@ -143,6 +148,7 @@ export const IdentityOciAuthForm = ({
|
|||||||
if (data) {
|
if (data) {
|
||||||
await updateMutateAsync({
|
await updateMutateAsync({
|
||||||
organizationId: orgId,
|
organizationId: orgId,
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames,
|
allowedUsernames,
|
||||||
identityId,
|
identityId,
|
||||||
accessTokenTTL: Number(accessTokenTTL),
|
accessTokenTTL: Number(accessTokenTTL),
|
||||||
@@ -154,6 +160,7 @@ export const IdentityOciAuthForm = ({
|
|||||||
await addMutateAsync({
|
await addMutateAsync({
|
||||||
organizationId: orgId,
|
organizationId: orgId,
|
||||||
identityId,
|
identityId,
|
||||||
|
tenancyOcid,
|
||||||
allowedUsernames: allowedUsernames || "",
|
allowedUsernames: allowedUsernames || "",
|
||||||
accessTokenTTL: Number(accessTokenTTL),
|
accessTokenTTL: Number(accessTokenTTL),
|
||||||
accessTokenMaxTTL: Number(accessTokenMaxTTL),
|
accessTokenMaxTTL: Number(accessTokenMaxTTL),
|
||||||
@@ -194,12 +201,22 @@ export const IdentityOciAuthForm = ({
|
|||||||
<Tab value={IdentityFormTab.Advanced}>Advanced</Tab>
|
<Tab value={IdentityFormTab.Advanced}>Advanced</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanel value={IdentityFormTab.Configuration}>
|
<TabPanel value={IdentityFormTab.Configuration}>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="tenancyOcid"
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl label="Tenancy OCID" isError={Boolean(error)} errorText={error?.message}>
|
||||||
|
<Input {...field} placeholder="ocid1.tenancy.oc1..example" />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="allowedUsernames"
|
name="allowedUsernames"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Allowed Usernames"
|
label="Allowed Usernames"
|
||||||
|
isOptional
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
>
|
>
|
||||||
|
|||||||
+3
@@ -59,6 +59,9 @@ export const ViewIdentityOciAuthContent = ({
|
|||||||
<IdentityAuthFieldDisplay label="Access Token Trusted IPs">
|
<IdentityAuthFieldDisplay label="Access Token Trusted IPs">
|
||||||
{data.accessTokenTrustedIps.map((ip) => ip.ipAddress).join(", ")}
|
{data.accessTokenTrustedIps.map((ip) => ip.ipAddress).join(", ")}
|
||||||
</IdentityAuthFieldDisplay>
|
</IdentityAuthFieldDisplay>
|
||||||
|
<IdentityAuthFieldDisplay className="col-span-2" label="Tenancy OCID">
|
||||||
|
{data.tenancyOcid}
|
||||||
|
</IdentityAuthFieldDisplay>
|
||||||
<IdentityAuthFieldDisplay className="col-span-2" label="Allowed Usernames">
|
<IdentityAuthFieldDisplay className="col-span-2" label="Allowed Usernames">
|
||||||
{data.allowedUsernames
|
{data.allowedUsernames
|
||||||
?.split(",")
|
?.split(",")
|
||||||
|
|||||||
Reference in New Issue
Block a user