ワンクリックで
a2a-workflow
Use when working with Safeguard A2A certificate auth, credential retrieval, brokering, or A2A event listeners.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Use when working with Safeguard A2A certificate auth, credential retrieval, brokering, or A2A event listeners.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Use when running tests, writing tests, investigating test failures, setting up a test environment against a live Safeguard appliance, or working with the PowerShell integration test framework. Covers live appliance workflow, PKCE vs ROG, running test suites, writing new suites, assertion functions, TOTP generation, and module-to-suite mapping.
Use when making standard Safeguard Web API calls with ISafeguardConnection and related SDK helpers.
Use when working on SDK internals, authentication mechanisms, connection classes, PKCE login flow, rSTS protocol details, event listeners, A2A integration, SPS integration, or exploring the Safeguard API via Swagger. Covers the entry point, auth strategy pattern, decorator pattern, rSTS step flow, and SignalR event architecture.
Use when reproducing SafeguardDotNet CI/CD, version stamping, signing, packaging, or release publishing.
| name | a2a-workflow |
| description | Use when working with Safeguard A2A certificate auth, credential retrieval, brokering, or A2A event listeners. |
Safeguard A2A (Application-to-Application) is the SDK surface for unattended,
certificate-based integrations. In this repo, Safeguard.A2A.GetContext(...)
creates an ISafeguardA2AContext that talks to /service/A2A/v<apiVersion>/...
with a client certificate plus an A2A API key. It is used for retrieving passwords,
SSH keys, API key secrets, brokering access requests, and subscribing to A2A
credential-change events.
A2A is the automation-friendly side of Safeguard. Unlike normal Safeguard.Connect()
flows that authenticate a user and then send bearer tokens, A2A uses a client
certificate to establish trust and an Authorization: A2A <apiKey> header to scope
credential retrieval or brokering to a configured registration. The SDK models this
with ISafeguardA2AContext, SafeguardA2AContext, A2ARetrievableAccount,
BrokeredAccessRequest, and ApiKeySecret.
The repository does not create A2A registrations for you; that setup happens on the Safeguard appliance. The codebase shows the expected appliance-side shape.
Safeguard.A2A.GetContext(...) supports the same three certificate sources used by
other certificate-based SDK entry points:
Examples:
using var context = Safeguard.A2A.GetContext(
appliance,
thumbprint,
apiVersion: 4,
ignoreSsl: true);
using var context = Safeguard.A2A.GetContext(
appliance,
certificatePath,
certificatePassword,
apiVersion: 4,
ignoreSsl: true);
var bytes = File.ReadAllBytes(certificatePath);
using var context = Safeguard.A2A.GetContext(
appliance,
bytes,
certificatePassword,
apiVersion: 4,
ignoreSsl: true);
Validation-callback overloads also exist when you want custom certificate validation
instead of ignoreSsl.
Samples\SampleA2aService\SampleService.cs shows a practical discovery flow:
ISafeguardConnectionService.Core A2ARegistrationsCertificateUserThumbprintA2ARegistrations/{id}/RetrievableAccountsApiKey values and cache them as SecureStringThat sample uses:
var a2AJson = _connection.InvokeMethod(
Service.Core,
Method.Get,
"A2ARegistrations",
parameters: new Dictionary<string, string>
{
["filter"] = $"CertificateUserThumbprint ieq '{thumbprint}'",
});
Important setup notes pulled from the repo:
ISafeguardA2AContext.GetRetrievableAccounts() is documented as a Safeguard v2.8+
feature that must be enabled in the A2A configuration.SampleA2aService throws if no API keys are found after enumeration.ISafeguardA2AContext| Method | Purpose |
|---|---|
GetRetrievableAccounts() / GetRetrievableAccounts(filter) | Discover accessible accounts and API keys |
RetrievePassword(apiKey) | Fetch a password as SecureString |
SetPassword(apiKey, password) | Rotate/update a password |
RetrievePrivateKey(apiKey, keyFormat) | Fetch an SSH private key |
SetPrivateKey(apiKey, privateKey, password, keyFormat) | Upload/update an SSH private key |
RetrieveApiKeySecret(apiKey) | Fetch API key secret material as IList<ApiKeySecret> |
SafeguardA2AContext uses these routes internally:
GET Core/A2ARegistrationsGET Core/A2ARegistrations/{id}/RetrievableAccountsGET A2A/Credentials?type=PasswordPUT A2A/Credentials/PasswordGET A2A/Credentials?type=PrivateKey&keyFormat=<format>PUT A2A/Credentials/SshKey?keyFormat=<format>GET A2A/Credentials?type=ApiKeyThe context sends:
Accept: application/jsonAuthorization: A2A <apiKey> when an API key is requiredusing var context = Safeguard.A2A.GetContext(appliance, thumbprint, apiVersion: 4, ignoreSsl: true);
using var password = context.RetrievePassword(apiKey.ToSecureString());
var clearText = password.ToInsecureString();
Test\SafeguardDotNetA2aTool uses GetRetrievableAccounts() in two modes:
AccountName eq 'admin'The filter is applied server-side to each registration's retrievable-accounts endpoint.
RetrieveApiKeySecret() returns ApiKeySecret objects whose ClientSecret is a
SecureString. Dispose them when you are done.
ApiKeySecret implements IDisposableA2ARetrievableAccount.ApiKey is treated as sensitive dataSecureStringSampleA2aService dispose listeners, connections, and
A2A contexts during shutdownYes. ISafeguardA2AContext.BrokerAccessRequest() posts a BrokeredAccessRequest
object to A2A/AccessRequests.
SafeguardA2AContext enforces these before the HTTP call:
ForUserId or ForUserNameAssetId or AssetNameIf either is missing, it throws SafeguardDotNetException before contacting the
server.
BrokeredAccessRequestAccessType (Password, Ssh, Rdp)AccountId / AccountNameAccountAssetId / AccountAssetNameReasonCodeId / ReasonCodeReasonCommentTicketNumberRequestedForRequestedDurationTest\SafeguardDotNetAccessRequestBrokerTool shows the intended calling pattern:
using var context = CreateA2AContext(opts);
var accessRequest = GetBrokeredAccessRequestObject(opts);
var json = context.BrokerAccessRequest(opts.ApiKey.ToSecureString(), accessRequest);
The tool accepts either IDs or names for user, asset, account, and reason code, then
maps numeric strings to the *Id properties.
Yes. A2A supports both non-persistent and persistent SignalR listeners.
| Method | Recovery behavior |
|---|---|
GetA2AEventListener(apiKey, handler) | Does not recover from a 30+ second outage |
GetA2AEventListener(apiKeys, handler) | Same, but for multiple API keys |
GetPersistentA2AEventListener(apiKey, handler) | Reconnects automatically |
GetPersistentA2AEventListener(apiKeys, handler) | Reconnects automatically |
Safeguard.A2A.Event.GetPersistentA2AEventListener(...) exposes the same persistent
listener pattern directly from:
The implementation registers handlers for three A2A events:
AssetAccountPasswordUpdatedAssetAccountSshKeyUpdatedAccountApiKeySecretUpdatedThis is worth knowing because some XML comments still describe only the password update event.
Persistent A2A listeners are backed by PersistentSafeguardA2AEventListener, which
inherits the shared reconnect loop from PersistentSafeguardEventListenerBase:
Use the persistent variant for Windows services, daemon-style workloads, or anything that must survive appliance/network interruptions.
Samples\SampleA2aService\SampleService.cs starts one persistent listener per API keyTest\SafeguardDotNetEventTool supports single-key, multi-key, and "discover all keys"
flows before starting a listenerStart() explicitly after creating the listenerInvalidOperationException("Must specify CertificateFile or Thumbprint")apiKey, password, privateKey, or accessRequest -> ArgumentExceptionArgumentExceptionSafeguardDotNetExceptionSafeguardA2AContext.ApiRequest() throws SafeguardDotNetException when Safeguard
returns a non-success HTTP status. The exception includes status and raw response
content, so inspect HttpStatusCode, ErrorMessage, and Response.
SafeguardDotNetException("Request timeout to ...")RetrievePassword(), RetrievePrivateKey(), or BrokerAccessRequest()
is the caller's responsibilityignoreSsl bypasses certificate validation and is intended for dev/test onlyIf registration enumeration fails in the sample flow, check:
GetRetrievableAccounts()A2ARegistrationsIf you only need retrieval and already have a valid API key, skip the Core registration lookup and call the A2A context methods directly.