venafi-connector-machine 1.0.5 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -9
- package/bundle.mjs +79 -6
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# venafi-connector-machine
|
|
2
2
|
|
|
3
|
-
An MCP (Model Context Protocol) server that provides machine connector-specific knowledge, templates, and tools for building **Venafi
|
|
3
|
+
An MCP (Model Context Protocol) server that provides machine connector-specific knowledge, templates, and tools for building **Venafi machine connectors**.
|
|
4
4
|
|
|
5
5
|
Use this with Claude Code or any MCP-compatible AI assistant to get expert guidance on SSH and REST API machine connectors — discovery, provisioning, manifest design, and all the gotchas.
|
|
6
6
|
|
|
@@ -43,11 +43,8 @@ Covering SSH and REST API patterns from all machine connector projects:
|
|
|
43
43
|
### Quick Install (Claude Code CLI)
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
# Add to your project
|
|
47
|
-
claude mcp add venafi-
|
|
48
|
-
|
|
49
|
-
# Best used alongside the core MCP
|
|
50
|
-
claude mcp add venafi-connector-core -- npx -y venafi-connector-core
|
|
46
|
+
# Add to your project (best used alongside the core MCP)
|
|
47
|
+
claude mcp add venafi-integration-core -- npx -y venafi-integration-core
|
|
51
48
|
claude mcp add venafi-connector-machine -- npx -y venafi-connector-machine
|
|
52
49
|
```
|
|
53
50
|
|
|
@@ -58,9 +55,9 @@ Alternatively, add to your project's `.claude/settings.json`:
|
|
|
58
55
|
```json
|
|
59
56
|
{
|
|
60
57
|
"mcpServers": {
|
|
61
|
-
"venafi-
|
|
58
|
+
"venafi-integration-core": {
|
|
62
59
|
"command": "npx",
|
|
63
|
-
"args": ["-y", "venafi-
|
|
60
|
+
"args": ["-y", "venafi-integration-core"]
|
|
64
61
|
},
|
|
65
62
|
"venafi-connector-machine": {
|
|
66
63
|
"command": "npx",
|
|
@@ -83,8 +80,9 @@ Knowledge extracted from building these machine connectors:
|
|
|
83
80
|
|
|
84
81
|
## Related Packages
|
|
85
82
|
|
|
86
|
-
- [`venafi-
|
|
83
|
+
- [`venafi-integration-core`](https://www.npmjs.com/package/venafi-integration-core) — Shared architecture, templates, deployment, troubleshooting
|
|
87
84
|
- [`venafi-connector-ca`](https://www.npmjs.com/package/venafi-connector-ca) — CA connector endpoints, certificate issuance/import/revocation
|
|
85
|
+
- [`venafi-adaptable-app`](https://www.npmjs.com/package/venafi-adaptable-app) — Adaptable app driver templates, field definitions, PowerShell patterns
|
|
88
86
|
|
|
89
87
|
## License
|
|
90
88
|
|
package/bundle.mjs
CHANGED
|
@@ -31877,6 +31877,79 @@ All fields listed in \`x-primaryKey\` MUST:
|
|
|
31877
31877
|
3. Be of type \`"string"\` \u2014 complex types are not supported in primary keys
|
|
31878
31878
|
|
|
31879
31879
|
The \`x-primaryKey\` array defines uniqueness for machine identity bindings during discovery. Every unique combination of primary key values creates a separate binding entry. For provisioning, unused primary key fields default to empty string.
|
|
31880
|
+
|
|
31881
|
+
### 41. CRITICAL: Do NOT Re-Marshal Private Keys When Target Accepts PEM
|
|
31882
|
+
|
|
31883
|
+
**The mistake**: Parsing a DER private key into a Go type and then re-marshaling it back to DER before PEM-encoding. This round-trip can subtly change the DER encoding, causing the target to reject the key.
|
|
31884
|
+
|
|
31885
|
+
**The symptom**: GCP Certificate Manager returns \`400: unsupported encryption key size\` when updating a self-managed certificate with a re-marshaled EC key. The key parses fine in Go, but the re-marshaled DER bytes differ from the original.
|
|
31886
|
+
|
|
31887
|
+
**The wrong approach** (from lesson #21's example used for PKCS12):
|
|
31888
|
+
|
|
31889
|
+
\`\`\`go
|
|
31890
|
+
// WRONG for PEM output \u2014 re-marshaling changes the DER encoding
|
|
31891
|
+
if key, err := x509.ParseECPrivateKey(keyDER); err == nil {
|
|
31892
|
+
ecDER, _ := x509.MarshalECPrivateKey(key) // re-marshaled bytes may differ!
|
|
31893
|
+
return pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: ecDER}), nil
|
|
31894
|
+
}
|
|
31895
|
+
\`\`\`
|
|
31896
|
+
|
|
31897
|
+
**The correct approach** \u2014 detect the type but wrap the original bytes:
|
|
31898
|
+
|
|
31899
|
+
\`\`\`go
|
|
31900
|
+
// CORRECT for PEM output \u2014 use original DER bytes, no re-marshaling
|
|
31901
|
+
if _, err := x509.ParsePKCS1PrivateKey(keyDER); err == nil {
|
|
31902
|
+
return pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: keyDER}), nil
|
|
31903
|
+
}
|
|
31904
|
+
if _, err := x509.ParseECPrivateKey(keyDER); err == nil {
|
|
31905
|
+
return pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: keyDER}), nil
|
|
31906
|
+
}
|
|
31907
|
+
if _, err := x509.ParsePKCS8PrivateKey(keyDER); err == nil {
|
|
31908
|
+
return pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDER}), nil
|
|
31909
|
+
}
|
|
31910
|
+
\`\`\`
|
|
31911
|
+
|
|
31912
|
+
**When to use which approach**:
|
|
31913
|
+
- **Target accepts PEM** (GCP, AWS, cloud APIs): Use the no-re-marshal approach above. Just detect the type for the PEM header and wrap the original DER bytes.
|
|
31914
|
+
- **Target requires PKCS12** (FortiGate, network appliances): You MUST parse into Go types to pass to \`pkcs12.Encode()\`. Re-marshaling is unavoidable and acceptable here because the PKCS12 encoder produces its own encoding.
|
|
31915
|
+
|
|
31916
|
+
### 42. CRITICAL: Handle Both DER and PEM Input in Certificate Bundle
|
|
31917
|
+
|
|
31918
|
+
**The problem**: The Venafi platform sends certificate bundles with \`contentEncoding: "base64"\` in the manifest. Go's JSON unmarshaler automatically base64-decodes \`[]byte\` fields. However, the decoded bytes may be either **raw DER** or **PEM-encoded text**, depending on how the certificate was originally stored.
|
|
31919
|
+
|
|
31920
|
+
**The symptom**: \`x509.ParseCertificate()\` fails with "asn1: structure error" when the input is PEM text (which starts with \`-----BEGIN\` ASCII bytes, not a valid ASN.1 sequence). Or the private key parser fails silently.
|
|
31921
|
+
|
|
31922
|
+
**The fix**: Always check for PEM encoding first before assuming DER:
|
|
31923
|
+
|
|
31924
|
+
\`\`\`go
|
|
31925
|
+
func convertBundleToPEM(bundle *domain.CertificateBundle) (certPEM, keyPEM string, chainPEMs []string, err error) {
|
|
31926
|
+
// Handle both DER and PEM input
|
|
31927
|
+
certBytes := bundle.Certificate
|
|
31928
|
+
if block, _ := pem.Decode(bundle.Certificate); block != nil {
|
|
31929
|
+
certBytes = block.Bytes // extract DER from PEM
|
|
31930
|
+
}
|
|
31931
|
+
cert, err := x509.ParseCertificate(certBytes)
|
|
31932
|
+
// ...
|
|
31933
|
+
|
|
31934
|
+
// Same for private key
|
|
31935
|
+
if block, _ := pem.Decode(bundle.PrivateKey); block != nil {
|
|
31936
|
+
keyPEM = string(pem.EncodeToMemory(block)) // already PEM, re-encode cleanly
|
|
31937
|
+
} else {
|
|
31938
|
+
keyPEM = derKeyToPEM(bundle.PrivateKey) // DER, wrap in PEM
|
|
31939
|
+
}
|
|
31940
|
+
|
|
31941
|
+
// Same for chain certificates
|
|
31942
|
+
for _, chainBytes := range bundle.CertificateChain {
|
|
31943
|
+
if block, _ := pem.Decode(chainBytes); block != nil {
|
|
31944
|
+
chainPEMs = append(chainPEMs, string(pem.EncodeToMemory(block)))
|
|
31945
|
+
} else {
|
|
31946
|
+
// parse DER and encode to PEM
|
|
31947
|
+
}
|
|
31948
|
+
}
|
|
31949
|
+
}
|
|
31950
|
+
\`\`\`
|
|
31951
|
+
|
|
31952
|
+
**Key insight**: This pattern makes the connector resilient to both input formats. The \`pem.Decode()\` check is cheap (just looks for \`-----BEGIN\`) and handles the ambiguity gracefully.
|
|
31880
31953
|
`;
|
|
31881
31954
|
var MACHINE_MANIFEST_TEMPLATE = `
|
|
31882
31955
|
{
|
|
@@ -33803,37 +33876,37 @@ var server = new McpServer({
|
|
|
33803
33876
|
name: "venafi-connector-machine",
|
|
33804
33877
|
version: "1.0.0"
|
|
33805
33878
|
});
|
|
33806
|
-
server.resource("machine-blueprint", "machine
|
|
33879
|
+
server.resource("machine-blueprint", "venafi://connector-machine/blueprint", {
|
|
33807
33880
|
description: "Machine connector architecture \u2014 5 endpoints, Temporal workflow model, SSH client abstraction, discovery/provisioning patterns, manifest domainSchema",
|
|
33808
33881
|
mimeType: "text/markdown"
|
|
33809
33882
|
}, async () => ({
|
|
33810
33883
|
contents: [
|
|
33811
33884
|
{
|
|
33812
|
-
uri: "machine
|
|
33885
|
+
uri: "venafi://connector-machine/blueprint",
|
|
33813
33886
|
text: MACHINE_BLUEPRINT,
|
|
33814
33887
|
mimeType: "text/markdown"
|
|
33815
33888
|
}
|
|
33816
33889
|
]
|
|
33817
33890
|
}));
|
|
33818
|
-
server.resource("lessons-learned", "machine
|
|
33891
|
+
server.resource("lessons-learned", "venafi://connector-machine/lessons-learned", {
|
|
33819
33892
|
description: "What worked, what failed, and mistakes to avoid \u2014 from building the Splunk SSH connector. Covers SSH patterns, discovery challenges, certificate format issues, and more.",
|
|
33820
33893
|
mimeType: "text/markdown"
|
|
33821
33894
|
}, async () => ({
|
|
33822
33895
|
contents: [
|
|
33823
33896
|
{
|
|
33824
|
-
uri: "machine
|
|
33897
|
+
uri: "venafi://connector-machine/lessons-learned",
|
|
33825
33898
|
text: LESSONS_LEARNED,
|
|
33826
33899
|
mimeType: "text/markdown"
|
|
33827
33900
|
}
|
|
33828
33901
|
]
|
|
33829
33902
|
}));
|
|
33830
|
-
server.resource("machine-manifest-template", "machine
|
|
33903
|
+
server.resource("machine-manifest-template", "venafi://connector-machine/manifest-template", {
|
|
33831
33904
|
description: "Complete machine connector manifest.json template with connection (SSH), keystore, binding, certificateBundle, discovery, discoveryControl, discoveryPage sections",
|
|
33832
33905
|
mimeType: "application/json"
|
|
33833
33906
|
}, async () => ({
|
|
33834
33907
|
contents: [
|
|
33835
33908
|
{
|
|
33836
|
-
uri: "machine
|
|
33909
|
+
uri: "venafi://connector-machine/manifest-template",
|
|
33837
33910
|
text: MACHINE_MANIFEST_TEMPLATE,
|
|
33838
33911
|
mimeType: "application/json"
|
|
33839
33912
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "venafi-connector-machine",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "MCP server providing machine connector-specific knowledge, templates, and tools for building Venafi
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "MCP server providing machine connector-specific knowledge, templates, and tools for building Venafi machine connectors",
|
|
5
5
|
"main": "bundle.mjs",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
"mcp",
|
|
21
21
|
"model-context-protocol",
|
|
22
22
|
"venafi",
|
|
23
|
-
"tls-protect-cloud",
|
|
24
23
|
"machine-connector",
|
|
25
24
|
"ssh",
|
|
26
25
|
"rest-api",
|
|
@@ -32,7 +31,7 @@
|
|
|
32
31
|
"license": "Apache-2.0",
|
|
33
32
|
"repository": {
|
|
34
33
|
"type": "git",
|
|
35
|
-
"url": "https://github.com/abhadfield/venafi-
|
|
34
|
+
"url": "https://github.com/abhadfield/venafi-integration-mcps"
|
|
36
35
|
},
|
|
37
36
|
"dependencies": {
|
|
38
37
|
"@modelcontextprotocol/sdk": "^1.12.1"
|