PageSourceSearch

https://bruce.tools/_app/immutable/nodes/31.CC5lPCpK.js

js bruce.tools collected 2026-10-09 23:01:27 UTC 13,341 bytes, 164 lines download raw bytes

1import"../chunks/Bzak7iHL.js";import"../chunks/Cu8yTRT6.js";import{x as n,a1 as $,b6 as i,a6 as c,K as T,a_ as a,$ as x,aA as s,aL as S}from"../chunks/tHWzkC21.js";import{h as E}from"../chunks/ClIHA1yg.js";import{C as A}from"../chunks/DSiGV02n.js";import{H as _}from"../chunks/CkwJwLyB.js";import{C as r}from"../chunks/DR00_3tq.js";import{I as C}from"../chunks/C68Ma9LA.js";var q=c('<meta name="description" content="Use your build server to build your first application"/>'),B=c('An endpoint that has a security context enabled requires the following: <ul><li>For personal agents & actions the user must be the owner to trigger the action in the workspace (play button).</li> <li>For personal agents & actions the user must still use a bearer token to trigger the action or agent outside of the dashboard.</li> <li>For organizational / teams the user must have the <em class="text-highlight">Resource Protected</em> permission to trigger the endpoint from the dashboard.</li> <li>For organizational / teams the endpoint must be triggered with the valid bearer token.  Please safe guard your private secret key used to generate bearer tokens.</li></ul>',1),P=c(`<div class="box"><!> <!> <h2>Introduction</h2> <p>Bruce is a lightweight build server designed for efficient iteration and seamless integration with your workflows. In this tutorial, we'll explore the concepts of enabling just-in-time access to your systems and applications.</p> <h2>Requirements & Getting Started</h2> <p>Setting up at least a basic Bruce installation, or following the Build Server guides, will provide a foundation for understanding the concepts in this guide. For reference, visit the <a href="/guides/build-server-1">Build
2        Server, Part 1</a> guide.  Key points that we will focus on include the ability to make use of the Bruce workspace actions to trigger specific events that enable just in time access to your systems.</p> <h2>Theory and architecture behind this problem</h2> <p>Just in time access implies the ability to grant access to a system or application when it is needed, and to revoke that access when it is no longer required. This is a common problem in many organizations, where access to systems is
3        granted for a specific purpose, but the access is not revoked after the task is completed. This can lead to security vulnerabilities and potential data breaches. Bruce provides a solution to this problem by enabling you to create events
4        that can trigger a door opening from the inside of your network, allowing access to a system or application for a specific period of time. This access can be revoked automatically after the task is completed, ensuring that your systems
5        remain secure.  The notion of opening the door from the inside ensures you have a guard internal that can open the door which is something that is extremely hard to do with traditional systems.  Let’s dive into how Bruce can help solve this
6        problem.</p> <p>To reduce the complexity of the problem, we will focus on a simple use case of fully disabling ssh on a linux instance, and only enabling it when access is required, then shortly afterwards disabling it again ensuring that the access is
7        removed once a time window has passed.</p> <h2>Lets build it</h2> <p>To get started, we first need to create a new agent and action on the system.  We can borrow from the build server guides to bootstrap the beginning of this process.  The first step is to create a systemd unit file that
8        starts the agent on boot and ensures that it is always running.  This is a simple process that can be done by creating a new file in <em class="text-highlight">/etc/systemd/system/bruce-agent.service</em> with the following contents:</p> <!> <p>As with before the unit file starts bruce in server mode and points to a local file (can be remote also, for the root configuration). An example of this base configuration looks like below:</p> <!> <p>Some key items to review here which is slightly different from previous guides include the use of the scp:// protocol to pull the agent configuration from a remote server.  This is a powerful feature of Bruce that allows you to centralize
9        your agent configurations and ensure that they are always up to date.  This allows you to dynamically adapt the agent configuration for your systems as time goes on.  As of this writing the configuration can be read from a local
10        file, s3, scp, http or https locations, giving a massive amount of flexibility not only in how you configure your agents but also in how you manage and maintain them.</p> <p>The new action that was created include a custom actions called <em class="text-highlight">jit-ssh-on</em> and <em class="text-highlight">jit-ssh-off</em> which will be used to enable and disable ssh on the system.  So lets take a look at
11        what these manifests may look like below.</p> <h2>Keeping it Simple</h2> <p>For illustration purposes we will keep this very short and simple, for simplicity sake we'll assume bruce is running as root here.  The first manifest enables 
11SSH on the system, and the second disables it:</p> <p>/etc/bruce/just-in-time-ssh-on.yml:</p> <!> <p>/etc/bruce/just-in-time-ssh-off.yml:</p> <!> <h2>Let’s Review</h2> <p>While this is an extremely simple example, in reality you may want to set SELinux contexts, update the firewall or updating additional things, the key takeaway here is that even in this simple example we can ensure that SSH is only enabled
12        when it is needed and disabled when it is not.  This capability ensures your systems are secure by granting access only when required and revoking it once it's no longer needed.</p> <h2>Make It Actionable</h2> <p>The final part of this guide is to make it actionable from outside of the system. Something sends our man on the inside a message to open the door.  This is done in the bruce.tools workspace.  As before we create 2 new actions in the
13        workspace that map to the <em class="text-highlight">jit-ssh-on</em> and <em class="text-highlight">jit-ssh-off</em> actions.  Once these are created you can trigger them by clicking the play button in the workspace.  You can also trigger
14        them via their respective endpoints, be sure to enable a security key for these actions to ensure that only authorized users and systems can trigger them.</p> <p>For brevity the process of creating the actions is not shown here, but it is the same as in the build server guides.  The key takeaway is that you can create custom actions to enable and disable SSH on your systems, triggered securely from
15        external sources within your control.</p> <h2>Endpoint Security</h2> <!> <p>To ensure that these capabilities do not get misused you should consider adding a security context to your actions and agents.  This ensures that you make use of a secure token that will be able to trigger the endpoint and no other means
16        will be allowed, preventing a regular person from doing a curl command to gain access to your box without the appropriate entitlements or access.</p> <p>Once you apply a Security Context (Checkbox when creating & editing your action) you will be presented by a Secret Key input box that you can either use the generate button to generate a key or use your own provided key.  The key will be
17        used in order to generate the bearer token that will be evaluated on the server side.  Examples of how to create a sha-256 bearer token is below:</p> <p>Bash</p> <!> <p>Golang</p> <!> <p>Python</p> <!> <p>JavaScript</p> <!> <h2>Conclusion</h2> <p>In this guide we have looked at how to enable just in time access to your systems and applications using Bruce. By creating custom actions that can be triggered from the outside, you can ensure that access is only granted when it is
18        needed and that it is revoked when it is no longer required. This is a powerful capability that can be used to ensure that your systems are secure and that access is only granted when it is needed.  Additionally, this capability can extend to
19        running automated playbooks and other tasks, eliminating the need for manual system access.  We’ll explore this further in an upcoming NOC/SOC runbook guide.</p></div>`);function G(v){var l=P();E("rfctiu",e=>{var o=q();$(()=>{x.title="Bruce - Just-in-Time Access"}),n(e,o)});var h=T(l);A(h,{alignment:"center",image:"/pictures/digital-corridor.jpg",title:"Just in time Access",subTitle:"Access when you need it!"});var u=a(h,2);_(u,{title:"Just in time access",type:"h2"});var d=a(u,20);r(d,{language:"yaml",children:(e,o)=>{s();var t=i(`[Unit]
20Description=Bruce Build Server
21After=docker.service
22Requires=docker.service
23
24[Service]
25User=bruce
26Group=bruce
27TimeoutStartSec=5
28Restart=always
29ExecStart=/usr/local/bin/bruce server /etc/bruce/node.yml
30
31[Install]
32WantedBy=multi-user.target`);n(e,t)},$$slots:{default:!0}});var p=a(d,4);r(p,{language:"yaml",children:(e,o)=>{s();var t=i(`---
33endpoint: <Agent Endpoint>
34runner-id: <Agent ID>
35authorization: <Auth Key>
36execution:
37- name: node action
38  action: default
39  type: event
40  target: scp://secure-access-server.yourdomain.com/$(hostname -f)/agent.yml
41- name: just in time ssh
42  action: jit-ssh-on
43  type: event
44  target: /etc/bruce/just-in-time-ssh-on.yml
45- name: just in time ssh off
46  action: jit-ssh-off
47  type: event
48  target: /etc/bruce/just-in-time-ssh-off.yml`);n(e,t)},$$slots:{default:!0}});var m=a(p,12);r(m,{language:"yaml",children:(e,o)=>{s();var t=i(`---
49steps:
50- cmd: /usr/bin/systemctl start sshd`);n(e,t)},$$slots:{default:!0}});var y=a(m,4);r(y,{language:"yaml",children:(e,o)=>{s();var t=i(`---
51steps:
52- cmd: /usr/bin/systemctl stop sshd`);n(e,t)},$$slots:{default:!0}});var g=a(y,14);C(g,{type:"info",children:(e,o)=>{s();var t=B();s(),n(e,t)},$$slots:{default:!0}});var f=a(g,8);r(f,{language:"bash",children:(e,o)=>{s();var t=i(`#!/bin/bash
53# Variables
54ENDPOINT="https://bruce.tools/your-endpoint"
55SECURITY_KEY="your-security-key"
56TIMESTAMP=$(date +%s)
57
58# Create payload and token
59PAYLOAD="\${\\"key\\":\\"$SECURITY_KEY\\",\\"iat\\":$TIMESTAMP}"
60TOKEN=$(echo -n $PAYLOAD | openssl dgst -sha256 -hmac $SECURITY_KEY | awk '\${print $2}')
61
62# Make the GET request
63curl -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" $ENDPOINT`);n(e,t)},$$slots:{default:!0}});var b=a(f,4);r(b,{language:"go",children:(e,o)=>{s();var t=i(`package main
64
65import (
66    "crypto/hmac"
67    "crypto/sha256"
68    "encoding/hex"
69    "fmt"
70    "net/http"
71    "time"
72)
73
74func main() \${
75    endpoint := "https://bruce.tools/your-endpoint"
76    securityKey := "your-security-key"
77
78    // Generate Bearer Token
79    timestamp := time.Now().Unix()
80    payload := fmt.Sprintf(\`\${"key":"%s","iat":%d}\`, securityKey, timestamp)
81    token := generateHMACSHA256(payload, securityKey)
82
83    // Make GET request
84    client := &http.Client\${}
85    req, err := http.NewRequest("GET", endpoint, nil)
86    if err != nil \${
87        fmt.Println("Error creating request:", err)
88        return
89    }
90    req.Header.Set("Authorization", "Bearer "+token)
91    req.Header.Set("Content-Type", "application/json")
92
93    resp, err := client.Do(req)
94    if err != nil \${
95        fmt.Println("Error making request:", err)
96        return
97    }
98    defer resp.Body.Close()
99
100    fmt.Println("Response Status:", resp.Status)
101}
102
103// Function to create an HMAC-SHA256 signature
104func generateHMACSHA256(payload, key string) string \${
105    h := hmac.New(sha256.New, []byte(key))
106    h.Write([]byte(payload))
107    return hex.EncodeToString(h.Sum(nil))
108}`);n(e,t)},$$slots:{default:!0}});var w=a(b,4);r(w,{language:"python",children:(e,o)=>{s();var t=i(`import hashlib
109import hmac
110import time
111import requests
112
113# Variables
114ENDPOINT = "https://bruce.tools/your-endpoint"
115SECURITY_KEY = "your-security-key"
116
117# Generate Bearer Token
118timestamp = int(time.time())
119payload = f'{{"key":"{SECURITY_KEY}","iat":{timestamp}}}'
120token = hmac.new(SECURITY_KEY.encode(), payload.encode(), hashlib.sha256).hexdigest()
121
122# Make GET request
123headers = {
124    "Authorization": f"Bearer {token}",
125    "Content-Type": "application/json"
126}
127response = requests.get(ENDPOINT, headers=headers)
128
129print("Response Status:", response.status_code)
130print("Response Body:", response.text)`);n(e,t)},$$slots:{default:!0}});var k=a(w,4);r(k,{language:"javascript",children:(e,o)=>{s();var t=i(`const crypto = require("crypto");
131const https = require("https");
132
133// Variables
134const endpoint = "https://bruce.tools/your-endpoint";
135const securityKey = "your-security-key";
136
137// Generate Bearer Token
138const timestamp = Math.floor(Date.now() / 1000);
139const payload = \`{"key":"\${securityKey}","iat":\${timestamp}}\`;
140const token = crypto.createHmac("sha256", securityKey).update(payload).digest("hex");
141
142// Make GET request
143const options = {
144    hostname: "bruce.tools",
145    path: "/your-endpoint",
146    method: "GET",
147    headers: {
148        "Authorization": \`Bearer \${token}\`,
149        "Content-Type": "application/json"
150    }
151};
152
153const req = https.request(options, (res) => {
154    console.log(\`Status Code: \${res.statusCode}\`);
155    res.on("data", (data) => {
156    process.stdout.write(data);
157    });
158});
159
160req.on("error", (e) => {
161    console.error(\`Error: \${e.message}\`);
162});
163
164req.end();`);n(e,t)},$$slots:{default:!0}}),s(4),S(l),n(v,l)}export{G as component};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.