Add agentless adoption tool for endpoints
Standalone one-shot enrollment tool that creates a ShopDB PC + Endpoint entry using only the endpoints collector key, reusing the existing collector adopt path. Collects identity, WMI hardware, and installed-software SBOM; requires admin. Server-side packaging route attaches to the existing endpoints blueprint; no core contract change.
This commit is contained in:
committed by
cproudlock
parent
cfb0b9ca4e
commit
7040832565
@@ -138,6 +138,57 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ====================================================================
|
||||
Adoption tool (spike)
|
||||
================================================================= -->
|
||||
<section class="settings-section">
|
||||
<h3>Adoption tool</h3>
|
||||
<div class="card form-card">
|
||||
<p class="field-hint">
|
||||
Generate a one-shot, agentless enrollment tool. Run it once on a PC and
|
||||
it creates a ShopDB PC and Endpoint entry using only the collector key -
|
||||
no service, no polling, no ongoing telemetry. Use this for machines you
|
||||
want inventoried without running the full endpoint agent.
|
||||
</p>
|
||||
<p class="field-hint">
|
||||
Paste a collector key below (generate one above first; the secret is
|
||||
only shown once). The key is embedded in the downloaded config and is
|
||||
not stored on the server.
|
||||
</p>
|
||||
|
||||
<label class="field-label" for="adopt-baseurl">Server base URL</label>
|
||||
<input
|
||||
id="adopt-baseurl"
|
||||
v-model="adoptbaseurl"
|
||||
class="form-control"
|
||||
type="text"
|
||||
placeholder="https://shopdb.example"
|
||||
/>
|
||||
|
||||
<label class="field-label" for="adopt-key">Collector key</label>
|
||||
<input
|
||||
id="adopt-key"
|
||||
v-model="adoptcollectorkey"
|
||||
class="form-control mono"
|
||||
type="text"
|
||||
placeholder="Paste the endpoint agent key"
|
||||
/>
|
||||
|
||||
<div class="button-row">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
:disabled="adoptbusy || !adoptbaseurl || !adoptcollectorkey"
|
||||
@click="downloadAdoptionTool"
|
||||
>
|
||||
{{ adoptbusy ? 'Building...' : 'Download adoption tool' }}
|
||||
</button>
|
||||
</div>
|
||||
<p v-if="adoptmessage" class="field-hint">{{ adoptmessage }}</p>
|
||||
<p v-if="adopterror" class="field-error">{{ adopterror }}</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ====================================================================
|
||||
Build site agent (placeholder)
|
||||
================================================================= -->
|
||||
@@ -197,6 +248,13 @@ const copied = ref(false)
|
||||
const message = ref('')
|
||||
const error = ref('')
|
||||
|
||||
// Adoption tool (spike): build a one-shot, agentless enrollment download.
|
||||
const adoptbaseurl = ref('')
|
||||
const adoptcollectorkey = ref('')
|
||||
const adoptbusy = ref(false)
|
||||
const adoptmessage = ref('')
|
||||
const adopterror = ref('')
|
||||
|
||||
function formatDate(value) {
|
||||
if (!value) return ''
|
||||
const parsed = new Date(value)
|
||||
@@ -209,6 +267,7 @@ function applyStatus(data) {
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
adoptbaseurl.value = window.location.origin
|
||||
try {
|
||||
const response = await api.get('/endpoints/agentkey')
|
||||
applyStatus(response.data.data || {})
|
||||
@@ -238,6 +297,9 @@ async function regenerate() {
|
||||
const data = response.data.data || {}
|
||||
applyStatus(data)
|
||||
secret.value = data.secret || ''
|
||||
if (data.secret) {
|
||||
adoptcollectorkey.value = data.secret
|
||||
}
|
||||
message.value = 'Endpoint agent key generated.'
|
||||
} catch (regenError) {
|
||||
error.value = regenError.response?.data?.data?.error?.message
|
||||
@@ -276,6 +338,34 @@ async function copySecret() {
|
||||
console.error(copyError)
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadAdoptionTool() {
|
||||
adoptbusy.value = true
|
||||
adoptmessage.value = ''
|
||||
adopterror.value = ''
|
||||
try {
|
||||
const response = await api.post(
|
||||
'/endpoints/adoptiontool/package',
|
||||
{ baseurl: adoptbaseurl.value, collectorkey: adoptcollectorkey.value },
|
||||
{ responseType: 'blob' })
|
||||
const url = window.URL.createObjectURL(response.data)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = 'shopdb-adoption-tool.zip'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
link.remove()
|
||||
window.URL.revokeObjectURL(url)
|
||||
adoptmessage.value = 'Adoption tool downloaded.'
|
||||
} catch (downloadError) {
|
||||
adopterror.value = downloadError.response?.status === 403
|
||||
? 'Only an administrator can build the adoption tool'
|
||||
: 'Could not build the adoption tool'
|
||||
console.error(downloadError)
|
||||
} finally {
|
||||
adoptbusy.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user