It is not unreasonable for downstream users of the request and response
messages to mutate them, indeed we mutate the response
on the way out to get the desired external API. To avoid
inconsistent messages being audited, make a copy of the
entire message before returning from the interceptor.
This was discovered while testing the new subtype transformation
interceptor.
This interceptor is responsible for maintaining compatability with the
JSON API with the change to the protobuf messages. The messages are
changing from a single attribue field to a oneof to explicitly associate
subtype attribute messages with the resource message. The interceptor
transforms the request prior to the auditReqeust interceptor, and
transforms the response after the auditResponse interceptor. This allows
the audit interceptors to use all the necessary classification
information when creating the audit events.
Other parts of the system make use of a "type" field, while the
AuthenticateResponse sets a "token_type" on the response attributes
directly. Rename this field to "type", and move it up to the response
level, to be more consistent with other RPCs.
Also adds a new field to the AuthenticateRequest, "type" which will
replace the "token_type" field over time.
The Go docs now say to use request.Clone (introduced in Go
1.13) instead of request.WithContext (introduced in Go 1.7) as it deep
copies instead of shallow copies.
* feat(worker): Instrumentation for Controller Cluster Communication
Adds request latency observations to the worker side (client) of
worker <-> controller cluster communications by integrating a new
grpc client interceptor.
* style(controller): make-gen-deltas changes
gRPC status.Handler gives us visibility into gRPC returned errors. In contrast, there are some situations where no metric would be counted at all using the interceptor approach (for example, in out of memory cases where gRPC would return a resource exhausted error).
When requesting a token, any error is fatal to the test.
The previous behavior would return a nil token, which
could cause subsequent uses to panic. This will instead
interrupt any test immediately on error.
The Scheduler is dependant on the server being inserted into the
database. Adding an upsert server call before starting scheduler
and tickers removes the race that caused log spam due to a missing
foreign key relationship.
It is documented as illegal to use t.FailNow in a goroutine.
Uses of require assertions call t.FailNow. This may have led to
inconsistent test results as some assertions were subject to
undefined behavior. Note that it is still allowed to call
assert assertions in goroutines.
See: https://pkg.go.dev/testing#T.FailNow
This allows us to use SNI for actual host (e.g. routing) information. We
don't have the client cert yet so we can't look at that, so this
provides a way for us to convey the information needed to look up that
session's TLS stack.
Using SNI for hosts means we also run into the fact that we don't have
automatic agreement in terms of SANs. So when generating the certs we
now also pass worker address information to the function to be encoded
in the cert.
Finally, there is a change in how the websocket dialing happens, because
http.RoundTripper tries to be too clever for its own good and overwrites
NextProtos on a whim.
We never ended up using this and it makes it much harder to reason about the listeners.
An explanation: for the moment I separated out all of the listeners in the struct, even though one should suffice, because when I did it that way first I was hitting some really weird and hard to find intermittent behavior where it seemed like the listeners were getting crossed. So I re-did it this way with each listener very explicitly referenced. I'm happy to make a follow-up PR that attempts to combine them all into a single listener without hitting the issues I did, if desired, but at least doing it via a separate PR means that it won't be something with removing the ALPN muxer that is at fault.
* feat(controller): New health service and server
This change also implements a new listener purpose, `ops`.
`ops` (short for operations) is a new listener purpose that is
responsible for serving Boundary's operations endpoints, like health
and possibly metrics.
At Startup: `ops` listeners get configured as late as possible to catch
any errors with the startup process;
At Shutdown: If the health endpoint has been set-up, we introduce a
configurable delay in the process. This is to enable the health endpoint
to report unhealthy for that amount of time. `ops` listeners are also
the last listeners to be shutdown.
In general, these changes were introduced in the same vein of the
changes to controller `startListeners`.
Specifically, these changes also decouple the Controller and the Worker
shutdown processes. Currently, a call to `stopListeners` on an instance
that is running as both a Controller and a Worker would stop the
listeners for both.
Lastly, we also add unit/integration tests to the shutdown code.
Previously, we initialized the listeners on the order they were provided
to us on the config file. In the future, we'll want to add new listener
purposes that depend on existing ones, so the init order needs to be
deterministic.
With this change, we'll initialize components in this order:
1. gRPC Server for Controller API.
2. All `api` HTTP Servers & gRPC Gateway Muxes.
3. `cluster` gRPC Server.
This commit introduces some renames for the sake of clarity as well as
improved test coverage:
- Removes `gatewayMux` reference from Controller object. This object was
misleading and is now uneeded.
- Removed uneeded `context.Context` arguments.
- Separates gRPC Server and gRPC Gateway concerns, both in functionality
and in naming. These two were conflated before.
- Added unit tests on `startListeners`.
With this change, the Controller is now aware of its own listeners in a
more codified and structured way.
The reasoning behind these changes are as follows:
1. Currently, we're iterating over these listeners in multiple spots
along this initialization flow to check each listeners' purpose. By
doing this once when we create a Controller and essentially storing the
result, we can clean up the downstream code to use those results.
2. Initial effort to centralize Controller validation. At the moment, we
are doing a lot of validation all over the `cmd` and `config` packages.
From a conceptual perspective, Controller-related validation should
be performed in the function that is responsible for constructing the
Controller object itself. This enables any developer to look in a
single place for all the constraints that we place on creating a
Controller.
This contains to related things:
1. An adapter allowing an hclog interface to take in information and send them to the eventer
2. A gate on the eventer, which is the analogue to the behavior prior to eventing where we'd ensure logs were not printed prior to the startup information. Without this, plugin logs using the hclog adapter will start showing up too early.
This removes or reduces the time that is waited in a number of tests by
allowing the grace period time be a configuration option on the
connection repository.
This creates a domain service function `session.WorkerStatusReport`. The
service performs two functions:
1. Checks the status for all of the reported sessions, returning a
report of the sessions that are in a "non-active" state, i.e.
"cacneling" or "terminated".
2. Looks for any "orphaned" session connections, i.e. connections that
are active but were not reported by the worker. These connections are
marked as closed.
This also removes the "ShouldCloseConnectionsOnWorker" logic, as this
was determined to not be a possible state, and was unnecessary.
* fix(controller/targets): authorize-session should allow h_ ids
The targets controller previously only allowed hosts from a static catalog
since it checked for the ID subtype from the static package.
This change validates host ids with the plugin.Subtype as well
Fixes: #1850
* test: cover authorize-session with host id
Add a regression test to cover the case where an explicit host ID was
given when calling AuthorizeSession
* feat(host): Add host set information to static host
Updates LookupHost and ListHost API to include sets a static host is part of, as like with plugin hosts.
* test: updated TestList_Plugin and TestCrud to be more consistent under race conditions
* chore: Add new dbw dependency
* refactor: Convert to use dbw.DB
* refactor (db): Change GetTicket(...) signature
* feature (db tests): Added TestDeleteWhere(...)
Adding this allows us to eliminate a leak of the gorm library
* refactor: Add ctx to ScanRows(...) signature
This is required to refactor all the deprecated errors pkg calls.
This refactor required adding a context to quite a few call chains
and in particular the job scheduler bits
* feature (db/tests): Add support for test opt: WithTestLogLevel(...)
This test only option allows callers to specify a log level for the
underlying db package (where supported/applicable) when calling
TestSetup(...)
* refactor (db): Simplify Db type
Only store the underlying *DB and create the *RW on demand when
needed.
* refactor (oplog): Port to using dbw pkg for db operations
* refactor (db): Remove gormDB(...) func
* tests (db): Add unit tests for TestDeleteWhere(...)
* chore: make fmt changes to formatting
Egress credentials Issued during AuthorizeSession are stored in the
session repo. These credentials are retrieved and stored in-memory on the
worker during the LookupSession call. Each proxy handler will need to
handle the credentials as required.
This allows users to set the type of credential that a credential
library will provide.
A User Password credential type and an Unspecified credential type are included
with the expectation that additional credential types will be added in the
future. This change also adds the credential type attribute to existing
credential libraries and sets it to Unspecified. The credential type can
only be set when a credential library is created.
The vault credential library includes functionality for converting a
Vault Secret into a User Password Credential. This mapping is enabled by
default, however, the user can override the attributes used for this
mapping.
* feat(sdk): Add fields to credential library proto
Adds CredentialType and CredentialMappingOverrides to credential
library SDK.
* feat(api): Add fields to credenttial library service
Adds support for CredentialType and CredentialMappingOverrides
to the credential library service (API)
* feat(cli): Add feilds for credential library cmd
Adds support for CredentialType and CredentialMappingOverrides to the
credential library cmd command.