1 | |
2 |
|
3 | async function connect(auth: RT.F5Bigip): Promise<{ |
4 | base: string |
5 | headers: { [key: string]: string } |
6 | release: () => Promise<void> |
7 | }> { |
8 | const base = auth.base_url.replace(/\/+$/, "") |
9 | if (auth.auth_method === "basic") { |
10 | return { |
11 | base, |
12 | headers: { |
13 | Authorization: `Basic ${btoa(`${auth.username}:${auth.password}`)}`, |
14 | }, |
15 | release: async () => {}, |
16 | } |
17 | } |
18 | const login = await fetch(`${base}/mgmt/shared/authn/login`, { |
19 | method: "POST", |
20 | headers: { "Content-Type": "application/json", Accept: "application/json" }, |
21 | body: JSON.stringify({ |
22 | username: auth.username, |
23 | password: auth.password, |
24 | loginProviderName: auth.login_provider_name || "tmos", |
25 | }), |
26 | }) |
27 | if (!login.ok) { |
28 | throw new Error(`${login.status} ${await login.text()}`) |
29 | } |
30 | const token: string = (await login.json()).token.token |
31 | return { |
32 | base, |
33 | headers: { "X-F5-Auth-Token": token }, |
34 | release: async () => { |
35 | await fetch( |
36 | `${base}/mgmt/shared/authz/tokens/${encodeURIComponent(token)}`, |
37 | { |
38 | method: "DELETE", |
39 | headers: { "X-F5-Auth-Token": token }, |
40 | } |
41 | ) |
42 | }, |
43 | } |
44 | } |
45 |
|
46 | |
47 | |
48 | function ref(name: string, partition: string | undefined) { |
49 | const path = name.startsWith("/") ? name : `/${partition || "Common"}/${name}` |
50 | return path.replace(/\//g, "~").replace(/[%?#]/g, encodeURIComponent) |
51 | } |
52 |
|
53 | |
54 | * Apply access policy |
55 | * Apply the access policy of an APM access profile (the "Apply Access Policy" action of the BIG-IP UI), by incrementing the profile's generation. New sessions use the updated policy. |
56 | */ |
57 | export async function main( |
58 | auth: RT.F5Bigip, |
59 | access_profile: string, |
60 | partition: string | undefined |
61 | ) { |
62 | const f5 = await connect(auth) |
63 | try { |
64 | const response = await fetch( |
65 | `${f5.base}/mgmt/tm/apm/profile/access/${ref(access_profile, partition)}`, |
66 | { |
67 | method: "PATCH", |
68 | headers: { |
69 | ...f5.headers, |
70 | "Content-Type": "application/json", |
71 | Accept: "application/json", |
72 | }, |
73 | body: JSON.stringify({ generationAction: "increment" }), |
74 | } |
75 | ) |
76 |
|
77 | if (!response.ok) { |
78 | throw new Error(`${response.status} ${await response.text()}`) |
79 | } |
80 |
|
81 | return await response.json() |
82 | } finally { |
83 | await f5.release() |
84 | } |
85 | } |
86 |
|