Update MI docs for client id/secret

This commit is contained in:
Tuan Dang
2023-12-04 23:04:04 +07:00
parent 8b1eaad7b5
commit 28b617fd89
18 changed files with 52 additions and 71 deletions

View File

@ -531,6 +531,8 @@ export const updateMachineIdentity = async (req: Request, res: Response) => {
if (!machineIdentity) throw ResourceNotFoundError({
message: `Machine identity with id ${machineId} not found`
});
// TODO: validate existing role (if it is currently admin then cant demote it)
const { permission } = await getUserOrgPermissions(req.user._id, machineIdentity.organization.toString());

View File

@ -19,11 +19,11 @@ fetch secrets back from the `/` path of the `development` environment in some pr
Here's a few pointers to get you acquainted with MIs:
- When you create a MI, you get issued a refresh token that can be exchanged for an access token to authenticate with the Infisical API.
- Each MI has a **Client ID** for which you can generate one or more **Client Secret(s)**. Together, a **Client ID** and **Client Secret** can be exchanged for an access token to authenticate with the Infisical API.
- MIs support IP allowlisting; this means you can restrict the usage of a MI access token to a specific IP or CIDR range.
- MIs rely on the role-based permission system to provision access to resources like secrets.
- MIs support expiration, so, if specified, the refresh token of the MI will automatically be defunct after a period of time.
- MIs tracks most recent usage of their refresh and access tokens; they also keeps track of each token's usage count.
- MIs support expiration, so, if specified, the client secret of the MI will automatically be defunct after a period of time.
- MIs tracks most recent usage of their client secrets and access tokens; they also keep track of each token's usage count.
- MIs are editable.
## Using machine identities
@ -32,7 +32,7 @@ In the following steps, we explore how to create and use MIs for your applicatio
<Steps>
<Step title="Creating a MI">
To create a machine identity, head to your Organization Settings > Access Control > Machine Identities and press **Create MI**.
To create a machine identity, head to your Organization Settings > Access Control > Machine Identities and press **Create identity**.
![machine identities organization](../../images/platform/machine-identity/machine-identity-org.png)
@ -42,23 +42,36 @@ In the following steps, we explore how to create and use MIs for your applicatio
- Name (required): A friendly name for the MI
- Role (required): A role from the **Organization Roles** tab to permit the MI to access certain resources.
- Refresh Token Expires In: The number of days from now to deactivate the MI refresh token
- Trusted IPs: The IPs or CIDR ranges that the refresh and access tokens can be used from. By default, each token is given the `0.0.0.0/0` entry representing all possible IPv4 addresses.
- Access Token TTL: The time-to-live for each acccess token in seconds.
- Refresh Token Rotation: Whether or not to return a new refresh token when exchanging an existing refresh token; if enabled, the existing refresh token is invalidated upon the refresh operation.
- 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.
<Warning>
Restricting token usage to specific trusted IPs is a paid feature.
Restricting **Client Secret** and access token usage to specific trusted IPs is a paid feature.
If youre using Infisical Cloud, then it is available under the Pro Tier. If youre self-hosting Infisical, then you should contact team@infisical.com to purchase an enterprise license to use it.
</Warning>
Once you've created the MI, you'll be issued a refresh token for it; copy the token and keep it handy.
</Step>
<Step title="Creating a Client Secret">
In order to use the MI, you'll need the non-sensitive **Client ID**
of the MI and a **Client Secret** for it; you can think of these credentials akin to a username
and password used to authenticate with the Infisical API. With that, press on the key icon on the MI to generate a **Client Secret**
for it.
![machine identities client secret create](../../images/platform/machine-identity/machine-identity-org-client-secret.png)
![machine identities client secret create](../../images/platform/machine-identity/machine-identity-org-client-secret-create-1.png)
![machine identities client secret create](../../images/platform/machine-identity/machine-identity-org-client-secret-create-2.png)
Feel free to input any (optional) details for the **Client Secret** configuration:
- Description: A description for the **Client Secret**.
- TTL: The time-to-live for the **Client Secret**. By default, the TTL will be set to 0 which implies that the **Client Secret** will never expire.
</Step>
<Step title="Adding a MI to a project">
If you intend the MI access project-level resources such as secrets within a specific project, you should add it to that project.
To enable the MI to access project-level resources such as secrets within a specific project, you should add it to that project.
To do this, head over to the project you want to add the MI to and go to Project Settings > Access Control > Machine Identities and press **Add MI**.
To do this, head over to the project you want to add the MI to and go to Project Settings > Access Control > Machine Identities and press **Add identity**.
Next, select the MI you want to add to the project and the role you want to assign it.
@ -67,22 +80,23 @@ In the following steps, we explore how to create and use MIs for your applicatio
![machine identities project create](../../images/platform/machine-identity/machine-identity-project-create.png)
</Step>
<Step title="Accessing the Infisical API with the MI">
To access the Infisical API as the MI, you should first exchange the MI refresh token from **Step 1** for an access token
by making a request to the `/api/v3/machines/me/token` endpoint.
To access the Infisical API as the MI, you should first perform a login operation
that is to exchange the **Client ID** and **Client Secret** of the MI for an access token
by making a request to the `/api/v3/machines/login` endpoint.
#### Sample request
```
curl --location --request POST 'http://localhost:8080/api/v3/machines/me/token' \
curl --location --request POST 'https://app.infisical.com/api/v3/machines/login' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'refreshToken=<token>'
--data-urlencode 'clientSecret=...' \
--data-urlencode 'clientId=...'
```
#### Sample response
```
{
"refreshToken": "...",
"accessToken": "...",
"expiresIn": 7200,
"tokenType": "Bearer"
@ -92,11 +106,11 @@ In the following steps, we explore how to create and use MIs for your applicatio
Next, you can use the access token to authenticate with the [Infisical API](/api-reference/overview/introduction)
<Note>
Each MI access token has a time-to-live (TLL) which you can infer from the response of the refresh token exchange;
Each MI access token has a time-to-live (TLL) which you can infer from the response of the login operation;
the default TTL is `7200` seconds which can be adjusted in the **Advanced** settings of the MI.
If a MI access token expires, it can no longer authenticate with the Infisical API. In this case,
a new access token should be obtained from the refresh token exchange.
a new access token should be obtained from the aforementioned login operation.
</Note>
</Step>
</Steps>
@ -113,10 +127,10 @@ In the following steps, we explore how to create and use MIs for your applicatio
<Accordion title="Why is the Infisical API rejecting my machine identity credentials?">
There are a few reasons for why this might happen:
- The refresh/access token has expired.
- The client secret or access token has expired.
- The MI is insufficently permissioned to interact with the resources you wish to access.
- You are attempting to access a `/raw` secrets endpoint that requires your project to disable E2EE.
- The refresh/access token is being used from an untrusted IP.
- The client secret/access token is being used from an untrusted IP.
</Accordion>
<Accordion title="Can you provide examples for using glob patterns?">
1. `/**`: This pattern matches all folders at any depth in the directory structure. For example, it would match folders like `/folder1/`, `/folder1/subfolder/`, and so on.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -27,7 +27,7 @@ export const MembersPage = withPermission(
<Tab value={TabSections.Member}>People</Tab>
<Tab value={TabSections.MachineIdentities}>
<div className="flex items-center">
<p>App Clients</p>
<p>Machine Identities</p>
<div className="ml-2 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
New
</div>

View File

@ -263,7 +263,7 @@ export const AddMachineIdentityModal = ({
reset();
}}
>
<ModalContent title={`${popUp?.machineIdentity?.data ? "Update" : "Create"} App Client`}>
<ModalContent title={`${popUp?.machineIdentity?.data ? "Update" : "Create"} Machine Identity`}>
<form onSubmit={handleSubmit(onFormSubmit)}>
<Tabs defaultValue={TabSections.General}>
<TabList>

View File

@ -270,7 +270,7 @@ export const CreateClientSecretModal = ({
{!isLoading && data && data?.length === 0 && (
<Tr>
<Td colSpan={4}>
<EmptyState title="No client secrets have been created for this app client yet" icon={faKey} />
<EmptyState title="No client secrets have been created for this machine identity yet" icon={faKey} />
</Td>
</Tr>
)}

View File

@ -51,7 +51,7 @@ export const MachineIdentitySection = withPermission(
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex justify-between mb-8">
<p className="text-xl font-semibold text-mineshaft-100">
App Clients
Machine Identities
</p>
<OrgPermissionCan
I={OrgPermissionActions.Create}
@ -65,7 +65,7 @@ export const MachineIdentitySection = withPermission(
onClick={() => handlePopUpOpen("machineIdentity")}
isDisabled={!isAllowed}
>
Create client
Create identity
</Button>
)}
</OrgPermissionCan>

View File

@ -151,29 +151,9 @@ export const MachineIdentityTable = ({
customRole
}) => {
return (
<Tr className="h-10" key={`st-v3-${_id}`}>
<Tr className="h-10" key={`machine-identity-${_id}`}>
<Td>{name}</Td>
<Td>{clientId}</Td>
{/* <Td>
<OrgPermissionCan
I={OrgPermissionActions.Edit}
a={OrgPermissionSubjects.MachineIdentity}
>
{(isAllowed) => (
<Switch
id={`enable-service-token-${_id}`}
onCheckedChange={(value) => handleToggleStatus({
serviceTokenDataId: _id,
isActive: value
})}
isChecked={isActive}
isDisabled={!isAllowed}
>
<p className="w-12 mr-4">{isActive ? "Active" : "Inactive"}</p>
</Switch>
)}
</OrgPermissionCan>
</Td> */}
<Td>
<OrgPermissionCan
I={OrgPermissionActions.Edit}
@ -206,24 +186,8 @@ export const MachineIdentityTable = ({
}}
</OrgPermissionCan>
</Td>
{/* <Td>
{trustedIps.map(({
_id: trustedIpId,
ipAddress,
prefix
}) => {
return (
<p key={`service-token-${_id}-}-trusted-ip-${trustedIpId}`}>
{`${ipAddress}${prefix !== undefined ? `/${prefix}` : ""}`}
</p>
);
})}
</Td> */}
{/* <Td>{accessTokenTTL}</Td> */}
{/* <Td>{format(new Date(createdAt), "yyyy-MM-dd")}</Td> */}
{/* <Td>{expiresAt ? format(new Date(expiresAt), "yyyy-MM-dd") : "-"}</Td> */}
<Td className="flex justify-end">
<Td>
<div className="flex justify-end items-center">
<Tooltip content="Manage client secrets">
<IconButton
onClick={async () => {
@ -292,6 +256,7 @@ export const MachineIdentityTable = ({
</IconButton>
)}
</OrgPermissionCan>
</div>
</Td>
</Tr>
);
@ -299,7 +264,7 @@ export const MachineIdentityTable = ({
{!isLoading && data && data?.length === 0 && (
<Tr>
<Td colSpan={7}>
<EmptyState title="No app clients have been created in this organization" icon={faServer} />
<EmptyState title="No machine identities have been created in this organization" icon={faServer} />
</Td>
</Tr>
)}

View File

@ -32,7 +32,7 @@ export const MembersPage = withProjectPermission(
<Tab value={TabSections.Member}>People</Tab>
<Tab value={TabSections.MachineIdentities}>
<div className="flex items-center">
<p>App Clients</p>
<p>Machine Identities</p>
<div className="ml-2 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
New
</div>

View File

@ -120,7 +120,7 @@ export const AddMachineIdentityModal = ({
reset();
}}
>
<ModalContent title="Add App Client to Project">
<ModalContent title="Add Machine Identity to Project">
{filteredMachineMembershipOrgs.length ? (
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
@ -129,7 +129,7 @@ export const AddMachineIdentityModal = ({
defaultValue={filteredMachineMembershipOrgs?.[0]?._id}
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl
label="App Client"
label="Machine Identity"
errorText={error?.message}
isError={Boolean(error)}
>

View File

@ -62,7 +62,7 @@ export const MachineIdentitySection = withProjectPermission(
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex justify-between mb-8">
<p className="text-xl font-semibold text-mineshaft-100">
App Clients
Machine Identities
</p>
<ProjectPermissionCan
I={ProjectPermissionActions.Create}
@ -76,7 +76,7 @@ export const MachineIdentitySection = withProjectPermission(
onClick={() => handlePopUpOpen("machineIdentity")}
isDisabled={!isAllowed}
>
Add client
Add identity
</Button>
)}
</ProjectPermissionCan>

View File

@ -188,7 +188,7 @@ export const MachineIdentityTable = ({
{!isLoading && data && data?.length === 0 && (
<Tr>
<Td colSpan={7}>
<EmptyState title="No app clients have been added to this project" icon={faServer} />
<EmptyState title="No machine identities have been added to this project" icon={faServer} />
</Td>
</Tr>
)}