Merge remote-tracking branch 'origin/main' into llb-byow
This commit is contained in:
commit
704d68848c
160 files changed
+15933
-4684
No files matched your search
+26
-2
@@ -6,6 +6,19 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.
|
||||
|
||||
### New and Improved
|
||||
|
||||
* Credentials: This release introduces a new credential store type `static`,
|
||||
which simply takes in a user-supplied credential and stores it (encrypted)
|
||||
directly in Boundary. Currently, the `static` credential store can hold
|
||||
credentials of type `username_password`. These credentials can act as
|
||||
credential sources for targets, similar to credential libraries from the
|
||||
`vault` credential store, and thus can be brokered to users at session
|
||||
authorization time. [PR](https://github.com/hashicorp/boundary/pull/2174)
|
||||
* `boundary connect` Credential Brokering Integration: we have extended integration
|
||||
into the `boundary connect` helpers. A new `sshpass` style has been added to the
|
||||
`ssh` helper, when used, if the credential contains a username/password and `sshpass`
|
||||
is installed, the command will automatically pass the credentials to the `ssh` process.
|
||||
Additionally, the default `ssh` helper will now use the `username` of the brokered credential.
|
||||
[PR](https://github.com/hashicorp/boundary/pull/2191).
|
||||
* controller: Improve response time for listing sessions.
|
||||
This also creates a new periodic job that will delete terminated
|
||||
sessions after 1 hour.
|
||||
@@ -14,8 +27,21 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.
|
||||
* event filtering: Change event filters to use lowercase and snake case for data
|
||||
elements like the rest of Boundary filters do.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* The plugin execution_dir configuration parameter is now respected.
|
||||
[PR](https://github.com/hashicorp/boundary/pull/2183).
|
||||
|
||||
### Deprecations/Changes
|
||||
|
||||
* Targets: Removes support for `credential libraries` with respect to Target resources.
|
||||
The `library` `fields` and `actions` were deprecated in [Boundary 0.5.0](#050-20210802),
|
||||
please use `credential sources` instead. See changelog referenced above for
|
||||
more details ([PR](https://github.com/hashicorp/boundary/pull/1533)).
|
||||
* Credential Libraries: The `user_password` credential type has been renamed to
|
||||
`username_password` to remove any inconsistency over what the credential type is.
|
||||
All existing `user_password` typed credential libraries will be migrated to
|
||||
`username_password` ([PR](https://github.com/hashicorp/boundary/pull/2154)).
|
||||
* controller: Change the default behavior of the session list endpoint
|
||||
to no longer include sessions in a terminated state and introduces
|
||||
a new query parameter/cli flag to include the terminated sessions.
|
||||
@@ -30,8 +56,6 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.
|
||||
documentation](https://www.boundaryproject.io/docs/concepts/security/permissions/assignable-permissions)
|
||||
for more details.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
## 0.8.1 (2022/05/13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -159,6 +159,7 @@ protobuild:
|
||||
@protoc-go-inject-tag -input=./internal/scheduler/job/store/job.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/credential/store/credential.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/credential/vault/store/vault.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/credential/static/store/static.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/servers/servers.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/kms/store/audit_key.pb.go
|
||||
|
||||
@@ -188,6 +189,8 @@ protobuild:
|
||||
@protoc-go-inject-tag -input=./internal/gen/controller/api/services/credential_store_service.pb.go
|
||||
@protoc-go-inject-tag -input=./sdk/pbs/controller/api/resources/credentiallibraries/credential_library.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/gen/controller/api/services/credential_library_service.pb.go
|
||||
@protoc-go-inject-tag -input=./sdk/pbs/controller/api/resources/credentials/credential.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/gen/controller/api/services/credential_service.pb.go
|
||||
@protoc-go-inject-tag -input=./sdk/pbs/controller/api/resources/roles/role.pb.go
|
||||
@protoc-go-inject-tag -input=./internal/gen/controller/api/services/role_service.pb.go
|
||||
@protoc-go-inject-tag -input=./sdk/pbs/controller/api/resources/sessions/session.pb.go
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
// Code generated by "make api"; DO NOT EDIT.
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/scopes"
|
||||
)
|
||||
|
||||
type Credential struct {
|
||||
Id string `json:"id,omitempty"`
|
||||
CredentialStoreId string `json:"credential_store_id,omitempty"`
|
||||
Scope *scopes.ScopeInfo `json:"scope,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
CreatedTime time.Time `json:"created_time,omitempty"`
|
||||
UpdatedTime time.Time `json:"updated_time,omitempty"`
|
||||
Version uint32 `json:"version,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
AuthorizedActions []string `json:"authorized_actions,omitempty"`
|
||||
|
||||
response *api.Response
|
||||
}
|
||||
|
||||
type CredentialReadResult struct {
|
||||
Item *Credential
|
||||
response *api.Response
|
||||
}
|
||||
|
||||
func (n CredentialReadResult) GetItem() interface{} {
|
||||
return n.Item
|
||||
}
|
||||
|
||||
func (n CredentialReadResult) GetResponse() *api.Response {
|
||||
return n.response
|
||||
}
|
||||
|
||||
type CredentialCreateResult = CredentialReadResult
|
||||
type CredentialUpdateResult = CredentialReadResult
|
||||
|
||||
type CredentialDeleteResult struct {
|
||||
response *api.Response
|
||||
}
|
||||
|
||||
// GetItem will always be nil for CredentialDeleteResult
|
||||
func (n CredentialDeleteResult) GetItem() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n CredentialDeleteResult) GetResponse() *api.Response {
|
||||
return n.response
|
||||
}
|
||||
|
||||
type CredentialListResult struct {
|
||||
Items []*Credential
|
||||
response *api.Response
|
||||
}
|
||||
|
||||
func (n CredentialListResult) GetItems() interface{} {
|
||||
return n.Items
|
||||
}
|
||||
|
||||
func (n CredentialListResult) GetResponse() *api.Response {
|
||||
return n.response
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, resourceType string, credentialStoreId string, opt ...Option) (*CredentialCreateResult, error) {
|
||||
if credentialStoreId == "" {
|
||||
return nil, fmt.Errorf("empty credentialStoreId value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if c.client == nil {
|
||||
return nil, fmt.Errorf("nil client")
|
||||
}
|
||||
if resourceType == "" {
|
||||
return nil, fmt.Errorf("empty resourceType value passed into Create request")
|
||||
} else {
|
||||
opts.postMap["type"] = resourceType
|
||||
}
|
||||
|
||||
opts.postMap["credential_store_id"] = credentialStoreId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", "credentials", opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error performing client request during Create call: %w", err)
|
||||
}
|
||||
|
||||
target := new(CredentialCreateResult)
|
||||
target.Item = new(Credential)
|
||||
apiErr, err := resp.Decode(target.Item)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding Create response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
target.response = resp
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (c *Client) Read(ctx context.Context, id string, opt ...Option) (*CredentialReadResult, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("empty id value passed into Read request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("credentials/%s", url.PathEscape(id)), nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating Read request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error performing client request during Read call: %w", err)
|
||||
}
|
||||
|
||||
target := new(CredentialReadResult)
|
||||
target.Item = new(Credential)
|
||||
apiErr, err := resp.Decode(target.Item)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding Read response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
target.response = resp
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (c *Client) Update(ctx context.Context, id string, version uint32, opt ...Option) (*CredentialUpdateResult, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("empty id value passed into Update request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
|
||||
}
|
||||
existingTarget, existingErr := c.Read(ctx, id, append([]Option{WithSkipCurlOutput(true)}, opt...)...)
|
||||
if existingErr != nil {
|
||||
if api.AsServerError(existingErr) != nil {
|
||||
return nil, fmt.Errorf("error from controller when performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
return nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
if existingTarget == nil {
|
||||
return nil, errors.New("nil resource response found when performing initial check-and-set read")
|
||||
}
|
||||
if existingTarget.Item == nil {
|
||||
return nil, errors.New("nil resource found when performing initial check-and-set read")
|
||||
}
|
||||
version = existingTarget.Item.Version
|
||||
}
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "PATCH", fmt.Sprintf("credentials/%s", url.PathEscape(id)), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating Update request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error performing client request during Update call: %w", err)
|
||||
}
|
||||
|
||||
target := new(CredentialUpdateResult)
|
||||
target.Item = new(Credential)
|
||||
apiErr, err := resp.Decode(target.Item)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding Update response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
target.response = resp
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (c *Client) Delete(ctx context.Context, id string, opt ...Option) (*CredentialDeleteResult, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("empty id value passed into Delete request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("credentials/%s", url.PathEscape(id)), nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating Delete request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error performing client request during Delete call: %w", err)
|
||||
}
|
||||
|
||||
apiErr, err := resp.Decode(nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding Delete response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
|
||||
target := &CredentialDeleteResult{
|
||||
response: resp,
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (c *Client) List(ctx context.Context, credentialStoreId string, opt ...Option) (*CredentialListResult, error) {
|
||||
if credentialStoreId == "" {
|
||||
return nil, fmt.Errorf("empty credentialStoreId value passed into List request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
opts.queryMap["credential_store_id"] = credentialStoreId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "credentials", nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating List request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error performing client request during List call: %w", err)
|
||||
}
|
||||
|
||||
target := new(CredentialListResult)
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding List response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
target.response = resp
|
||||
return target, nil
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
)
|
||||
|
||||
// Option is a func that sets optional attributes for a call. This does not need
|
||||
// to be used directly, but instead option arguments are built from the
|
||||
// functions in this package. WithX options set a value to that given in the
|
||||
// argument; DefaultX options indicate that the value should be set to its
|
||||
// default. When an API call is made options are processed in ther order they
|
||||
// appear in the function call, so for a given argument X, a succession of WithX
|
||||
// or DefaultX calls will result in the last call taking effect.
|
||||
type Option func(*options)
|
||||
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withAutomaticVersioning bool
|
||||
withSkipCurlOutput bool
|
||||
withFilter string
|
||||
}
|
||||
|
||||
func getDefaultOptions() options {
|
||||
return options{
|
||||
postMap: make(map[string]interface{}),
|
||||
queryMap: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
func getOpts(opt ...Option) (options, []api.Option) {
|
||||
opts := getDefaultOptions()
|
||||
for _, o := range opt {
|
||||
if o != nil {
|
||||
o(&opts)
|
||||
}
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withSkipCurlOutput {
|
||||
apiOpts = append(apiOpts, api.WithSkipCurlOutput(true))
|
||||
}
|
||||
if opts.withFilter != "" {
|
||||
opts.queryMap["filter"] = opts.withFilter
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
// WithSkipCurlOutput tells the API to not use the current call for cURL output.
|
||||
// Useful for when we need to look up versions.
|
||||
func WithSkipCurlOutput(skip bool) Option {
|
||||
return func(o *options) {
|
||||
o.withSkipCurlOutput = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithFilter tells the API to filter the items returned using the provided
|
||||
// filter term. The filter should be in a format supported by
|
||||
// hashicorp/go-bexpr.
|
||||
func WithFilter(filter string) Option {
|
||||
return func(o *options) {
|
||||
o.withFilter = strings.TrimSpace(filter)
|
||||
}
|
||||
}
|
||||
|
||||
func WithAttributes(inAttributes map[string]interface{}) Option {
|
||||
return func(o *options) {
|
||||
o.postMap["attributes"] = inAttributes
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultAttributes() Option {
|
||||
return func(o *options) {
|
||||
o.postMap["attributes"] = nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithDescription(inDescription string) Option {
|
||||
return func(o *options) {
|
||||
o.postMap["description"] = inDescription
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultDescription() Option {
|
||||
return func(o *options) {
|
||||
o.postMap["description"] = nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithName(inName string) Option {
|
||||
return func(o *options) {
|
||||
o.postMap["name"] = inName
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultName() Option {
|
||||
return func(o *options) {
|
||||
o.postMap["name"] = nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithUsernamePasswordCredentialPassword(inPassword string) Option {
|
||||
return func(o *options) {
|
||||
raw, ok := o.postMap["attributes"]
|
||||
if !ok {
|
||||
raw = interface{}(map[string]interface{}{})
|
||||
}
|
||||
val := raw.(map[string]interface{})
|
||||
val["password"] = inPassword
|
||||
o.postMap["attributes"] = val
|
||||
}
|
||||
}
|
||||
|
||||
func WithUsernamePasswordCredentialUsername(inUsername string) Option {
|
||||
return func(o *options) {
|
||||
raw, ok := o.postMap["attributes"]
|
||||
if !ok {
|
||||
raw = interface{}(map[string]interface{}{})
|
||||
}
|
||||
val := raw.(map[string]interface{})
|
||||
val["username"] = inUsername
|
||||
o.postMap["attributes"] = val
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Code generated by "make api"; DO NOT EDIT.
|
||||
package credentials
|
||||
|
||||
type UsernamePasswordAttributes struct {
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
PasswordHmac string `json:"password_hmac,omitempty"`
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// Code generated by "make api"; DO NOT EDIT.
|
||||
package targets
|
||||
|
||||
type CredentialLibrary struct {
|
||||
Id string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
CredentialStoreId string `json:"credential_store_id,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
@@ -87,18 +87,6 @@ func WithRecursive(recurse bool) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func WithApplicationCredentialLibraryIds(inApplicationCredentialLibraryIds []string) Option {
|
||||
return func(o *options) {
|
||||
o.postMap["application_credential_library_ids"] = inApplicationCredentialLibraryIds
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultApplicationCredentialLibraryIds() Option {
|
||||
return func(o *options) {
|
||||
o.postMap["application_credential_library_ids"] = nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithApplicationCredentialSourceIds(inApplicationCredentialSourceIds []string) Option {
|
||||
return func(o *options) {
|
||||
o.postMap["application_credential_source_ids"] = inApplicationCredentialSourceIds
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
package targets
|
||||
|
||||
type SessionCredential struct {
|
||||
CredentialSource *CredentialSource `json:"credential_source,omitempty"`
|
||||
CredentialLibrary *CredentialLibrary `json:"credential_library,omitempty"`
|
||||
Secret *SessionSecret `json:"secret,omitempty"`
|
||||
Credential map[string]interface{} `json:"credential,omitempty"`
|
||||
CredentialSource *CredentialSource `json:"credential_source,omitempty"`
|
||||
Secret *SessionSecret `json:"secret,omitempty"`
|
||||
Credential map[string]interface{} `json:"credential,omitempty"`
|
||||
}
|
||||
+22
-216
@@ -13,30 +13,28 @@ import (
|
||||
)
|
||||
|
||||
type Target struct {
|
||||
Id string `json:"id,omitempty"`
|
||||
ScopeId string `json:"scope_id,omitempty"`
|
||||
Scope *scopes.ScopeInfo `json:"scope,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
CreatedTime time.Time `json:"created_time,omitempty"`
|
||||
UpdatedTime time.Time `json:"updated_time,omitempty"`
|
||||
Version uint32 `json:"version,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
HostSetIds []string `json:"host_set_ids,omitempty"`
|
||||
HostSets []*HostSet `json:"host_sets,omitempty"`
|
||||
HostSourceIds []string `json:"host_source_ids,omitempty"`
|
||||
HostSources []*HostSource `json:"host_sources,omitempty"`
|
||||
SessionMaxSeconds uint32 `json:"session_max_seconds,omitempty"`
|
||||
SessionConnectionLimit int32 `json:"session_connection_limit,omitempty"`
|
||||
WorkerFilter string `json:"worker_filter,omitempty"`
|
||||
ApplicationCredentialLibraryIds []string `json:"application_credential_library_ids,omitempty"`
|
||||
ApplicationCredentialLibraries []*CredentialLibrary `json:"application_credential_libraries,omitempty"`
|
||||
ApplicationCredentialSourceIds []string `json:"application_credential_source_ids,omitempty"`
|
||||
ApplicationCredentialSources []*CredentialSource `json:"application_credential_sources,omitempty"`
|
||||
EgressCredentialSourceIds []string `json:"egress_credential_source_ids,omitempty"`
|
||||
EgressCredentialSources []*CredentialSource `json:"egress_credential_sources,omitempty"`
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
AuthorizedActions []string `json:"authorized_actions,omitempty"`
|
||||
Id string `json:"id,omitempty"`
|
||||
ScopeId string `json:"scope_id,omitempty"`
|
||||
Scope *scopes.ScopeInfo `json:"scope,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
CreatedTime time.Time `json:"created_time,omitempty"`
|
||||
UpdatedTime time.Time `json:"updated_time,omitempty"`
|
||||
Version uint32 `json:"version,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
HostSetIds []string `json:"host_set_ids,omitempty"`
|
||||
HostSets []*HostSet `json:"host_sets,omitempty"`
|
||||
HostSourceIds []string `json:"host_source_ids,omitempty"`
|
||||
HostSources []*HostSource `json:"host_sources,omitempty"`
|
||||
SessionMaxSeconds uint32 `json:"session_max_seconds,omitempty"`
|
||||
SessionConnectionLimit int32 `json:"session_connection_limit,omitempty"`
|
||||
WorkerFilter string `json:"worker_filter,omitempty"`
|
||||
ApplicationCredentialSourceIds []string `json:"application_credential_source_ids,omitempty"`
|
||||
ApplicationCredentialSources []*CredentialSource `json:"application_credential_sources,omitempty"`
|
||||
EgressCredentialSourceIds []string `json:"egress_credential_source_ids,omitempty"`
|
||||
EgressCredentialSources []*CredentialSource `json:"egress_credential_sources,omitempty"`
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
AuthorizedActions []string `json:"authorized_actions,omitempty"`
|
||||
|
||||
response *api.Response
|
||||
}
|
||||
@@ -337,70 +335,6 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) (*Targ
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (c *Client) AddCredentialLibraries(ctx context.Context, id string, version uint32, opt ...Option) (*TargetUpdateResult, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("empty id value passed into AddCredentialLibraries request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, errors.New("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, errors.New("zero version number passed into AddCredentialLibraries request")
|
||||
}
|
||||
existingTarget, existingErr := c.Read(ctx, id, append([]Option{WithSkipCurlOutput(true)}, opt...)...)
|
||||
if existingErr != nil {
|
||||
if api.AsServerError(existingErr) != nil {
|
||||
return nil, fmt.Errorf("error from controller when performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
return nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
if existingTarget == nil {
|
||||
return nil, errors.New("nil resource response found when performing initial check-and-set read")
|
||||
}
|
||||
if existingTarget.Item == nil {
|
||||
return nil, errors.New("nil resource found when performing initial check-and-set read")
|
||||
}
|
||||
version = existingTarget.Item.Version
|
||||
}
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("targets/%s:add-credential-libraries", url.PathEscape(id)), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating AddCredentialLibraries request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error performing client request during AddCredentialLibraries call: %w", err)
|
||||
}
|
||||
|
||||
target := new(TargetUpdateResult)
|
||||
target.Item = new(Target)
|
||||
apiErr, err := resp.Decode(target.Item)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding AddCredentialLibraries response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
target.response = resp
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (c *Client) AddCredentialSources(ctx context.Context, id string, version uint32, opt ...Option) (*TargetUpdateResult, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("empty id value passed into AddCredentialSources request")
|
||||
@@ -605,70 +539,6 @@ func (c *Client) AddHostSources(ctx context.Context, id string, version uint32,
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (c *Client) SetCredentialLibraries(ctx context.Context, id string, version uint32, opt ...Option) (*TargetUpdateResult, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("empty id value passed into SetCredentialLibraries request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, errors.New("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, errors.New("zero version number passed into SetCredentialLibraries request")
|
||||
}
|
||||
existingTarget, existingErr := c.Read(ctx, id, append([]Option{WithSkipCurlOutput(true)}, opt...)...)
|
||||
if existingErr != nil {
|
||||
if api.AsServerError(existingErr) != nil {
|
||||
return nil, fmt.Errorf("error from controller when performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
return nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
if existingTarget == nil {
|
||||
return nil, errors.New("nil resource response found when performing initial check-and-set read")
|
||||
}
|
||||
if existingTarget.Item == nil {
|
||||
return nil, errors.New("nil resource found when performing initial check-and-set read")
|
||||
}
|
||||
version = existingTarget.Item.Version
|
||||
}
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("targets/%s:set-credential-libraries", url.PathEscape(id)), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating SetCredentialLibraries request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error performing client request during SetCredentialLibraries call: %w", err)
|
||||
}
|
||||
|
||||
target := new(TargetUpdateResult)
|
||||
target.Item = new(Target)
|
||||
apiErr, err := resp.Decode(target.Item)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding SetCredentialLibraries response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
target.response = resp
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (c *Client) SetCredentialSources(ctx context.Context, id string, version uint32, opt ...Option) (*TargetUpdateResult, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("empty id value passed into SetCredentialSources request")
|
||||
@@ -865,70 +735,6 @@ func (c *Client) SetHostSources(ctx context.Context, id string, version uint32,
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (c *Client) RemoveCredentialLibraries(ctx context.Context, id string, version uint32, opt ...Option) (*TargetUpdateResult, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("empty id value passed into RemoveCredentialLibraries request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, errors.New("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, errors.New("zero version number passed into RemoveCredentialLibraries request")
|
||||
}
|
||||
existingTarget, existingErr := c.Read(ctx, id, append([]Option{WithSkipCurlOutput(true)}, opt...)...)
|
||||
if existingErr != nil {
|
||||
if api.AsServerError(existingErr) != nil {
|
||||
return nil, fmt.Errorf("error from controller when performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
return nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
if existingTarget == nil {
|
||||
return nil, errors.New("nil resource response found when performing initial check-and-set read")
|
||||
}
|
||||
if existingTarget.Item == nil {
|
||||
return nil, errors.New("nil resource found when performing initial check-and-set read")
|
||||
}
|
||||
version = existingTarget.Item.Version
|
||||
}
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("targets/%s:remove-credential-libraries", url.PathEscape(id)), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating RemoveCredentialLibraries request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error performing client request during RemoveCredentialLibraries call: %w", err)
|
||||
}
|
||||
|
||||
target := new(TargetUpdateResult)
|
||||
target.Item = new(Target)
|
||||
apiErr, err := resp.Decode(target.Item)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding RemoveCredentialLibraries response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr
|
||||
}
|
||||
target.response = resp
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (c *Client) RemoveCredentialSources(ctx context.Context, id string, version uint32, opt ...Option) (*TargetUpdateResult, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("empty id value passed into RemoveCredentialSources request")
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/authmethods"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/authtokens"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentiallibraries"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentials"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentialstores"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/groups"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostcatalogs"
|
||||
@@ -453,15 +454,24 @@ var inputStructs = []*structInfo{
|
||||
versionEnabled: true,
|
||||
createResponseTypes: true,
|
||||
},
|
||||
// Credentials
|
||||
{
|
||||
inProto: &credentialstores.VaultCredentialStoreAttributes{},
|
||||
outFile: "credentialstores/vault_credential_store_attributes.gen.go",
|
||||
subtypeName: "VaultCredentialStore",
|
||||
inProto: &credentials.UsernamePasswordAttributes{},
|
||||
outFile: "credentials/username_password_attributes.gen.go",
|
||||
subtypeName: "UsernamePasswordCredential",
|
||||
fieldOverrides: []fieldInfo{
|
||||
{
|
||||
Name: "Username",
|
||||
SkipDefault: true,
|
||||
},
|
||||
{
|
||||
Name: "Password",
|
||||
SkipDefault: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
inProto: &credentialstores.CredentialStore{},
|
||||
outFile: "credentialstores/credential_store.gen.go",
|
||||
inProto: &credentials.Credential{},
|
||||
outFile: "credentials/credential.gen.go",
|
||||
templates: []*template.Template{
|
||||
clientTemplate,
|
||||
commonCreateTemplate,
|
||||
@@ -470,8 +480,6 @@ var inputStructs = []*structInfo{
|
||||
deleteTemplate,
|
||||
listTemplate,
|
||||
},
|
||||
pluralResourceName: "credential-stores",
|
||||
parentTypeName: "scope",
|
||||
extraRequiredParams: []requiredParam{
|
||||
{
|
||||
Name: "resourceType",
|
||||
@@ -479,47 +487,12 @@ var inputStructs = []*structInfo{
|
||||
PostType: "type",
|
||||
},
|
||||
},
|
||||
versionEnabled: true,
|
||||
createResponseTypes: true,
|
||||
recursiveListing: true,
|
||||
fieldOverrides: []fieldInfo{
|
||||
{
|
||||
Name: "Address",
|
||||
SkipDefault: true,
|
||||
},
|
||||
{
|
||||
Name: "Token",
|
||||
SkipDefault: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
inProto: &credentiallibraries.VaultCredentialLibraryAttributes{},
|
||||
outFile: "credentiallibraries/vault_credential_library_attributes.gen.go",
|
||||
subtypeName: "VaultCredentialLibrary",
|
||||
fieldOverrides: []fieldInfo{
|
||||
{
|
||||
Name: "Path",
|
||||
SkipDefault: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
inProto: &credentiallibraries.CredentialLibrary{},
|
||||
outFile: "credentiallibraries/credential_library.gen.go",
|
||||
templates: []*template.Template{
|
||||
clientTemplate,
|
||||
commonCreateTemplate,
|
||||
readTemplate,
|
||||
updateTemplate,
|
||||
deleteTemplate,
|
||||
listTemplate,
|
||||
},
|
||||
pluralResourceName: "credential-libraries",
|
||||
pluralResourceName: "credentials",
|
||||
parentTypeName: "credential-store",
|
||||
versionEnabled: true,
|
||||
createResponseTypes: true,
|
||||
},
|
||||
|
||||
// Host related resources
|
||||
{
|
||||
inProto: &hostcatalogs.HostCatalog{},
|
||||
@@ -610,10 +583,6 @@ var inputStructs = []*structInfo{
|
||||
inProto: &targets.HostSource{},
|
||||
outFile: "targets/host_source.gen.go",
|
||||
},
|
||||
{
|
||||
inProto: &targets.CredentialLibrary{},
|
||||
outFile: "targets/credential_library.gen.go",
|
||||
},
|
||||
{
|
||||
inProto: &targets.CredentialSource{},
|
||||
outFile: "targets/credential_source.gen.go",
|
||||
@@ -668,8 +637,7 @@ var inputStructs = []*structInfo{
|
||||
SliceType: "[]string",
|
||||
VarName: "hostSourceIds",
|
||||
},
|
||||
"CredentialLibraries": {},
|
||||
"CredentialSources": {},
|
||||
"CredentialSources": {},
|
||||
},
|
||||
extraFields: []fieldInfo{
|
||||
{
|
||||
@@ -690,11 +658,6 @@ var inputStructs = []*structInfo{
|
||||
FieldType: "string",
|
||||
SkipDefault: true,
|
||||
},
|
||||
{
|
||||
Name: "ApplicationCredentialLibraryIds",
|
||||
ProtoName: "application_credential_library_ids",
|
||||
FieldType: "[]string",
|
||||
},
|
||||
{
|
||||
Name: "ApplicationCredentialSourceIds",
|
||||
ProtoName: "application_credential_source_ids",
|
||||
|
||||
@@ -589,6 +589,7 @@ func (b *Server) SetupKMSes(ctx context.Context, ui cli.Ui, config *config.Confi
|
||||
configutil.WithPluginOptions(
|
||||
pluginutil.WithPluginsMap(kms_plugin_assets.BuiltinKmsPlugins()),
|
||||
pluginutil.WithPluginsFilesystem(kms_plugin_assets.KmsPluginPrefix, kms_plugin_assets.FileSystem()),
|
||||
pluginutil.WithPluginExecutionDirectory(config.Plugins.ExecutionDir),
|
||||
),
|
||||
configutil.WithLogger(pluginLogger.Named(kms.Type).With("purpose", purpose)),
|
||||
)
|
||||
|
||||
+61
-18
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/config"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/connect"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/credentiallibrariescmd"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/credentialscmd"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/credentialstorescmd"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/database"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/dev"
|
||||
@@ -411,6 +412,12 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||
Func: "create",
|
||||
}, nil
|
||||
},
|
||||
"credential-stores create static": func() (cli.Command, error) {
|
||||
return &credentialstorescmd.StaticCommand{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "create",
|
||||
}, nil
|
||||
},
|
||||
"credential-stores update": func() (cli.Command, error) {
|
||||
return &credentialstorescmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
@@ -423,6 +430,60 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||
Func: "update",
|
||||
}, nil
|
||||
},
|
||||
"credential-stores update static": func() (cli.Command, error) {
|
||||
return &credentialstorescmd.StaticCommand{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "update",
|
||||
}, nil
|
||||
},
|
||||
|
||||
"credentials": func() (cli.Command, error) {
|
||||
return &credentialscmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
}, nil
|
||||
},
|
||||
"credentials read": func() (cli.Command, error) {
|
||||
return &credentialscmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "read",
|
||||
}, nil
|
||||
},
|
||||
"credentials delete": func() (cli.Command, error) {
|
||||
return &credentialscmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "delete",
|
||||
}, nil
|
||||
},
|
||||
"credentials list": func() (cli.Command, error) {
|
||||
return &credentialscmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "list",
|
||||
}, nil
|
||||
},
|
||||
"credentials create": func() (cli.Command, error) {
|
||||
return &credentialscmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "create",
|
||||
}, nil
|
||||
},
|
||||
"credentials create username-password": func() (cli.Command, error) {
|
||||
return &credentialscmd.UsernamePasswordCommand{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "create",
|
||||
}, nil
|
||||
},
|
||||
"credentials update": func() (cli.Command, error) {
|
||||
return &credentialscmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "update",
|
||||
}, nil
|
||||
},
|
||||
"credentials update username-password": func() (cli.Command, error) {
|
||||
return &credentialscmd.UsernamePasswordCommand{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "update",
|
||||
}, nil
|
||||
},
|
||||
|
||||
"groups": func() (cli.Command, error) {
|
||||
return &groupscmd.Command{
|
||||
@@ -939,24 +1000,6 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||
Func: "set-host-sources",
|
||||
}, nil
|
||||
},
|
||||
"targets add-credential-libraries": func() (cli.Command, error) {
|
||||
return &targetscmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "add-credential-libraries",
|
||||
}, nil
|
||||
},
|
||||
"targets remove-credential-libraries": func() (cli.Command, error) {
|
||||
return &targetscmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "remove-credential-libraries",
|
||||
}, nil
|
||||
},
|
||||
"targets set-credential-libraries": func() (cli.Command, error) {
|
||||
return &targetscmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "set-credential-libraries",
|
||||
}, nil
|
||||
},
|
||||
"targets add-credential-sources": func() (cli.Command, error) {
|
||||
return &targetscmd.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
|
||||
@@ -492,6 +492,15 @@ func (c *Command) Run(args []string) (retCode int) {
|
||||
// Credentials are brokered when connecting to the postgres db.
|
||||
// TODO: Figure out how to handle cases where we don't automatically know how to
|
||||
// broker the credentials like unrecognized or multiple credentials.
|
||||
case "ssh":
|
||||
if c.flagExec == "sshpass" {
|
||||
// If we can broker ssh credentials using sshpass, skip displaying creds on client side.
|
||||
// TODO: Figure out how to handle multiple credentials
|
||||
break
|
||||
}
|
||||
|
||||
// We cannot broker credentials print to user
|
||||
fallthrough
|
||||
case "connect":
|
||||
// "connect" indicates there is no subcommand to the connect function.
|
||||
// The only way a user will be able to connect to the session is by
|
||||
@@ -838,7 +847,13 @@ func (c *Command) handleExec(passthroughArgs []string) {
|
||||
args = append(args, c.rdpFlags.buildArgs(c, port, ip, addr)...)
|
||||
|
||||
case "ssh":
|
||||
args = append(args, c.sshFlags.buildArgs(c, port, ip, addr)...)
|
||||
sshArgs, sshEnvs, sshErr := c.sshFlags.buildArgs(c, port, ip, addr)
|
||||
if sshErr != nil {
|
||||
argsErr = sshErr
|
||||
break
|
||||
}
|
||||
args = append(args, sshArgs...)
|
||||
envs = append(envs, sshEnvs...)
|
||||
|
||||
case "kube":
|
||||
kubeArgs, err := c.kubeFlags.buildArgs(c, port, ip, addr)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package connect
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/hashicorp/boundary/api/targets"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
type usernamePasswordCredentials struct {
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
}
|
||||
|
||||
// TODO: this should support multiple types of credentials and return an interface instead
|
||||
// of only usernamepassword. Each subcommand can use the returned credentials as it needs.
|
||||
func parseCredentials(creds []*targets.SessionCredential) ([]usernamePasswordCredentials, error) {
|
||||
if creds == nil {
|
||||
return nil, nil
|
||||
}
|
||||
var out []usernamePasswordCredentials
|
||||
for _, cred := range creds {
|
||||
if cred.CredentialSource == nil {
|
||||
return nil, errors.New("missing credential source")
|
||||
}
|
||||
|
||||
var c usernamePasswordCredentials
|
||||
if cred.CredentialSource.CredentialType == string(credential.UsernamePasswordType) {
|
||||
// Decode attributes from credential struct
|
||||
if err := mapstructure.Decode(cred.Credential, &c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.Username != "" && c.Password != "" {
|
||||
out = append(out, c)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Credential type is unspecified, make a best effort attempt to parse both username
|
||||
// and password from Decoded field if it exists
|
||||
if cred.Secret == nil || cred.Secret.Decoded == nil {
|
||||
// No secret data continue to next credential
|
||||
continue
|
||||
}
|
||||
|
||||
switch cred.CredentialSource.Type {
|
||||
case "vault", "static":
|
||||
// Attempt unmarshaling into creds
|
||||
if err := mapstructure.Decode(cred.Secret.Decoded, &c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if c.Username != "" && c.Password != "" {
|
||||
out = append(out, c)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
package connect
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/api/targets"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_parseUsernamePasswordCredentials(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
creds []*targets.SessionCredential
|
||||
wantCreds []usernamePasswordCredentials
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "no-creds",
|
||||
wantCreds: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "no-credential-source",
|
||||
creds: []*targets.SessionCredential{
|
||||
{
|
||||
Credential: map[string]interface{}{
|
||||
"username": "user",
|
||||
"password": "pass",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantCreds: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-typed",
|
||||
creds: []*targets.SessionCredential{
|
||||
{
|
||||
CredentialSource: &targets.CredentialSource{
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
Credential: map[string]interface{}{
|
||||
"username": "user",
|
||||
"password": "pass",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantCreds: []usernamePasswordCredentials{
|
||||
{
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid-typed-instead-of-decoded",
|
||||
creds: []*targets.SessionCredential{
|
||||
{
|
||||
CredentialSource: &targets.CredentialSource{
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
Credential: map[string]interface{}{
|
||||
"username": "user",
|
||||
"password": "pass",
|
||||
},
|
||||
Secret: &targets.SessionSecret{
|
||||
Decoded: map[string]interface{}{
|
||||
"username": "secret-user",
|
||||
"password": "secret-pass",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantCreds: []usernamePasswordCredentials{
|
||||
{
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid-vault-not-typed",
|
||||
creds: []*targets.SessionCredential{
|
||||
{
|
||||
CredentialSource: &targets.CredentialSource{
|
||||
Type: "vault",
|
||||
},
|
||||
Secret: &targets.SessionSecret{
|
||||
Decoded: map[string]interface{}{
|
||||
"username": "user",
|
||||
"password": "pass",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantCreds: []usernamePasswordCredentials{
|
||||
{
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid-static-not-typed",
|
||||
creds: []*targets.SessionCredential{
|
||||
{
|
||||
CredentialSource: &targets.CredentialSource{
|
||||
Type: "static",
|
||||
},
|
||||
Secret: &targets.SessionSecret{
|
||||
Decoded: map[string]interface{}{
|
||||
"username": "user",
|
||||
"password": "pass",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantCreds: []usernamePasswordCredentials{
|
||||
{
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid-multiple",
|
||||
creds: []*targets.SessionCredential{
|
||||
{
|
||||
CredentialSource: &targets.CredentialSource{
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
Credential: map[string]interface{}{
|
||||
"username": "user",
|
||||
"password": "pass",
|
||||
},
|
||||
},
|
||||
{
|
||||
CredentialSource: &targets.CredentialSource{
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
Credential: map[string]interface{}{
|
||||
"username": "user1",
|
||||
"password": "pass1",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantCreds: []usernamePasswordCredentials{
|
||||
{
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
{
|
||||
Username: "user1",
|
||||
Password: "pass1",
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid-multiple-mixed",
|
||||
creds: []*targets.SessionCredential{
|
||||
{
|
||||
CredentialSource: &targets.CredentialSource{
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
Credential: map[string]interface{}{
|
||||
"username": "user",
|
||||
"password": "pass",
|
||||
},
|
||||
},
|
||||
{
|
||||
CredentialSource: &targets.CredentialSource{
|
||||
Type: "vault",
|
||||
},
|
||||
Secret: &targets.SessionSecret{
|
||||
Decoded: map[string]interface{}{
|
||||
"username": "user1",
|
||||
"password": "pass1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CredentialSource: &targets.CredentialSource{
|
||||
Type: "static",
|
||||
},
|
||||
Secret: &targets.SessionSecret{
|
||||
Decoded: map[string]interface{}{
|
||||
"username": "user2",
|
||||
"password": "pass2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantCreds: []usernamePasswordCredentials{
|
||||
{
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
{
|
||||
Username: "user1",
|
||||
Password: "pass1",
|
||||
},
|
||||
{
|
||||
Username: "user2",
|
||||
Password: "pass2",
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
creds, err := parseCredentials(tt.creds)
|
||||
if tt.wantErr {
|
||||
require.Error(err)
|
||||
assert.Nil(creds)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.ElementsMatch(tt.wantCreds, creds)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ func fmtSecretForTable(indent int, sc *targets.SessionCredential) []string {
|
||||
prefixStr := strings.Repeat(" ", indent)
|
||||
origSecret := []string{fmt.Sprintf("%s %s", prefixStr, sc.Secret.Raw)}
|
||||
switch sc.CredentialSource.Type {
|
||||
case "vault":
|
||||
case "vault", "static":
|
||||
if sc.Credential != nil {
|
||||
maxLength := 0
|
||||
for k := range sc.Credential {
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
@@ -52,33 +51,18 @@ func (p *postgresFlags) defaultExec() string {
|
||||
return strings.ToLower(p.flagPostgresStyle)
|
||||
}
|
||||
|
||||
type postgresCredentials struct {
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
}
|
||||
|
||||
func (p *postgresFlags) buildArgs(c *Command, port, ip, addr string) (args, envs []string, retErr error) {
|
||||
var creds postgresCredentials
|
||||
if c.sessionAuthz != nil && len(c.sessionAuthz.Credentials) > 0 {
|
||||
for _, cred := range c.sessionAuthz.Credentials {
|
||||
if cred.Secret == nil || cred.Secret.Decoded == nil {
|
||||
continue
|
||||
}
|
||||
// TODO: Could allow switching on library ID or name
|
||||
switch cred.CredentialLibrary.Type {
|
||||
case "vault":
|
||||
// Attempt unmarshaling into creds
|
||||
if err := mapstructure.Decode(cred.Secret.Decoded, &creds); err != nil {
|
||||
return nil, nil, fmt.Errorf("Error interpreting Vault secret: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if creds.Username != "" && creds.Password != "" {
|
||||
// In the future we can look for other types if we support other
|
||||
// authentication mechanisms
|
||||
break
|
||||
}
|
||||
var cred usernamePasswordCredentials
|
||||
if c.sessionAuthz != nil {
|
||||
creds, err := parseCredentials(c.sessionAuthz.Credentials)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error interpreting secret: %w", err)
|
||||
}
|
||||
if len(creds) > 0 {
|
||||
// Just use first credentials returned
|
||||
cred = creds[0]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch p.flagPostgresStyle {
|
||||
@@ -90,13 +74,13 @@ func (p *postgresFlags) buildArgs(c *Command, port, ip, addr string) (args, envs
|
||||
}
|
||||
|
||||
switch {
|
||||
case creds.Username != "":
|
||||
args = append(args, "-U", creds.Username)
|
||||
case cred.Username != "":
|
||||
args = append(args, "-U", cred.Username)
|
||||
case c.flagUsername != "":
|
||||
args = append(args, "-U", c.flagUsername)
|
||||
}
|
||||
|
||||
if creds.Password != "" {
|
||||
if cred.Password != "" {
|
||||
passfile, err := ioutil.TempFile("", "*")
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error saving postgres password to tmp file: %w", err)
|
||||
@@ -107,7 +91,7 @@ func (p *postgresFlags) buildArgs(c *Command, port, ip, addr string) (args, envs
|
||||
}
|
||||
return nil
|
||||
})
|
||||
_, err = passfile.WriteString(fmt.Sprintf("*:*:*:*:%s", creds.Password))
|
||||
_, err = passfile.WriteString(fmt.Sprintf("*:*:*:*:%s", cred.Password))
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error writing password file to %s: %w", passfile.Name(), err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package connect
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -19,7 +20,7 @@ func sshOptions(c *Command, set *base.FlagSets) {
|
||||
Name: "style",
|
||||
Target: &c.flagSshStyle,
|
||||
EnvVar: "BOUNDARY_CONNECT_SSH_STYLE",
|
||||
Completion: complete.PredictSet("ssh", "putty"),
|
||||
Completion: complete.PredictSet("ssh", "putty", "sshpass"),
|
||||
Default: "ssh",
|
||||
Usage: `Specifies how the CLI will attempt to invoke an SSH client. This will also set a suitable default for -exec if a value was not specified. Currently-understood values are "ssh" and "putty".`,
|
||||
})
|
||||
@@ -41,18 +42,52 @@ func (s *sshFlags) defaultExec() string {
|
||||
return strings.ToLower(s.flagSshStyle)
|
||||
}
|
||||
|
||||
func (s *sshFlags) buildArgs(c *Command, port, ip, addr string) []string {
|
||||
// Might want -t for ssh or -tt but seems fine without it for now...
|
||||
var args []string
|
||||
switch s.flagSshStyle {
|
||||
func (s *sshFlags) buildArgs(c *Command, port, ip, addr string) (args, envs []string, retErr error) {
|
||||
var cred usernamePasswordCredentials
|
||||
if c.sessionAuthz != nil {
|
||||
creds, err := parseCredentials(c.sessionAuthz.Credentials)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error interpreting secret: %w", err)
|
||||
}
|
||||
if len(creds) > 0 {
|
||||
// Just use first credentials returned
|
||||
cred = creds[0]
|
||||
}
|
||||
}
|
||||
|
||||
switch strings.ToLower(s.flagSshStyle) {
|
||||
case "ssh":
|
||||
// Might want -t for ssh or -tt but seems fine without it for now...
|
||||
args = append(args, "-p", port, ip)
|
||||
args = append(args, "-o", fmt.Sprintf("HostKeyAlias=%s", c.sessionAuthzData.HostId))
|
||||
|
||||
// SSH detects a host key change when localhost proxy port changes, disable localhost
|
||||
// host key verification to avoid 'WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED...'
|
||||
args = append(args, "-o", "NoHostAuthenticationForLocalhost=yes")
|
||||
|
||||
case "sshpass":
|
||||
if cred.Password == "" {
|
||||
return nil, nil, errors.New("Password is required when using sshpass")
|
||||
}
|
||||
// sshpass requires that the password is passed as env-var "SSHPASS"
|
||||
// when the using env-vars.
|
||||
envs = append(envs, fmt.Sprintf("SSHPASS=%s", cred.Password))
|
||||
args = append(args, "-e", "ssh")
|
||||
args = append(args, "-p", port, ip)
|
||||
|
||||
// sshpass cannot handle host key checking, disable localhost key verification
|
||||
// to avoid error: 'SSHPASS detected host authentication prompt. Exiting.'
|
||||
args = append(args, "-o", "NoHostAuthenticationForLocalhost=yes")
|
||||
|
||||
case "putty":
|
||||
args = append(args, "-P", port, ip)
|
||||
}
|
||||
if c.flagUsername != "" {
|
||||
|
||||
switch {
|
||||
case cred.Username != "":
|
||||
args = append(args, "-l", cred.Username)
|
||||
case c.flagUsername != "":
|
||||
args = append(args, "-l", c.flagUsername)
|
||||
}
|
||||
return args
|
||||
|
||||
return args, envs, nil
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
// Code generated by "make cli"; DO NOT EDIT.
|
||||
package credentialscmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/credentials"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/common"
|
||||
"github.com/hashicorp/go-secure-stdlib/strutil"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
func initFlags() {
|
||||
flagsOnce.Do(func() {
|
||||
extraFlags := extraActionsFlagsMapFunc()
|
||||
for k, v := range extraFlags {
|
||||
flagsMap[k] = append(flagsMap[k], v...)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
_ cli.Command = (*Command)(nil)
|
||||
_ cli.CommandAutocomplete = (*Command)(nil)
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
|
||||
plural string
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteArgs() complete.Predictor {
|
||||
initFlags()
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteFlags() complete.Flags {
|
||||
initFlags()
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *Command) Synopsis() string {
|
||||
if extra := extraSynopsisFunc(c); extra != "" {
|
||||
return extra
|
||||
}
|
||||
|
||||
synopsisStr := "credential"
|
||||
|
||||
return common.SynopsisFunc(c.Func, synopsisStr)
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
initFlags()
|
||||
|
||||
var helpStr string
|
||||
helpMap := common.HelpMap("credential")
|
||||
|
||||
switch c.Func {
|
||||
|
||||
case "read":
|
||||
helpStr = helpMap[c.Func]() + c.Flags().Help()
|
||||
|
||||
case "delete":
|
||||
helpStr = helpMap[c.Func]() + c.Flags().Help()
|
||||
|
||||
case "list":
|
||||
helpStr = helpMap[c.Func]() + c.Flags().Help()
|
||||
|
||||
default:
|
||||
|
||||
helpStr = c.extraHelpFunc(helpMap)
|
||||
|
||||
}
|
||||
|
||||
// Keep linter from complaining if we don't actually generate code using it
|
||||
_ = helpMap
|
||||
return helpStr
|
||||
}
|
||||
|
||||
var flagsMap = map[string][]string{
|
||||
|
||||
"read": {"id"},
|
||||
|
||||
"delete": {"id"},
|
||||
|
||||
"list": {"credential-store-id", "filter"},
|
||||
}
|
||||
|
||||
func (c *Command) Flags() *base.FlagSets {
|
||||
if len(flagsMap[c.Func]) == 0 {
|
||||
return c.FlagSet(base.FlagSetNone)
|
||||
}
|
||||
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
f := set.NewFlagSet("Command Options")
|
||||
common.PopulateCommonFlags(c.Command, f, "credential", flagsMap, c.Func)
|
||||
|
||||
extraFlagsFunc(c, set, f)
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *Command) Run(args []string) int {
|
||||
initFlags()
|
||||
|
||||
switch c.Func {
|
||||
case "":
|
||||
return cli.RunResultHelp
|
||||
|
||||
case "create":
|
||||
return cli.RunResultHelp
|
||||
|
||||
case "update":
|
||||
return cli.RunResultHelp
|
||||
|
||||
}
|
||||
|
||||
c.plural = "credential"
|
||||
switch c.Func {
|
||||
case "list":
|
||||
c.plural = "credentials"
|
||||
}
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.PrintCliError(err)
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.PrintCliError(errors.New("ID is required but not passed in via -id"))
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
var opts []credentials.Option
|
||||
|
||||
if strutil.StrListContains(flagsMap[c.Func], "credential-store-id") {
|
||||
switch c.Func {
|
||||
|
||||
case "list":
|
||||
if c.FlagCredentialStoreId == "" {
|
||||
c.PrintCliError(errors.New("CredentialStore ID must be passed in via -credential-store-id or BOUNDARY_CREDENTIAL_STORE_ID"))
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if c.WrapperCleanupFunc != nil {
|
||||
defer func() {
|
||||
if err := c.WrapperCleanupFunc(); err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error cleaning kms wrapper: %w", err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
if err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error creating API client: %w", err))
|
||||
return base.CommandCliError
|
||||
}
|
||||
credentialsClient := credentials.NewClient(client)
|
||||
|
||||
if c.FlagFilter != "" {
|
||||
opts = append(opts, credentials.WithFilter(c.FlagFilter))
|
||||
}
|
||||
|
||||
var version uint32
|
||||
|
||||
if ok := extraFlagsHandlingFunc(c, f, &opts); !ok {
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
var result api.GenericResult
|
||||
|
||||
var listResult api.GenericListResult
|
||||
|
||||
switch c.Func {
|
||||
|
||||
case "read":
|
||||
result, err = credentialsClient.Read(c.Context, c.FlagId, opts...)
|
||||
|
||||
case "delete":
|
||||
result, err = credentialsClient.Delete(c.Context, c.FlagId, opts...)
|
||||
|
||||
case "list":
|
||||
listResult, err = credentialsClient.List(c.Context, c.FlagCredentialStoreId, opts...)
|
||||
|
||||
}
|
||||
|
||||
result, err = executeExtraActions(c, result, err, credentialsClient, version, opts)
|
||||
|
||||
if err != nil {
|
||||
if apiErr := api.AsServerError(err); apiErr != nil {
|
||||
var opts []base.Option
|
||||
|
||||
c.PrintApiError(apiErr, fmt.Sprintf("Error from controller when performing %s on %s", c.Func, c.plural), opts...)
|
||||
return base.CommandApiError
|
||||
}
|
||||
c.PrintCliError(fmt.Errorf("Error trying to %s %s: %s", c.Func, c.plural, err.Error()))
|
||||
return base.CommandCliError
|
||||
}
|
||||
|
||||
output, err := printCustomActionOutput(c)
|
||||
if err != nil {
|
||||
c.PrintCliError(err)
|
||||
return base.CommandUserError
|
||||
}
|
||||
if output {
|
||||
return base.CommandSuccess
|
||||
}
|
||||
|
||||
switch c.Func {
|
||||
|
||||
case "delete":
|
||||
switch base.Format(c.UI) {
|
||||
case "json":
|
||||
if ok := c.PrintJsonItem(result); !ok {
|
||||
return base.CommandCliError
|
||||
}
|
||||
|
||||
case "table":
|
||||
c.UI.Output("The delete operation completed successfully.")
|
||||
}
|
||||
|
||||
return base.CommandSuccess
|
||||
|
||||
case "list":
|
||||
switch base.Format(c.UI) {
|
||||
case "json":
|
||||
if ok := c.PrintJsonItems(listResult); !ok {
|
||||
return base.CommandCliError
|
||||
}
|
||||
|
||||
case "table":
|
||||
listedItems := listResult.GetItems().([]*credentials.Credential)
|
||||
c.UI.Output(c.printListTable(listedItems))
|
||||
}
|
||||
|
||||
return base.CommandSuccess
|
||||
|
||||
}
|
||||
|
||||
switch base.Format(c.UI) {
|
||||
case "table":
|
||||
c.UI.Output(printItemTable(result))
|
||||
|
||||
case "json":
|
||||
if ok := c.PrintJsonItem(result); !ok {
|
||||
return base.CommandCliError
|
||||
}
|
||||
}
|
||||
|
||||
return base.CommandSuccess
|
||||
}
|
||||
|
||||
var (
|
||||
flagsOnce = new(sync.Once)
|
||||
|
||||
extraActionsFlagsMapFunc = func() map[string][]string { return nil }
|
||||
extraSynopsisFunc = func(*Command) string { return "" }
|
||||
extraFlagsFunc = func(*Command, *base.FlagSets, *base.FlagSet) {}
|
||||
extraFlagsHandlingFunc = func(*Command, *base.FlagSets, *[]credentials.Option) bool { return true }
|
||||
executeExtraActions = func(_ *Command, inResult api.GenericResult, inErr error, _ *credentials.Client, _ uint32, _ []credentials.Option) (api.GenericResult, error) {
|
||||
return inResult, inErr
|
||||
}
|
||||
printCustomActionOutput = func(*Command) (bool, error) { return false, nil }
|
||||
)
|
||||
@@ -0,0 +1,177 @@
|
||||
package credentialscmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/credentials"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
)
|
||||
|
||||
func (c *Command) extraHelpFunc(helpMap map[string]func() string) string {
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
case "":
|
||||
return base.WrapForHelpText([]string{
|
||||
"Usage: boundary credentials [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows operations on Boundary credential resources. Example:",
|
||||
"",
|
||||
" Read a credential:",
|
||||
"",
|
||||
` $ boundary credentials read -id cred_1234567890`,
|
||||
"",
|
||||
" Please see the credentials subcommand help for detailed usage information.",
|
||||
})
|
||||
case "create":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary credentials create [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows create operations on Boundary credential resources. Example:",
|
||||
"",
|
||||
" Create a credential:",
|
||||
"",
|
||||
` $ boundary credentials create username-password -credential-store-id cs_1234567890 -username user -password pass`,
|
||||
"",
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
case "update":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary credentials update [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows update operations on Boundary credential resources. Example:",
|
||||
"",
|
||||
" Update a user password credential:",
|
||||
"",
|
||||
` $ boundary credentials update username-password -id cred_1234567890 -name devops -description "For DevOps usage"`,
|
||||
"",
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
default:
|
||||
helpStr = helpMap["base"]()
|
||||
}
|
||||
return helpStr + c.Flags().Help()
|
||||
}
|
||||
|
||||
func (c *Command) printListTable(items []*credentials.Credential) string {
|
||||
if len(items) == 0 {
|
||||
return "No credentials found"
|
||||
}
|
||||
|
||||
var output []string
|
||||
output = []string{
|
||||
"",
|
||||
"Credential information:",
|
||||
}
|
||||
for i, m := range items {
|
||||
if i > 0 {
|
||||
output = append(output, "")
|
||||
}
|
||||
if m.Id != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" ID: %s", m.Id),
|
||||
)
|
||||
} else {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" ID: %s", "(not available)"),
|
||||
)
|
||||
}
|
||||
if m.Version > 0 {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Version: %d", m.Version),
|
||||
)
|
||||
}
|
||||
if m.Type != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Type: %s", m.Type),
|
||||
)
|
||||
}
|
||||
if m.Name != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Name: %s", m.Name),
|
||||
)
|
||||
}
|
||||
if m.Description != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Description: %s", m.Description),
|
||||
)
|
||||
}
|
||||
if len(m.AuthorizedActions) > 0 {
|
||||
output = append(output,
|
||||
" Authorized Actions:",
|
||||
base.WrapSlice(6, m.AuthorizedActions),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return base.WrapForHelpText(output)
|
||||
}
|
||||
|
||||
func printItemTable(result api.GenericResult) string {
|
||||
item := result.GetItem().(*credentials.Credential)
|
||||
nonAttributeMap := map[string]interface{}{}
|
||||
if item.Id != "" {
|
||||
nonAttributeMap["ID"] = item.Id
|
||||
}
|
||||
if item.Version != 0 {
|
||||
nonAttributeMap["Version"] = item.Version
|
||||
}
|
||||
if !item.CreatedTime.IsZero() {
|
||||
nonAttributeMap["Created Time"] = item.CreatedTime.Local().Format(time.RFC1123)
|
||||
}
|
||||
if !item.UpdatedTime.IsZero() {
|
||||
nonAttributeMap["Updated Time"] = item.UpdatedTime.Local().Format(time.RFC1123)
|
||||
}
|
||||
if item.CredentialStoreId != "" {
|
||||
nonAttributeMap["Credential Store ID"] = item.CredentialStoreId
|
||||
}
|
||||
if item.Name != "" {
|
||||
nonAttributeMap["Name"] = item.Name
|
||||
}
|
||||
if item.Description != "" {
|
||||
nonAttributeMap["Description"] = item.Description
|
||||
}
|
||||
if item.Type != "" {
|
||||
nonAttributeMap["Type"] = item.Type
|
||||
}
|
||||
|
||||
maxLength := base.MaxAttributesLength(nonAttributeMap, item.Attributes, keySubstMap)
|
||||
|
||||
ret := []string{
|
||||
"",
|
||||
"Credential information:",
|
||||
base.WrapMap(2, maxLength+2, nonAttributeMap),
|
||||
}
|
||||
|
||||
if item.Scope != nil {
|
||||
ret = append(ret,
|
||||
"",
|
||||
" Scope:",
|
||||
base.ScopeInfoForOutput(item.Scope, maxLength),
|
||||
)
|
||||
}
|
||||
|
||||
if len(item.AuthorizedActions) > 0 {
|
||||
ret = append(ret,
|
||||
"",
|
||||
" Authorized Actions:",
|
||||
base.WrapSlice(4, item.AuthorizedActions),
|
||||
)
|
||||
}
|
||||
|
||||
if len(item.Attributes) > 0 {
|
||||
ret = append(ret,
|
||||
"",
|
||||
" Attributes:",
|
||||
base.WrapMap(4, maxLength, item.Attributes),
|
||||
)
|
||||
}
|
||||
|
||||
return base.WrapForHelpText(ret)
|
||||
}
|
||||
|
||||
var keySubstMap = map[string]string{
|
||||
"username": "Username",
|
||||
"password_hmac": "Password HMAC",
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
// Code generated by "make cli"; DO NOT EDIT.
|
||||
package credentialscmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/credentials"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/common"
|
||||
"github.com/hashicorp/go-secure-stdlib/strutil"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
func initUsernamePasswordFlags() {
|
||||
flagsOnce.Do(func() {
|
||||
extraFlags := extraUsernamePasswordActionsFlagsMapFunc()
|
||||
for k, v := range extraFlags {
|
||||
flagsUsernamePasswordMap[k] = append(flagsUsernamePasswordMap[k], v...)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
_ cli.Command = (*UsernamePasswordCommand)(nil)
|
||||
_ cli.CommandAutocomplete = (*UsernamePasswordCommand)(nil)
|
||||
)
|
||||
|
||||
type UsernamePasswordCommand struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
|
||||
plural string
|
||||
|
||||
extraUsernamePasswordCmdVars
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCommand) AutocompleteArgs() complete.Predictor {
|
||||
initUsernamePasswordFlags()
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCommand) AutocompleteFlags() complete.Flags {
|
||||
initUsernamePasswordFlags()
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCommand) Synopsis() string {
|
||||
if extra := extraUsernamePasswordSynopsisFunc(c); extra != "" {
|
||||
return extra
|
||||
}
|
||||
|
||||
synopsisStr := "credential"
|
||||
|
||||
synopsisStr = fmt.Sprintf("%s %s", "username_password-type", synopsisStr)
|
||||
|
||||
return common.SynopsisFunc(c.Func, synopsisStr)
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCommand) Help() string {
|
||||
initUsernamePasswordFlags()
|
||||
|
||||
var helpStr string
|
||||
helpMap := common.HelpMap("credential")
|
||||
|
||||
switch c.Func {
|
||||
|
||||
default:
|
||||
|
||||
helpStr = c.extraUsernamePasswordHelpFunc(helpMap)
|
||||
|
||||
}
|
||||
|
||||
// Keep linter from complaining if we don't actually generate code using it
|
||||
_ = helpMap
|
||||
return helpStr
|
||||
}
|
||||
|
||||
var flagsUsernamePasswordMap = map[string][]string{
|
||||
|
||||
"create": {"credential-store-id", "name", "description"},
|
||||
|
||||
"update": {"id", "name", "description", "version"},
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCommand) Flags() *base.FlagSets {
|
||||
if len(flagsUsernamePasswordMap[c.Func]) == 0 {
|
||||
return c.FlagSet(base.FlagSetNone)
|
||||
}
|
||||
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
f := set.NewFlagSet("Command Options")
|
||||
common.PopulateCommonFlags(c.Command, f, "username_password-type credential", flagsUsernamePasswordMap, c.Func)
|
||||
|
||||
extraUsernamePasswordFlagsFunc(c, set, f)
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCommand) Run(args []string) int {
|
||||
initUsernamePasswordFlags()
|
||||
|
||||
switch c.Func {
|
||||
case "":
|
||||
return cli.RunResultHelp
|
||||
|
||||
}
|
||||
|
||||
c.plural = "username_password-type credential"
|
||||
switch c.Func {
|
||||
case "list":
|
||||
c.plural = "username_password-type credentials"
|
||||
}
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.PrintCliError(err)
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsUsernamePasswordMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.PrintCliError(errors.New("ID is required but not passed in via -id"))
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
var opts []credentials.Option
|
||||
|
||||
if strutil.StrListContains(flagsUsernamePasswordMap[c.Func], "credential-store-id") {
|
||||
switch c.Func {
|
||||
|
||||
case "create":
|
||||
if c.FlagCredentialStoreId == "" {
|
||||
c.PrintCliError(errors.New("CredentialStore ID must be passed in via -credential-store-id or BOUNDARY_CREDENTIAL_STORE_ID"))
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if c.WrapperCleanupFunc != nil {
|
||||
defer func() {
|
||||
if err := c.WrapperCleanupFunc(); err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error cleaning kms wrapper: %w", err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
if err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error creating API client: %w", err))
|
||||
return base.CommandCliError
|
||||
}
|
||||
credentialsClient := credentials.NewClient(client)
|
||||
|
||||
switch c.FlagName {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, credentials.DefaultName())
|
||||
default:
|
||||
opts = append(opts, credentials.WithName(c.FlagName))
|
||||
}
|
||||
|
||||
switch c.FlagDescription {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, credentials.DefaultDescription())
|
||||
default:
|
||||
opts = append(opts, credentials.WithDescription(c.FlagDescription))
|
||||
}
|
||||
|
||||
if c.FlagFilter != "" {
|
||||
opts = append(opts, credentials.WithFilter(c.FlagFilter))
|
||||
}
|
||||
|
||||
var version uint32
|
||||
|
||||
switch c.Func {
|
||||
|
||||
case "update":
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, credentials.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ok := extraUsernamePasswordFlagsHandlingFunc(c, f, &opts); !ok {
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
var result api.GenericResult
|
||||
|
||||
switch c.Func {
|
||||
|
||||
case "create":
|
||||
result, err = credentialsClient.Create(c.Context, "username_password", c.FlagCredentialStoreId, opts...)
|
||||
|
||||
case "update":
|
||||
result, err = credentialsClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
|
||||
}
|
||||
|
||||
result, err = executeExtraUsernamePasswordActions(c, result, err, credentialsClient, version, opts)
|
||||
|
||||
if err != nil {
|
||||
if apiErr := api.AsServerError(err); apiErr != nil {
|
||||
var opts []base.Option
|
||||
|
||||
opts = append(opts, base.WithAttributeFieldPrefix("username_password"))
|
||||
|
||||
c.PrintApiError(apiErr, fmt.Sprintf("Error from controller when performing %s on %s", c.Func, c.plural), opts...)
|
||||
return base.CommandApiError
|
||||
}
|
||||
c.PrintCliError(fmt.Errorf("Error trying to %s %s: %s", c.Func, c.plural, err.Error()))
|
||||
return base.CommandCliError
|
||||
}
|
||||
|
||||
output, err := printCustomUsernamePasswordActionOutput(c)
|
||||
if err != nil {
|
||||
c.PrintCliError(err)
|
||||
return base.CommandUserError
|
||||
}
|
||||
if output {
|
||||
return base.CommandSuccess
|
||||
}
|
||||
|
||||
switch c.Func {
|
||||
|
||||
}
|
||||
|
||||
switch base.Format(c.UI) {
|
||||
case "table":
|
||||
c.UI.Output(printItemTable(result))
|
||||
|
||||
case "json":
|
||||
if ok := c.PrintJsonItem(result); !ok {
|
||||
return base.CommandCliError
|
||||
}
|
||||
}
|
||||
|
||||
return base.CommandSuccess
|
||||
}
|
||||
|
||||
var (
|
||||
extraUsernamePasswordActionsFlagsMapFunc = func() map[string][]string { return nil }
|
||||
extraUsernamePasswordSynopsisFunc = func(*UsernamePasswordCommand) string { return "" }
|
||||
extraUsernamePasswordFlagsFunc = func(*UsernamePasswordCommand, *base.FlagSets, *base.FlagSet) {}
|
||||
extraUsernamePasswordFlagsHandlingFunc = func(*UsernamePasswordCommand, *base.FlagSets, *[]credentials.Option) bool { return true }
|
||||
executeExtraUsernamePasswordActions = func(_ *UsernamePasswordCommand, inResult api.GenericResult, inErr error, _ *credentials.Client, _ uint32, _ []credentials.Option) (api.GenericResult, error) {
|
||||
return inResult, inErr
|
||||
}
|
||||
printCustomUsernamePasswordActionOutput = func(*UsernamePasswordCommand) (bool, error) { return false, nil }
|
||||
)
|
||||
@@ -0,0 +1,97 @@
|
||||
package credentialscmd
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/boundary/api/credentials"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
)
|
||||
|
||||
func init() {
|
||||
extraUsernamePasswordFlagsFunc = extraUsernamePasswordFlagsFuncImpl
|
||||
extraUsernamePasswordActionsFlagsMapFunc = extraUsernamePasswordActionsFlagsMapFuncImpl
|
||||
extraUsernamePasswordFlagsHandlingFunc = extraUsernamePasswordFlagHandlingFuncImpl
|
||||
}
|
||||
|
||||
const (
|
||||
usernameFlagName = "username"
|
||||
passwordFlagName = "password"
|
||||
)
|
||||
|
||||
type extraUsernamePasswordCmdVars struct {
|
||||
flagUsername string
|
||||
flagPassword string
|
||||
}
|
||||
|
||||
func extraUsernamePasswordActionsFlagsMapFuncImpl() map[string][]string {
|
||||
flags := map[string][]string{
|
||||
"create": {
|
||||
usernameFlagName,
|
||||
passwordFlagName,
|
||||
},
|
||||
}
|
||||
flags["update"] = flags["create"]
|
||||
return flags
|
||||
}
|
||||
|
||||
func extraUsernamePasswordFlagsFuncImpl(c *UsernamePasswordCommand, set *base.FlagSets, _ *base.FlagSet) {
|
||||
f := set.NewFlagSet("User Password Credential Options")
|
||||
|
||||
for _, name := range flagsUsernamePasswordMap[c.Func] {
|
||||
switch name {
|
||||
case usernameFlagName:
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: usernameFlagName,
|
||||
Target: &c.flagUsername,
|
||||
Usage: "The username associated with the credential.",
|
||||
})
|
||||
case passwordFlagName:
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: passwordFlagName,
|
||||
Target: &c.flagPassword,
|
||||
Usage: "The password associated with the credential.",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func extraUsernamePasswordFlagHandlingFuncImpl(c *UsernamePasswordCommand, _ *base.FlagSets, opts *[]credentials.Option) bool {
|
||||
switch c.flagUsername {
|
||||
case "":
|
||||
default:
|
||||
*opts = append(*opts, credentials.WithUsernamePasswordCredentialUsername(c.flagUsername))
|
||||
}
|
||||
switch c.flagPassword {
|
||||
case "":
|
||||
default:
|
||||
*opts = append(*opts, credentials.WithUsernamePasswordCredentialPassword(c.flagPassword))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCommand) extraUsernamePasswordHelpFunc(_ map[string]func() string) string {
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
case "create":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary credentials create username-password -credential-store-id [options] [args]",
|
||||
"",
|
||||
" Create a user password credential. Example:",
|
||||
"",
|
||||
` $ boundary credentials create username-password -credential-store-id csvlt_1234567890 -username user -password pass`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
|
||||
case "update":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary credentials update user password [options] [args]",
|
||||
"",
|
||||
" Update a user password credential given its ID. Example:",
|
||||
"",
|
||||
` $ boundary credentials update username-password -id clvlt_1234567890 -name devops -description "For DevOps usage"`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
}
|
||||
return helpStr + c.Flags().Help()
|
||||
}
|
||||
@@ -33,7 +33,11 @@ func (c *Command) extraHelpFunc(helpMap map[string]func() string) string {
|
||||
"",
|
||||
" Create a vault-type credential store:",
|
||||
"",
|
||||
` $ boundary credential-stores create vault -vault-address "http://localhost:8200" -vault-token "s.s0m3t0k3n"`,
|
||||
` $ boundary credential-stores create vault -scope-id p_1234567890 -vault-address "http://localhost:8200" -vault-token "s.s0m3t0k3n"`,
|
||||
"",
|
||||
" Create a static-type credential store:",
|
||||
"",
|
||||
` $ boundary credential-stores create static -scope-id p_1234567890`,
|
||||
"",
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
@@ -47,6 +51,10 @@ func (c *Command) extraHelpFunc(helpMap map[string]func() string) string {
|
||||
"",
|
||||
` $ boundary credential-stores update vault -id csvlt_1234567890 -name devops -description "For DevOps usage"`,
|
||||
"",
|
||||
" Update a static-type credential store:",
|
||||
"",
|
||||
` $ boundary credential-stores update static -id cs_1234567890 -name devops -description "For DevOps usage"`,
|
||||
"",
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
// Code generated by "make cli"; DO NOT EDIT.
|
||||
package credentialstorescmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/credentialstores"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/common"
|
||||
"github.com/hashicorp/go-secure-stdlib/strutil"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
func initStaticFlags() {
|
||||
flagsOnce.Do(func() {
|
||||
extraFlags := extraStaticActionsFlagsMapFunc()
|
||||
for k, v := range extraFlags {
|
||||
flagsStaticMap[k] = append(flagsStaticMap[k], v...)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
_ cli.Command = (*StaticCommand)(nil)
|
||||
_ cli.CommandAutocomplete = (*StaticCommand)(nil)
|
||||
)
|
||||
|
||||
type StaticCommand struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
|
||||
plural string
|
||||
}
|
||||
|
||||
func (c *StaticCommand) AutocompleteArgs() complete.Predictor {
|
||||
initStaticFlags()
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *StaticCommand) AutocompleteFlags() complete.Flags {
|
||||
initStaticFlags()
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *StaticCommand) Synopsis() string {
|
||||
if extra := extraStaticSynopsisFunc(c); extra != "" {
|
||||
return extra
|
||||
}
|
||||
|
||||
synopsisStr := "credential store"
|
||||
|
||||
synopsisStr = fmt.Sprintf("%s %s", "static-type", synopsisStr)
|
||||
|
||||
return common.SynopsisFunc(c.Func, synopsisStr)
|
||||
}
|
||||
|
||||
func (c *StaticCommand) Help() string {
|
||||
initStaticFlags()
|
||||
|
||||
var helpStr string
|
||||
helpMap := common.HelpMap("credential store")
|
||||
|
||||
switch c.Func {
|
||||
|
||||
default:
|
||||
|
||||
helpStr = c.extraStaticHelpFunc(helpMap)
|
||||
|
||||
}
|
||||
|
||||
// Keep linter from complaining if we don't actually generate code using it
|
||||
_ = helpMap
|
||||
return helpStr
|
||||
}
|
||||
|
||||
var flagsStaticMap = map[string][]string{
|
||||
|
||||
"create": {"scope-id", "name", "description"},
|
||||
|
||||
"update": {"id", "name", "description", "version"},
|
||||
}
|
||||
|
||||
func (c *StaticCommand) Flags() *base.FlagSets {
|
||||
if len(flagsStaticMap[c.Func]) == 0 {
|
||||
return c.FlagSet(base.FlagSetNone)
|
||||
}
|
||||
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
f := set.NewFlagSet("Command Options")
|
||||
common.PopulateCommonFlags(c.Command, f, "static-type credential store", flagsStaticMap, c.Func)
|
||||
|
||||
extraStaticFlagsFunc(c, set, f)
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *StaticCommand) Run(args []string) int {
|
||||
initStaticFlags()
|
||||
|
||||
switch c.Func {
|
||||
case "":
|
||||
return cli.RunResultHelp
|
||||
|
||||
}
|
||||
|
||||
c.plural = "static-type credential store"
|
||||
switch c.Func {
|
||||
case "list":
|
||||
c.plural = "static-type credential stores"
|
||||
}
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.PrintCliError(err)
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsStaticMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.PrintCliError(errors.New("ID is required but not passed in via -id"))
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
var opts []credentialstores.Option
|
||||
|
||||
if strutil.StrListContains(flagsStaticMap[c.Func], "scope-id") {
|
||||
switch c.Func {
|
||||
|
||||
case "create":
|
||||
if c.FlagScopeId == "" {
|
||||
c.PrintCliError(errors.New("Scope ID must be passed in via -scope-id or BOUNDARY_SCOPE_ID"))
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if c.WrapperCleanupFunc != nil {
|
||||
defer func() {
|
||||
if err := c.WrapperCleanupFunc(); err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error cleaning kms wrapper: %w", err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
if err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error creating API client: %w", err))
|
||||
return base.CommandCliError
|
||||
}
|
||||
credentialstoresClient := credentialstores.NewClient(client)
|
||||
|
||||
switch c.FlagName {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, credentialstores.DefaultName())
|
||||
default:
|
||||
opts = append(opts, credentialstores.WithName(c.FlagName))
|
||||
}
|
||||
|
||||
switch c.FlagDescription {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, credentialstores.DefaultDescription())
|
||||
default:
|
||||
opts = append(opts, credentialstores.WithDescription(c.FlagDescription))
|
||||
}
|
||||
|
||||
switch c.FlagRecursive {
|
||||
case true:
|
||||
opts = append(opts, credentialstores.WithRecursive(true))
|
||||
}
|
||||
|
||||
if c.FlagFilter != "" {
|
||||
opts = append(opts, credentialstores.WithFilter(c.FlagFilter))
|
||||
}
|
||||
|
||||
var version uint32
|
||||
|
||||
switch c.Func {
|
||||
|
||||
case "update":
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, credentialstores.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ok := extraStaticFlagsHandlingFunc(c, f, &opts); !ok {
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
var result api.GenericResult
|
||||
|
||||
switch c.Func {
|
||||
|
||||
case "create":
|
||||
result, err = credentialstoresClient.Create(c.Context, "static", c.FlagScopeId, opts...)
|
||||
|
||||
case "update":
|
||||
result, err = credentialstoresClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
|
||||
}
|
||||
|
||||
result, err = executeExtraStaticActions(c, result, err, credentialstoresClient, version, opts)
|
||||
|
||||
if err != nil {
|
||||
if apiErr := api.AsServerError(err); apiErr != nil {
|
||||
var opts []base.Option
|
||||
|
||||
opts = append(opts, base.WithAttributeFieldPrefix("static"))
|
||||
|
||||
c.PrintApiError(apiErr, fmt.Sprintf("Error from controller when performing %s on %s", c.Func, c.plural), opts...)
|
||||
return base.CommandApiError
|
||||
}
|
||||
c.PrintCliError(fmt.Errorf("Error trying to %s %s: %s", c.Func, c.plural, err.Error()))
|
||||
return base.CommandCliError
|
||||
}
|
||||
|
||||
output, err := printCustomStaticActionOutput(c)
|
||||
if err != nil {
|
||||
c.PrintCliError(err)
|
||||
return base.CommandUserError
|
||||
}
|
||||
if output {
|
||||
return base.CommandSuccess
|
||||
}
|
||||
|
||||
switch c.Func {
|
||||
|
||||
}
|
||||
|
||||
switch base.Format(c.UI) {
|
||||
case "table":
|
||||
c.UI.Output(printItemTable(result))
|
||||
|
||||
case "json":
|
||||
if ok := c.PrintJsonItem(result); !ok {
|
||||
return base.CommandCliError
|
||||
}
|
||||
}
|
||||
|
||||
return base.CommandSuccess
|
||||
}
|
||||
|
||||
var (
|
||||
extraStaticActionsFlagsMapFunc = func() map[string][]string { return nil }
|
||||
extraStaticSynopsisFunc = func(*StaticCommand) string { return "" }
|
||||
extraStaticFlagsFunc = func(*StaticCommand, *base.FlagSets, *base.FlagSet) {}
|
||||
extraStaticFlagsHandlingFunc = func(*StaticCommand, *base.FlagSets, *[]credentialstores.Option) bool { return true }
|
||||
executeExtraStaticActions = func(_ *StaticCommand, inResult api.GenericResult, inErr error, _ *credentialstores.Client, _ uint32, _ []credentialstores.Option) (api.GenericResult, error) {
|
||||
return inResult, inErr
|
||||
}
|
||||
printCustomStaticActionOutput = func(*StaticCommand) (bool, error) { return false, nil }
|
||||
)
|
||||
@@ -0,0 +1,33 @@
|
||||
package credentialstorescmd
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
)
|
||||
|
||||
func (c *StaticCommand) extraStaticHelpFunc(helpMap map[string]func() string) string {
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
case "create":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary credential-stores create static [options] [args]",
|
||||
"",
|
||||
" Create a static-type credential store. Example:",
|
||||
"",
|
||||
` $ boundary credential-stores create static -scope-id p_1234567890`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
|
||||
case "update":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary credential-stores update static [options] [args]",
|
||||
"",
|
||||
" Update a static-type credential store given its ID. Example:",
|
||||
"",
|
||||
` $ boundary credential-stores update static -name devops -description "For DevOps usage"`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
}
|
||||
return helpStr + c.Flags().Help()
|
||||
}
|
||||
@@ -30,30 +30,26 @@ func init() {
|
||||
}
|
||||
|
||||
type extraCmdVars struct {
|
||||
flagHostSets []string
|
||||
flagHostSources []string
|
||||
flagApplicationCredentialLibraries []string
|
||||
flagApplicationCredentialSources []string
|
||||
flagEgressCredentialSources []string
|
||||
flagHostId string
|
||||
sar *targets.SessionAuthorizationResult
|
||||
flagHostSets []string
|
||||
flagHostSources []string
|
||||
flagApplicationCredentialSources []string
|
||||
flagEgressCredentialSources []string
|
||||
flagHostId string
|
||||
sar *targets.SessionAuthorizationResult
|
||||
}
|
||||
|
||||
func extraActionsFlagsMapFuncImpl() map[string][]string {
|
||||
return map[string][]string{
|
||||
"authorize-session": {"id", "host-id"},
|
||||
"add-host-sets": {"id", "host-set", "version"},
|
||||
"remove-host-sets": {"id", "host-set", "version"},
|
||||
"set-host-sets": {"id", "host-set", "version"},
|
||||
"add-host-sources": {"id", "host-source", "version"},
|
||||
"remove-host-sources": {"id", "host-source", "version"},
|
||||
"set-host-sources": {"id", "host-source", "version"},
|
||||
"add-credential-libraries": {"id", "application-credential-library", "version"},
|
||||
"remove-credential-libraries": {"id", "application-credential-library", "version"},
|
||||
"set-credential-libraries": {"id", "application-credential-library", "version"},
|
||||
"add-credential-sources": {"id", "application-credential-source", "egress-credential-source", "version"},
|
||||
"remove-credential-sources": {"id", "application-credential-source", "egress-credential-source", "version"},
|
||||
"set-credential-sources": {"id", "application-credential-source", "egress-credential-source", "version"},
|
||||
"authorize-session": {"id", "host-id"},
|
||||
"add-host-sets": {"id", "host-set", "version"},
|
||||
"remove-host-sets": {"id", "host-set", "version"},
|
||||
"set-host-sets": {"id", "host-set", "version"},
|
||||
"add-host-sources": {"id", "host-source", "version"},
|
||||
"remove-host-sources": {"id", "host-source", "version"},
|
||||
"set-host-sources": {"id", "host-source", "version"},
|
||||
"add-credential-sources": {"id", "application-credential-source", "egress-credential-source", "version"},
|
||||
"remove-credential-sources": {"id", "application-credential-source", "egress-credential-source", "version"},
|
||||
"set-credential-sources": {"id", "application-credential-source", "egress-credential-source", "version"},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,18 +79,6 @@ func extraSynopsisFuncImpl(c *Command) string {
|
||||
}
|
||||
return wordwrap.WrapString(fmt.Sprintf("%s a target", in), base.TermWidth)
|
||||
|
||||
case "add-credential-libraries", "set-credential-libraries", "remove-credential-libraries":
|
||||
var in string
|
||||
switch {
|
||||
case strings.HasPrefix(c.Func, "add"):
|
||||
in = "Add credential libraries to"
|
||||
case strings.HasPrefix(c.Func, "set"):
|
||||
in = "Set the full contents of the credential libraries on"
|
||||
case strings.HasPrefix(c.Func, "remove"):
|
||||
in = "Remove credential libraries from"
|
||||
}
|
||||
return wordwrap.WrapString(fmt.Sprintf("%s a target. DEPRECATED; use the -sources version instead.", in), base.TermWidth)
|
||||
|
||||
case "add-credential-sources", "set-credential-sources", "remove-credential-sources":
|
||||
var in string
|
||||
switch {
|
||||
@@ -232,48 +216,6 @@ func (c *Command) extraHelpFunc(helpMap map[string]func() string) string {
|
||||
"",
|
||||
"",
|
||||
})
|
||||
case "add-credential-libraries":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary target add-credential-libraries [options] [args]",
|
||||
"",
|
||||
" DEPRECATED: Use add-credential-sources instead.",
|
||||
"",
|
||||
" This command allows adding credential-library resources to target resources. Example:",
|
||||
"",
|
||||
" Add credential-library resources to a tcp-type target:",
|
||||
"",
|
||||
` $ boundary targets add-credential-libraries -id ttcp_1234567890 -application-credential-library clvlt_1234567890 -application-credential-library clvlt_0987654321`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
case "remove-credential-libraries":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary target remove-credential-libraries [options] [args]",
|
||||
"",
|
||||
" DEPRECATED: Use remove-credential-sources instead.",
|
||||
"",
|
||||
" This command allows removing credential-library resources from target resources. Example:",
|
||||
"",
|
||||
" Remove credential-library resources from a tcp-type target:",
|
||||
"",
|
||||
` $ boundary targets remove-credential-libraries -id ttcp_1234567890 -application-credential-library clvlt_1234567890 -application-credential-library clvlt_0987654321`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
case "set-credential-libraries":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary target set-credential-libraries [options] [args]",
|
||||
"",
|
||||
" DEPRECATED: Use set-credential-sources instead.",
|
||||
"",
|
||||
" This command allows setting the complete set of credential-library resources on a target resource. Example:",
|
||||
"",
|
||||
" Set credential-library resources on a tcp-type target:",
|
||||
"",
|
||||
` $ boundary targets set-credential-libraries -id ttcp_1234567890 -application-credential-library clvlt_1234567890`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
case "add-credential-sources":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary target add-credential-sources [options] [args]",
|
||||
@@ -351,12 +293,6 @@ func extraFlagsFuncImpl(c *Command, _ *base.FlagSets, f *base.FlagSet) {
|
||||
Target: &c.flagHostId,
|
||||
Usage: "The ID of a specific host to connect to out of the hosts from the target's host sets. If not specified, one is chosen at random.",
|
||||
})
|
||||
case "application-credential-library":
|
||||
f.StringSliceVar(&base.StringSliceVar{
|
||||
Name: "application-credential-library",
|
||||
Target: &c.flagApplicationCredentialLibraries,
|
||||
Usage: "The credential-library resource for application purpose to add, set, or remove. May be specified multiple times.",
|
||||
})
|
||||
case "application-credential-source":
|
||||
f.StringSliceVar(&base.StringSliceVar{
|
||||
Name: "application-credential-source",
|
||||
@@ -467,13 +403,6 @@ func extraFlagsHandlingFuncImpl(c *Command, _ *base.FlagSets, opts *[]targets.Op
|
||||
}
|
||||
}
|
||||
|
||||
case "add-credential-libraries", "remove-credential-libraries":
|
||||
if len(c.flagApplicationCredentialLibraries) == 0 {
|
||||
c.UI.Error("No credential-libraries supplied via -application-credential-library")
|
||||
return false
|
||||
}
|
||||
*opts = append(*opts, targets.WithApplicationCredentialLibraryIds(c.flagApplicationCredentialLibraries))
|
||||
|
||||
case "add-credential-sources", "remove-credential-sources":
|
||||
// TODO: As we add other purposes, add them to this check
|
||||
if len(c.flagApplicationCredentialSources)+len(c.flagEgressCredentialSources) == 0 {
|
||||
@@ -488,21 +417,6 @@ func extraFlagsHandlingFuncImpl(c *Command, _ *base.FlagSets, opts *[]targets.Op
|
||||
*opts = append(*opts, targets.WithEgressCredentialSourceIds(c.flagEgressCredentialSources))
|
||||
}
|
||||
|
||||
case "set-credential-libraries":
|
||||
switch len(c.flagApplicationCredentialLibraries) {
|
||||
case 0:
|
||||
c.UI.Error("No credential-libraries supplied via -application-credential-library")
|
||||
return false
|
||||
case 1:
|
||||
if c.flagApplicationCredentialLibraries[0] == "null" {
|
||||
*opts = append(*opts, targets.DefaultApplicationCredentialLibraryIds())
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
*opts = append(*opts, targets.WithApplicationCredentialLibraryIds(c.flagApplicationCredentialLibraries))
|
||||
}
|
||||
|
||||
case "set-credential-sources":
|
||||
// TODO: As we add other purposes, add them to this check
|
||||
if len(c.flagApplicationCredentialSources)+len(c.flagEgressCredentialSources) == 0 {
|
||||
@@ -558,12 +472,6 @@ func executeExtraActionsImpl(c *Command, origResult api.GenericResult, origError
|
||||
return targetClient.RemoveHostSources(c.Context, c.FlagId, version, c.flagHostSources, opts...)
|
||||
case "set-host-sources":
|
||||
return targetClient.SetHostSources(c.Context, c.FlagId, version, c.flagHostSources, opts...)
|
||||
case "add-credential-libraries":
|
||||
return targetClient.AddCredentialLibraries(c.Context, c.FlagId, version, opts...)
|
||||
case "remove-credential-libraries":
|
||||
return targetClient.RemoveCredentialLibraries(c.Context, c.FlagId, version, opts...)
|
||||
case "set-credential-libraries":
|
||||
return targetClient.SetCredentialLibraries(c.Context, c.FlagId, version, opts...)
|
||||
case "add-credential-sources":
|
||||
return targetClient.AddCredentialSources(c.Context, c.FlagId, version, opts...)
|
||||
case "remove-credential-sources":
|
||||
@@ -702,23 +610,6 @@ func printItemTable(result api.GenericResult) string {
|
||||
}
|
||||
|
||||
var credentialSourceMaps map[credential.Purpose][]map[string]interface{}
|
||||
if len(item.ApplicationCredentialLibraries) > 0 {
|
||||
if credentialSourceMaps == nil {
|
||||
credentialSourceMaps = make(map[credential.Purpose][]map[string]interface{})
|
||||
}
|
||||
var applicationCredentialSourceMaps []map[string]interface{}
|
||||
for _, lib := range item.ApplicationCredentialLibraries {
|
||||
m := map[string]interface{}{
|
||||
"ID": lib.Id,
|
||||
"Credential Store ID": lib.CredentialStoreId,
|
||||
}
|
||||
applicationCredentialSourceMaps = append(applicationCredentialSourceMaps, m)
|
||||
}
|
||||
credentialSourceMaps[credential.ApplicationPurpose] = applicationCredentialSourceMaps
|
||||
if l := len("Credential Store ID"); l > maxLength {
|
||||
maxLength = l
|
||||
}
|
||||
}
|
||||
if len(item.ApplicationCredentialSources) > 0 {
|
||||
if credentialSourceMaps == nil {
|
||||
credentialSourceMaps = make(map[credential.Purpose][]map[string]interface{})
|
||||
@@ -888,7 +779,7 @@ func printCustomActionOutputImpl(c *Command) (bool, error) {
|
||||
|
||||
var secretStr []string
|
||||
switch cred.CredentialSource.Type {
|
||||
case "vault":
|
||||
case "vault", "static":
|
||||
switch {
|
||||
case cred.Credential != nil:
|
||||
maxLength := 0
|
||||
|
||||
@@ -249,30 +249,6 @@ func (c *Command) Run(args []string) int {
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
|
||||
case "add-credential-libraries":
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, targets.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
|
||||
case "remove-credential-libraries":
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, targets.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
|
||||
case "set-credential-libraries":
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, targets.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
|
||||
case "add-credential-sources":
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
|
||||
@@ -197,6 +197,21 @@ var inputStructs = map[string][]*cmdInfo{
|
||||
NeedsSubtypeInCreate: true,
|
||||
PrefixAttributeFieldErrorsWithSubactionPrefix: true,
|
||||
},
|
||||
{
|
||||
ResourceType: resource.CredentialStore.String(),
|
||||
Pkg: "credentialstores",
|
||||
StdActions: []string{"create", "update"},
|
||||
SubActionPrefix: "static",
|
||||
SkipNormalHelp: true,
|
||||
HasExtraHelpFunc: true,
|
||||
HasId: true,
|
||||
HasName: true,
|
||||
HasDescription: true,
|
||||
Container: "Scope",
|
||||
VersionedActions: []string{"update"},
|
||||
NeedsSubtypeInCreate: true,
|
||||
PrefixAttributeFieldErrorsWithSubactionPrefix: true,
|
||||
},
|
||||
},
|
||||
"credentiallibraries": {
|
||||
{
|
||||
@@ -223,6 +238,32 @@ var inputStructs = map[string][]*cmdInfo{
|
||||
PrefixAttributeFieldErrorsWithSubactionPrefix: true,
|
||||
},
|
||||
},
|
||||
"credentials": {
|
||||
{
|
||||
ResourceType: resource.Credential.String(),
|
||||
Pkg: "credentials",
|
||||
StdActions: []string{"read", "delete", "list"},
|
||||
HasExtraHelpFunc: true,
|
||||
Container: "CredentialStore",
|
||||
HasId: true,
|
||||
},
|
||||
{
|
||||
ResourceType: resource.Credential.String(),
|
||||
Pkg: "credentials",
|
||||
StdActions: []string{"create", "update"},
|
||||
SubActionPrefix: "username_password",
|
||||
HasExtraCommandVars: true,
|
||||
SkipNormalHelp: true,
|
||||
HasExtraHelpFunc: true,
|
||||
HasId: true,
|
||||
HasName: true,
|
||||
HasDescription: true,
|
||||
Container: "CredentialStore",
|
||||
VersionedActions: []string{"update"},
|
||||
NeedsSubtypeInCreate: true,
|
||||
PrefixAttributeFieldErrorsWithSubactionPrefix: true,
|
||||
},
|
||||
},
|
||||
"groups": {
|
||||
{
|
||||
ResourceType: resource.Group.String(),
|
||||
@@ -421,7 +462,7 @@ var inputStructs = map[string][]*cmdInfo{
|
||||
HasName: true,
|
||||
HasDescription: true,
|
||||
Container: "Scope",
|
||||
VersionedActions: []string{"add-host-sets", "remove-host-sets", "set-host-sets", "add-host-sources", "remove-host-sources", "set-host-sources", "add-credential-libraries", "remove-credential-libraries", "set-credential-libraries", "add-credential-sources", "remove-credential-sources", "set-credential-sources"},
|
||||
VersionedActions: []string{"add-host-sets", "remove-host-sets", "set-host-sets", "add-host-sources", "remove-host-sources", "set-host-sources", "add-credential-sources", "remove-credential-sources", "set-credential-sources"},
|
||||
},
|
||||
{
|
||||
ResourceType: resource.Target.String(),
|
||||
|
||||
@@ -26,8 +26,8 @@ type Type string
|
||||
|
||||
// Credential type values.
|
||||
const (
|
||||
UnspecifiedType Type = "unspecified"
|
||||
UserPasswordType Type = "user_password"
|
||||
UnspecifiedType Type = "unspecified"
|
||||
UsernamePasswordType Type = "username_password"
|
||||
)
|
||||
|
||||
// A Library is a resource that provides credentials that are of the same
|
||||
@@ -86,6 +86,12 @@ type Dynamic interface {
|
||||
Purpose() Purpose
|
||||
}
|
||||
|
||||
// Static is a static credential that is stored directly in a credential store.
|
||||
type Static interface {
|
||||
boundary.Resource
|
||||
GetStoreId() string
|
||||
}
|
||||
|
||||
// A Request represents a request for a credential from the SourceId for
|
||||
// the given purpose. For dynamic credentials, the SourceId is the PublicId
|
||||
// of a credential library.
|
||||
@@ -118,8 +124,8 @@ type Password string
|
||||
// PrivateKey represents a secret private key.
|
||||
type PrivateKey []byte
|
||||
|
||||
// UserPassword is a credential containing a username and a password.
|
||||
type UserPassword interface {
|
||||
// UsernamePassword is a credential containing a username and a password.
|
||||
type UsernamePassword interface {
|
||||
Credential
|
||||
Username() string
|
||||
Password() Password
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/boundary/internal/credential/static/store"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// A CredentialStore contains credentials. It is owned by a scope.
|
||||
type CredentialStore struct {
|
||||
*store.CredentialStore
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewCredentialStore creates a new in memory static CredentialStore assigned to scopeId.
|
||||
// Name and description are the only valid options. All other options are ignored.
|
||||
func NewCredentialStore(scopeId string, opt ...Option) (*CredentialStore, error) {
|
||||
opts := getOpts(opt...)
|
||||
cs := &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
ScopeId: scopeId,
|
||||
Name: opts.withName,
|
||||
Description: opts.withDescription,
|
||||
},
|
||||
}
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
func allocCredentialStore() *CredentialStore {
|
||||
return &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{},
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *CredentialStore) clone() *CredentialStore {
|
||||
cp := proto.Clone(cs.CredentialStore)
|
||||
return &CredentialStore{
|
||||
CredentialStore: cp.(*store.CredentialStore),
|
||||
}
|
||||
}
|
||||
|
||||
// TableName returns the table name.
|
||||
func (cs *CredentialStore) TableName() string {
|
||||
if cs.tableName != "" {
|
||||
return cs.tableName
|
||||
}
|
||||
return "credential_static_store"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name.
|
||||
func (cs *CredentialStore) SetTableName(n string) {
|
||||
cs.tableName = n
|
||||
}
|
||||
|
||||
func (cs *CredentialStore) oplog(op oplog.OpType) oplog.Metadata {
|
||||
metadata := oplog.Metadata{
|
||||
"resource-public-id": []string{cs.PublicId},
|
||||
"resource-type": []string{"credential-static-store"},
|
||||
"op-type": []string{op.String()},
|
||||
}
|
||||
if cs.ScopeId != "" {
|
||||
metadata["scope-id"] = []string{cs.ScopeId}
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/boundary/internal/credential/static/store"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
)
|
||||
|
||||
func TestCredentialStore_New(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
rw := db.New(conn)
|
||||
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
scope := prj
|
||||
|
||||
type args struct {
|
||||
scopeId string
|
||||
opts []Option
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *CredentialStore
|
||||
wantCreateErr bool
|
||||
}{
|
||||
{
|
||||
name: "missing-scope-id",
|
||||
want: allocCredentialStore(),
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-no-options",
|
||||
args: args{
|
||||
scopeId: scope.PublicId,
|
||||
},
|
||||
want: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
ScopeId: scope.PublicId,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
args: args{
|
||||
scopeId: scope.PublicId,
|
||||
opts: []Option{
|
||||
WithName("test-name"),
|
||||
},
|
||||
},
|
||||
want: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
ScopeId: scope.PublicId,
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
args: args{
|
||||
scopeId: scope.PublicId,
|
||||
opts: []Option{
|
||||
WithDescription("test-description"),
|
||||
},
|
||||
},
|
||||
want: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
ScopeId: scope.PublicId,
|
||||
Description: "test-description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
got, err := NewCredentialStore(tt.args.scopeId, tt.args.opts...)
|
||||
require.NoError(err)
|
||||
require.NotNil(got)
|
||||
|
||||
assert.Emptyf(got.PublicId, "PublicId set")
|
||||
assert.Equal(tt.want, got)
|
||||
assert.Empty(cmp.Diff(tt.want, got.clone(), protocmp.Transform()))
|
||||
|
||||
id, err := newCredentialStoreId(context.Background())
|
||||
assert.NoError(err)
|
||||
|
||||
tt.want.PublicId = id
|
||||
got.PublicId = id
|
||||
|
||||
err = rw.Create(context.Background(), got)
|
||||
if tt.wantCreateErr {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.NoError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// Package static implements a credential store for static credentials.
|
||||
package static
|
||||
@@ -0,0 +1,9 @@
|
||||
package static
|
||||
|
||||
// These constants are the field names used in the static related field masks.
|
||||
const (
|
||||
nameField = "Name"
|
||||
descriptionField = "Description"
|
||||
usernameField = "Username"
|
||||
passwordField = "Password"
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
package static
|
||||
|
||||
// getOpts - iterate the inbound Options and return a struct
|
||||
func getOpts(opt ...Option) options {
|
||||
opts := getDefaultOptions()
|
||||
for _, o := range opt {
|
||||
o(&opts)
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
// Option - how Options are passed as arguments.
|
||||
type Option func(*options)
|
||||
|
||||
// options = how options are represented
|
||||
type options struct {
|
||||
withName string
|
||||
withDescription string
|
||||
withLimit int
|
||||
}
|
||||
|
||||
func getDefaultOptions() options {
|
||||
return options{}
|
||||
}
|
||||
|
||||
// WithDescription provides an optional description.
|
||||
func WithDescription(desc string) Option {
|
||||
return func(o *options) {
|
||||
o.withDescription = desc
|
||||
}
|
||||
}
|
||||
|
||||
// WithName provides an optional name.
|
||||
func WithName(name string) Option {
|
||||
return func(o *options) {
|
||||
o.withName = name
|
||||
}
|
||||
}
|
||||
|
||||
// WithLimit provides an option to provide a limit. Intentionally allowing
|
||||
// negative integers. If WithLimit < 0, then unlimited results are
|
||||
// returned. If WithLimit == 0, then default limits are used for results.
|
||||
func WithLimit(l int) Option {
|
||||
return func(o *options) {
|
||||
o.withLimit = l
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_GetOpts(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("WithName", func(t *testing.T) {
|
||||
opts := getOpts(WithName("test"))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withName = "test"
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithDescription", func(t *testing.T) {
|
||||
opts := getOpts(WithDescription("test desc"))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withDescription = "test desc"
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithLimit", func(t *testing.T) {
|
||||
opts := getOpts(WithLimit(5))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withLimit = 5
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/types/subtypes"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := subtypes.Register(credential.Domain, Subtype, CredentialStorePrefix); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := subtypes.Register(credential.Domain, UsernamePasswordSubtype, CredentialPrefix); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// PublicId prefixes for the resources in the static package.
|
||||
const (
|
||||
CredentialStorePrefix = "cs"
|
||||
CredentialPrefix = "cred"
|
||||
|
||||
Subtype = subtypes.Subtype("static")
|
||||
UsernamePasswordSubtype = subtypes.Subtype("username_password")
|
||||
)
|
||||
|
||||
func newCredentialStoreId(ctx context.Context) (string, error) {
|
||||
id, err := db.NewPublicId(CredentialStorePrefix)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(ctx, err, "static.newCredentialStoreId")
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func newCredentialId(ctx context.Context) (string, error) {
|
||||
id, err := db.NewPublicId(CredentialPrefix)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(ctx, err, "static.newCredentialId")
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
)
|
||||
|
||||
// A Repository stores and retrieves the persistent types in the static
|
||||
// package. It is not safe to use a repository concurrently.
|
||||
type Repository struct {
|
||||
reader db.Reader
|
||||
writer db.Writer
|
||||
kms *kms.Kms
|
||||
// defaultLimit provides a default for limiting the number of results
|
||||
// returned from the repo
|
||||
defaultLimit int
|
||||
}
|
||||
|
||||
// NewRepository creates a new Repository. The returned repository should
|
||||
// only be used for one transaction and it is not safe for concurrent go
|
||||
// routines to access it. WithLimit option is used as a repo wide default
|
||||
// limit applied to all ListX methods.
|
||||
func NewRepository(ctx context.Context, r db.Reader, w db.Writer, kms *kms.Kms, opt ...Option) (*Repository, error) {
|
||||
const op = "static.NewRepository"
|
||||
switch {
|
||||
case r == nil:
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "db.Reader")
|
||||
case w == nil:
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "db.Writer")
|
||||
case kms == nil:
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "kms")
|
||||
}
|
||||
|
||||
opts := getOpts(opt...)
|
||||
if opts.withLimit == 0 {
|
||||
// zero signals the boundary defaults should be used.
|
||||
opts.withLimit = db.DefaultLimit
|
||||
}
|
||||
|
||||
return &Repository{
|
||||
reader: r,
|
||||
writer: w,
|
||||
kms: kms,
|
||||
defaultLimit: opts.withLimit,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
dbcommon "github.com/hashicorp/boundary/internal/db/common"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
)
|
||||
|
||||
// CreateUsernamePasswordCredential inserts c into the repository and returns a new
|
||||
// UsernamePasswordCredential containing the credential's PublicId. c is not
|
||||
// changed. c must not contain a PublicId. The PublicId is generated and
|
||||
// assigned by this method. c must contain a valid StoreId.
|
||||
//
|
||||
// The password is encrypted and a HmacSha256 of the password is calculated. Only the
|
||||
// PasswordHmac is returned, the plain-text and encrypted password is not returned.
|
||||
//
|
||||
// Both c.Name and c.Description are optional. If c.Name is set, it must
|
||||
// be unique within c.ScopeId. Both c.CreateTime and c.UpdateTime are
|
||||
// ignored.
|
||||
func (r *Repository) CreateUsernamePasswordCredential(
|
||||
ctx context.Context,
|
||||
scopeId string,
|
||||
c *UsernamePasswordCredential,
|
||||
_ ...Option,
|
||||
) (*UsernamePasswordCredential, error) {
|
||||
const op = "static.(Repository).CreateUsernamePasswordCredential"
|
||||
if c == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing credential")
|
||||
}
|
||||
if c.UsernamePasswordCredential == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing embedded credential")
|
||||
}
|
||||
if scopeId == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing scope id")
|
||||
}
|
||||
if c.Username == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing username")
|
||||
}
|
||||
if c.Password == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing password")
|
||||
}
|
||||
if c.StoreId == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing store id")
|
||||
}
|
||||
if c.PublicId != "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "public id not empty")
|
||||
}
|
||||
|
||||
c = c.clone()
|
||||
id, err := newCredentialId(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
c.PublicId = id
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get oplog wrapper"))
|
||||
}
|
||||
|
||||
// encrypt
|
||||
databaseWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeDatabase)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get database wrapper"))
|
||||
}
|
||||
if err := c.encrypt(ctx, databaseWrapper); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
var newCred *UsernamePasswordCredential
|
||||
_, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
newCred = c.clone()
|
||||
if err := w.Create(ctx, newCred,
|
||||
db.WithOplog(oplogWrapper, newCred.oplog(oplog.OpType_OP_TYPE_CREATE))); err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if errors.IsUniqueError(err) {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("in store: %s: name %s already exists", c.StoreId, c.Name)))
|
||||
}
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("in store: %s", c.StoreId)))
|
||||
}
|
||||
|
||||
// Clear password fields, only passwordHmac should be returned
|
||||
newCred.CtPassword = nil
|
||||
newCred.Password = nil
|
||||
|
||||
return newCred, nil
|
||||
}
|
||||
|
||||
// LookupCredential returns the Credential for the publicId. Returns
|
||||
// nil, nil if no Credential is found for the publicId.
|
||||
// TODO: This should hit a view and return the interface type...
|
||||
func (r *Repository) LookupCredential(ctx context.Context, publicId string, _ ...Option) (*UsernamePasswordCredential, error) {
|
||||
const op = "static.(Repository).LookupCredential"
|
||||
if publicId == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no public id")
|
||||
}
|
||||
cred := allocUsernamePasswordCredential()
|
||||
cred.PublicId = publicId
|
||||
if err := r.reader.LookupByPublicId(ctx, cred); err != nil {
|
||||
if errors.IsNotFoundError(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for: %s", publicId)))
|
||||
}
|
||||
|
||||
// Clear password fields, only passwordHmac should be returned
|
||||
cred.CtPassword = nil
|
||||
cred.Password = nil
|
||||
|
||||
return cred, nil
|
||||
}
|
||||
|
||||
// UpdateUsernamePasswordCredential updates the repository entry for c.PublicId with
|
||||
// the values in c for the fields listed in fieldMaskPaths. It returns a
|
||||
// new UsernamePasswordCredential containing the updated values and a count of the
|
||||
// number of records updated. c is not changed.
|
||||
//
|
||||
// c must contain a valid PublicId. Only Name, Description, Username and Password can be
|
||||
// changed. If c.Name is set to a non-empty string, it must be unique within c.ScopeId.
|
||||
//
|
||||
// An attribute of c will be set to NULL in the database if the attribute
|
||||
// in c is the zero value and it is included in fieldMaskPaths.
|
||||
func (r *Repository) UpdateUsernamePasswordCredential(ctx context.Context,
|
||||
scopeId string,
|
||||
c *UsernamePasswordCredential,
|
||||
version uint32,
|
||||
fieldMaskPaths []string,
|
||||
_ ...Option,
|
||||
) (*UsernamePasswordCredential, int, error) {
|
||||
const op = "static.(Repository).UpdateUsernamePasswordCredential"
|
||||
if c == nil {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing Credential")
|
||||
}
|
||||
if c.UsernamePasswordCredential == nil {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing embedded Credential")
|
||||
}
|
||||
if c.PublicId == "" {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidPublicId, op, "missing public id")
|
||||
}
|
||||
if version == 0 {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing version")
|
||||
}
|
||||
if scopeId == "" {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing scope id")
|
||||
}
|
||||
if c.StoreId == "" {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing store id")
|
||||
}
|
||||
c = c.clone()
|
||||
|
||||
for _, f := range fieldMaskPaths {
|
||||
switch {
|
||||
case strings.EqualFold(nameField, f):
|
||||
case strings.EqualFold(descriptionField, f):
|
||||
case strings.EqualFold(usernameField, f):
|
||||
case strings.EqualFold(passwordField, f):
|
||||
default:
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidFieldMask, op, f)
|
||||
}
|
||||
}
|
||||
dbMask, nullFields := dbcommon.BuildUpdatePaths(
|
||||
map[string]interface{}{
|
||||
nameField: c.Name,
|
||||
descriptionField: c.Description,
|
||||
usernameField: c.Username,
|
||||
passwordField: c.Password,
|
||||
},
|
||||
fieldMaskPaths,
|
||||
nil,
|
||||
)
|
||||
if len(dbMask) == 0 && len(nullFields) == 0 {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.EmptyFieldMask, op, "missing field mask")
|
||||
}
|
||||
|
||||
for _, f := range fieldMaskPaths {
|
||||
if strings.EqualFold(passwordField, f) {
|
||||
// Password has been updated, re-encrypt and recalculate hmac
|
||||
databaseWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeDatabase)
|
||||
if err != nil {
|
||||
return nil, db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get database wrapper"))
|
||||
}
|
||||
if err := c.encrypt(ctx, databaseWrapper); err != nil {
|
||||
return nil, db.NoRowsAffected, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
// Set PasswordHmac and CtPassword masks for update.
|
||||
dbMask = append(dbMask, "PasswordHmac", "CtPassword")
|
||||
}
|
||||
}
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
return nil, db.NoRowsAffected,
|
||||
errors.Wrap(ctx, err, op, errors.WithMsg("unable to get oplog wrapper"))
|
||||
}
|
||||
|
||||
var rowsUpdated int
|
||||
var returnedCredential *UsernamePasswordCredential
|
||||
_, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
returnedCredential = c.clone()
|
||||
var err error
|
||||
rowsUpdated, err = w.Update(ctx, returnedCredential,
|
||||
dbMask, nullFields,
|
||||
db.WithOplog(oplogWrapper, returnedCredential.oplog(oplog.OpType_OP_TYPE_UPDATE)),
|
||||
db.WithVersion(&version))
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if rowsUpdated > 1 {
|
||||
return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been updated")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, db.NoRowsAffected, err
|
||||
}
|
||||
|
||||
// Clear password fields, only passwordHmac should be returned
|
||||
returnedCredential.CtPassword = nil
|
||||
returnedCredential.Password = nil
|
||||
|
||||
return returnedCredential, rowsUpdated, nil
|
||||
}
|
||||
|
||||
// ListCredentials returns a slice of UsernamePasswordCredentials for the
|
||||
// scopeIds. WithLimit is the only option supported.
|
||||
// TODO: This should hit a view and return the interface type...
|
||||
func (r *Repository) ListCredentials(ctx context.Context, storeId string, opt ...Option) ([]*UsernamePasswordCredential, error) {
|
||||
const op = "static.(Repository).ListCredentials"
|
||||
if storeId == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no storeId")
|
||||
}
|
||||
opts := getOpts(opt...)
|
||||
limit := r.defaultLimit
|
||||
if opts.withLimit != 0 {
|
||||
// non-zero signals an override of the default limit for the repo.
|
||||
limit = opts.withLimit
|
||||
}
|
||||
var creds []*UsernamePasswordCredential
|
||||
err := r.reader.SearchWhere(ctx, &creds, "store_id = ?", []interface{}{storeId}, db.WithLimit(limit))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
for _, c := range creds {
|
||||
// Clear password fields, only passwordHmac should be returned
|
||||
c.CtPassword = nil
|
||||
c.Password = nil
|
||||
}
|
||||
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
// DeleteCredential deletes publicId from the repository and returns
|
||||
// the number of records deleted. All options are ignored.
|
||||
// TODO: This should hit a view...
|
||||
func (r *Repository) DeleteCredential(ctx context.Context, scopeId, id string, _ ...Option) (int, error) {
|
||||
const op = "static.(Repository).DeleteCredential"
|
||||
if id == "" {
|
||||
return db.NoRowsAffected, errors.New(ctx, errors.InvalidPublicId, op, "missing public id")
|
||||
}
|
||||
if scopeId == "" {
|
||||
return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "no scope id")
|
||||
}
|
||||
|
||||
c := allocUsernamePasswordCredential()
|
||||
c.PublicId = id
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt), errors.WithMsg("unable to get oplog wrapper"))
|
||||
}
|
||||
|
||||
var rowsDeleted int
|
||||
_, err = r.writer.DoTx(
|
||||
ctx,
|
||||
db.StdRetryCnt,
|
||||
db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) (err error) {
|
||||
rowsDeleted, err = w.Delete(ctx, c, db.WithOplog(oplogWrapper, c.oplog(oplog.OpType_OP_TYPE_DELETE)))
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if rowsDeleted > 1 {
|
||||
return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(id))
|
||||
}
|
||||
|
||||
return rowsDeleted, nil
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
dbcommon "github.com/hashicorp/boundary/internal/db/common"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
)
|
||||
|
||||
// CreateCredentialStore inserts cs into the repository and returns a new
|
||||
// CredentialStore containing the credential store's PublicId. cs is not
|
||||
// changed. cs must not contain a PublicId. The PublicId is generated and
|
||||
// assigned by this method. cs must contain a valid ScopeId.
|
||||
//
|
||||
// Both cs.Name and cs.Description are optional. If cs.Name is set, it must
|
||||
// be unique within cs.ScopeId. Both cs.CreateTime and cs.UpdateTime are
|
||||
// ignored.
|
||||
func (r *Repository) CreateCredentialStore(ctx context.Context, cs *CredentialStore, _ ...Option) (*CredentialStore, error) {
|
||||
const op = "static.(Repository).CreateCredentialStore"
|
||||
if cs == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing CredentialStore")
|
||||
}
|
||||
if cs.CredentialStore == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing embedded CredentialStore")
|
||||
}
|
||||
if cs.ScopeId == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing scope id")
|
||||
}
|
||||
if cs.PublicId != "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "public id not empty")
|
||||
}
|
||||
|
||||
cs = cs.clone()
|
||||
id, err := newCredentialStoreId(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
cs.PublicId = id
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, cs.ScopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get oplog wrapper"))
|
||||
}
|
||||
|
||||
var newCredentialStore *CredentialStore
|
||||
_, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
newCredentialStore = cs.clone()
|
||||
if err := w.Create(ctx, newCredentialStore,
|
||||
db.WithOplog(oplogWrapper, newCredentialStore.oplog(oplog.OpType_OP_TYPE_CREATE))); err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if errors.IsUniqueError(err) {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("in scope: %s: name %s already exists", cs.ScopeId, cs.Name)))
|
||||
}
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("in scope: %s", cs.ScopeId)))
|
||||
}
|
||||
|
||||
return newCredentialStore, nil
|
||||
}
|
||||
|
||||
// LookupCredentialStore returns the CredentialStore for publicId. Returns
|
||||
// nil, nil if no CredentialStore is found for publicId.
|
||||
func (r *Repository) LookupCredentialStore(ctx context.Context, publicId string, _ ...Option) (*CredentialStore, error) {
|
||||
const op = "static.(Repository).LookupCredentialStore"
|
||||
if publicId == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no public id")
|
||||
}
|
||||
cs := allocCredentialStore()
|
||||
cs.PublicId = publicId
|
||||
if err := r.reader.LookupByPublicId(ctx, cs); err != nil {
|
||||
if errors.IsNotFoundError(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for: %s", publicId)))
|
||||
}
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
// UpdateCredentialStore updates the repository entry for cs.PublicId with
|
||||
// the values in cs for the fields listed in fieldMaskPaths. It returns a
|
||||
// new CredentialStore containing the updated values and a count of the
|
||||
// number of records updated. cs is not changed.
|
||||
//
|
||||
// cs must contain a valid PublicId. Only Name and Description can be changed. If cs.Name
|
||||
// is set to a non-empty string, it must be unique within cs.ScopeId.
|
||||
//
|
||||
// An attribute of cs will be set to NULL in the database if the attribute
|
||||
// in cs is the zero value and it is included in fieldMaskPaths.
|
||||
func (r *Repository) UpdateCredentialStore(ctx context.Context, cs *CredentialStore, version uint32, fieldMaskPaths []string, _ ...Option) (*CredentialStore, int, error) {
|
||||
const op = "static.(Repository).UpdateCredentialStore"
|
||||
if cs == nil {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing CredentialStore")
|
||||
}
|
||||
if cs.CredentialStore == nil {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing embedded CredentialStore")
|
||||
}
|
||||
if cs.PublicId == "" {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidPublicId, op, "missing public id")
|
||||
}
|
||||
if version == 0 {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing version")
|
||||
}
|
||||
if cs.ScopeId == "" {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing scope id")
|
||||
}
|
||||
cs = cs.clone()
|
||||
|
||||
for _, f := range fieldMaskPaths {
|
||||
switch {
|
||||
case strings.EqualFold(nameField, f):
|
||||
case strings.EqualFold(descriptionField, f):
|
||||
default:
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidFieldMask, op, f)
|
||||
}
|
||||
}
|
||||
dbMask, nullFields := dbcommon.BuildUpdatePaths(
|
||||
map[string]interface{}{
|
||||
nameField: cs.Name,
|
||||
descriptionField: cs.Description,
|
||||
},
|
||||
fieldMaskPaths,
|
||||
nil,
|
||||
)
|
||||
if len(dbMask) == 0 && len(nullFields) == 0 {
|
||||
return nil, db.NoRowsAffected, errors.New(ctx, errors.EmptyFieldMask, op, "missing field mask")
|
||||
}
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, cs.ScopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
return nil, db.NoRowsAffected,
|
||||
errors.Wrap(ctx, err, op, errors.WithMsg("unable to get oplog wrapper"))
|
||||
}
|
||||
|
||||
var rowsUpdated int
|
||||
var returnedCredentialStore *CredentialStore
|
||||
_, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
returnedCredentialStore = cs.clone()
|
||||
var err error
|
||||
rowsUpdated, err = w.Update(ctx, returnedCredentialStore,
|
||||
dbMask, nullFields,
|
||||
db.WithOplog(oplogWrapper, returnedCredentialStore.oplog(oplog.OpType_OP_TYPE_UPDATE)),
|
||||
db.WithVersion(&version))
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if rowsUpdated > 1 {
|
||||
return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been updated")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, db.NoRowsAffected, err
|
||||
}
|
||||
|
||||
return returnedCredentialStore, rowsUpdated, nil
|
||||
}
|
||||
|
||||
// ListCredentialStores returns a slice of CredentialStores for the
|
||||
// scopeIds. WithLimit is the only option supported.
|
||||
func (r *Repository) ListCredentialStores(ctx context.Context, scopeIds []string, opt ...Option) ([]*CredentialStore, error) {
|
||||
const op = "static.(Repository).ListCredentialStores"
|
||||
if len(scopeIds) == 0 {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no scopeIds")
|
||||
}
|
||||
opts := getOpts(opt...)
|
||||
limit := r.defaultLimit
|
||||
if opts.withLimit != 0 {
|
||||
// non-zero signals an override of the default limit for the repo.
|
||||
limit = opts.withLimit
|
||||
}
|
||||
var credentialStores []*CredentialStore
|
||||
err := r.reader.SearchWhere(ctx, &credentialStores, "scope_id in (?)", []interface{}{scopeIds}, db.WithLimit(limit))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
return credentialStores, nil
|
||||
}
|
||||
|
||||
// DeleteCredentialStore deletes publicId from the repository and returns
|
||||
// the number of records deleted. All options are ignored.
|
||||
func (r *Repository) DeleteCredentialStore(ctx context.Context, publicId string, _ ...Option) (int, error) {
|
||||
const op = "static.(Repository).DeleteCredentialStore"
|
||||
if publicId == "" {
|
||||
return db.NoRowsAffected, errors.New(ctx, errors.InvalidPublicId, op, "missing public id")
|
||||
}
|
||||
cs := allocCredentialStore()
|
||||
cs.PublicId = publicId
|
||||
if err := r.reader.LookupByPublicId(ctx, cs); err != nil {
|
||||
if errors.IsNotFoundError(err) {
|
||||
return db.NoRowsAffected, nil
|
||||
}
|
||||
return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", publicId)))
|
||||
}
|
||||
if cs.ScopeId == "" {
|
||||
return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "no scope id")
|
||||
}
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, cs.ScopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt), errors.WithMsg("unable to get oplog wrapper"))
|
||||
}
|
||||
|
||||
var rowsDeleted int
|
||||
_, err = r.writer.DoTx(
|
||||
ctx,
|
||||
db.StdRetryCnt,
|
||||
db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) (err error) {
|
||||
rowsDeleted, err = w.Delete(ctx, cs, db.WithOplog(oplogWrapper, cs.oplog(oplog.OpType_OP_TYPE_DELETE)))
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if rowsDeleted > 1 {
|
||||
return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(publicId))
|
||||
}
|
||||
|
||||
return rowsDeleted, nil
|
||||
}
|
||||
@@ -0,0 +1,746 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential/static/store"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
dbassert "github.com/hashicorp/boundary/internal/db/assert"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func assertPublicId(t *testing.T, prefix, actual string) {
|
||||
t.Helper()
|
||||
assert.NotEmpty(t, actual)
|
||||
parts := strings.Split(actual, "_")
|
||||
assert.Equalf(t, 2, len(parts), "want one '_' in PublicId, got multiple in %q", actual)
|
||||
assert.Equalf(t, prefix, parts[0], "PublicId want prefix: %q, got: %q in %q", prefix, parts[0], actual)
|
||||
}
|
||||
|
||||
func TestRepository_CreateCredentialStore(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
store *CredentialStore
|
||||
wantErr bool
|
||||
wantErrCode errors.Code
|
||||
}{
|
||||
{
|
||||
name: "missing-store",
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "missing-embedded-store",
|
||||
store: &CredentialStore{},
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "missing-scope-id",
|
||||
store: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{},
|
||||
},
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "public-id-set",
|
||||
store: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
ScopeId: prj.PublicId,
|
||||
PublicId: "bad-dont-set-this",
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
store: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
ScopeId: prj.PublicId,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
store: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
ScopeId: prj.PublicId,
|
||||
Name: "test-store",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
store: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
ScopeId: prj.PublicId,
|
||||
Description: "test-store-description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kms)
|
||||
require.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
got, err := repo.CreateCredentialStore(ctx, tt.store)
|
||||
if tt.wantErr {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantErr), err), "want err: %q got: %q", tt.wantErr, err)
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.Empty(tt.store.PublicId)
|
||||
require.NotNil(got)
|
||||
assertPublicId(t, CredentialStorePrefix, got.PublicId)
|
||||
assert.NotSame(tt.store, got)
|
||||
assert.Equal(got.CreateTime, got.UpdateTime)
|
||||
assert.NoError(db.TestVerifyOplog(t, rw, got.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)))
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("duplicate-names", func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kms)
|
||||
require.NoError(err)
|
||||
require.NotNil(repo)
|
||||
org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
require.NoError(err)
|
||||
|
||||
in, err := NewCredentialStore(prj.GetPublicId(), WithName("my-name"), WithDescription("desc"))
|
||||
assert.NoError(err)
|
||||
|
||||
got, err := repo.CreateCredentialStore(ctx, in)
|
||||
require.NoError(err)
|
||||
assert.Equal(in.Name, got.Name)
|
||||
assert.Equal(in.Description, got.Description)
|
||||
|
||||
in2, err := NewCredentialStore(prj.GetPublicId(), WithName("my-name"), WithDescription("desc"))
|
||||
got2, err := repo.CreateCredentialStore(ctx, in2)
|
||||
assert.Truef(errors.Match(errors.T(errors.NotUnique), err), "want err code: %v got err: %v", errors.NotUnique, err)
|
||||
assert.Nil(got2)
|
||||
|
||||
// Creating credential in different scope should not conflict
|
||||
in3, err := NewCredentialStore(org.GetPublicId(), WithName("my-name"), WithDescription("desc"))
|
||||
got3, err := repo.CreateCredentialStore(ctx, in3)
|
||||
require.NoError(err)
|
||||
assert.Equal(in.Name, got3.Name)
|
||||
assert.Equal(in3.Name, got3.Name)
|
||||
assert.Equal(in3.Description, got3.Description)
|
||||
|
||||
assert.NotEqual(got.PublicId, got3.PublicId)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRepository_LookupCredentialStore(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
store := TestCredentialStore(t, conn, wrapper, prj.PublicId)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
id string
|
||||
want *CredentialStore
|
||||
wantErr errors.Code
|
||||
}{
|
||||
{
|
||||
name: "valid-with-client-cert",
|
||||
id: store.GetPublicId(),
|
||||
want: store,
|
||||
},
|
||||
{
|
||||
name: "empty-public-id",
|
||||
id: "",
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "not-found",
|
||||
id: "cs_fake",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
got, err := repo.LookupCredentialStore(ctx, tt.id)
|
||||
if tt.wantErr != 0 {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantErr), err), "want err: %q got: %q", tt.wantErr, err)
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
|
||||
if tt.want == nil {
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
assert.NotNil(got)
|
||||
assert.Equal(got, tt.want)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_UpdateCredentialStore(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
changeName := func(n string) func(*CredentialStore) *CredentialStore {
|
||||
return func(cs *CredentialStore) *CredentialStore {
|
||||
cs.Name = n
|
||||
return cs
|
||||
}
|
||||
}
|
||||
|
||||
changeDescription := func(d string) func(*CredentialStore) *CredentialStore {
|
||||
return func(cs *CredentialStore) *CredentialStore {
|
||||
cs.Description = d
|
||||
return cs
|
||||
}
|
||||
}
|
||||
|
||||
makeNil := func() func(*CredentialStore) *CredentialStore {
|
||||
return func(cs *CredentialStore) *CredentialStore {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
makeEmbeddedNil := func() func(*CredentialStore) *CredentialStore {
|
||||
return func(cs *CredentialStore) *CredentialStore {
|
||||
return &CredentialStore{}
|
||||
}
|
||||
}
|
||||
|
||||
deletePublicId := func() func(*CredentialStore) *CredentialStore {
|
||||
return func(cs *CredentialStore) *CredentialStore {
|
||||
cs.PublicId = ""
|
||||
return cs
|
||||
}
|
||||
}
|
||||
|
||||
nonExistentPublicId := func() func(*CredentialStore) *CredentialStore {
|
||||
return func(cs *CredentialStore) *CredentialStore {
|
||||
cs.PublicId = "abcd_OOOOOOOOOO"
|
||||
return cs
|
||||
}
|
||||
}
|
||||
|
||||
combine := func(fns ...func(cs *CredentialStore) *CredentialStore) func(*CredentialStore) *CredentialStore {
|
||||
return func(cs *CredentialStore) *CredentialStore {
|
||||
for _, fn := range fns {
|
||||
cs = fn(cs)
|
||||
}
|
||||
return cs
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
orig *CredentialStore
|
||||
chgFn func(*CredentialStore) *CredentialStore
|
||||
masks []string
|
||||
want *CredentialStore
|
||||
wantCount int
|
||||
wantErr errors.Code
|
||||
}{
|
||||
{
|
||||
name: "nil-credential-store",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{},
|
||||
},
|
||||
chgFn: makeNil(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-embedded-credential-store",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{},
|
||||
},
|
||||
chgFn: makeEmbeddedNil(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "no-public-id",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{},
|
||||
},
|
||||
chgFn: deletePublicId(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantErr: errors.InvalidPublicId,
|
||||
},
|
||||
{
|
||||
name: "updating-non-existent-credential-store",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: combine(nonExistentPublicId(), changeName("test-update-name-repo")),
|
||||
masks: []string{"Name"},
|
||||
wantErr: errors.RecordNotFound,
|
||||
},
|
||||
{
|
||||
name: "empty-field-mask",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
wantErr: errors.EmptyFieldMask,
|
||||
},
|
||||
{
|
||||
name: "read-only-fields-in-field-mask",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"PublicId", "CreateTime", "UpdateTime", "ScopeId"},
|
||||
wantErr: errors.InvalidFieldMask,
|
||||
},
|
||||
{
|
||||
name: "unknown-field-in-field-mask",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"Bilbo"},
|
||||
wantErr: errors.InvalidFieldMask,
|
||||
},
|
||||
{
|
||||
name: "change-name",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"Name"},
|
||||
want: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-update-name-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-description",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeDescription("test-update-description-repo"),
|
||||
masks: []string{"Description"},
|
||||
want: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Description: "test-update-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-name-and-description",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("test-update-name-repo")),
|
||||
masks: []string{"Name", "Description"},
|
||||
want: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-update-name-repo",
|
||||
Description: "test-update-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "delete-name",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Name"},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("")),
|
||||
want: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "delete-description",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Description"},
|
||||
chgFn: combine(changeDescription(""), changeName("test-update-name-repo")),
|
||||
want: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "do-not-delete-name",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Description"},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("")),
|
||||
want: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-update-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "do-not-delete-description",
|
||||
orig: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Name"},
|
||||
chgFn: combine(changeDescription(""), changeName("test-update-name-repo")),
|
||||
want: &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-update-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
tt.orig.ScopeId = prj.GetPublicId()
|
||||
|
||||
orig, err := repo.CreateCredentialStore(ctx, tt.orig)
|
||||
assert.NoError(err)
|
||||
require.NotNil(orig)
|
||||
|
||||
if tt.chgFn != nil {
|
||||
orig = tt.chgFn(orig)
|
||||
}
|
||||
got, gotCount, err := repo.UpdateCredentialStore(ctx, orig, 1, tt.masks)
|
||||
if tt.wantErr != 0 {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantErr), err), "want err: %q got: %q", tt.wantErr, err)
|
||||
assert.Equal(tt.wantCount, gotCount, "row count")
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.Empty(tt.orig.PublicId)
|
||||
require.NotNil(got)
|
||||
assertPublicId(t, CredentialStorePrefix, got.PublicId)
|
||||
assert.Equal(tt.wantCount, gotCount, "row count")
|
||||
assert.NotSame(tt.orig, got)
|
||||
assert.Equal(tt.orig.ScopeId, got.ScopeId)
|
||||
underlyingDB, err := conn.SqlDB(ctx)
|
||||
require.NoError(err)
|
||||
dbassert := dbassert.New(t, underlyingDB)
|
||||
if tt.want.Name == "" {
|
||||
dbassert.IsNull(got, "name")
|
||||
} else {
|
||||
assert.Equal(tt.want.Name, got.Name)
|
||||
}
|
||||
|
||||
if tt.want.Description == "" {
|
||||
dbassert.IsNull(got, "description")
|
||||
} else {
|
||||
assert.Equal(tt.want.Description, got.Description)
|
||||
}
|
||||
|
||||
if tt.wantCount > 0 {
|
||||
assert.NoError(db.TestVerifyOplog(t, rw, got.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_UPDATE), db.WithCreateNotBefore(10*time.Second)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("invalid-duplicate-names", func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
require.NoError(err)
|
||||
|
||||
name := "test-dup-name"
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
css := TestCredentialStores(t, conn, wrapper, prj.PublicId, 2)
|
||||
|
||||
csA, csB := css[0], css[1]
|
||||
|
||||
csA.Name = name
|
||||
got1, gotCount1, err := repo.UpdateCredentialStore(ctx, csA, 1, []string{"Name"})
|
||||
assert.NoError(err)
|
||||
require.NotNil(got1)
|
||||
assert.Equal(name, got1.Name)
|
||||
assert.Equal(1, gotCount1, "row count")
|
||||
assert.NoError(db.TestVerifyOplog(t, rw, csA.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_UPDATE), db.WithCreateNotBefore(10*time.Second)))
|
||||
|
||||
csB.Name = name
|
||||
got2, gotCount2, err := repo.UpdateCredentialStore(ctx, csB, 1, []string{"Name"})
|
||||
assert.Truef(errors.Match(errors.T(errors.NotUnique), err), "want err code: %v got err: %v", errors.NotUnique, err)
|
||||
assert.Nil(got2)
|
||||
assert.Equal(db.NoRowsAffected, gotCount2, "row count")
|
||||
})
|
||||
|
||||
t.Run("valid-duplicate-names-diff-scopes", func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
in := &CredentialStore{
|
||||
CredentialStore: &store.CredentialStore{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
}
|
||||
in2 := in.clone()
|
||||
|
||||
in.ScopeId = prj.GetPublicId()
|
||||
got, err := repo.CreateCredentialStore(ctx, in)
|
||||
assert.NoError(err)
|
||||
require.NotNil(got)
|
||||
assertPublicId(t, CredentialStorePrefix, got.PublicId)
|
||||
assert.NotSame(in, got)
|
||||
assert.Equal(in.Name, got.Name)
|
||||
assert.Equal(in.Description, got.Description)
|
||||
|
||||
in2.ScopeId = org.GetPublicId()
|
||||
in2.Name = "first-name"
|
||||
got2, err := repo.CreateCredentialStore(ctx, in2)
|
||||
assert.NoError(err)
|
||||
require.NotNil(got2)
|
||||
got2.Name = got.Name
|
||||
got3, gotCount3, err := repo.UpdateCredentialStore(ctx, got2, 1, []string{"Name"})
|
||||
assert.NoError(err)
|
||||
require.NotNil(got3)
|
||||
assert.NotSame(got2, got3)
|
||||
assert.Equal(got.Name, got3.Name)
|
||||
assert.Equal(got2.Description, got3.Description)
|
||||
assert.Equal(1, gotCount3, "row count")
|
||||
})
|
||||
|
||||
t.Run("change-scope-id", func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
_, prj1 := iam.TestScopes(t, iamRepo)
|
||||
_, prj2 := iam.TestScopes(t, iamRepo)
|
||||
csA, csB := TestCredentialStores(t, conn, wrapper, prj1.PublicId, 1)[0], TestCredentialStores(t, conn, wrapper, prj2.PublicId, 1)[0]
|
||||
assert.NotEqual(csA.ScopeId, csB.ScopeId)
|
||||
orig := csA.clone()
|
||||
|
||||
csA.ScopeId = csB.ScopeId
|
||||
assert.Equal(csA.ScopeId, csB.ScopeId)
|
||||
|
||||
got1, gotCount1, err := repo.UpdateCredentialStore(ctx, csA, 1, []string{"Name"})
|
||||
|
||||
assert.NoError(err)
|
||||
require.NotNil(got1)
|
||||
assert.Equal(orig.ScopeId, got1.ScopeId)
|
||||
assert.Equal(1, gotCount1, "row count")
|
||||
})
|
||||
}
|
||||
|
||||
func TestRepository_ListCredentialStores(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
repo, err := NewRepository(context.Background(), rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
const num = 10
|
||||
var prjs []string
|
||||
var total int
|
||||
for i := 0; i < num; i++ {
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
prjs = append(prjs, prj.GetPublicId())
|
||||
TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), num)
|
||||
total += num
|
||||
}
|
||||
|
||||
type args struct {
|
||||
scopeIds []string
|
||||
opt []Option
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantCnt int
|
||||
}{
|
||||
{
|
||||
name: "no-limit",
|
||||
args: args{
|
||||
scopeIds: prjs,
|
||||
opt: []Option{WithLimit(-1)},
|
||||
},
|
||||
wantCnt: total,
|
||||
},
|
||||
{
|
||||
name: "default-limit",
|
||||
args: args{
|
||||
scopeIds: prjs,
|
||||
},
|
||||
wantCnt: total,
|
||||
},
|
||||
{
|
||||
name: "custom-limit",
|
||||
args: args{
|
||||
scopeIds: prjs,
|
||||
opt: []Option{WithLimit(3)},
|
||||
},
|
||||
wantCnt: 3,
|
||||
},
|
||||
{
|
||||
name: "bad-scope",
|
||||
args: args{
|
||||
scopeIds: []string{"bad-id"},
|
||||
},
|
||||
wantCnt: 0,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
got, err := repo.ListCredentialStores(context.Background(), tt.args.scopeIds, tt.args.opt...)
|
||||
require.NoError(err)
|
||||
assert.Equal(tt.wantCnt, len(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_DeleteCredentialStore(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
iam.TestRepo(t, conn, wrapper)
|
||||
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
store := TestCredentialStore(t, conn, wrapper, prj.PublicId)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
in string
|
||||
want int
|
||||
wantErr bool
|
||||
wantErrCode errors.Code
|
||||
}{
|
||||
{
|
||||
name: "With no public id",
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidPublicId,
|
||||
},
|
||||
{
|
||||
name: "With non existing account id",
|
||||
in: "cs_fakeid",
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "With existing account id",
|
||||
in: store.GetPublicId(),
|
||||
want: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
repo, err := NewRepository(context.Background(), rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
got, err := repo.DeleteCredentialStore(context.Background(), tt.in)
|
||||
if tt.wantErr {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "Unexpected error %s", err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.EqualValues(tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,896 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential/static/store"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
dbassert "github.com/hashicorp/boundary/internal/db/assert"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/libs/crypto"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRepository_CreateUsernamePasswordCredential(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
|
||||
cs := TestCredentialStore(t, conn, wrapper, prj.PublicId)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
scopeId string
|
||||
cred *UsernamePasswordCredential
|
||||
wantErr bool
|
||||
wantErrCode errors.Code
|
||||
}{
|
||||
{
|
||||
name: "missing-store",
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "missing-embedded-cred",
|
||||
cred: &UsernamePasswordCredential{},
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "missing-scope-id",
|
||||
cred: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "my-user",
|
||||
Password: []byte("secret"),
|
||||
StoreId: cs.PublicId,
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "missing-username",
|
||||
scopeId: prj.PublicId,
|
||||
cred: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Password: []byte("secret"),
|
||||
StoreId: cs.PublicId,
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "missing-password",
|
||||
scopeId: prj.PublicId,
|
||||
cred: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "my-user",
|
||||
StoreId: cs.PublicId,
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "missing-store-id",
|
||||
scopeId: prj.PublicId,
|
||||
cred: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "my-user",
|
||||
Password: []byte("secret"),
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
scopeId: prj.PublicId,
|
||||
cred: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "my-user",
|
||||
Password: []byte("secret"),
|
||||
StoreId: cs.PublicId,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kkms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kkms)
|
||||
require.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
got, err := repo.CreateUsernamePasswordCredential(ctx, tt.scopeId, tt.cred)
|
||||
if tt.wantErr {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantErr), err), "want err: %q got: %q", tt.wantErr, err)
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assertPublicId(t, CredentialPrefix, got.PublicId)
|
||||
assert.Equal(tt.cred.Username, got.Username)
|
||||
assert.Nil(got.Password)
|
||||
assert.Nil(got.CtPassword)
|
||||
|
||||
// Validate password
|
||||
lookupCred := allocUsernamePasswordCredential()
|
||||
lookupCred.PublicId = got.PublicId
|
||||
require.NoError(rw.LookupById(ctx, lookupCred))
|
||||
|
||||
databaseWrapper, err := kkms.GetWrapper(context.Background(), tt.scopeId, kms.KeyPurposeDatabase)
|
||||
require.NoError(err)
|
||||
require.NoError(lookupCred.decrypt(ctx, databaseWrapper))
|
||||
assert.Equal(tt.cred.Password, lookupCred.Password)
|
||||
|
||||
assert.Empty(got.Password)
|
||||
assert.Empty(got.CtPassword)
|
||||
assert.NotEmpty(got.PasswordHmac)
|
||||
|
||||
// Validate hmac
|
||||
hm, err := crypto.HmacSha256(ctx, tt.cred.Password, databaseWrapper, []byte(tt.cred.StoreId), nil, crypto.WithEd25519())
|
||||
require.NoError(err)
|
||||
assert.Equal([]byte(hm), got.PasswordHmac)
|
||||
|
||||
// Validate oplog
|
||||
assert.NoError(db.TestVerifyOplog(t, rw, got.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)))
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("duplicate-names", func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kms)
|
||||
require.NoError(err)
|
||||
require.NotNil(repo)
|
||||
org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
require.NoError(err)
|
||||
|
||||
prjCs := TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
orgCs := TestCredentialStore(t, conn, wrapper, org.GetPublicId())
|
||||
|
||||
in, err := NewUsernamePasswordCredential(prjCs.GetPublicId(), "user", "pass", WithName("my-name"), WithDescription("original"))
|
||||
assert.NoError(err)
|
||||
|
||||
got, err := repo.CreateUsernamePasswordCredential(ctx, prj.PublicId, in)
|
||||
require.NoError(err)
|
||||
assert.Equal(in.Name, got.Name)
|
||||
assert.Equal(in.Description, got.Description)
|
||||
|
||||
in2, err := NewUsernamePasswordCredential(prjCs.GetPublicId(), "user", "pass", WithName("my-name"), WithDescription("different"))
|
||||
got2, err := repo.CreateUsernamePasswordCredential(ctx, prj.GetPublicId(), in2)
|
||||
assert.Truef(errors.Match(errors.T(errors.NotUnique), err), "want err code: %v got err: %v", errors.NotUnique, err)
|
||||
assert.Nil(got2)
|
||||
|
||||
// Creating credential in different scope should not conflict
|
||||
in3, err := NewUsernamePasswordCredential(orgCs.GetPublicId(), "user", "pass", WithName("my-name"), WithDescription("different"))
|
||||
got3, err := repo.CreateUsernamePasswordCredential(ctx, org.GetPublicId(), in3)
|
||||
require.NoError(err)
|
||||
assert.Equal(in3.Name, got3.Name)
|
||||
assert.Equal(in3.Description, got3.Description)
|
||||
|
||||
assert.NotEqual(got.PublicId, got3.PublicId)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRepository_LookupCredential(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
store := TestCredentialStore(t, conn, wrapper, prj.PublicId)
|
||||
cred := TestUsernamePasswordCredential(t, conn, wrapper, "username", "password", store.PublicId, prj.PublicId)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
id string
|
||||
want *UsernamePasswordCredential
|
||||
wantErr errors.Code
|
||||
}{
|
||||
{
|
||||
name: "valid-with-client-cert",
|
||||
id: cred.GetPublicId(),
|
||||
want: cred,
|
||||
},
|
||||
{
|
||||
name: "empty-public-id",
|
||||
id: "",
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "not-found",
|
||||
id: "cred_fake",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
got, err := repo.LookupCredential(ctx, tt.id)
|
||||
if tt.wantErr != 0 {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantErr), err), "want err: %q got: %q", tt.wantErr, err)
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
|
||||
if tt.want == nil {
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
|
||||
assert.NotNil(got)
|
||||
assert.Empty(got.Password)
|
||||
assert.Empty(got.CtPassword)
|
||||
assert.NotEmpty(got.PasswordHmac)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_ListCredentials(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
repo, err := NewRepository(context.Background(), rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
total := 10
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
store := TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
TestUsernamePasswordCredentials(t, conn, wrapper, "user", "pass", store.GetPublicId(), prj.GetPublicId(), total)
|
||||
|
||||
type args struct {
|
||||
storeId string
|
||||
opt []Option
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantCnt int
|
||||
}{
|
||||
{
|
||||
name: "no-limit",
|
||||
args: args{
|
||||
storeId: store.PublicId,
|
||||
opt: []Option{WithLimit(-1)},
|
||||
},
|
||||
wantCnt: total,
|
||||
},
|
||||
{
|
||||
name: "default-limit",
|
||||
args: args{
|
||||
storeId: store.PublicId,
|
||||
},
|
||||
wantCnt: total,
|
||||
},
|
||||
{
|
||||
name: "custom-limit",
|
||||
args: args{
|
||||
storeId: store.PublicId,
|
||||
opt: []Option{WithLimit(3)},
|
||||
},
|
||||
wantCnt: 3,
|
||||
},
|
||||
{
|
||||
name: "bad-store",
|
||||
args: args{
|
||||
storeId: "bad-id",
|
||||
},
|
||||
wantCnt: 0,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
got, err := repo.ListCredentials(context.Background(), tt.args.storeId, tt.args.opt...)
|
||||
require.NoError(err)
|
||||
assert.Equal(tt.wantCnt, len(got))
|
||||
|
||||
// Validate only passwordHmac is returned
|
||||
for _, c := range got {
|
||||
assert.Empty(c.Password)
|
||||
assert.Empty(c.CtPassword)
|
||||
assert.NotEmpty(c.PasswordHmac)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_DeleteCredential(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
iam.TestRepo(t, conn, wrapper)
|
||||
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
store := TestCredentialStore(t, conn, wrapper, prj.PublicId)
|
||||
cred := TestUsernamePasswordCredential(t, conn, wrapper, "user", "pass", store.GetPublicId(), prj.GetPublicId())
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
in string
|
||||
want int
|
||||
wantErr bool
|
||||
wantErrCode errors.Code
|
||||
}{
|
||||
{
|
||||
name: "With no public id",
|
||||
wantErr: true,
|
||||
wantErrCode: errors.InvalidPublicId,
|
||||
},
|
||||
{
|
||||
name: "With non existing account id",
|
||||
in: "cred_fakeid",
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "With existing id",
|
||||
in: cred.GetPublicId(),
|
||||
want: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
repo, err := NewRepository(context.Background(), rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
got, err := repo.DeleteCredential(context.Background(), prj.GetPublicId(), tt.in)
|
||||
if tt.wantErr {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "Unexpected error %s", err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.EqualValues(tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_UpdateUsernamePasswordCredential(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
changeName := func(n string) func(credential *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(c *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
c.Name = n
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
changeDescription := func(d string) func(*UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(c *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
c.Description = d
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
makeNil := func() func(*UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(_ *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
makeEmbeddedNil := func() func(*UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(_ *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return &UsernamePasswordCredential{}
|
||||
}
|
||||
}
|
||||
|
||||
deletePublicId := func() func(*UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(c *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
c.PublicId = ""
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
deleteStoreId := func() func(*UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(c *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
c.StoreId = ""
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
deleteVersion := func() func(*UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(c *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
c.Version = 0
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
nonExistentPublicId := func() func(*UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(c *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
c.PublicId = "abcd_OOOOOOOOOO"
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
changeUser := func(n string) func(credential *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(c *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
c.Username = n
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
changePassword := func(d string) func(*UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(c *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
c.Password = []byte(d)
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
combine := func(fns ...func(cs *UsernamePasswordCredential) *UsernamePasswordCredential) func(*UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
return func(c *UsernamePasswordCredential) *UsernamePasswordCredential {
|
||||
for _, fn := range fns {
|
||||
c = fn(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
orig *UsernamePasswordCredential
|
||||
chgFn func(*UsernamePasswordCredential) *UsernamePasswordCredential
|
||||
masks []string
|
||||
want *UsernamePasswordCredential
|
||||
wantCount int
|
||||
wantErr errors.Code
|
||||
}{
|
||||
{
|
||||
name: "nil-credential",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: makeNil(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-embedded-credential",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: makeEmbeddedNil(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "no-public-id",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: deletePublicId(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantErr: errors.InvalidPublicId,
|
||||
},
|
||||
{
|
||||
name: "no-store-id",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: deleteStoreId(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "no-version",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: deleteVersion(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "updating-non-existent-credential",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: combine(nonExistentPublicId(), changeName("test-update-name-repo")),
|
||||
masks: []string{"Name"},
|
||||
wantErr: errors.RecordNotFound,
|
||||
},
|
||||
{
|
||||
name: "empty-field-mask",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
wantErr: errors.EmptyFieldMask,
|
||||
},
|
||||
{
|
||||
name: "read-only-fields-in-field-mask",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"PublicId", "CreateTime", "UpdateTime", "ScopeId"},
|
||||
wantErr: errors.InvalidFieldMask,
|
||||
},
|
||||
{
|
||||
name: "unknown-field-in-field-mask",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"Bilbo"},
|
||||
wantErr: errors.InvalidFieldMask,
|
||||
},
|
||||
{
|
||||
name: "change-name",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"Name"},
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-update-name-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-description",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Description: "test-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: changeDescription("test-update-description-repo"),
|
||||
masks: []string{"Description"},
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Description: "test-update-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-name-and-description",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("test-update-name-repo")),
|
||||
masks: []string{"Name", "Description"},
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-update-name-repo",
|
||||
Description: "test-update-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-username",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: changeUser("test-update-user"),
|
||||
masks: []string{"Username"},
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "test-update-user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-password",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: changePassword("test-update-pass"),
|
||||
masks: []string{"Password"},
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("test-update-pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-username-and-password",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
chgFn: combine(changeUser("test-update-user"), changePassword("test-update-pass")),
|
||||
masks: []string{"Username", "Password"},
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "test-update-user",
|
||||
Password: []byte("test-update-pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "do-not-delete-password",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
masks: []string{"Username"},
|
||||
chgFn: combine(changeUser("test-new-user"), changePassword("")),
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "test-new-user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "do-not-delete-username",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
masks: []string{"Password"},
|
||||
chgFn: combine(changeUser(""), changePassword("test-new-password")),
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "user",
|
||||
Password: []byte("test-new-password"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "delete-name",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
masks: []string{"Name"},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("")),
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Description: "test-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "delete-description",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
masks: []string{"Description"},
|
||||
chgFn: combine(changeDescription(""), changeName("test-update-name-repo")),
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "do-not-delete-name",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
masks: []string{"Description"},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("")),
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-update-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "do-not-delete-description",
|
||||
orig: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
masks: []string{"Name"},
|
||||
chgFn: combine(changeDescription(""), changeName("test-update-name-repo")),
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Name: "test-update-name-repo",
|
||||
Description: "test-description-repo",
|
||||
Username: "user",
|
||||
Password: []byte("pass"),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
kkms := kms.TestKms(t, conn, wrapper)
|
||||
repo, err := NewRepository(ctx, rw, rw, kkms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
store := TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
tt.orig.StoreId = store.PublicId
|
||||
|
||||
orig, err := repo.CreateUsernamePasswordCredential(ctx, prj.GetPublicId(), tt.orig)
|
||||
assert.NoError(err)
|
||||
require.NotNil(orig)
|
||||
|
||||
if tt.chgFn != nil {
|
||||
orig = tt.chgFn(orig)
|
||||
}
|
||||
var version uint32
|
||||
if orig != nil {
|
||||
version = orig.GetVersion()
|
||||
}
|
||||
got, gotCount, err := repo.UpdateUsernamePasswordCredential(ctx, prj.GetPublicId(), orig, version, tt.masks)
|
||||
if tt.wantErr != 0 {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantErr), err), "want err: %q got: %q", tt.wantErr, err)
|
||||
assert.Equal(tt.wantCount, gotCount, "row count")
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.Empty(tt.orig.PublicId)
|
||||
require.NotNil(got)
|
||||
assertPublicId(t, CredentialPrefix, got.PublicId)
|
||||
assert.Equal(tt.wantCount, gotCount, "row count")
|
||||
assert.NotSame(tt.orig, got)
|
||||
assert.Equal(tt.orig.StoreId, got.StoreId)
|
||||
underlyingDB, err := conn.SqlDB(ctx)
|
||||
require.NoError(err)
|
||||
dbassert := dbassert.New(t, underlyingDB)
|
||||
if tt.want.Name == "" {
|
||||
got := got.clone()
|
||||
dbassert.IsNull(got, "name")
|
||||
} else {
|
||||
assert.Equal(tt.want.Name, got.Name)
|
||||
}
|
||||
|
||||
if tt.want.Description == "" {
|
||||
got := got.clone()
|
||||
dbassert.IsNull(got, "description")
|
||||
} else {
|
||||
assert.Equal(tt.want.Description, got.Description)
|
||||
}
|
||||
|
||||
assert.Equal(tt.want.Username, got.Username)
|
||||
|
||||
// Validate only passwordHmac is returned
|
||||
assert.Empty(got.Password)
|
||||
assert.Empty(got.CtPassword)
|
||||
assert.NotEmpty(got.PasswordHmac)
|
||||
|
||||
// Validate hmac
|
||||
databaseWrapper, err := kkms.GetWrapper(context.Background(), prj.GetPublicId(), kms.KeyPurposeDatabase)
|
||||
require.NoError(err)
|
||||
hm, err := crypto.HmacSha256(ctx, tt.want.Password, databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(err)
|
||||
assert.Equal([]byte(hm), got.PasswordHmac)
|
||||
|
||||
if tt.wantCount > 0 {
|
||||
assert.NoError(db.TestVerifyOplog(t, rw, got.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_UPDATE), db.WithCreateNotBefore(10*time.Second)))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
)
|
||||
|
||||
// Retrieve retrieves and returns static credentials from Boundary for all the provided
|
||||
// ids. All the returned static credentials will have their secret fields decrypted.
|
||||
func (r *Repository) Retrieve(ctx context.Context, scopeId string, ids []string) ([]credential.Static, error) {
|
||||
const op = "static.(Repository).Retrieve"
|
||||
if len(ids) == 0 {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no ids")
|
||||
}
|
||||
|
||||
var creds []*UsernamePasswordCredential
|
||||
err := r.reader.SearchWhere(ctx, &creds, "public_id in (?)", []interface{}{ids})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if len(creds) != len(ids) {
|
||||
return nil, errors.New(ctx, errors.NotSpecificIntegrity, op,
|
||||
fmt.Sprintf("mismatch between creds and number of ids requested, expected %d got %d", len(ids), len(creds)))
|
||||
}
|
||||
|
||||
out := make([]credential.Static, 0, len(ids))
|
||||
for _, c := range creds {
|
||||
// decrypt credential
|
||||
databaseWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeDatabase)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get database wrapper"))
|
||||
}
|
||||
if err := c.decrypt(ctx, databaseWrapper); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
out = append(out, c)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/static/store"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/db/timestamp"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRepository_Retrieve(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
repo, err := NewRepository(context.Background(), rw, rw, kms)
|
||||
assert.NoError(err)
|
||||
require.NotNil(repo)
|
||||
|
||||
org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
staticStore := TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
cred1 := TestUsernamePasswordCredential(t, conn, wrapper, "user", "pass", staticStore.GetPublicId(), prj.GetPublicId())
|
||||
cred2 := TestUsernamePasswordCredential(t, conn, wrapper, "different user", "better password", staticStore.GetPublicId(), prj.GetPublicId())
|
||||
cred3 := TestUsernamePasswordCredential(t, conn, wrapper, "final user", "horrible password", staticStore.GetPublicId(), prj.GetPublicId())
|
||||
|
||||
type args struct {
|
||||
credIds []string
|
||||
scopeId string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
wantCreds []credential.Static
|
||||
}{
|
||||
{
|
||||
name: "no-scope",
|
||||
args: args{
|
||||
credIds: []string{cred1.GetPublicId()},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid-scope",
|
||||
args: args{
|
||||
scopeId: org.GetPublicId(),
|
||||
credIds: []string{cred1.GetPublicId()},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-one-cred",
|
||||
args: args{
|
||||
scopeId: prj.GetPublicId(),
|
||||
credIds: []string{cred1.GetPublicId()},
|
||||
},
|
||||
wantCreds: []credential.Static{
|
||||
cred1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-multiple-creds",
|
||||
args: args{
|
||||
scopeId: prj.GetPublicId(),
|
||||
credIds: []string{cred1.GetPublicId(), cred2.GetPublicId(), cred3.GetPublicId()},
|
||||
},
|
||||
wantCreds: []credential.Static{
|
||||
cred1, cred2, cred3,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotCreds, err := repo.Retrieve(context.Background(), tt.args.scopeId, tt.args.credIds)
|
||||
if tt.wantErr {
|
||||
require.Error(err)
|
||||
assert.Nil(gotCreds)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.Empty(
|
||||
cmp.Diff(
|
||||
tt.wantCreds,
|
||||
gotCreds,
|
||||
cmpopts.IgnoreUnexported(UsernamePasswordCredential{}, store.UsernamePasswordCredential{}),
|
||||
cmpopts.IgnoreTypes(×tamp.Timestamp{}),
|
||||
cmpopts.SortSlices(func(x, y credential.Static) bool {
|
||||
return x.GetPublicId() < y.GetPublicId()
|
||||
}),
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRepository_New(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
|
||||
type args struct {
|
||||
r db.Reader
|
||||
w db.Writer
|
||||
kms *kms.Kms
|
||||
opts []Option
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *Repository
|
||||
wantIsErr errors.Code
|
||||
}{
|
||||
{
|
||||
name: "valid",
|
||||
args: args{
|
||||
r: rw,
|
||||
w: rw,
|
||||
kms: kmsCache,
|
||||
},
|
||||
want: &Repository{
|
||||
reader: rw,
|
||||
writer: rw,
|
||||
kms: kmsCache,
|
||||
defaultLimit: db.DefaultLimit,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-limit",
|
||||
args: args{
|
||||
r: rw,
|
||||
w: rw,
|
||||
kms: kmsCache,
|
||||
opts: []Option{WithLimit(5)},
|
||||
},
|
||||
want: &Repository{
|
||||
reader: rw,
|
||||
writer: rw,
|
||||
kms: kmsCache,
|
||||
defaultLimit: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "nil-reader",
|
||||
args: args{
|
||||
r: nil,
|
||||
w: rw,
|
||||
kms: kmsCache,
|
||||
},
|
||||
want: nil,
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-writer",
|
||||
args: args{
|
||||
r: rw,
|
||||
w: nil,
|
||||
kms: kmsCache,
|
||||
},
|
||||
want: nil,
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-kms",
|
||||
args: args{
|
||||
r: rw,
|
||||
w: rw,
|
||||
kms: nil,
|
||||
},
|
||||
want: nil,
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "all-nils",
|
||||
args: args{
|
||||
r: nil,
|
||||
w: nil,
|
||||
kms: nil,
|
||||
},
|
||||
want: nil,
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
got, err := NewRepository(context.Background(), tt.args.r, tt.args.w, tt.args.kms, tt.args.opts...)
|
||||
if tt.wantIsErr != 0 {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "want err: %q got: %q", tt.wantIsErr, err)
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
require.NotNil(got)
|
||||
assert.Equal(tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,467 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc (unknown)
|
||||
// source: controller/storage/credential/static/store/v1/static.proto
|
||||
|
||||
// Package store provides protobufs for storing types in the static
|
||||
// credential package.
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
timestamp "github.com/hashicorp/boundary/internal/db/timestamp"
|
||||
_ "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type CredentialStore struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// public_id is a surrogate key suitable for use in a public API.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
PublicId string `protobuf:"bytes,1,opt,name=public_id,json=publicId,proto3" json:"public_id,omitempty" gorm:"primary_key"`
|
||||
// The create_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
CreateTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty" gorm:"default:current_timestamp"`
|
||||
// The update_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
UpdateTime *timestamp.Timestamp `protobuf:"bytes,3,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty" gorm:"default:current_timestamp"`
|
||||
// name is optional. If set, it must be unique within scope_id.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty" gorm:"default:null"`
|
||||
// description is optional.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty" gorm:"default:null"`
|
||||
// The scope_id of the owning scope.
|
||||
// It must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
ScopeId string `protobuf:"bytes,6,opt,name=scope_id,json=scopeId,proto3" json:"scope_id,omitempty" gorm:"not_null"`
|
||||
// version allows optimistic locking of the resource.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Version uint32 `protobuf:"varint,7,opt,name=version,proto3" json:"version,omitempty" gorm:"default:null"`
|
||||
}
|
||||
|
||||
func (x *CredentialStore) Reset() {
|
||||
*x = CredentialStore{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_credential_static_store_v1_static_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *CredentialStore) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CredentialStore) ProtoMessage() {}
|
||||
|
||||
func (x *CredentialStore) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_credential_static_store_v1_static_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CredentialStore.ProtoReflect.Descriptor instead.
|
||||
func (*CredentialStore) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_credential_static_store_v1_static_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *CredentialStore) GetPublicId() string {
|
||||
if x != nil {
|
||||
return x.PublicId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CredentialStore) GetCreateTime() *timestamp.Timestamp {
|
||||
if x != nil {
|
||||
return x.CreateTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *CredentialStore) GetUpdateTime() *timestamp.Timestamp {
|
||||
if x != nil {
|
||||
return x.UpdateTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *CredentialStore) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CredentialStore) GetDescription() string {
|
||||
if x != nil {
|
||||
return x.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CredentialStore) GetScopeId() string {
|
||||
if x != nil {
|
||||
return x.ScopeId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CredentialStore) GetVersion() uint32 {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type UsernamePasswordCredential struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// public_id is a surrogate key suitable for use in a public API.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
PublicId string `protobuf:"bytes,1,opt,name=public_id,json=publicId,proto3" json:"public_id,omitempty" gorm:"primary_key"`
|
||||
// create_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
CreateTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty" gorm:"default:current_timestamp"`
|
||||
// update_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
UpdateTime *timestamp.Timestamp `protobuf:"bytes,3,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty" gorm:"default:current_timestamp"`
|
||||
// name is optional. If set, it must be unique within scope_id.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty" gorm:"default:null"`
|
||||
// description is optional.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty" gorm:"default:null"`
|
||||
// store_id of the owning static credential store.
|
||||
// It must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
StoreId string `protobuf:"bytes,6,opt,name=store_id,json=storeId,proto3" json:"store_id,omitempty" gorm:"not_null"`
|
||||
// version allows optimistic locking of the resource.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Version uint32 `protobuf:"varint,7,opt,name=version,proto3" json:"version,omitempty" gorm:"default:null"`
|
||||
// username is the username associated with the credential.
|
||||
// It must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
Username string `protobuf:"bytes,8,opt,name=username,proto3" json:"username,omitempty" gorm:"not_null"`
|
||||
// password is the plain-text of the password associated with the credential. We are
|
||||
// not storing this plain-text password in the database.
|
||||
// @inject_tag: `gorm:"-" wrapping:"pt,password_data"`
|
||||
Password []byte `protobuf:"bytes,9,opt,name=password,proto3" json:"password,omitempty" gorm:"-" wrapping:"pt,password_data"`
|
||||
// ct_password is the ciphertext of the password. It
|
||||
// is stored in the database.
|
||||
// @inject_tag: `gorm:"column:password_encrypted;not_null" wrapping:"ct,password_data"`
|
||||
CtPassword []byte `protobuf:"bytes,10,opt,name=ct_password,json=ctPassword,proto3" json:"ct_password,omitempty" gorm:"column:password_encrypted;not_null" wrapping:"ct,password_data"`
|
||||
// password_hmac is a sha256-hmac of the unencrypted password. It is recalculated
|
||||
// everytime the password is updated.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
PasswordHmac []byte `protobuf:"bytes,11,opt,name=password_hmac,json=passwordHmac,proto3" json:"password_hmac,omitempty" gorm:"not_null"`
|
||||
// The key_id of the kms database key used for encrypting this entry.
|
||||
// It must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
KeyId string `protobuf:"bytes,12,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty" gorm:"not_null"`
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) Reset() {
|
||||
*x = UsernamePasswordCredential{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_credential_static_store_v1_static_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UsernamePasswordCredential) ProtoMessage() {}
|
||||
|
||||
func (x *UsernamePasswordCredential) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_credential_static_store_v1_static_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UsernamePasswordCredential.ProtoReflect.Descriptor instead.
|
||||
func (*UsernamePasswordCredential) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_credential_static_store_v1_static_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetPublicId() string {
|
||||
if x != nil {
|
||||
return x.PublicId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetCreateTime() *timestamp.Timestamp {
|
||||
if x != nil {
|
||||
return x.CreateTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetUpdateTime() *timestamp.Timestamp {
|
||||
if x != nil {
|
||||
return x.UpdateTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetDescription() string {
|
||||
if x != nil {
|
||||
return x.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetStoreId() string {
|
||||
if x != nil {
|
||||
return x.StoreId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetVersion() uint32 {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetUsername() string {
|
||||
if x != nil {
|
||||
return x.Username
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetPassword() []byte {
|
||||
if x != nil {
|
||||
return x.Password
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetCtPassword() []byte {
|
||||
if x != nil {
|
||||
return x.CtPassword
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetPasswordHmac() []byte {
|
||||
if x != nil {
|
||||
return x.PasswordHmac
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UsernamePasswordCredential) GetKeyId() string {
|
||||
if x != nil {
|
||||
return x.KeyId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_controller_storage_credential_static_store_v1_static_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_controller_storage_credential_static_store_v1_static_proto_rawDesc = []byte{
|
||||
0x0a, 0x3a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x61, 0x67, 0x65, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f,
|
||||
0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x2f,
|
||||
0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2d, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
|
||||
0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2e, 0x73, 0x74, 0x61, 0x74,
|
||||
0x69, 0x63, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x2a, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x6c, 0x65, 0x72, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x74, 0x69, 0x6d, 0x65,
|
||||
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
|
||||
0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe5, 0x02, 0x0a, 0x0f, 0x43, 0x72, 0x65,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x1b, 0x0a, 0x09,
|
||||
0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65,
|
||||
0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72,
|
||||
0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
|
||||
0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54,
|
||||
0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x09, 0x42, 0x10, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x64, 0x65, 0x73,
|
||||
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1e,
|
||||
0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b,
|
||||
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x73,
|
||||
0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73,
|
||||
0x63, 0x6f, 0x70, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x22, 0xfd, 0x04, 0x0a, 0x1a, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12,
|
||||
0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b,
|
||||
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63,
|
||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72,
|
||||
0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x12, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b,
|
||||
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||
0x09, 0x42, 0x1e, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19,
|
||||
0x0a, 0x08, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18,
|
||||
0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, 0xc2, 0xdd, 0x29, 0x1f, 0x0a, 0x08, 0x55, 0x73, 0x65,
|
||||
0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x13, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
|
||||
0x73, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
||||
0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x23, 0xc2, 0xdd, 0x29, 0x1f, 0x0a, 0x08, 0x50, 0x61,
|
||||
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x13, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
|
||||
0x65, 0x73, 0x2e, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x08, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x74, 0x5f, 0x70, 0x61, 0x73, 0x73,
|
||||
0x77, 0x6f, 0x72, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x74, 0x50, 0x61,
|
||||
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x51, 0x0a, 0x0d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x2c, 0xc2,
|
||||
0xdd, 0x29, 0x28, 0x0a, 0x0c, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x48, 0x6d, 0x61,
|
||||
0x63, 0x12, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x61,
|
||||
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x52, 0x0c, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x48, 0x6d, 0x61, 0x63, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64,
|
||||
0x42, 0x46, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68,
|
||||
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72,
|
||||
0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x2f, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_controller_storage_credential_static_store_v1_static_proto_rawDescOnce sync.Once
|
||||
file_controller_storage_credential_static_store_v1_static_proto_rawDescData = file_controller_storage_credential_static_store_v1_static_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_controller_storage_credential_static_store_v1_static_proto_rawDescGZIP() []byte {
|
||||
file_controller_storage_credential_static_store_v1_static_proto_rawDescOnce.Do(func() {
|
||||
file_controller_storage_credential_static_store_v1_static_proto_rawDescData = protoimpl.X.CompressGZIP(file_controller_storage_credential_static_store_v1_static_proto_rawDescData)
|
||||
})
|
||||
return file_controller_storage_credential_static_store_v1_static_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_controller_storage_credential_static_store_v1_static_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_controller_storage_credential_static_store_v1_static_proto_goTypes = []interface{}{
|
||||
(*CredentialStore)(nil), // 0: controller.storage.credential.static.store.v1.CredentialStore
|
||||
(*UsernamePasswordCredential)(nil), // 1: controller.storage.credential.static.store.v1.UsernamePasswordCredential
|
||||
(*timestamp.Timestamp)(nil), // 2: controller.storage.timestamp.v1.Timestamp
|
||||
}
|
||||
var file_controller_storage_credential_static_store_v1_static_proto_depIdxs = []int32{
|
||||
2, // 0: controller.storage.credential.static.store.v1.CredentialStore.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
2, // 1: controller.storage.credential.static.store.v1.CredentialStore.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
2, // 2: controller.storage.credential.static.store.v1.UsernamePasswordCredential.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
2, // 3: controller.storage.credential.static.store.v1.UsernamePasswordCredential.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
4, // [4:4] is the sub-list for method output_type
|
||||
4, // [4:4] is the sub-list for method input_type
|
||||
4, // [4:4] is the sub-list for extension type_name
|
||||
4, // [4:4] is the sub-list for extension extendee
|
||||
0, // [0:4] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_controller_storage_credential_static_store_v1_static_proto_init() }
|
||||
func file_controller_storage_credential_static_store_v1_static_proto_init() {
|
||||
if File_controller_storage_credential_static_store_v1_static_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_controller_storage_credential_static_store_v1_static_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*CredentialStore); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_storage_credential_static_store_v1_static_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UsernamePasswordCredential); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_controller_storage_credential_static_store_v1_static_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_controller_storage_credential_static_store_v1_static_proto_goTypes,
|
||||
DependencyIndexes: file_controller_storage_credential_static_store_v1_static_proto_depIdxs,
|
||||
MessageInfos: file_controller_storage_credential_static_store_v1_static_proto_msgTypes,
|
||||
}.Build()
|
||||
File_controller_storage_credential_static_store_v1_static_proto = out.File
|
||||
file_controller_storage_credential_static_store_v1_static_proto_rawDesc = nil
|
||||
file_controller_storage_credential_static_store_v1_static_proto_goTypes = nil
|
||||
file_controller_storage_credential_static_store_v1_static_proto_depIdxs = nil
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestCredentialStore creates a static credential store in the provided DB with
|
||||
// the provided scope and any values passed in through the Options vars.
|
||||
// If any errors are encountered during the creation of the store, the test will fail.
|
||||
func TestCredentialStore(t testing.TB, conn *db.DB, wrapper wrapping.Wrapper, scopeId string, opts ...Option) *CredentialStore {
|
||||
t.Helper()
|
||||
ctx := context.Background()
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
w := db.New(conn)
|
||||
|
||||
databaseWrapper, err := kmsCache.GetWrapper(ctx, scopeId, kms.KeyPurposeDatabase)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, databaseWrapper)
|
||||
|
||||
cs, err := NewCredentialStore(scopeId, opts...)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, cs)
|
||||
id, err := newCredentialStoreId(ctx)
|
||||
assert.NoError(t, err)
|
||||
require.NotEmpty(t, id)
|
||||
cs.PublicId = id
|
||||
|
||||
_, err2 := w.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
|
||||
func(_ db.Reader, iw db.Writer) error {
|
||||
require.NoError(t, iw.Create(ctx, cs))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
require.NoError(t, err2)
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// TestCredentialStores creates count number of static credential stores in
|
||||
// the provided DB with the provided scope id. If any errors are
|
||||
// encountered during the creation of the credential stores, the test will
|
||||
// fail.
|
||||
func TestCredentialStores(t testing.TB, conn *db.DB, wrapper wrapping.Wrapper, scopeId string, count int) []*CredentialStore {
|
||||
t.Helper()
|
||||
ctx := context.Background()
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
|
||||
databaseWrapper, err := kmsCache.GetWrapper(ctx, scopeId, kms.KeyPurposeDatabase)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, databaseWrapper)
|
||||
|
||||
css := make([]*CredentialStore, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
css = append(css, TestCredentialStore(t, conn, wrapper, scopeId))
|
||||
}
|
||||
return css
|
||||
}
|
||||
|
||||
// TestUsernamePasswordCredential creates a user password credential in the provided DB with
|
||||
// the provided scope and any values passed in through.
|
||||
// If any errors are encountered during the creation of the store, the test will fail.
|
||||
func TestUsernamePasswordCredential(
|
||||
t testing.TB,
|
||||
conn *db.DB,
|
||||
wrapper wrapping.Wrapper,
|
||||
username, password, storeId, scopeId string,
|
||||
opts ...Option,
|
||||
) *UsernamePasswordCredential {
|
||||
t.Helper()
|
||||
ctx := context.Background()
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
w := db.New(conn)
|
||||
|
||||
databaseWrapper, err := kmsCache.GetWrapper(ctx, scopeId, kms.KeyPurposeDatabase)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, databaseWrapper)
|
||||
|
||||
cred, err := NewUsernamePasswordCredential(storeId, username, credential.Password(password), opts...)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, cred)
|
||||
|
||||
id, err := newCredentialId(ctx)
|
||||
require.NoError(t, err)
|
||||
cred.PublicId = id
|
||||
|
||||
err = cred.encrypt(ctx, databaseWrapper)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err2 := w.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
|
||||
func(_ db.Reader, iw db.Writer) error {
|
||||
require.NoError(t, iw.Create(ctx, cred))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
require.NoError(t, err2)
|
||||
|
||||
return cred
|
||||
}
|
||||
|
||||
// TestUsernamePasswordCredentials creates count number of user password credentials in
|
||||
// the provided DB with the provided scope id. If any errors are
|
||||
// encountered during the creation of the credentials, the test will fail.
|
||||
func TestUsernamePasswordCredentials(
|
||||
t testing.TB,
|
||||
conn *db.DB,
|
||||
wrapper wrapping.Wrapper,
|
||||
username, password, storeId, scopeId string,
|
||||
count int,
|
||||
) []*UsernamePasswordCredential {
|
||||
t.Helper()
|
||||
ctx := context.Background()
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
|
||||
databaseWrapper, err := kmsCache.GetWrapper(ctx, scopeId, kms.KeyPurposeDatabase)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, databaseWrapper)
|
||||
|
||||
creds := make([]*UsernamePasswordCredential, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
creds = append(creds, TestUsernamePasswordCredential(t, conn, wrapper, username, password, storeId, scopeId))
|
||||
}
|
||||
return creds
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/libs/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_TestCredentialStore(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
require.NotNil(prj)
|
||||
assert.NotEmpty(prj.GetPublicId())
|
||||
|
||||
cs := TestCredentialStore(t, conn, wrapper, prj.GetPublicId(), WithName("my-name"), WithDescription("my-description"))
|
||||
require.NotNil(cs)
|
||||
assert.NotEmpty(cs.GetPublicId())
|
||||
assert.Equal(cs.Name, "my-name")
|
||||
assert.Equal(cs.Description, "my-description")
|
||||
}
|
||||
|
||||
func Test_TestCredentialStores(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
require.NotNil(prj)
|
||||
assert.NotEmpty(prj.GetPublicId())
|
||||
|
||||
count := 4
|
||||
css := TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), count)
|
||||
assert.Len(css, count)
|
||||
}
|
||||
|
||||
func Test_TestUsernamePasswordCredential(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kkms := kms.TestKms(t, conn, wrapper)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
require.NotNil(prj)
|
||||
assert.NotEmpty(prj.GetPublicId())
|
||||
|
||||
store := TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
|
||||
cred := TestUsernamePasswordCredential(t, conn, wrapper, "user", "pass", store.GetPublicId(), prj.GetPublicId(), WithName("my-name"), WithDescription("my-description"))
|
||||
require.NotNil(cred)
|
||||
assert.NotEmpty(cred.GetPublicId())
|
||||
assert.Equal(cred.Name, "my-name")
|
||||
assert.Equal(cred.Description, "my-description")
|
||||
assert.Equal(cred.Username, "user")
|
||||
assert.Equal(cred.Password, []byte("pass"))
|
||||
|
||||
// Validate hmac
|
||||
databaseWrapper, err := kkms.GetWrapper(context.Background(), prj.PublicId, kms.KeyPurposeDatabase)
|
||||
hm, err := crypto.HmacSha256(context.Background(), cred.Password, databaseWrapper, []byte(cred.StoreId), nil, crypto.WithEd25519())
|
||||
require.NoError(err)
|
||||
assert.Equal([]byte(hm), cred.PasswordHmac)
|
||||
}
|
||||
|
||||
func Test_TestUsernamePasswordCredentials(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
require.NotNil(prj)
|
||||
assert.NotEmpty(prj.GetPublicId())
|
||||
|
||||
store := TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
|
||||
count := 4
|
||||
creds := TestUsernamePasswordCredentials(t, conn, wrapper, "user", "pass", store.GetPublicId(), prj.GetPublicId(), count)
|
||||
assert.Len(creds, count)
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/static/store"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/libs/crypto"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
|
||||
"github.com/hashicorp/go-kms-wrapping/v2/extras/structwrapping"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var _ credential.Static = (*UsernamePasswordCredential)(nil)
|
||||
|
||||
// A UsernamePasswordCredential contains the credential with a username and password.
|
||||
// It is owned by a credential store.
|
||||
type UsernamePasswordCredential struct {
|
||||
*store.UsernamePasswordCredential
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewUsernamePasswordCredential creates a new in memory static Credential containing a
|
||||
// username and password that is assigned to storeId. Name and description are the only
|
||||
// valid options. All other options are ignored.
|
||||
func NewUsernamePasswordCredential(
|
||||
storeId string,
|
||||
username string,
|
||||
password credential.Password,
|
||||
opt ...Option,
|
||||
) (*UsernamePasswordCredential, error) {
|
||||
opts := getOpts(opt...)
|
||||
l := &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
StoreId: storeId,
|
||||
Name: opts.withName,
|
||||
Description: opts.withDescription,
|
||||
Username: username,
|
||||
Password: []byte(password),
|
||||
},
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func allocUsernamePasswordCredential() *UsernamePasswordCredential {
|
||||
return &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCredential) clone() *UsernamePasswordCredential {
|
||||
cp := proto.Clone(c.UsernamePasswordCredential)
|
||||
return &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: cp.(*store.UsernamePasswordCredential),
|
||||
}
|
||||
}
|
||||
|
||||
// TableName returns the table name.
|
||||
func (c *UsernamePasswordCredential) TableName() string {
|
||||
if c.tableName != "" {
|
||||
return c.tableName
|
||||
}
|
||||
return "credential_static_username_password_credential"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name.
|
||||
func (c *UsernamePasswordCredential) SetTableName(n string) {
|
||||
c.tableName = n
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCredential) oplog(op oplog.OpType) oplog.Metadata {
|
||||
metadata := oplog.Metadata{
|
||||
"resource-public-id": []string{c.PublicId},
|
||||
"resource-type": []string{"credential-static-username-password"},
|
||||
"op-type": []string{op.String()},
|
||||
}
|
||||
if c.StoreId != "" {
|
||||
metadata["store-id"] = []string{c.StoreId}
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCredential) encrypt(ctx context.Context, cipher wrapping.Wrapper) error {
|
||||
const op = "static.(UsernamePasswordCredential).encrypt"
|
||||
if len(c.Password) == 0 {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "no password defined")
|
||||
}
|
||||
if err := structwrapping.WrapStruct(ctx, cipher, c.UsernamePasswordCredential, nil); err != nil {
|
||||
return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt))
|
||||
}
|
||||
keyId, err := cipher.KeyId(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt), errors.WithMsg("error reading cipher key id"))
|
||||
}
|
||||
c.KeyId = keyId
|
||||
if err := c.hmacPassword(ctx, cipher); err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCredential) decrypt(ctx context.Context, cipher wrapping.Wrapper) error {
|
||||
const op = "static.(UsernamePasswordCredential).decrypt"
|
||||
if err := structwrapping.UnwrapStruct(ctx, cipher, c.UsernamePasswordCredential, nil); err != nil {
|
||||
return errors.Wrap(ctx, err, op, errors.WithCode(errors.Decrypt))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCredential) hmacPassword(ctx context.Context, cipher wrapping.Wrapper) error {
|
||||
const op = "static.(UsernamePasswordCredential).hmacPassword"
|
||||
if cipher == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing cipher")
|
||||
}
|
||||
hm, err := crypto.HmacSha256(ctx, c.Password, cipher, []byte(c.StoreId), nil, crypto.WithEd25519())
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
c.PasswordHmac = []byte(hm)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/static/store"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/libs/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
)
|
||||
|
||||
func TestCredential_New(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kkms := kms.TestKms(t, conn, wrapper)
|
||||
rw := db.New(conn)
|
||||
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
cs := TestCredentialStore(t, conn, wrapper, prj.PublicId)
|
||||
|
||||
type args struct {
|
||||
username string
|
||||
password credential.Password
|
||||
storeId string
|
||||
options []Option
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *UsernamePasswordCredential
|
||||
wantCreateErr bool
|
||||
wantEncryptErr bool
|
||||
}{
|
||||
{
|
||||
name: "missing-password",
|
||||
args: args{
|
||||
username: "test-user",
|
||||
storeId: cs.PublicId,
|
||||
},
|
||||
want: allocUsernamePasswordCredential(),
|
||||
wantEncryptErr: true,
|
||||
},
|
||||
{
|
||||
name: "missing-username",
|
||||
args: args{
|
||||
password: "test-pass",
|
||||
storeId: cs.PublicId,
|
||||
},
|
||||
want: allocUsernamePasswordCredential(),
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "missing-store-id",
|
||||
args: args{
|
||||
username: "test-user",
|
||||
password: "test-pass",
|
||||
},
|
||||
want: allocUsernamePasswordCredential(),
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-no-options",
|
||||
args: args{
|
||||
username: "test-user",
|
||||
password: "test-pass",
|
||||
storeId: cs.PublicId,
|
||||
},
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "test-user",
|
||||
Password: []byte("test-pass"),
|
||||
StoreId: cs.PublicId,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
args: args{
|
||||
username: "test-user",
|
||||
password: "test-pass",
|
||||
storeId: cs.PublicId,
|
||||
options: []Option{WithName("my-credential")},
|
||||
},
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "test-user",
|
||||
Password: []byte("test-pass"),
|
||||
StoreId: cs.PublicId,
|
||||
Name: "my-credential",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
args: args{
|
||||
username: "test-user",
|
||||
password: "test-pass",
|
||||
storeId: cs.PublicId,
|
||||
options: []Option{WithDescription("my-credential-description")},
|
||||
},
|
||||
want: &UsernamePasswordCredential{
|
||||
UsernamePasswordCredential: &store.UsernamePasswordCredential{
|
||||
Username: "test-user",
|
||||
Password: []byte("test-pass"),
|
||||
StoreId: cs.PublicId,
|
||||
Description: "my-credential-description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
got, err := NewUsernamePasswordCredential(tt.args.storeId, tt.args.username, tt.args.password, tt.args.options...)
|
||||
require.NoError(err)
|
||||
require.NotNil(got)
|
||||
assert.Emptyf(got.PublicId, "PublicId set")
|
||||
|
||||
id, err := newCredentialId(ctx)
|
||||
require.NoError(err)
|
||||
|
||||
tt.want.PublicId = id
|
||||
got.PublicId = id
|
||||
|
||||
databaseWrapper, err := kkms.GetWrapper(context.Background(), prj.PublicId, kms.KeyPurposeDatabase)
|
||||
|
||||
err = got.encrypt(ctx, databaseWrapper)
|
||||
if tt.wantEncryptErr {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
|
||||
err = rw.Create(context.Background(), got)
|
||||
if tt.wantCreateErr {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
|
||||
got2 := allocUsernamePasswordCredential()
|
||||
got2.PublicId = id
|
||||
assert.Equal(id, got2.GetPublicId())
|
||||
require.NoError(rw.LookupById(ctx, got2))
|
||||
|
||||
err = got2.decrypt(ctx, databaseWrapper)
|
||||
require.NoError(err)
|
||||
|
||||
// Timestamps and version are automatically set
|
||||
tt.want.CreateTime = got2.CreateTime
|
||||
tt.want.UpdateTime = got2.UpdateTime
|
||||
tt.want.Version = got2.Version
|
||||
|
||||
// KeyId is allocated via kms no need to validate in this test
|
||||
tt.want.KeyId = got2.KeyId
|
||||
got2.CtPassword = nil
|
||||
|
||||
// encrypt also calculates the hmac, validate it is correct
|
||||
hm, err := crypto.HmacSha256(ctx, got.Password, databaseWrapper, []byte(got.StoreId), nil, crypto.WithEd25519())
|
||||
require.NoError(err)
|
||||
tt.want.PasswordHmac = []byte(hm)
|
||||
|
||||
assert.Empty(cmp.Diff(tt.want, got2.clone(), protocmp.Transform()))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -214,7 +214,7 @@ func TestCredentialLibrary_New(t *testing.T) {
|
||||
vaultPath: "vault/path",
|
||||
opts: []Option{
|
||||
WithMethod(MethodGet),
|
||||
WithCredentialType(credential.UserPasswordType),
|
||||
WithCredentialType(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
@@ -222,7 +222,7 @@ func TestCredentialLibrary_New(t *testing.T) {
|
||||
StoreId: cs.PublicId,
|
||||
VaultPath: "vault/path",
|
||||
HttpMethod: string(MethodGet),
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -233,7 +233,7 @@ func TestCredentialLibrary_New(t *testing.T) {
|
||||
vaultPath: "vault/path",
|
||||
opts: []Option{
|
||||
WithMethod(MethodGet),
|
||||
WithCredentialType(credential.UserPasswordType),
|
||||
WithCredentialType(credential.UsernamePasswordType),
|
||||
WithMappingOverride(NewUserPasswordOverride(WithOverrideUsernameAttribute("test"))),
|
||||
},
|
||||
},
|
||||
@@ -243,7 +243,7 @@ func TestCredentialLibrary_New(t *testing.T) {
|
||||
StoreId: cs.PublicId,
|
||||
VaultPath: "vault/path",
|
||||
HttpMethod: string(MethodGet),
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -262,8 +262,8 @@ func TestCredentialLibrary_New(t *testing.T) {
|
||||
assert.Equal(tt.want, got)
|
||||
|
||||
switch ct := tt.want.GetCredentialType(); ct {
|
||||
case string(credential.UserPasswordType):
|
||||
assert.Equal(credential.UserPasswordType, got.CredentialType())
|
||||
case string(credential.UsernamePasswordType):
|
||||
assert.Equal(credential.UsernamePasswordType, got.CredentialType())
|
||||
case string(credential.UnspecifiedType), "":
|
||||
assert.Equal(credential.UnspecifiedType, got.CredentialType())
|
||||
default:
|
||||
|
||||
@@ -15,7 +15,7 @@ func validMappingOverride(m MappingOverride, ct credential.Type) bool {
|
||||
case nil:
|
||||
return true // it is always valid to not specify a mapping override
|
||||
case *UserPasswordOverride:
|
||||
return ct == credential.UserPasswordType
|
||||
return ct == credential.UsernamePasswordType
|
||||
default:
|
||||
return false // an unknown mapping override type is never valid
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestValidMappingOverrides(t *testing.T) {
|
||||
},
|
||||
{
|
||||
m: nil,
|
||||
ct: credential.UserPasswordType,
|
||||
ct: credential.UsernamePasswordType,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
@@ -44,7 +44,7 @@ func TestValidMappingOverrides(t *testing.T) {
|
||||
},
|
||||
{
|
||||
m: unknownMapper(1),
|
||||
ct: credential.UserPasswordType,
|
||||
ct: credential.UsernamePasswordType,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
@@ -54,7 +54,7 @@ func TestValidMappingOverrides(t *testing.T) {
|
||||
},
|
||||
{
|
||||
m: allocUserPasswordOverride(),
|
||||
ct: credential.UserPasswordType,
|
||||
ct: credential.UsernamePasswordType,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -85,9 +85,9 @@ func Test_GetOpts(t *testing.T) {
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithCredentialType", func(t *testing.T) {
|
||||
opts := getOpts(WithCredentialType(credential.UserPasswordType))
|
||||
opts := getOpts(WithCredentialType(credential.UsernamePasswordType))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withCredentialType = credential.UserPasswordType
|
||||
testOpts.withCredentialType = credential.UsernamePasswordType
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithOverrideUsernameAttribute", func(t *testing.T) {
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var _ credential.UserPassword = (*usrPassCred)(nil)
|
||||
var _ credential.UsernamePassword = (*usrPassCred)(nil)
|
||||
|
||||
type usrPassCred struct {
|
||||
*baseCred
|
||||
@@ -47,7 +47,7 @@ func (bc *baseCred) getExpiration() time.Duration { return bc.expiration }
|
||||
// UnspecifiedType.
|
||||
func convert(ctx context.Context, bc *baseCred) (dynamicCred, error) {
|
||||
switch bc.Library().CredentialType() {
|
||||
case credential.UserPasswordType:
|
||||
case credential.UsernamePasswordType:
|
||||
return baseToUsrPass(ctx, bc)
|
||||
}
|
||||
return bc, nil
|
||||
@@ -59,7 +59,7 @@ func baseToUsrPass(ctx context.Context, bc *baseCred) (*usrPassCred, error) {
|
||||
return nil, errors.E(ctx, errors.WithCode(errors.InvalidParameter), errors.WithMsg("nil baseCred"))
|
||||
case bc.lib == nil:
|
||||
return nil, errors.E(ctx, errors.WithCode(errors.InvalidParameter), errors.WithMsg("nil baseCred.lib"))
|
||||
case bc.Library().CredentialType() != credential.UserPasswordType:
|
||||
case bc.Library().CredentialType() != credential.UsernamePasswordType:
|
||||
return nil, errors.E(ctx, errors.WithCode(errors.InvalidParameter), errors.WithMsg("invalid credential type"))
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ func TestRepository_getPrivateLibraries(t *testing.T) {
|
||||
}
|
||||
{
|
||||
opts := []Option{
|
||||
WithCredentialType(credential.UserPasswordType),
|
||||
WithCredentialType(credential.UsernamePasswordType),
|
||||
}
|
||||
libIn, err := NewCredentialLibrary(origStore.GetPublicId(), "/vault/path", opts...)
|
||||
assert.NoError(err)
|
||||
@@ -129,7 +129,7 @@ func TestRepository_getPrivateLibraries(t *testing.T) {
|
||||
}
|
||||
{
|
||||
opts := []Option{
|
||||
WithCredentialType(credential.UserPasswordType),
|
||||
WithCredentialType(credential.UsernamePasswordType),
|
||||
WithMappingOverride(NewUserPasswordOverride(
|
||||
WithOverrideUsernameAttribute("test-username"),
|
||||
)),
|
||||
@@ -146,7 +146,7 @@ func TestRepository_getPrivateLibraries(t *testing.T) {
|
||||
}
|
||||
{
|
||||
opts := []Option{
|
||||
WithCredentialType(credential.UserPasswordType),
|
||||
WithCredentialType(credential.UsernamePasswordType),
|
||||
WithMappingOverride(NewUserPasswordOverride(
|
||||
WithOverridePasswordAttribute("test-password"),
|
||||
)),
|
||||
@@ -163,7 +163,7 @@ func TestRepository_getPrivateLibraries(t *testing.T) {
|
||||
}
|
||||
{
|
||||
opts := []Option{
|
||||
WithCredentialType(credential.UserPasswordType),
|
||||
WithCredentialType(credential.UsernamePasswordType),
|
||||
WithMappingOverride(NewUserPasswordOverride(
|
||||
WithOverrideUsernameAttribute("test-username"),
|
||||
WithOverridePasswordAttribute("test-password"),
|
||||
@@ -336,7 +336,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-no-username-default-password-attribute",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"password": "my-password",
|
||||
@@ -348,7 +348,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-no-password-default-username-attribute",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"username": "my-username",
|
||||
@@ -360,7 +360,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "valid-default-attributes",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"username": "my-username",
|
||||
@@ -376,7 +376,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "valid-override-attributes",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
UsernameAttribute: "test-username",
|
||||
PasswordAttribute: "test-password",
|
||||
},
|
||||
@@ -396,7 +396,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "valid-default-username-override-password",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
PasswordAttribute: "test-password",
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
@@ -415,7 +415,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "valid-override-username-default-password",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
UsernameAttribute: "test-username",
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
@@ -434,7 +434,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-username-override",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
UsernameAttribute: "missing-username",
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
@@ -450,7 +450,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-password-override",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
UsernameAttribute: "missing-password",
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
@@ -466,7 +466,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-kv2-no-metadata-field",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
@@ -481,7 +481,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-kv2-no-data-field",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{},
|
||||
@@ -493,7 +493,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-kv2-no-username-default-password-attribute",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{},
|
||||
@@ -508,7 +508,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-kv2-no-passsword-default-username-attribute",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{},
|
||||
@@ -523,7 +523,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-kv2-invalid-metadata-type",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"metadata": "hello",
|
||||
@@ -539,7 +539,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-kv2-invalid-metadata-type",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{},
|
||||
@@ -552,7 +552,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "invalid-kv2-additional-field",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"bad-field": "hello",
|
||||
@@ -569,7 +569,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "valid-kv2-default-attributes",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{},
|
||||
@@ -588,7 +588,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "valid-kv2-override-attributes",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
UsernameAttribute: "test-username",
|
||||
PasswordAttribute: "test-password",
|
||||
},
|
||||
@@ -611,7 +611,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "valid-kv2-default-username-override-password",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
PasswordAttribute: "test-password",
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
@@ -633,7 +633,7 @@ func TestBaseToUsrPass(t *testing.T) {
|
||||
name: "valid-kv2-override-username-default-password",
|
||||
given: &baseCred{
|
||||
lib: &privateLibrary{
|
||||
CredType: string(credential.UserPasswordType),
|
||||
CredType: string(credential.UsernamePasswordType),
|
||||
UsernameAttribute: "test-username",
|
||||
},
|
||||
secretData: map[string]interface{}{
|
||||
|
||||
@@ -171,7 +171,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
@@ -179,7 +179,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -191,7 +191,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidMappingOverride,
|
||||
@@ -218,7 +218,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
@@ -229,7 +229,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -243,7 +243,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
@@ -254,7 +254,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -269,7 +269,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
@@ -281,7 +281,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -761,7 +761,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/old/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
chgFn: changeVaultPath("/new/path"),
|
||||
@@ -771,7 +771,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/new/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
@@ -921,7 +921,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
chgFn: changeCredentialType(credential.UnspecifiedType),
|
||||
@@ -939,7 +939,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
chgFn: changeMappingOverride(
|
||||
@@ -956,7 +956,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
@@ -972,7 +972,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
chgFn: changeMappingOverride(
|
||||
@@ -989,7 +989,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
@@ -1005,7 +1005,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
chgFn: changeMappingOverride(
|
||||
@@ -1024,7 +1024,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
@@ -1036,7 +1036,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
chgFn: changeMappingOverride(
|
||||
@@ -1055,7 +1055,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
@@ -1071,7 +1071,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
chgFn: changeMappingOverride(nil),
|
||||
@@ -1081,7 +1081,7 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
@@ -1324,7 +1324,7 @@ func TestRepository_LookupCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1338,7 +1338,7 @@ func TestRepository_LookupCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1352,7 +1352,7 @@ func TestRepository_LookupCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1367,7 +1367,7 @@ func TestRepository_LookupCredentialLibrary(t *testing.T) {
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1528,7 +1528,7 @@ func TestRepository_DeleteCredentialLibrary(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1572,7 +1572,7 @@ func TestRepository_ListCredentialLibraries(t *testing.T) {
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-name-repo",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ func TestRepository_IssueCredentials(t *testing.T) {
|
||||
{
|
||||
libPath := path.Join("database", "creds", "opened")
|
||||
opts := []vault.Option{
|
||||
vault.WithCredentialType(credential.UserPasswordType),
|
||||
vault.WithCredentialType(credential.UsernamePasswordType),
|
||||
}
|
||||
libIn, err := vault.NewCredentialLibrary(origStore.GetPublicId(), libPath, opts...)
|
||||
assert.NoError(t, err)
|
||||
@@ -141,7 +141,7 @@ func TestRepository_IssueCredentials(t *testing.T) {
|
||||
{
|
||||
libPath := path.Join("database", "creds", "opened")
|
||||
opts := []vault.Option{
|
||||
vault.WithCredentialType(credential.UserPasswordType),
|
||||
vault.WithCredentialType(credential.UsernamePasswordType),
|
||||
vault.WithMappingOverride(vault.NewUserPasswordOverride(
|
||||
vault.WithOverrideUsernameAttribute("test-username"),
|
||||
vault.WithOverridePasswordAttribute("test-password"),
|
||||
@@ -158,7 +158,7 @@ func TestRepository_IssueCredentials(t *testing.T) {
|
||||
{
|
||||
libPath := path.Join("secret", "data", "my-secret")
|
||||
opts := []vault.Option{
|
||||
vault.WithCredentialType(credential.UserPasswordType),
|
||||
vault.WithCredentialType(credential.UsernamePasswordType),
|
||||
}
|
||||
libIn, err := vault.NewCredentialLibrary(origStore.GetPublicId(), libPath, opts...)
|
||||
assert.NoError(t, err)
|
||||
@@ -326,15 +326,15 @@ func TestRepository_IssueCredentials(t *testing.T) {
|
||||
assert.NotZero(len(got))
|
||||
for _, dc := range got {
|
||||
switch dc.Library().CredentialType() {
|
||||
case credential.UserPasswordType:
|
||||
if upc, ok := dc.(credential.UserPassword); ok {
|
||||
case credential.UsernamePasswordType:
|
||||
if upc, ok := dc.(credential.UsernamePassword); ok {
|
||||
assert.NotEmpty(upc.Username())
|
||||
assert.NotEmpty(upc.Password())
|
||||
break
|
||||
}
|
||||
assert.Fail("want UserPassword credential from library with credential type UserPassword")
|
||||
assert.Fail("want UserPassword credential from library with credential type UsernamePassword")
|
||||
case credential.UnspecifiedType:
|
||||
if _, ok := dc.(credential.UserPassword); ok {
|
||||
if _, ok := dc.(credential.UsernamePassword); ok {
|
||||
assert.Fail("do not want UserPassword credential from library with credential type Unspecified")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ func TestSetupSleepyDevEnvironment(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, lib)
|
||||
tgt, err = tcl.AddCredentialLibraries(ctx, tgt.Item.Id, 0, targets.WithAutomaticVersioning(true), targets.WithApplicationCredentialLibraryIds([]string{lib.Item.Id}))
|
||||
tgt, err = tcl.AddCredentialSources(ctx, tgt.Item.Id, 0, targets.WithAutomaticVersioning(true), targets.WithApplicationCredentialSourceIds([]string{lib.Item.Id}))
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, tgt)
|
||||
// Worker 1
|
||||
|
||||
@@ -3,6 +3,7 @@ package common
|
||||
import (
|
||||
"github.com/hashicorp/boundary/internal/auth/oidc"
|
||||
"github.com/hashicorp/boundary/internal/auth/password"
|
||||
credstatic "github.com/hashicorp/boundary/internal/credential/static"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault"
|
||||
pluginhost "github.com/hashicorp/boundary/internal/host/plugin"
|
||||
"github.com/hashicorp/boundary/internal/host/static"
|
||||
@@ -16,6 +17,7 @@ import (
|
||||
type (
|
||||
AuthTokenRepoFactory = oidc.AuthTokenRepoFactory
|
||||
VaultCredentialRepoFactory = func() (*vault.Repository, error)
|
||||
StaticCredentialRepoFactory = func() (*credstatic.Repository, error)
|
||||
IamRepoFactory func() (*iam.Repository, error)
|
||||
OidcAuthRepoFactory = oidc.OidcRepoFactory
|
||||
PasswordAuthRepoFactory func() (*password.Repository, error)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/authtoken"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/config"
|
||||
credstatic "github.com/hashicorp/boundary/internal/credential/static"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/common"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/health"
|
||||
@@ -67,6 +68,7 @@ type Controller struct {
|
||||
// Repo factory methods
|
||||
AuthTokenRepoFn common.AuthTokenRepoFactory
|
||||
VaultCredentialRepoFn common.VaultCredentialRepoFactory
|
||||
StaticCredentialRepoFn common.StaticCredentialRepoFactory
|
||||
IamRepoFn common.IamRepoFactory
|
||||
OidcRepoFn common.OidcAuthRepoFactory
|
||||
PasswordAuthRepoFn common.PasswordAuthRepoFactory
|
||||
@@ -249,9 +251,8 @@ func New(ctx context.Context, conf *Config) (*Controller, error) {
|
||||
jobRepoFn := func() (*job.Repository, error) {
|
||||
return job.NewRepository(dbase, dbase, c.kms)
|
||||
}
|
||||
// TODO: the RunJobsLimit is temporary until a better fix gets in. This
|
||||
// currently caps the scheduler at running 10 jobs per interval.
|
||||
schedulerOpts := []scheduler.Option{scheduler.WithRunJobsLimit(20)}
|
||||
// TODO: Allow setting run jobs limit from config
|
||||
schedulerOpts := []scheduler.Option{scheduler.WithRunJobsLimit(-1)}
|
||||
if c.conf.RawConfig.Controller.SchedulerRunJobInterval > 0 {
|
||||
schedulerOpts = append(schedulerOpts, scheduler.WithRunJobsInterval(c.conf.RawConfig.Controller.SchedulerRunJobInterval))
|
||||
}
|
||||
@@ -279,6 +280,9 @@ func New(ctx context.Context, conf *Config) (*Controller, error) {
|
||||
c.VaultCredentialRepoFn = func() (*vault.Repository, error) {
|
||||
return vault.NewRepository(dbase, dbase, c.kms, c.scheduler)
|
||||
}
|
||||
c.StaticCredentialRepoFn = func() (*credstatic.Repository, error) {
|
||||
return credstatic.NewRepository(ctx, dbase, dbase, c.kms)
|
||||
}
|
||||
c.ServersRepoFn = func() (*servers.Repository, error) {
|
||||
return servers.NewRepository(dbase, dbase, c.kms)
|
||||
}
|
||||
|
||||
@@ -2,12 +2,17 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/config"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
host_plugin_assets "github.com/hashicorp/boundary/plugins/host"
|
||||
"github.com/hashicorp/go-secure-stdlib/listenerutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -223,3 +228,39 @@ func TestControllerNewListenerConfig(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestController_NewPluginsConfig(t *testing.T) {
|
||||
require := require.New(t)
|
||||
testCtx := context.Background()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
tc := &TestController{
|
||||
t: t,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
opts: nil,
|
||||
}
|
||||
|
||||
initialConfig, err := config.DevController()
|
||||
require.NoError(err)
|
||||
tmpDir := t.TempDir()
|
||||
initialConfig.Plugins.ExecutionDir = tmpDir
|
||||
conf := TestControllerConfig(t, ctx, tc, &TestControllerOpts{Config: initialConfig})
|
||||
conf.EnabledPlugins = []base.EnabledPlugin{
|
||||
base.EnabledPluginHostAws,
|
||||
base.EnabledPluginHostAzure,
|
||||
}
|
||||
|
||||
_, err = New(testCtx, conf)
|
||||
require.NoError(err)
|
||||
|
||||
// Check that both plugins were written to the temp dir
|
||||
files, err := os.ReadDir(tmpDir)
|
||||
require.NoError(err)
|
||||
require.Len(files, 2)
|
||||
var pluginNames []string
|
||||
for _, file := range files {
|
||||
pluginNames = append(pluginNames, filepath.Base(file.Name()))
|
||||
}
|
||||
expectedPluginNames := []string{host_plugin_assets.HostPluginPrefix + "aws.gz", host_plugin_assets.HostPluginPrefix + "azure.gz"}
|
||||
require.Empty(cmp.Diff(expectedPluginNames, pluginNames))
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/authmethods"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/authtokens"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/credentiallibraries"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/credentials"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/credentialstores"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/groups"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/health"
|
||||
@@ -175,7 +176,8 @@ func (c *Controller) registerGrpcServices(s *grpc.Server) error {
|
||||
c.SessionRepoFn,
|
||||
c.PluginHostRepoFn,
|
||||
c.StaticHostRepoFn,
|
||||
c.VaultCredentialRepoFn)
|
||||
c.VaultCredentialRepoFn,
|
||||
c.StaticCredentialRepoFn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create target handler service: %w", err)
|
||||
}
|
||||
@@ -210,7 +212,7 @@ func (c *Controller) registerGrpcServices(s *grpc.Server) error {
|
||||
services.RegisterManagedGroupServiceServer(s, mgs)
|
||||
}
|
||||
if _, ok := currentServices[services.CredentialStoreService_ServiceDesc.ServiceName]; !ok {
|
||||
cs, err := credentialstores.NewService(c.VaultCredentialRepoFn, c.IamRepoFn)
|
||||
cs, err := credentialstores.NewService(c.VaultCredentialRepoFn, c.StaticCredentialRepoFn, c.IamRepoFn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create credential store handler service: %w", err)
|
||||
}
|
||||
@@ -230,6 +232,13 @@ func (c *Controller) registerGrpcServices(s *grpc.Server) error {
|
||||
}
|
||||
services.RegisterWorkerServiceServer(s, ws)
|
||||
}
|
||||
if _, ok := currentServices[services.CredentialService_ServiceDesc.ServiceName]; !ok {
|
||||
c, err := credentials.NewService(c.StaticCredentialRepoFn, c.IamRepoFn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create credential handler service: %w", err)
|
||||
}
|
||||
services.RegisterCredentialServiceServer(s, c)
|
||||
}
|
||||
if _, ok := s.GetServiceInfo()[opsservices.HealthService_ServiceDesc.ServiceName]; !ok {
|
||||
hs := health.NewService()
|
||||
opsservices.RegisterHealthServiceServer(s, hs)
|
||||
@@ -290,6 +299,9 @@ func registerGrpcGatewayEndpoints(ctx context.Context, gwMux *runtime.ServeMux,
|
||||
if err := services.RegisterWorkerServiceHandlerFromEndpoint(ctx, gwMux, gatewayTarget, dialOptions); err != nil {
|
||||
return fmt.Errorf("failed to register worker service handler: %w", err)
|
||||
}
|
||||
if err := services.RegisterCredentialServiceHandlerFromEndpoint(ctx, gwMux, gatewayTarget, dialOptions); err != nil {
|
||||
return fmt.Errorf("failed to register credential service handler: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -163,6 +163,12 @@ func TestHandleImplementedPaths(t *testing.T) {
|
||||
"v1/targets/someid:add-host-sets",
|
||||
"v1/targets/someid:set-host-sets",
|
||||
"v1/targets/someid:remove-host-sets",
|
||||
"v1/targets/someid:add-host-sources",
|
||||
"v1/targets/someid:set-host-sources",
|
||||
"v1/targets/someid:remove-host-sources",
|
||||
"v1/targets/someid:add-credential-sources",
|
||||
"v1/targets/someid:set-credential-sources",
|
||||
"v1/targets/someid:remove-credential-sources",
|
||||
"v1/users/someid:add-accounts",
|
||||
"v1/users/someid:set-accounts",
|
||||
"v1/users/someid:remove-accounts",
|
||||
|
||||
@@ -1265,7 +1265,9 @@ func transformAuthenticateRequestAttributes(msg proto.Message) error {
|
||||
return fmt.Errorf("%s: unknown command %q", op, authRequest.GetCommand())
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("%s: unknown auth method subtype in ID %q", op, authRequest.GetAuthMethodId())
|
||||
return &subtypes.UnknownSubtypeIDError{
|
||||
ID: authRequest.GetAuthMethodId(),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+3
-3
@@ -579,7 +579,7 @@ func toStorageVaultLibrary(storeId string, in *pb.CredentialLibrary) (out *vault
|
||||
|
||||
credentialType := credential.Type(in.GetCredentialType())
|
||||
switch credentialType {
|
||||
case credential.UserPasswordType:
|
||||
case credential.UsernamePasswordType:
|
||||
opts = append(opts, vault.WithCredentialType(credentialType))
|
||||
overrides := in.CredentialMappingOverrides.AsMap()
|
||||
var mapOpts []vault.Option
|
||||
@@ -694,7 +694,7 @@ func validateMapping(badFields map[string]string, credentialType credential.Type
|
||||
badFields[globals.CredentialMappingOverridesField] = fmt.Sprintf("This field can only be set if %q is set", globals.CredentialTypeField)
|
||||
}
|
||||
return
|
||||
case credential.UserPasswordType:
|
||||
case credential.UsernamePasswordType:
|
||||
validFields[usernameAttribute] = true
|
||||
validFields[passwordAttribute] = true
|
||||
default:
|
||||
@@ -734,7 +734,7 @@ func getMappingUpdates(credentialType credential.Type, current vault.MappingOver
|
||||
}
|
||||
|
||||
switch credentialType {
|
||||
case credential.UserPasswordType:
|
||||
case credential.UsernamePasswordType:
|
||||
var currentUser, currentPass interface{}
|
||||
if overrides, ok := current.(*vault.UserPasswordOverride); ok {
|
||||
currentUser = overrides.UsernameAttribute
|
||||
|
||||
+22
-22
@@ -318,7 +318,7 @@ func TestCreate(t *testing.T) {
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Invalid user_password mapping",
|
||||
name: "Invalid username_password mapping",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Attrs: &pb.CredentialLibrary_VaultCredentialLibraryAttributes{
|
||||
@@ -326,7 +326,7 @@ func TestCreate(t *testing.T) {
|
||||
Path: wrapperspb.String("something"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]interface{}{
|
||||
usernameAttribute: "user-test",
|
||||
@@ -410,7 +410,7 @@ func TestCreate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Create a valid vault CredentialLibrary user_password type",
|
||||
name: "Create a valid vault CredentialLibrary username_password type",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Attrs: &pb.CredentialLibrary_VaultCredentialLibraryAttributes{
|
||||
@@ -418,7 +418,7 @@ func TestCreate(t *testing.T) {
|
||||
Path: wrapperspb.String("something"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
}},
|
||||
idPrefix: vault.CredentialLibraryPrefix + "_",
|
||||
res: &pbs.CreateCredentialLibraryResponse{
|
||||
@@ -437,13 +437,13 @@ func TestCreate(t *testing.T) {
|
||||
HttpMethod: wrapperspb.String("GET"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Create a valid vault CredentialLibrary user_password type with username mapping",
|
||||
name: "Create a valid vault CredentialLibrary username_password type with username mapping",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Attrs: &pb.CredentialLibrary_VaultCredentialLibraryAttributes{
|
||||
@@ -459,7 +459,7 @@ func TestCreate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
}},
|
||||
idPrefix: vault.CredentialLibraryPrefix + "_",
|
||||
res: &pbs.CreateCredentialLibraryResponse{
|
||||
@@ -478,7 +478,7 @@ func TestCreate(t *testing.T) {
|
||||
HttpMethod: wrapperspb.String("GET"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]interface{}{
|
||||
usernameAttribute: "user-test",
|
||||
@@ -492,7 +492,7 @@ func TestCreate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Create a valid vault CredentialLibrary user_password type with username/password mapping",
|
||||
name: "Create a valid vault CredentialLibrary username_password type with username/password mapping",
|
||||
req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Attrs: &pb.CredentialLibrary_VaultCredentialLibraryAttributes{
|
||||
@@ -509,7 +509,7 @@ func TestCreate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
return ret
|
||||
}(),
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
}},
|
||||
idPrefix: vault.CredentialLibraryPrefix + "_",
|
||||
res: &pbs.CreateCredentialLibraryResponse{
|
||||
@@ -528,7 +528,7 @@ func TestCreate(t *testing.T) {
|
||||
HttpMethod: wrapperspb.String("GET"),
|
||||
},
|
||||
},
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
CredentialType: string(credential.UsernamePasswordType),
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]interface{}{
|
||||
usernameAttribute: "user-test",
|
||||
@@ -607,7 +607,7 @@ func TestGet(t *testing.T) {
|
||||
repo, err := repoFn()
|
||||
require.NoError(t, err)
|
||||
lib, err := vault.NewCredentialLibrary(store.GetPublicId(), "vault/path",
|
||||
vault.WithCredentialType("user_password"),
|
||||
vault.WithCredentialType("username_password"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUserPasswordOverride(
|
||||
vault.WithOverrideUsernameAttribute("user"),
|
||||
@@ -664,7 +664,7 @@ func TestGet(t *testing.T) {
|
||||
HttpMethod: wrapperspb.String(userPassLib.GetHttpMethod()),
|
||||
},
|
||||
},
|
||||
CredentialType: "user_password",
|
||||
CredentialType: "username_password",
|
||||
CredentialMappingOverrides: func() *structpb.Struct {
|
||||
v := map[string]interface{}{
|
||||
usernameAttribute: "user",
|
||||
@@ -903,7 +903,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
name: "user-password-attributes-change-username-attribute",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("user_password"),
|
||||
vault.WithCredentialType("username_password"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUserPasswordOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
@@ -932,7 +932,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
name: "user-password-attributes-change-password-attribute",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("user_password"),
|
||||
vault.WithCredentialType("username_password"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUserPasswordOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
@@ -961,7 +961,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
name: "user-password-attributes-change-username-and-password-attributes",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("user_password"),
|
||||
vault.WithCredentialType("username_password"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUserPasswordOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
@@ -992,7 +992,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
name: "no-mapping-override-change-username-and-password-attributes",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("user_password"),
|
||||
vault.WithCredentialType("username_password"),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(passwordAttrField, usernameAttrField),
|
||||
@@ -1023,7 +1023,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
name: "user-password-attributes-delete-mapping-override",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("user_password"),
|
||||
vault.WithCredentialType("username_password"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUserPasswordOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
@@ -1045,7 +1045,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
name: "no-mapping-override-delete-mapping-override",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("user_password"),
|
||||
vault.WithCredentialType("username_password"),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(credentialMappingPathField),
|
||||
@@ -1062,7 +1062,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
name: "user-password-attributes-delete-mapping-override-field-specific",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("user_password"),
|
||||
vault.WithCredentialType("username_password"),
|
||||
vault.WithMappingOverride(
|
||||
vault.NewUserPasswordOverride(
|
||||
vault.WithOverrideUsernameAttribute("orig-user"),
|
||||
@@ -1092,7 +1092,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
name: "no-mapping-override-delete-mapping-override-field-specific",
|
||||
opts: []vault.Option{
|
||||
vault.WithCredentialType("user_password"),
|
||||
vault.WithCredentialType("username_password"),
|
||||
},
|
||||
req: &pbs.UpdateCredentialLibraryRequest{
|
||||
UpdateMask: fieldmask(passwordAttrField, usernameAttrField),
|
||||
@@ -1185,7 +1185,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
name: "read only credential type",
|
||||
path: "credential_type",
|
||||
item: &pb.CredentialLibrary{CredentialType: string(credential.UserPasswordType)},
|
||||
item: &pb.CredentialLibrary{CredentialType: string(credential.UsernamePasswordType)},
|
||||
},
|
||||
}
|
||||
for _, tc := range errCases {
|
||||
|
||||
@@ -0,0 +1,592 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/globals"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/static"
|
||||
"github.com/hashicorp/boundary/internal/credential/static/store"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/common"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
"github.com/hashicorp/boundary/internal/perms"
|
||||
"github.com/hashicorp/boundary/internal/requests"
|
||||
"github.com/hashicorp/boundary/internal/types/action"
|
||||
"github.com/hashicorp/boundary/internal/types/resource"
|
||||
"github.com/hashicorp/boundary/internal/types/subtypes"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentials"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
const (
|
||||
usernameField = "attributes.username"
|
||||
passwordField = "attributes.password"
|
||||
domain = "credential"
|
||||
)
|
||||
|
||||
var (
|
||||
maskManager handlers.MaskManager
|
||||
|
||||
// IdActions contains the set of actions that can be performed on
|
||||
// individual resources
|
||||
IdActions = action.ActionSet{
|
||||
action.NoOp,
|
||||
action.Read,
|
||||
action.Update,
|
||||
action.Delete,
|
||||
}
|
||||
|
||||
// CollectionActions contains the set of actions that can be performed on
|
||||
// this collection
|
||||
CollectionActions = action.ActionSet{
|
||||
action.Create,
|
||||
action.List,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
if maskManager, err = handlers.NewMaskManager(handlers.MaskDestination{&store.UsernamePasswordCredential{}},
|
||||
handlers.MaskSource{&pb.Credential{}, &pb.UsernamePasswordAttributes{}}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Service handles request as described by the pbs.CredentialServiceServer interface.
|
||||
type Service struct {
|
||||
pbs.UnimplementedCredentialServiceServer
|
||||
|
||||
iamRepoFn common.IamRepoFactory
|
||||
repoFn common.StaticCredentialRepoFactory
|
||||
}
|
||||
|
||||
// NewService returns a credential service which handles credential related requests to boundary.
|
||||
func NewService(repo common.StaticCredentialRepoFactory, iamRepo common.IamRepoFactory) (Service, error) {
|
||||
const op = "credentials.NewService"
|
||||
if iamRepo == nil {
|
||||
return Service{}, errors.NewDeprecated(errors.InvalidParameter, op, "missing iam repository")
|
||||
}
|
||||
if repo == nil {
|
||||
return Service{}, errors.NewDeprecated(errors.InvalidParameter, op, "missing static credential repository")
|
||||
}
|
||||
return Service{iamRepoFn: iamRepo, repoFn: repo}, nil
|
||||
}
|
||||
|
||||
var _ pbs.CredentialServiceServer = Service{}
|
||||
|
||||
// ListCredentials implements the interface pbs.CredentialServiceServer
|
||||
func (s Service) ListCredentials(ctx context.Context, req *pbs.ListCredentialsRequest) (*pbs.ListCredentialsResponse, error) {
|
||||
if err := validateListRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetCredentialStoreId(), action.List)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
|
||||
creds, err := s.listFromRepo(ctx, req.GetCredentialStoreId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(creds) == 0 {
|
||||
return &pbs.ListCredentialsResponse{}, nil
|
||||
}
|
||||
|
||||
filter, err := handlers.NewFilter(req.GetFilter())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalItems := make([]*pb.Credential, 0, len(creds))
|
||||
res := perms.Resource{
|
||||
ScopeId: authResults.Scope.Id,
|
||||
Type: resource.Credential,
|
||||
Pin: req.GetCredentialStoreId(),
|
||||
}
|
||||
for _, item := range creds {
|
||||
res.Id = item.GetPublicId()
|
||||
authorizedActions := authResults.FetchActionSetForId(ctx, item.GetPublicId(), IdActions, auth.WithResource(&res)).Strings()
|
||||
if len(authorizedActions) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
outputFields := authResults.FetchOutputFields(res, action.List).SelfOrDefaults(authResults.UserId)
|
||||
outputOpts := make([]handlers.Option, 0, 3)
|
||||
outputOpts = append(outputOpts, handlers.WithOutputFields(&outputFields))
|
||||
if outputFields.Has(globals.ScopeField) {
|
||||
outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedActionsField) {
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authorizedActions))
|
||||
}
|
||||
|
||||
item, err := toProto(item, outputOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filterable, err := subtypes.Filterable(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if filter.Match(filterable) {
|
||||
finalItems = append(finalItems, item)
|
||||
}
|
||||
}
|
||||
return &pbs.ListCredentialsResponse{Items: finalItems}, nil
|
||||
}
|
||||
|
||||
// GetCredential implements the interface pbs.CredentialServiceServer.
|
||||
func (s Service) GetCredential(ctx context.Context, req *pbs.GetCredentialRequest) (*pbs.GetCredentialResponse, error) {
|
||||
const op = "credentials.(Service).GetCredential"
|
||||
|
||||
if err := validateGetRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.Read)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
c, err := s.getFromRepo(ctx, req.GetId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outputFields, ok := requests.OutputFields(ctx)
|
||||
if !ok {
|
||||
return nil, errors.New(ctx, errors.Internal, op, "no request context found")
|
||||
}
|
||||
|
||||
outputOpts := make([]handlers.Option, 0, 3)
|
||||
outputOpts = append(outputOpts, handlers.WithOutputFields(&outputFields))
|
||||
if outputFields.Has(globals.ScopeField) {
|
||||
outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedActionsField) {
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, c.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
|
||||
item, err := toProto(c, outputOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pbs.GetCredentialResponse{Item: item}, nil
|
||||
}
|
||||
|
||||
// CreateCredential implements the interface pbs.CredentialServiceServer.
|
||||
func (s Service) CreateCredential(ctx context.Context, req *pbs.CreateCredentialRequest) (*pbs.CreateCredentialResponse, error) {
|
||||
const op = "credentials.(Service).CreateCredential"
|
||||
|
||||
if err := validateCreateRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetItem().GetCredentialStoreId(), action.Create)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
cl, err := s.createInRepo(ctx, authResults.Scope.GetId(), req.GetItem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outputFields, ok := requests.OutputFields(ctx)
|
||||
if !ok {
|
||||
return nil, errors.New(ctx, errors.Internal, op, "no request context found")
|
||||
}
|
||||
|
||||
outputOpts := make([]handlers.Option, 0, 3)
|
||||
outputOpts = append(outputOpts, handlers.WithOutputFields(&outputFields))
|
||||
if outputFields.Has(globals.ScopeField) {
|
||||
outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedActionsField) {
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, cl.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
|
||||
item, err := toProto(cl, outputOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pbs.CreateCredentialResponse{
|
||||
Item: item,
|
||||
Uri: fmt.Sprintf("credentials/%s", item.GetId()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateCredential implements the interface pbs.CredentialServiceServer.
|
||||
func (s Service) UpdateCredential(ctx context.Context, req *pbs.UpdateCredentialRequest) (*pbs.UpdateCredentialResponse, error) {
|
||||
const op = "credentials.(Service).UpdateCredential"
|
||||
|
||||
cur, err := s.getFromRepo(ctx, req.GetId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storeId := cur.GetStoreId()
|
||||
|
||||
if err := validateUpdateRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.Update)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
c, err := s.updateInRepo(ctx, authResults.Scope.GetId(), storeId, req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outputFields, ok := requests.OutputFields(ctx)
|
||||
if !ok {
|
||||
return nil, errors.New(ctx, errors.Internal, op, "no request context found")
|
||||
}
|
||||
|
||||
outputOpts := make([]handlers.Option, 0, 3)
|
||||
outputOpts = append(outputOpts, handlers.WithOutputFields(&outputFields))
|
||||
if outputFields.Has(globals.ScopeField) {
|
||||
outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedActionsField) {
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, c.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
|
||||
item, err := toProto(c, outputOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pbs.UpdateCredentialResponse{Item: item}, nil
|
||||
}
|
||||
|
||||
// DeleteCredential implements the interface pbs.CredentialServiceServer.
|
||||
func (s Service) DeleteCredential(ctx context.Context, req *pbs.DeleteCredentialRequest) (*pbs.DeleteCredentialResponse, error) {
|
||||
if err := validateDeleteRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.Delete)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
_, err := s.deleteFromRepo(ctx, authResults.Scope.GetId(), req.GetId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s Service) listFromRepo(ctx context.Context, storeId string) ([]credential.Static, error) {
|
||||
const op = "credentials.(Service).listFromRepo"
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
up, err := repo.ListCredentials(ctx, storeId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
creds := make([]credential.Static, 0, len(up))
|
||||
for _, s := range up {
|
||||
creds = append(creds, s)
|
||||
}
|
||||
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
func (s Service) getFromRepo(ctx context.Context, id string) (credential.Static, error) {
|
||||
const op = "credentials.(Service).getFromRepo"
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
cred, err := repo.LookupCredential(ctx, id)
|
||||
if err != nil && !errors.IsNotFoundError(err) {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if cred == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("credential %q not found", id))
|
||||
}
|
||||
return cred, err
|
||||
}
|
||||
|
||||
func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Credential) (credential.Static, error) {
|
||||
const op = "credentials.(Service).createInRepo"
|
||||
switch item.GetType() {
|
||||
case static.UsernamePasswordSubtype.String():
|
||||
cred, err := toUsernamePasswordStorageCredential(item.GetCredentialStoreId(), item)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
out, err := repo.CreateUsernamePasswordCredential(ctx, scopeId, cred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create credential"))
|
||||
}
|
||||
if out == nil {
|
||||
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create credential but no error returned from repository.")
|
||||
}
|
||||
return out, nil
|
||||
default:
|
||||
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, fmt.Sprintf("Unsupported credential type %q", item.GetType()))
|
||||
}
|
||||
}
|
||||
|
||||
func (s Service) updateInRepo(
|
||||
ctx context.Context,
|
||||
scopeId, storeId, id string,
|
||||
masks []string,
|
||||
in *pb.Credential,
|
||||
) (credential.Static, error) {
|
||||
const op = "credentials.(Service).updateInRepo"
|
||||
|
||||
var dbMasks []string
|
||||
item := proto.Clone(in).(*pb.Credential)
|
||||
|
||||
dbMasks = append(dbMasks, maskManager.Translate(masks)...)
|
||||
if len(dbMasks) == 0 {
|
||||
return nil, handlers.InvalidArgumentErrorf("No valid fields included in the update mask.", map[string]string{"update_mask": "No valid fields provided in the update mask."})
|
||||
}
|
||||
|
||||
switch subtypes.SubtypeFromId(domain, id) {
|
||||
case static.UsernamePasswordSubtype:
|
||||
cred, err := toUsernamePasswordStorageCredential(storeId, in)
|
||||
cred.PublicId = id
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
out, rowsUpdated, err := repo.UpdateUsernamePasswordCredential(ctx, scopeId, cred, item.GetVersion(), dbMasks)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to update credential"))
|
||||
}
|
||||
if rowsUpdated == 0 {
|
||||
return nil, handlers.NotFoundErrorf("Credential %q doesn't exist or incorrect version provided.", id)
|
||||
}
|
||||
return out, nil
|
||||
default:
|
||||
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, fmt.Sprintf("Unsupported credential type %q", item.GetType()))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, error) {
|
||||
const op = "credentials.(Service).deleteFromRepo"
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
rows, err := repo.DeleteCredential(ctx, scopeId, id)
|
||||
if err != nil {
|
||||
if errors.IsNotFoundError(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, errors.Wrap(ctx, err, op, errors.WithMsg("unable to delete credential"))
|
||||
}
|
||||
return rows > 0, nil
|
||||
}
|
||||
|
||||
func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults {
|
||||
const op = "credentials.(Service).authResult"
|
||||
res := auth.VerifyResults{}
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
res.Error = err
|
||||
return res
|
||||
}
|
||||
|
||||
var parentId string
|
||||
opts := []auth.Option{auth.WithType(resource.Credential), auth.WithAction(a)}
|
||||
switch a {
|
||||
case action.List, action.Create:
|
||||
parentId = id
|
||||
default:
|
||||
opts = append(opts, auth.WithId(id))
|
||||
cred, err := repo.LookupCredential(ctx, id)
|
||||
if err != nil {
|
||||
res.Error = err
|
||||
return res
|
||||
}
|
||||
if cred == nil {
|
||||
res.Error = handlers.NotFoundError()
|
||||
return res
|
||||
}
|
||||
parentId = cred.GetStoreId()
|
||||
|
||||
}
|
||||
|
||||
if parentId == "" {
|
||||
res.Error = errors.New(ctx, errors.RecordNotFound, op, "unable to find credential store for provided credential")
|
||||
return res
|
||||
}
|
||||
opts = append(opts, auth.WithPin(parentId))
|
||||
|
||||
cs, err := repo.LookupCredentialStore(ctx, parentId)
|
||||
if err != nil {
|
||||
res.Error = err
|
||||
return res
|
||||
}
|
||||
if cs == nil {
|
||||
res.Error = handlers.NotFoundError()
|
||||
return res
|
||||
}
|
||||
opts = append(opts, auth.WithScopeId(cs.GetScopeId()))
|
||||
|
||||
return auth.Verify(ctx, opts...)
|
||||
}
|
||||
|
||||
func toProto(in credential.Static, opt ...handlers.Option) (*pb.Credential, error) {
|
||||
opts := handlers.GetOpts(opt...)
|
||||
if opts.WithOutputFields == nil {
|
||||
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "output fields not found when building credential proto")
|
||||
}
|
||||
outputFields := *opts.WithOutputFields
|
||||
|
||||
out := pb.Credential{}
|
||||
if outputFields.Has(globals.IdField) {
|
||||
out.Id = in.GetPublicId()
|
||||
}
|
||||
if outputFields.Has(globals.CredentialStoreIdField) {
|
||||
out.CredentialStoreId = in.GetStoreId()
|
||||
}
|
||||
if outputFields.Has(globals.TypeField) {
|
||||
switch in.(type) {
|
||||
case *static.UsernamePasswordCredential:
|
||||
out.Type = static.UsernamePasswordSubtype.String()
|
||||
}
|
||||
}
|
||||
if outputFields.Has(globals.DescriptionField) && in.GetDescription() != "" {
|
||||
out.Description = wrapperspb.String(in.GetDescription())
|
||||
}
|
||||
if outputFields.Has(globals.NameField) && in.GetName() != "" {
|
||||
out.Name = wrapperspb.String(in.GetName())
|
||||
}
|
||||
if outputFields.Has(globals.CreatedTimeField) {
|
||||
out.CreatedTime = in.GetCreateTime().GetTimestamp()
|
||||
}
|
||||
if outputFields.Has(globals.UpdatedTimeField) {
|
||||
out.UpdatedTime = in.GetUpdateTime().GetTimestamp()
|
||||
}
|
||||
if outputFields.Has(globals.VersionField) {
|
||||
out.Version = in.GetVersion()
|
||||
}
|
||||
if outputFields.Has(globals.ScopeField) {
|
||||
out.Scope = opts.WithScope
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedActionsField) {
|
||||
out.AuthorizedActions = opts.WithAuthorizedActions
|
||||
}
|
||||
|
||||
switch cred := in.(type) {
|
||||
case *static.UsernamePasswordCredential:
|
||||
if outputFields.Has(globals.AttributesField) {
|
||||
out.Attrs = &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String(cred.GetUsername()),
|
||||
PasswordHmac: base64.RawURLEncoding.EncodeToString(cred.GetPasswordHmac()),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func toUsernamePasswordStorageCredential(storeId string, in *pb.Credential) (out *static.UsernamePasswordCredential, err error) {
|
||||
const op = "credentials.toStorageCredential"
|
||||
var opts []static.Option
|
||||
if in.GetName() != nil {
|
||||
opts = append(opts, static.WithName(in.GetName().GetValue()))
|
||||
}
|
||||
if in.GetDescription() != nil {
|
||||
opts = append(opts, static.WithDescription(in.GetDescription().GetValue()))
|
||||
}
|
||||
|
||||
attrs := in.GetUsernamePasswordAttributes()
|
||||
cs, err := static.NewUsernamePasswordCredential(
|
||||
storeId,
|
||||
attrs.GetUsername().GetValue(),
|
||||
credential.Password(attrs.GetPassword().GetValue()),
|
||||
opts...)
|
||||
if err != nil {
|
||||
return nil, errors.WrapDeprecated(err, op, errors.WithMsg("unable to build credential"))
|
||||
}
|
||||
|
||||
return cs, err
|
||||
}
|
||||
|
||||
// A validateX method should exist for each method above. These methods do not make calls to any backing service but enforce
|
||||
// requirements on the structure of the request. They verify that:
|
||||
// * The path passed in is correctly formatted
|
||||
// * All required parameters are set
|
||||
// * There are no conflicting parameters provided
|
||||
func validateGetRequest(req *pbs.GetCredentialRequest) error {
|
||||
return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, static.CredentialPrefix)
|
||||
}
|
||||
|
||||
func validateCreateRequest(req *pbs.CreateCredentialRequest) error {
|
||||
return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if req.Item.GetType() != static.UsernamePasswordSubtype.String() {
|
||||
badFields[globals.TypeField] = fmt.Sprintf("Unsupported credential type %q", req.Item.GetType())
|
||||
}
|
||||
if req.Item.GetCredentialStoreId() == "" {
|
||||
badFields[globals.CredentialStoreIdField] = "This field must be a valid credential store id."
|
||||
}
|
||||
|
||||
if req.Item.GetUsernamePasswordAttributes().GetUsername().GetValue() == "" {
|
||||
badFields[usernameField] = "Field required for creating a username-password credential."
|
||||
}
|
||||
if req.Item.GetUsernamePasswordAttributes().GetPassword().GetValue() == "" {
|
||||
badFields[passwordField] = "Field required for creating a username-password credential."
|
||||
}
|
||||
|
||||
return badFields
|
||||
})
|
||||
}
|
||||
|
||||
func validateUpdateRequest(req *pbs.UpdateCredentialRequest) error {
|
||||
return handlers.ValidateUpdateRequest(req, req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if req.GetItem().GetType() != "" && req.GetItem().GetType() != static.UsernamePasswordSubtype.String() {
|
||||
badFields[globals.TypeField] = "Cannot modify resource type."
|
||||
}
|
||||
|
||||
attrs := req.GetItem().GetUsernamePasswordAttributes()
|
||||
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), usernameField) && attrs.GetUsername().GetValue() == "" {
|
||||
badFields[usernameField] = "This is a required field and cannot be set to empty."
|
||||
}
|
||||
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), passwordField) && attrs.GetPassword().GetValue() == "" {
|
||||
badFields[passwordField] = "This is a required field and cannot be set to empty."
|
||||
}
|
||||
|
||||
return badFields
|
||||
}, static.CredentialPrefix)
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteCredentialRequest) error {
|
||||
return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, static.CredentialPrefix)
|
||||
}
|
||||
|
||||
func validateListRequest(req *pbs.ListCredentialsRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(handlers.Id(req.GetCredentialStoreId()), static.CredentialStorePrefix) {
|
||||
badFields[globals.CredentialStoreIdField] = "This field must be a valid credential store id."
|
||||
}
|
||||
if _, err := handlers.NewFilter(req.GetFilter()); err != nil {
|
||||
badFields["filter"] = fmt.Sprintf("This field could not be parsed. %v", err)
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,742 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/boundary/internal/credential/static"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/libs/crypto"
|
||||
"github.com/hashicorp/boundary/internal/scheduler"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentials"
|
||||
scopepb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
"google.golang.org/protobuf/types/known/fieldmaskpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
var testAuthorizedActions = []string{"no-op", "read", "update", "delete"}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kkms := kms.TestKms(t, conn, wrapper)
|
||||
rw := db.New(conn)
|
||||
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
staticRepoFn := func() (*static.Repository, error) {
|
||||
return static.NewRepository(context.Background(), rw, rw, kkms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
store := static.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
storeNoCreds := static.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
|
||||
var wantCreds []*pb.Credential
|
||||
for i := 0; i < 10; i++ {
|
||||
user := fmt.Sprintf("user-%d", i)
|
||||
pass := fmt.Sprintf("pass-%d", i)
|
||||
c := static.TestUsernamePasswordCredential(t, conn, wrapper, user, pass, store.GetPublicId(), prj.GetPublicId())
|
||||
|
||||
databaseWrapper, err := kkms.GetWrapper(context.Background(), prj.GetPublicId(), kms.KeyPurposeDatabase)
|
||||
require.NoError(t, err)
|
||||
hm, err := crypto.HmacSha256(context.Background(), []byte(pass), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(t, err)
|
||||
|
||||
wantCreds = append(wantCreds, &pb.Credential{
|
||||
Id: c.GetPublicId(),
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()},
|
||||
CreatedTime: c.GetCreateTime().GetTimestamp(),
|
||||
UpdatedTime: c.GetUpdateTime().GetTimestamp(),
|
||||
Version: c.GetVersion(),
|
||||
Type: static.UsernamePasswordSubtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String(c.GetUsername()),
|
||||
PasswordHmac: base64.RawURLEncoding.EncodeToString([]byte(hm)),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
req *pbs.ListCredentialsRequest
|
||||
res *pbs.ListCredentialsResponse
|
||||
anonRes *pbs.ListCredentialsResponse
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "List many credentials",
|
||||
req: &pbs.ListCredentialsRequest{CredentialStoreId: store.GetPublicId()},
|
||||
res: &pbs.ListCredentialsResponse{Items: wantCreds},
|
||||
anonRes: &pbs.ListCredentialsResponse{Items: wantCreds},
|
||||
},
|
||||
{
|
||||
name: "List no credentials",
|
||||
req: &pbs.ListCredentialsRequest{CredentialStoreId: storeNoCreds.GetPublicId()},
|
||||
res: &pbs.ListCredentialsResponse{},
|
||||
anonRes: &pbs.ListCredentialsResponse{},
|
||||
},
|
||||
{
|
||||
name: "Filter to one credential",
|
||||
req: &pbs.ListCredentialsRequest{CredentialStoreId: store.GetPublicId(), Filter: fmt.Sprintf(`"/item/id"==%q`, wantCreds[1].GetId())},
|
||||
res: &pbs.ListCredentialsResponse{Items: wantCreds[1:2]},
|
||||
anonRes: &pbs.ListCredentialsResponse{Items: wantCreds[1:2]},
|
||||
},
|
||||
{
|
||||
name: "Filter on Attribute",
|
||||
req: &pbs.ListCredentialsRequest{CredentialStoreId: store.GetPublicId(), Filter: fmt.Sprintf(`"/item/attributes/username"==%q`, wantCreds[2].GetUsernamePasswordAttributes().GetUsername().Value)},
|
||||
res: &pbs.ListCredentialsResponse{Items: wantCreds[2:3]},
|
||||
anonRes: &pbs.ListCredentialsResponse{}, // anonymous user does not have access to attributes
|
||||
},
|
||||
{
|
||||
name: "Filter to no credential",
|
||||
req: &pbs.ListCredentialsRequest{CredentialStoreId: store.GetPublicId(), Filter: `"/item/id"=="doesnt match"`},
|
||||
res: &pbs.ListCredentialsResponse{},
|
||||
anonRes: &pbs.ListCredentialsResponse{},
|
||||
},
|
||||
{
|
||||
name: "Filter Bad Format",
|
||||
req: &pbs.ListCredentialsRequest{CredentialStoreId: store.GetPublicId(), Filter: `"//id/"=="bad"`},
|
||||
err: handlers.InvalidArgumentErrorf("bad format", nil),
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
s, err := NewService(staticRepoFn, iamRepoFn)
|
||||
require.NoError(t, err, "Couldn't create new host set service.")
|
||||
|
||||
// Test non-anonymous listing
|
||||
got, gErr := s.ListCredentials(auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId()), tc.req)
|
||||
if tc.err != nil {
|
||||
require.Error(t, gErr)
|
||||
assert.True(t, errors.Is(gErr, tc.err), "ListCredentialStore(%q) got error %v, wanted %v", tc.req, gErr, tc.err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, gErr)
|
||||
assert.Empty(t, cmp.Diff(got, tc.res, protocmp.Transform(), protocmp.SortRepeated(func(x, y *pb.Credential) bool {
|
||||
return x.Id < y.Id
|
||||
})))
|
||||
|
||||
// Test anonymous listing
|
||||
got, gErr = s.ListCredentials(auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId(), auth.WithUserId(auth.AnonymousUserId)), tc.req)
|
||||
require.NoError(t, gErr)
|
||||
assert.Len(t, got.Items, len(tc.anonRes.Items))
|
||||
for _, item := range got.GetItems() {
|
||||
require.Nil(t, item.CreatedTime)
|
||||
require.Nil(t, item.UpdatedTime)
|
||||
require.Zero(t, item.Version)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kkms := kms.TestKms(t, conn, wrapper)
|
||||
rw := db.New(conn)
|
||||
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
staticRepoFn := func() (*static.Repository, error) {
|
||||
return static.NewRepository(context.Background(), rw, rw, kkms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
|
||||
store := static.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
cred := static.TestUsernamePasswordCredential(t, conn, wrapper, "user", "pass", store.GetPublicId(), prj.GetPublicId())
|
||||
s, err := NewService(staticRepoFn, iamRepoFn)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Calculate hmac
|
||||
databaseWrapper, err := kkms.GetWrapper(context.Background(), prj.GetPublicId(), kms.KeyPurposeDatabase)
|
||||
require.NoError(t, err)
|
||||
hm, err := crypto.HmacSha256(context.Background(), []byte("pass"), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(t, err)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
id string
|
||||
res *pbs.GetCredentialResponse
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
id: cred.GetPublicId(),
|
||||
res: &pbs.GetCredentialResponse{
|
||||
Item: &pb.Credential{
|
||||
Id: cred.GetPublicId(),
|
||||
CredentialStoreId: cred.GetStoreId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: store.GetScopeId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()},
|
||||
Type: static.UsernamePasswordSubtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
CreatedTime: cred.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: cred.UpdateTime.GetTimestamp(),
|
||||
Version: 1,
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String("user"),
|
||||
PasswordHmac: base64.RawURLEncoding.EncodeToString([]byte(hm)),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found error",
|
||||
id: fmt.Sprintf("%s_1234567890", static.CredentialPrefix),
|
||||
err: handlers.NotFoundError(),
|
||||
},
|
||||
{
|
||||
name: "bad prefix",
|
||||
id: fmt.Sprintf("%s_1234567890", static.CredentialStorePrefix),
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := &pbs.GetCredentialRequest{Id: tc.id}
|
||||
// Test non-anonymous get
|
||||
got, gErr := s.GetCredential(auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId()), req)
|
||||
if tc.err != nil {
|
||||
require.Error(t, gErr)
|
||||
assert.True(t, errors.Is(gErr, tc.err))
|
||||
return
|
||||
}
|
||||
require.NoError(t, gErr)
|
||||
assert.Empty(t, cmp.Diff(got, tc.res, protocmp.Transform()))
|
||||
|
||||
// Test anonymous get
|
||||
got, gErr = s.GetCredential(auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId(), auth.WithUserId(auth.AnonymousUserId)), req)
|
||||
require.NoError(t, gErr)
|
||||
require.Nil(t, got.Item.CreatedTime)
|
||||
require.Nil(t, got.Item.UpdatedTime)
|
||||
require.Zero(t, got.Item.Version)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
sche := scheduler.TestScheduler(t, conn, wrapper)
|
||||
rw := db.New(conn)
|
||||
err := vault.RegisterJobs(context.Background(), sche, rw, rw, kms)
|
||||
require.NoError(t, err)
|
||||
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
staticRepoFn := func() (*static.Repository, error) {
|
||||
return static.NewRepository(context.Background(), rw, rw, kms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
|
||||
store := static.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
cred := static.TestUsernamePasswordCredential(t, conn, wrapper, "user", "pass", store.GetPublicId(), prj.GetPublicId())
|
||||
s, err := NewService(staticRepoFn, iamRepoFn)
|
||||
require.NoError(t, err)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
id string
|
||||
err error
|
||||
res *pbs.DeleteCredentialResponse
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
id: cred.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "not found error",
|
||||
id: fmt.Sprintf("%s_1234567890", static.CredentialPrefix),
|
||||
err: handlers.NotFoundError(),
|
||||
},
|
||||
{
|
||||
name: "bad prefix",
|
||||
id: fmt.Sprintf("%s_1234567890", static.CredentialStorePrefix),
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got, gErr := s.DeleteCredential(auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId()), &pbs.DeleteCredentialRequest{Id: tc.id})
|
||||
assert.EqualValuesf(t, tc.res, got, "DeleteCredentialStore got response %q, wanted %q", got, tc.res)
|
||||
if tc.err != nil {
|
||||
require.Error(t, gErr)
|
||||
assert.True(t, errors.Is(gErr, tc.err))
|
||||
return
|
||||
}
|
||||
require.NoError(t, gErr)
|
||||
g, err := s.GetCredential(auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId()), &pbs.GetCredentialRequest{Id: tc.id})
|
||||
assert.Nil(t, g)
|
||||
assert.True(t, errors.Is(err, handlers.NotFoundError()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kkms := kms.TestKms(t, conn, wrapper)
|
||||
rw := db.New(conn)
|
||||
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
repoFn := func() (*static.Repository, error) {
|
||||
return static.NewRepository(context.Background(), rw, rw, kkms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
store := static.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
req *pbs.CreateCredentialRequest
|
||||
res *pbs.CreateCredentialResponse
|
||||
idPrefix string
|
||||
err error
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Can't specify Id",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Id: static.CredentialPrefix + "_notallowed",
|
||||
Type: static.UsernamePasswordSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Can't specify Created Time",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
CreatedTime: timestamppb.Now(),
|
||||
Type: static.UsernamePasswordSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Can't specify Updated Time",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
UpdatedTime: timestamppb.Now(),
|
||||
Type: static.UsernamePasswordSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Must provide type",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Must provide username",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: static.UsernamePasswordSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Password: wrapperspb.String("password"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Must provide password]",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: static.UsernamePasswordSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
req: &pbs.CreateCredentialRequest{Item: &pb.Credential{
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
Type: static.UsernamePasswordSubtype.String(),
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String("username"),
|
||||
Password: wrapperspb.String("password"),
|
||||
},
|
||||
},
|
||||
}},
|
||||
idPrefix: static.CredentialPrefix + "_",
|
||||
res: &pbs.CreateCredentialResponse{
|
||||
Uri: fmt.Sprintf("credentials/%s_", static.CredentialPrefix),
|
||||
Item: &pb.Credential{
|
||||
Id: store.GetPublicId(),
|
||||
CredentialStoreId: store.GetPublicId(),
|
||||
CreatedTime: store.GetCreateTime().GetTimestamp(),
|
||||
UpdatedTime: store.GetUpdateTime().GetTimestamp(),
|
||||
Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: prj.GetType(), ParentScopeId: prj.GetParentId()},
|
||||
Version: 1,
|
||||
Type: static.UsernamePasswordSubtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
s, err := NewService(repoFn, iamRepoFn)
|
||||
require.NoError(err, "Error when getting new credential store service.")
|
||||
|
||||
got, gErr := s.CreateCredential(auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId()), tc.req)
|
||||
if tc.wantErr || tc.err != nil {
|
||||
require.Error(gErr)
|
||||
if tc.err != nil {
|
||||
assert.True(errors.Is(gErr, tc.err), "CreateCredential(...) got error %v, wanted %v", gErr, tc.err)
|
||||
}
|
||||
return
|
||||
}
|
||||
require.NoError(gErr)
|
||||
if tc.res == nil {
|
||||
require.Nil(got)
|
||||
}
|
||||
if got != nil {
|
||||
assert.Contains(got.GetUri(), tc.res.Uri)
|
||||
assert.True(strings.HasPrefix(got.GetItem().GetId(), tc.idPrefix))
|
||||
gotCreateTime := got.GetItem().GetCreatedTime()
|
||||
gotUpdateTime := got.GetItem().GetUpdatedTime()
|
||||
|
||||
// Verify it is a credential store created after the test setup's default credential store
|
||||
assert.True(gotCreateTime.AsTime().After(store.CreateTime.AsTime()), "New credential should have been created after default credential store. Was created %v, which is after %v", gotCreateTime, store.CreateTime.AsTime())
|
||||
assert.True(gotUpdateTime.AsTime().After(store.CreateTime.AsTime()), "New credential should have been updated after default credential store. Was updated %v, which is after %v", gotUpdateTime, store.CreateTime.AsTime())
|
||||
|
||||
// Calculate hmac
|
||||
databaseWrapper, err := kkms.GetWrapper(context.Background(), prj.PublicId, kms.KeyPurposeDatabase)
|
||||
password := tc.req.GetItem().GetUsernamePasswordAttributes().GetPassword().GetValue()
|
||||
hm, err := crypto.HmacSha256(context.Background(), []byte(password), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(err)
|
||||
|
||||
// Validate attributes equal
|
||||
assert.Equal(tc.req.GetItem().GetUsernamePasswordAttributes().GetUsername().GetValue(),
|
||||
got.GetItem().GetUsernamePasswordAttributes().GetUsername().GetValue())
|
||||
assert.Equal(base64.RawURLEncoding.EncodeToString([]byte(hm)), got.GetItem().GetUsernamePasswordAttributes().GetPasswordHmac())
|
||||
assert.Empty(got.GetItem().GetUsernamePasswordAttributes().GetPassword())
|
||||
|
||||
// Clear attributes for compare below
|
||||
got.Item.Attrs = nil
|
||||
|
||||
// Clear all values which are hard to compare against.
|
||||
got.Uri, tc.res.Uri = "", ""
|
||||
got.Item.Id, tc.res.Item.Id = "", ""
|
||||
got.Item.CreatedTime, got.Item.UpdatedTime, tc.res.Item.CreatedTime, tc.res.Item.UpdatedTime = nil, nil, nil, nil
|
||||
}
|
||||
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform(), protocmp.SortRepeatedFields(got)), "CreateCredential(%q) got response %q, wanted %q", tc.req, got, tc.res)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kkms := kms.TestKms(t, conn, wrapper)
|
||||
rw := db.New(conn)
|
||||
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
staticRepoFn := func() (*static.Repository, error) {
|
||||
return static.NewRepository(context.Background(), rw, rw, kkms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
ctx := auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId())
|
||||
|
||||
s, err := NewService(staticRepoFn, iamRepoFn)
|
||||
require.NoError(t, err)
|
||||
|
||||
fieldmask := func(paths ...string) *fieldmaskpb.FieldMask {
|
||||
return &fieldmaskpb.FieldMask{Paths: paths}
|
||||
}
|
||||
|
||||
store := static.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
|
||||
freshCred := func(user, pass string) (*static.UsernamePasswordCredential, func()) {
|
||||
t.Helper()
|
||||
cred := static.TestUsernamePasswordCredential(t, conn, wrapper, user, pass, store.GetPublicId(), prj.GetPublicId())
|
||||
clean := func() {
|
||||
_, err := s.DeleteCredential(ctx, &pbs.DeleteCredentialRequest{Id: cred.GetPublicId()})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
return cred, clean
|
||||
}
|
||||
|
||||
databaseWrapper, err := kkms.GetWrapper(context.Background(), prj.GetPublicId(), kms.KeyPurposeDatabase)
|
||||
require.NoError(t, err)
|
||||
|
||||
successCases := []struct {
|
||||
name string
|
||||
req *pbs.UpdateCredentialRequest
|
||||
res func(cred *pb.Credential) *pb.Credential
|
||||
}{
|
||||
{
|
||||
name: "name",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("name"),
|
||||
Item: &pb.Credential{
|
||||
Name: wrapperspb.String("new-name"),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
out.Name = wrapperspb.String("new-name")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "description",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("description"),
|
||||
Item: &pb.Credential{
|
||||
Description: wrapperspb.String("new-description"),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
out.Description = wrapperspb.String("new-description")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "name-and-description",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("name", "description"),
|
||||
Item: &pb.Credential{
|
||||
Name: wrapperspb.String("new-name"),
|
||||
Description: wrapperspb.String("new-description"),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
out.Name = wrapperspb.String("new-name")
|
||||
out.Description = wrapperspb.String("new-description")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-username",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("attributes.username"),
|
||||
Item: &pb.Credential{
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String("new-user-name"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
out.GetUsernamePasswordAttributes().Username = wrapperspb.String("new-user-name")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-password",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("attributes.password"),
|
||||
Item: &pb.Credential{
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Password: wrapperspb.String("new-password"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
hm, err := crypto.HmacSha256(context.Background(), []byte("new-password"), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(t, err)
|
||||
out.GetUsernamePasswordAttributes().PasswordHmac = base64.RawURLEncoding.EncodeToString([]byte(hm))
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update-username-and-password",
|
||||
req: &pbs.UpdateCredentialRequest{
|
||||
UpdateMask: fieldmask("attributes.username", "attributes.password"),
|
||||
Item: &pb.Credential{
|
||||
Attrs: &pb.Credential_UsernamePasswordAttributes{
|
||||
UsernamePasswordAttributes: &pb.UsernamePasswordAttributes{
|
||||
Username: wrapperspb.String("new-username"),
|
||||
Password: wrapperspb.String("new-password"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: func(in *pb.Credential) *pb.Credential {
|
||||
out := proto.Clone(in).(*pb.Credential)
|
||||
|
||||
out.GetUsernamePasswordAttributes().Username = wrapperspb.String("new-username")
|
||||
|
||||
hm, err := crypto.HmacSha256(context.Background(), []byte("new-password"), databaseWrapper, []byte(store.GetPublicId()), nil, crypto.WithEd25519())
|
||||
require.NoError(t, err)
|
||||
out.GetUsernamePasswordAttributes().PasswordHmac = base64.RawURLEncoding.EncodeToString([]byte(hm))
|
||||
return out
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range successCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
cred, cleanup := freshCred("user", "pass")
|
||||
defer cleanup()
|
||||
|
||||
if tc.req.Item.GetVersion() == 0 {
|
||||
tc.req.Item.Version = 1
|
||||
}
|
||||
if tc.req.GetId() == "" {
|
||||
tc.req.Id = cred.GetPublicId()
|
||||
}
|
||||
resToChange, err := s.GetCredential(ctx, &pbs.GetCredentialRequest{Id: cred.GetPublicId()})
|
||||
require.NoError(err)
|
||||
want := &pbs.UpdateCredentialResponse{Item: tc.res(resToChange.GetItem())}
|
||||
|
||||
got, gErr := s.UpdateCredential(ctx, tc.req)
|
||||
require.NoError(gErr)
|
||||
require.NotNil(got)
|
||||
|
||||
gotUpdateTime := got.GetItem().GetUpdatedTime()
|
||||
created := cred.GetCreateTime().GetTimestamp()
|
||||
assert.True(gotUpdateTime.AsTime().After(created.AsTime()), "Should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, created)
|
||||
|
||||
want.Item.UpdatedTime = got.Item.UpdatedTime
|
||||
|
||||
assert.EqualValues(2, got.Item.Version)
|
||||
want.Item.Version = 2
|
||||
|
||||
assert.Empty(cmp.Diff(got, want, protocmp.Transform()))
|
||||
})
|
||||
}
|
||||
|
||||
// cant update read only fields
|
||||
cred, cleanup := freshCred("user", "pass")
|
||||
defer cleanup()
|
||||
|
||||
newStore := static.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
|
||||
roCases := []struct {
|
||||
path string
|
||||
item *pb.Credential
|
||||
matcher func(t *testing.T, e error) // When not set defaults to checking against InvalidArgument Error
|
||||
}{
|
||||
{
|
||||
path: "type",
|
||||
item: &pb.Credential{Type: "something"},
|
||||
},
|
||||
{
|
||||
path: "store_id",
|
||||
item: &pb.Credential{CredentialStoreId: newStore.GetPublicId()},
|
||||
},
|
||||
{
|
||||
path: "updated_time",
|
||||
item: &pb.Credential{UpdatedTime: timestamppb.Now()},
|
||||
},
|
||||
{
|
||||
path: "created_time",
|
||||
item: &pb.Credential{UpdatedTime: timestamppb.Now()},
|
||||
},
|
||||
{
|
||||
path: "authorized_actions",
|
||||
item: &pb.Credential{AuthorizedActions: append(testAuthorizedActions, "another")},
|
||||
},
|
||||
}
|
||||
for _, tc := range roCases {
|
||||
t.Run(fmt.Sprintf("ReadOnlyField/%s", tc.path), func(t *testing.T) {
|
||||
req := &pbs.UpdateCredentialRequest{
|
||||
Id: cred.GetPublicId(),
|
||||
Item: tc.item,
|
||||
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{tc.path}},
|
||||
}
|
||||
req.Item.Version = cred.Version
|
||||
|
||||
got, gErr := s.UpdateCredential(ctx, req)
|
||||
assert.Error(t, gErr)
|
||||
matcher := tc.matcher
|
||||
if matcher == nil {
|
||||
matcher = func(t *testing.T, e error) {
|
||||
assert.Truef(t, errors.Is(gErr, handlers.ApiErrorWithCode(codes.InvalidArgument)), "got error %v, wanted invalid argument", gErr)
|
||||
}
|
||||
}
|
||||
matcher(t, gErr)
|
||||
assert.Nil(t, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/boundary/globals"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/static"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault/store"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/common/scopeids"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/credentiallibraries"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/credentials"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
"github.com/hashicorp/boundary/internal/perms"
|
||||
@@ -25,6 +27,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/types/subtypes"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentialstores"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
@@ -57,9 +60,12 @@ var (
|
||||
action.List,
|
||||
}
|
||||
|
||||
collectionTypeMap = map[resource.Type]action.ActionSet{
|
||||
vaultCollectionTypeMap = map[resource.Type]action.ActionSet{
|
||||
resource.CredentialLibrary: credentiallibraries.CollectionActions,
|
||||
}
|
||||
staticCollectionTypeMap = map[resource.Type]action.ActionSet{
|
||||
resource.Credential: credentials.CollectionActions,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -74,20 +80,28 @@ func init() {
|
||||
type Service struct {
|
||||
pbs.UnimplementedCredentialStoreServiceServer
|
||||
|
||||
iamRepoFn common.IamRepoFactory
|
||||
repoFn common.VaultCredentialRepoFactory
|
||||
iamRepoFn common.IamRepoFactory
|
||||
vaultRepoFn common.VaultCredentialRepoFactory
|
||||
staticRepoFn common.StaticCredentialRepoFactory
|
||||
}
|
||||
|
||||
// NewService returns a credential store service which handles credential store related requests to boundary.
|
||||
func NewService(repo common.VaultCredentialRepoFactory, iamRepo common.IamRepoFactory) (Service, error) {
|
||||
func NewService(
|
||||
vaultRepo common.VaultCredentialRepoFactory,
|
||||
staticRepo common.StaticCredentialRepoFactory,
|
||||
iamRepo common.IamRepoFactory,
|
||||
) (Service, error) {
|
||||
const op = "credentialstores.NewService"
|
||||
if iamRepo == nil {
|
||||
return Service{}, errors.NewDeprecated(errors.InvalidParameter, op, "missing iam repository")
|
||||
}
|
||||
if repo == nil {
|
||||
if vaultRepo == nil {
|
||||
return Service{}, errors.NewDeprecated(errors.InvalidParameter, op, "missing vault credential repository")
|
||||
}
|
||||
return Service{iamRepoFn: iamRepo, repoFn: repo}, nil
|
||||
if staticRepo == nil {
|
||||
return Service{}, errors.NewDeprecated(errors.InvalidParameter, op, "missing static credential repository")
|
||||
}
|
||||
return Service{iamRepoFn: iamRepo, vaultRepoFn: vaultRepo, staticRepoFn: staticRepo}, nil
|
||||
}
|
||||
|
||||
var _ pbs.CredentialStoreServiceServer = Service{}
|
||||
@@ -155,7 +169,7 @@ func (s Service) ListCredentialStores(ctx context.Context, req *pbs.ListCredenti
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authorizedActions))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedCollectionActionsField) {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, item.GetPublicId())
|
||||
collectionActions, err := calculateAuthorizedCollectionActions(ctx, authResults, item.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -208,7 +222,7 @@ func (s Service) GetCredentialStore(ctx context.Context, req *pbs.GetCredentialS
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, cs.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedCollectionActionsField) {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, cs.GetPublicId())
|
||||
collectionActions, err := calculateAuthorizedCollectionActions(ctx, authResults, cs.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -253,7 +267,7 @@ func (s Service) CreateCredentialStore(ctx context.Context, req *pbs.CreateCrede
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, cs.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedCollectionActionsField) {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, cs.GetPublicId())
|
||||
collectionActions, err := calculateAuthorizedCollectionActions(ctx, authResults, cs.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -301,7 +315,7 @@ func (s Service) UpdateCredentialStore(ctx context.Context, req *pbs.UpdateCrede
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, cs.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedCollectionActionsField) {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, cs.GetPublicId())
|
||||
collectionActions, err := calculateAuthorizedCollectionActions(ctx, authResults, cs.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -332,74 +346,154 @@ func (s Service) DeleteCredentialStore(ctx context.Context, req *pbs.DeleteCrede
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s Service) listFromRepo(ctx context.Context, scopeIds []string) ([]*vault.CredentialStore, error) {
|
||||
func (s Service) listFromRepo(ctx context.Context, scopeIds []string) ([]credential.Store, error) {
|
||||
const op = "credentialstores.(Service).listFromRepo"
|
||||
repo, err := s.repoFn()
|
||||
|
||||
vaultRepo, err := s.vaultRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
csl, err := repo.ListCredentialStores(ctx, scopeIds)
|
||||
vaultCsl, err := vaultRepo.ListCredentialStores(ctx, scopeIds)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
staticRepo, err := s.staticRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
staticCsl, err := staticRepo.ListCredentialStores(ctx, scopeIds)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
csl := make([]credential.Store, 0, len(staticCsl)+len(vaultCsl))
|
||||
for _, s := range vaultCsl {
|
||||
csl = append(csl, s)
|
||||
}
|
||||
for _, s := range staticCsl {
|
||||
csl = append(csl, s)
|
||||
}
|
||||
|
||||
return csl, nil
|
||||
}
|
||||
|
||||
func (s Service) getFromRepo(ctx context.Context, id string) (credential.Store, error) {
|
||||
const op = "credentialstores.(Service).getFromRepo"
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
|
||||
switch subtypes.SubtypeFromId(domain, id) {
|
||||
case vault.Subtype:
|
||||
repo, err := s.vaultRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
cs, err := repo.LookupCredentialStore(ctx, id)
|
||||
if err != nil && !errors.IsNotFoundError(err) {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if cs != nil {
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
case static.Subtype:
|
||||
repo, err := s.staticRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
cs, err := repo.LookupCredentialStore(ctx, id)
|
||||
if err != nil && !errors.IsNotFoundError(err) {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if cs != nil {
|
||||
return cs, nil
|
||||
}
|
||||
}
|
||||
cs, err := repo.LookupCredentialStore(ctx, id)
|
||||
if err != nil && !errors.IsNotFoundError(err) {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if cs == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("credential store %q not found", id))
|
||||
}
|
||||
return cs, err
|
||||
|
||||
return nil, handlers.NotFoundErrorf("credential store %q not found", id)
|
||||
}
|
||||
|
||||
func (s Service) createInRepo(ctx context.Context, projId string, item *pb.CredentialStore) (credential.Store, error) {
|
||||
const op = "credentialstores.(Service).createInRepo"
|
||||
cs, err := toStorageVaultStore(projId, item)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
|
||||
switch item.Type {
|
||||
case vault.Subtype.String():
|
||||
cs, err := toStorageVaultStore(projId, item)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
repo, err := s.vaultRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
out, err := repo.CreateCredentialStore(ctx, cs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create credential store"))
|
||||
}
|
||||
return out, nil
|
||||
|
||||
case static.Subtype.String():
|
||||
cs, err := toStorageStaticStore(projId, item)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
repo, err := s.staticRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
out, err := repo.CreateCredentialStore(ctx, cs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create credential store"))
|
||||
}
|
||||
return out, nil
|
||||
|
||||
default:
|
||||
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create credential store, unknown type.")
|
||||
}
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
out, err := repo.CreateCredentialStore(ctx, cs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create credential store"))
|
||||
}
|
||||
if out == nil {
|
||||
return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create credential store but no error returned from repository.")
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s Service) updateInRepo(ctx context.Context, projId, id string, mask []string, item *pb.CredentialStore) (credential.Store, error) {
|
||||
const op = "credentialstores.(Service).updateInRepo"
|
||||
cs, err := toStorageVaultStore(projId, item)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
cs.PublicId = id
|
||||
|
||||
var out credential.Store
|
||||
var rowsUpdated int
|
||||
|
||||
dbMask := maskManager.Translate(mask)
|
||||
if len(dbMask) == 0 {
|
||||
return nil, handlers.InvalidArgumentErrorf("No valid fields included in the update mask.", map[string]string{"update_mask": "No valid fields provided in the update mask."})
|
||||
}
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
out, rowsUpdated, err := repo.UpdateCredentialStore(ctx, cs, item.GetVersion(), dbMask)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to update credential store"))
|
||||
|
||||
switch subtypes.SubtypeFromId(domain, id) {
|
||||
case vault.Subtype:
|
||||
cs, err := toStorageVaultStore(projId, item)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
cs.PublicId = id
|
||||
|
||||
repo, err := s.vaultRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
out, rowsUpdated, err = repo.UpdateCredentialStore(ctx, cs, item.GetVersion(), dbMask)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to update credential store"))
|
||||
}
|
||||
|
||||
case static.Subtype:
|
||||
cs, err := toStorageStaticStore(projId, item)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
cs.PublicId = id
|
||||
|
||||
repo, err := s.staticRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
out, rowsUpdated, err = repo.UpdateCredentialStore(ctx, cs, item.GetVersion(), dbMask)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to update credential store"))
|
||||
}
|
||||
}
|
||||
if rowsUpdated == 0 {
|
||||
return nil, handlers.NotFoundErrorf("Credential Store %q doesn't exist or incorrect version provided.", id)
|
||||
@@ -409,16 +503,34 @@ func (s Service) updateInRepo(ctx context.Context, projId, id string, mask []str
|
||||
|
||||
func (s Service) deleteFromRepo(ctx context.Context, id string) (bool, error) {
|
||||
const op = "credentialstores.(Service).deleteFromRepo"
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
rows, err := repo.DeleteCredentialStore(ctx, id)
|
||||
if err != nil {
|
||||
if errors.IsNotFoundError(err) {
|
||||
return false, nil
|
||||
var rows int
|
||||
|
||||
switch subtypes.SubtypeFromId(domain, id) {
|
||||
case vault.Subtype:
|
||||
repo, err := s.vaultRepoFn()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
rows, err = repo.DeleteCredentialStore(ctx, id)
|
||||
if err != nil {
|
||||
if errors.IsNotFoundError(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, errors.Wrap(ctx, err, op, errors.WithMsg("unable to delete credential store"))
|
||||
}
|
||||
|
||||
case static.Subtype:
|
||||
repo, err := s.staticRepoFn()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
rows, err = repo.DeleteCredentialStore(ctx, id)
|
||||
if err != nil {
|
||||
if errors.IsNotFoundError(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, errors.Wrap(ctx, err, op, errors.WithMsg("unable to delete credential store"))
|
||||
}
|
||||
return false, errors.Wrap(ctx, err, op, errors.WithMsg("unable to delete credential store"))
|
||||
}
|
||||
return rows > 0, nil
|
||||
}
|
||||
@@ -430,7 +542,12 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.
|
||||
res.Error = err
|
||||
return res
|
||||
}
|
||||
repo, err := s.repoFn()
|
||||
vaultRepo, err := s.vaultRepoFn()
|
||||
if err != nil {
|
||||
res.Error = err
|
||||
return res
|
||||
}
|
||||
staticRepo, err := s.staticRepoFn()
|
||||
if err != nil {
|
||||
res.Error = err
|
||||
return res
|
||||
@@ -451,16 +568,32 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.
|
||||
return res
|
||||
}
|
||||
default:
|
||||
cs, err := repo.LookupCredentialStore(ctx, id)
|
||||
if err != nil {
|
||||
res.Error = err
|
||||
return res
|
||||
switch subtypes.SubtypeFromId(domain, id) {
|
||||
case vault.Subtype:
|
||||
cs, err := vaultRepo.LookupCredentialStore(ctx, id)
|
||||
if err != nil {
|
||||
res.Error = err
|
||||
return res
|
||||
}
|
||||
if cs == nil {
|
||||
res.Error = handlers.NotFoundError()
|
||||
return res
|
||||
}
|
||||
parentId = cs.GetScopeId()
|
||||
|
||||
case static.Subtype:
|
||||
var err error
|
||||
cs, err := staticRepo.LookupCredentialStore(ctx, id)
|
||||
if err != nil {
|
||||
res.Error = err
|
||||
return res
|
||||
}
|
||||
if cs == nil {
|
||||
res.Error = handlers.NotFoundError()
|
||||
return res
|
||||
}
|
||||
parentId = cs.GetScopeId()
|
||||
}
|
||||
if cs == nil {
|
||||
res.Error = handlers.NotFoundError()
|
||||
return res
|
||||
}
|
||||
parentId = cs.GetScopeId()
|
||||
opts = append(opts, auth.WithId(id))
|
||||
}
|
||||
opts = append(opts, auth.WithScopeId(parentId))
|
||||
@@ -550,6 +683,23 @@ func toProto(in credential.Store, opt ...handlers.Option) (*pb.CredentialStore,
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func toStorageStaticStore(scopeId string, in *pb.CredentialStore) (out *static.CredentialStore, err error) {
|
||||
const op = "credentialstores.toStorageStaticStore"
|
||||
var opts []static.Option
|
||||
if in.GetName() != nil {
|
||||
opts = append(opts, static.WithName(in.GetName().GetValue()))
|
||||
}
|
||||
if in.GetDescription() != nil {
|
||||
opts = append(opts, static.WithDescription(in.GetDescription().GetValue()))
|
||||
}
|
||||
|
||||
cs, err := static.NewCredentialStore(scopeId, opts...)
|
||||
if err != nil {
|
||||
return nil, errors.WrapDeprecated(err, op, errors.WithMsg("unable to build credential store for creation"))
|
||||
}
|
||||
return cs, err
|
||||
}
|
||||
|
||||
func toStorageVaultStore(scopeId string, in *pb.CredentialStore) (out *vault.CredentialStore, err error) {
|
||||
const op = "credentialstores.toStorageVaultStore"
|
||||
var opts []vault.Option
|
||||
@@ -609,7 +759,7 @@ func toStorageVaultStore(scopeId string, in *pb.CredentialStore) (out *vault.Cre
|
||||
// * All required parameters are set
|
||||
// * There are no conflicting parameters provided
|
||||
func validateGetRequest(req *pbs.GetCredentialStoreRequest) error {
|
||||
return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, vault.CredentialStorePrefix)
|
||||
return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, vault.CredentialStorePrefix, static.CredentialStorePrefix)
|
||||
}
|
||||
|
||||
func validateCreateRequest(req *pbs.CreateCredentialStoreRequest) error {
|
||||
@@ -651,6 +801,8 @@ func validateCreateRequest(req *pbs.CreateCredentialStoreRequest) error {
|
||||
if len(cs) > 0 && pk == nil {
|
||||
badFields[clientCertField] = "Cannot set a client certificate without a private key."
|
||||
}
|
||||
case static.Subtype:
|
||||
// No additional validation required for static credential store
|
||||
default:
|
||||
badFields[globals.TypeField] = "This is a required field and must be a known credential store type."
|
||||
}
|
||||
@@ -693,11 +845,11 @@ func validateUpdateRequest(req *pbs.UpdateCredentialStoreRequest) error {
|
||||
}
|
||||
}
|
||||
return badFields
|
||||
}, vault.CredentialStorePrefix)
|
||||
}, vault.CredentialStorePrefix, static.CredentialStorePrefix)
|
||||
}
|
||||
|
||||
func validateDeleteRequest(req *pbs.DeleteCredentialStoreRequest) error {
|
||||
return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, vault.CredentialStorePrefix)
|
||||
return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, vault.CredentialStorePrefix, static.CredentialStorePrefix)
|
||||
}
|
||||
|
||||
func validateListRequest(req *pbs.ListCredentialStoresRequest) error {
|
||||
@@ -714,3 +866,20 @@ func validateListRequest(req *pbs.ListCredentialStoresRequest) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func calculateAuthorizedCollectionActions(ctx context.Context, authResults auth.VerifyResults, id string) (map[string]*structpb.ListValue, error) {
|
||||
var collectionActions map[string]*structpb.ListValue
|
||||
var err error
|
||||
switch subtypes.SubtypeFromId(domain, id) {
|
||||
case vault.Subtype:
|
||||
collectionActions, err = auth.CalculateAuthorizedCollectionActions(ctx, authResults, vaultCollectionTypeMap, authResults.Scope.Id, id)
|
||||
|
||||
case static.Subtype:
|
||||
collectionActions, err = auth.CalculateAuthorizedCollectionActions(ctx, authResults, staticCollectionTypeMap, authResults.Scope.Id, id)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return collectionActions, nil
|
||||
}
|
||||
+453
-52
@@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
credstatic "github.com/hashicorp/boundary/internal/credential/static"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
|
||||
@@ -36,8 +37,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
testAuthorizedActions = []string{"no-op", "read", "update", "delete"}
|
||||
testAuthorizedCollectionActions = map[string]*structpb.ListValue{
|
||||
testAuthorizedActions = []string{"no-op", "read", "update", "delete"}
|
||||
testAuthorizedVaultCollectionActions = map[string]*structpb.ListValue{
|
||||
"credential-libraries": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
@@ -45,6 +46,14 @@ var (
|
||||
},
|
||||
},
|
||||
}
|
||||
testAuthorizedStaticCollectionActions = map[string]*structpb.ListValue{
|
||||
"credentials": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
@@ -60,9 +69,12 @@ func TestList(t *testing.T) {
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
repoFn := func() (*vault.Repository, error) {
|
||||
vaultRepoFn := func() (*vault.Repository, error) {
|
||||
return vault.NewRepository(rw, rw, kms, sche)
|
||||
}
|
||||
staticRepoFn := func() (*credstatic.Repository, error) {
|
||||
return credstatic.NewRepository(context.Background(), rw, rw, kms)
|
||||
}
|
||||
|
||||
_, prjNoStores := iam.TestScopes(t, iamRepo)
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
@@ -78,7 +90,7 @@ func TestList(t *testing.T) {
|
||||
Version: s.GetVersion(),
|
||||
Type: vault.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: testAuthorizedCollectionActions,
|
||||
AuthorizedCollectionActions: testAuthorizedVaultCollectionActions,
|
||||
Attrs: &pb.CredentialStore_VaultCredentialStoreAttributes{
|
||||
VaultCredentialStoreAttributes: &pb.VaultCredentialStoreAttributes{
|
||||
Address: wrapperspb.String(s.GetVaultAddress()),
|
||||
@@ -91,6 +103,20 @@ func TestList(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
for _, s := range credstatic.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 10) {
|
||||
wantStores = append(wantStores, &pb.CredentialStore{
|
||||
Id: s.GetPublicId(),
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()},
|
||||
CreatedTime: s.GetCreateTime().GetTimestamp(),
|
||||
UpdatedTime: s.GetUpdateTime().GetTimestamp(),
|
||||
Version: s.GetVersion(),
|
||||
Type: credstatic.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: testAuthorizedStaticCollectionActions,
|
||||
})
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
req *pbs.ListCredentialStoresRequest
|
||||
@@ -111,11 +137,17 @@ func TestList(t *testing.T) {
|
||||
anonRes: &pbs.ListCredentialStoresResponse{},
|
||||
},
|
||||
{
|
||||
name: "Filter to One Store",
|
||||
name: "Filter to One Vault Store",
|
||||
req: &pbs.ListCredentialStoresRequest{ScopeId: prj.GetPublicId(), Filter: fmt.Sprintf(`"/item/id"==%q`, wantStores[1].GetId())},
|
||||
res: &pbs.ListCredentialStoresResponse{Items: wantStores[1:2]},
|
||||
anonRes: &pbs.ListCredentialStoresResponse{Items: wantStores[1:2]},
|
||||
},
|
||||
{
|
||||
name: "Filter to One static Store",
|
||||
req: &pbs.ListCredentialStoresRequest{ScopeId: prj.GetPublicId(), Filter: fmt.Sprintf(`"/item/id"==%q`, wantStores[11].GetId())},
|
||||
res: &pbs.ListCredentialStoresResponse{Items: wantStores[11:12]},
|
||||
anonRes: &pbs.ListCredentialStoresResponse{Items: wantStores[11:12]},
|
||||
},
|
||||
{
|
||||
name: "Filter on Attribute",
|
||||
req: &pbs.ListCredentialStoresRequest{ScopeId: prj.GetPublicId(), Filter: fmt.Sprintf(`"/item/attributes/address"==%q`, wantStores[2].GetVaultCredentialStoreAttributes().GetAddress().Value)},
|
||||
@@ -136,7 +168,7 @@ func TestList(t *testing.T) {
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
s, err := NewService(repoFn, iamRepoFn)
|
||||
s, err := NewService(vaultRepoFn, staticRepoFn, iamRepoFn)
|
||||
require.NoError(t, err, "Couldn't create new host set service.")
|
||||
|
||||
// Test non-anonymous listing
|
||||
@@ -164,7 +196,7 @@ func TestList(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
func TestCreateVault(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
@@ -177,9 +209,12 @@ func TestCreate(t *testing.T) {
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
repoFn := func() (*vault.Repository, error) {
|
||||
vaultRepoFn := func() (*vault.Repository, error) {
|
||||
return vault.NewRepository(rw, rw, kms, sche)
|
||||
}
|
||||
staticRepoFn := func() (*credstatic.Repository, error) {
|
||||
return credstatic.NewRepository(context.Background(), rw, rw, kms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
defaultCreated := vault.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 1)[0].GetCreateTime().GetTimestamp()
|
||||
@@ -343,22 +378,6 @@ func TestCreate(t *testing.T) {
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Can't specify Update Time",
|
||||
req: &pbs.CreateCredentialStoreRequest{Item: &pb.CredentialStore{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
UpdatedTime: timestamppb.Now(),
|
||||
Type: vault.Subtype.String(),
|
||||
Attrs: &pb.CredentialStore_VaultCredentialStoreAttributes{
|
||||
VaultCredentialStoreAttributes: &pb.VaultCredentialStoreAttributes{
|
||||
Address: wrapperspb.String(v.Addr),
|
||||
Token: wrapperspb.String(newToken()),
|
||||
},
|
||||
},
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Must specify type",
|
||||
req: &pbs.CreateCredentialStoreRequest{Item: &pb.CredentialStore{
|
||||
@@ -433,7 +452,7 @@ func TestCreate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: testAuthorizedCollectionActions,
|
||||
AuthorizedCollectionActions: testAuthorizedVaultCollectionActions,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -474,7 +493,7 @@ func TestCreate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: testAuthorizedCollectionActions,
|
||||
AuthorizedCollectionActions: testAuthorizedVaultCollectionActions,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -483,7 +502,7 @@ func TestCreate(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
s, err := NewService(repoFn, iamRepoFn)
|
||||
s, err := NewService(vaultRepoFn, staticRepoFn, iamRepoFn)
|
||||
require.NoError(err, "Error when getting new credential store service.")
|
||||
defer cleanup(s)
|
||||
|
||||
@@ -533,6 +552,171 @@ func TestCreate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateStatic(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
sche := scheduler.TestScheduler(t, conn, wrapper)
|
||||
rw := db.New(conn)
|
||||
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
vaultRepoFn := func() (*vault.Repository, error) {
|
||||
return vault.NewRepository(rw, rw, kms, sche)
|
||||
}
|
||||
staticRepoFn := func() (*credstatic.Repository, error) {
|
||||
return credstatic.NewRepository(context.Background(), rw, rw, kms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
defaultCreated := credstatic.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
|
||||
cleanup := func(s Service) {
|
||||
ctx := auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId())
|
||||
r, err := s.ListCredentialStores(ctx, &pbs.ListCredentialStoresRequest{ScopeId: prj.GetPublicId()})
|
||||
require.NoError(t, err)
|
||||
for _, i := range r.GetItems() {
|
||||
_, err := s.DeleteCredentialStore(ctx, &pbs.DeleteCredentialStoreRequest{Id: i.GetId()})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
req *pbs.CreateCredentialStoreRequest
|
||||
res *pbs.CreateCredentialStoreResponse
|
||||
idPrefix string
|
||||
err error
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Can't specify Id",
|
||||
req: &pbs.CreateCredentialStoreRequest{Item: &pb.CredentialStore{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Id: credstatic.CredentialStorePrefix + "_notallowed",
|
||||
Type: credstatic.Subtype.String(),
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Can't specify Created Time",
|
||||
req: &pbs.CreateCredentialStoreRequest{Item: &pb.CredentialStore{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
CreatedTime: timestamppb.Now(),
|
||||
Type: credstatic.Subtype.String(),
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Can't specify Update Time",
|
||||
req: &pbs.CreateCredentialStoreRequest{Item: &pb.CredentialStore{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
UpdatedTime: timestamppb.Now(),
|
||||
Type: credstatic.Subtype.String(),
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Must specify type",
|
||||
req: &pbs.CreateCredentialStoreRequest{Item: &pb.CredentialStore{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Create a valid static CredentialStore",
|
||||
req: &pbs.CreateCredentialStoreRequest{Item: &pb.CredentialStore{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Type: credstatic.Subtype.String(),
|
||||
}},
|
||||
idPrefix: credstatic.CredentialStorePrefix + "_",
|
||||
res: &pbs.CreateCredentialStoreResponse{
|
||||
Uri: fmt.Sprintf("credential-stores/%s_", credstatic.CredentialStorePrefix),
|
||||
Item: &pb.CredentialStore{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: prj.GetType(), ParentScopeId: prj.GetParentId()},
|
||||
Version: 1,
|
||||
Type: credstatic.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: testAuthorizedStaticCollectionActions,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Create a valid static CredentialStore with name and description",
|
||||
req: &pbs.CreateCredentialStoreRequest{Item: &pb.CredentialStore{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Name: &wrapperspb.StringValue{Value: "name"},
|
||||
Description: &wrapperspb.StringValue{Value: "desc"},
|
||||
Type: credstatic.Subtype.String(),
|
||||
}},
|
||||
idPrefix: credstatic.CredentialStorePrefix + "_",
|
||||
res: &pbs.CreateCredentialStoreResponse{
|
||||
Uri: fmt.Sprintf("credential-stores/%s_", credstatic.CredentialStorePrefix),
|
||||
Item: &pb.CredentialStore{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: prj.GetType(), ParentScopeId: prj.GetParentId()},
|
||||
Version: 1,
|
||||
Type: credstatic.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Name: &wrapperspb.StringValue{Value: "name"},
|
||||
Description: &wrapperspb.StringValue{Value: "desc"},
|
||||
AuthorizedCollectionActions: testAuthorizedStaticCollectionActions,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
s, err := NewService(vaultRepoFn, staticRepoFn, iamRepoFn)
|
||||
require.NoError(err, "Error when getting new credential store service.")
|
||||
defer cleanup(s)
|
||||
|
||||
got, gErr := s.CreateCredentialStore(auth.DisabledAuthTestContext(iamRepoFn, tc.req.GetItem().GetScopeId()), tc.req)
|
||||
if tc.wantErr || tc.err != nil {
|
||||
require.Error(gErr)
|
||||
if tc.err != nil {
|
||||
assert.True(errors.Is(gErr, tc.err), "CreateCredentialStore(...) got error %v, wanted %v", gErr, tc.err)
|
||||
}
|
||||
return
|
||||
}
|
||||
require.NoError(gErr)
|
||||
if tc.res == nil {
|
||||
require.Nil(got)
|
||||
}
|
||||
cmpOptions := []cmp.Option{
|
||||
protocmp.Transform(),
|
||||
protocmp.SortRepeatedFields(got),
|
||||
}
|
||||
if got != nil {
|
||||
assert.Contains(got.GetUri(), tc.res.Uri)
|
||||
cmpOptions = append(cmpOptions, protocmp.IgnoreFields(&pbs.CreateCredentialStoreResponse{}, "uri"))
|
||||
|
||||
assert.True(strings.HasPrefix(got.GetItem().GetId(), tc.idPrefix))
|
||||
cmpOptions = append(cmpOptions, protocmp.IgnoreFields(&pb.CredentialStore{}, "id"))
|
||||
|
||||
gotCreateTime := got.GetItem().GetCreatedTime()
|
||||
gotUpdateTime := got.GetItem().GetUpdatedTime()
|
||||
|
||||
// Verify it is a credential store created after the test setup's default credential store
|
||||
assert.True(gotCreateTime.AsTime().After(defaultCreated.CreateTime.AsTime()), "New credential store should have been created after default credential store. Was created %v, which is after %v", gotCreateTime, defaultCreated)
|
||||
assert.True(gotUpdateTime.AsTime().After(defaultCreated.CreateTime.AsTime()), "New credential store should have been updated after default credential store. Was updated %v, which is after %v", gotUpdateTime, defaultCreated)
|
||||
cmpOptions = append(cmpOptions, protocmp.IgnoreFields(&pb.CredentialStore{}, "created_time"))
|
||||
cmpOptions = append(cmpOptions, protocmp.IgnoreFields(&pb.CredentialStore{}, "updated_time"))
|
||||
}
|
||||
assert.Empty(cmp.Diff(got, tc.res, cmpOptions...), "CreateCredentialStore(%q) got response %q, wanted %q", tc.req, got, tc.res)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
@@ -544,14 +728,18 @@ func TestGet(t *testing.T) {
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
repoFn := func() (*vault.Repository, error) {
|
||||
vaultRepoFn := func() (*vault.Repository, error) {
|
||||
return vault.NewRepository(rw, rw, kms, sche)
|
||||
}
|
||||
staticRepoFn := func() (*credstatic.Repository, error) {
|
||||
return credstatic.NewRepository(context.Background(), rw, rw, kms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
|
||||
store := vault.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 1)[0]
|
||||
s, err := NewService(repoFn, iamRepoFn)
|
||||
vaultStore := vault.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 1)[0]
|
||||
staticStore := credstatic.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
s, err := NewService(vaultRepoFn, staticRepoFn, iamRepoFn)
|
||||
require.NoError(t, err)
|
||||
|
||||
cases := []struct {
|
||||
@@ -561,35 +749,57 @@ func TestGet(t *testing.T) {
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
id: store.GetPublicId(),
|
||||
name: "vault success",
|
||||
id: vaultStore.GetPublicId(),
|
||||
res: &pbs.GetCredentialStoreResponse{
|
||||
Item: &pb.CredentialStore{
|
||||
Id: store.GetPublicId(),
|
||||
ScopeId: store.GetScopeId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: store.GetScopeId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()},
|
||||
Id: vaultStore.GetPublicId(),
|
||||
ScopeId: vaultStore.GetScopeId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: vaultStore.GetScopeId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()},
|
||||
Type: vault.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: testAuthorizedCollectionActions,
|
||||
CreatedTime: store.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: store.UpdateTime.GetTimestamp(),
|
||||
AuthorizedCollectionActions: testAuthorizedVaultCollectionActions,
|
||||
CreatedTime: vaultStore.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: vaultStore.UpdateTime.GetTimestamp(),
|
||||
Version: 1,
|
||||
Attrs: &pb.CredentialStore_VaultCredentialStoreAttributes{
|
||||
VaultCredentialStoreAttributes: &pb.VaultCredentialStoreAttributes{
|
||||
Address: wrapperspb.String(store.GetVaultAddress()),
|
||||
TokenHmac: base64.RawURLEncoding.EncodeToString(store.Token().GetTokenHmac()),
|
||||
ClientCertificate: wrapperspb.String(string(store.ClientCertificate().GetCertificate())),
|
||||
ClientCertificateKeyHmac: base64.RawURLEncoding.EncodeToString(store.ClientCertificate().GetCertificateKeyHmac()),
|
||||
Address: wrapperspb.String(vaultStore.GetVaultAddress()),
|
||||
TokenHmac: base64.RawURLEncoding.EncodeToString(vaultStore.Token().GetTokenHmac()),
|
||||
ClientCertificate: wrapperspb.String(string(vaultStore.ClientCertificate().GetCertificate())),
|
||||
ClientCertificateKeyHmac: base64.RawURLEncoding.EncodeToString(vaultStore.ClientCertificate().GetCertificateKeyHmac()),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found error",
|
||||
name: "static success",
|
||||
id: staticStore.GetPublicId(),
|
||||
res: &pbs.GetCredentialStoreResponse{
|
||||
Item: &pb.CredentialStore{
|
||||
Id: staticStore.GetPublicId(),
|
||||
ScopeId: staticStore.GetScopeId(),
|
||||
Scope: &scopepb.ScopeInfo{Id: staticStore.GetScopeId(), Type: scope.Project.String(), ParentScopeId: prj.GetParentId()},
|
||||
Type: credstatic.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: testAuthorizedStaticCollectionActions,
|
||||
CreatedTime: staticStore.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: staticStore.UpdateTime.GetTimestamp(),
|
||||
Version: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "vault not found error",
|
||||
id: fmt.Sprintf("%s_1234567890", vault.CredentialStorePrefix),
|
||||
err: handlers.NotFoundError(),
|
||||
},
|
||||
{
|
||||
name: "static not found error",
|
||||
id: fmt.Sprintf("%s_1234567890", credstatic.CredentialStorePrefix),
|
||||
err: handlers.NotFoundError(),
|
||||
},
|
||||
{
|
||||
name: "bad prefix",
|
||||
id: fmt.Sprintf("%s_1234567890", static.HostPrefix),
|
||||
@@ -632,14 +842,18 @@ func TestDelete(t *testing.T) {
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
repoFn := func() (*vault.Repository, error) {
|
||||
vaultRepoFn := func() (*vault.Repository, error) {
|
||||
return vault.NewRepository(rw, rw, kms, sche)
|
||||
}
|
||||
staticRepoFn := func() (*credstatic.Repository, error) {
|
||||
return credstatic.NewRepository(context.Background(), rw, rw, kms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
|
||||
store := vault.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 2)[0]
|
||||
s, err := NewService(repoFn, iamRepoFn)
|
||||
vaultStore := vault.TestCredentialStores(t, conn, wrapper, prj.GetPublicId(), 2)[0]
|
||||
staticStore := credstatic.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
s, err := NewService(vaultRepoFn, staticRepoFn, iamRepoFn)
|
||||
require.NoError(t, err)
|
||||
|
||||
cases := []struct {
|
||||
@@ -649,14 +863,23 @@ func TestDelete(t *testing.T) {
|
||||
res *pbs.DeleteCredentialStoreResponse
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
id: store.GetPublicId(),
|
||||
name: "vault success",
|
||||
id: vaultStore.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "not found error",
|
||||
name: "static success",
|
||||
id: staticStore.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "vault not found error",
|
||||
id: fmt.Sprintf("%s_1234567890", vault.CredentialStorePrefix),
|
||||
err: handlers.NotFoundError(),
|
||||
},
|
||||
{
|
||||
name: "static not found error",
|
||||
id: fmt.Sprintf("%s_1234567890", credstatic.CredentialStorePrefix),
|
||||
err: handlers.NotFoundError(),
|
||||
},
|
||||
{
|
||||
name: "bad prefix",
|
||||
id: fmt.Sprintf("%s_1234567890", static.HostPrefix),
|
||||
@@ -680,7 +903,7 @@ func TestDelete(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
func TestUpdateVault(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
@@ -693,14 +916,17 @@ func TestUpdate(t *testing.T) {
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
repoFn := func() (*vault.Repository, error) {
|
||||
vaultRepoFn := func() (*vault.Repository, error) {
|
||||
return vault.NewRepository(rw, rw, kms, sche)
|
||||
}
|
||||
staticRepoFn := func() (*credstatic.Repository, error) {
|
||||
return credstatic.NewRepository(context.Background(), rw, rw, kms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
ctx := auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId())
|
||||
|
||||
s, err := NewService(repoFn, iamRepoFn)
|
||||
s, err := NewService(vaultRepoFn, staticRepoFn, iamRepoFn)
|
||||
require.NoError(t, err)
|
||||
|
||||
fieldmask := func(paths ...string) *fieldmaskpb.FieldMask {
|
||||
@@ -1010,3 +1236,178 @@ func TestUpdate(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateStatic(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
sche := scheduler.TestScheduler(t, conn, wrapper)
|
||||
rw := db.New(conn)
|
||||
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
vaultRepoFn := func() (*vault.Repository, error) {
|
||||
return vault.NewRepository(rw, rw, kms, sche)
|
||||
}
|
||||
staticRepoFn := func() (*credstatic.Repository, error) {
|
||||
return credstatic.NewRepository(context.Background(), rw, rw, kms)
|
||||
}
|
||||
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
ctx := auth.DisabledAuthTestContext(iamRepoFn, prj.GetPublicId())
|
||||
|
||||
s, err := NewService(vaultRepoFn, staticRepoFn, iamRepoFn)
|
||||
require.NoError(t, err)
|
||||
|
||||
fieldmask := func(paths ...string) *fieldmaskpb.FieldMask {
|
||||
return &fieldmaskpb.FieldMask{Paths: paths}
|
||||
}
|
||||
|
||||
freshStore := func() (*credstatic.CredentialStore, func()) {
|
||||
t.Helper()
|
||||
st := credstatic.TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
|
||||
clean := func() {
|
||||
_, err := s.DeleteCredentialStore(ctx, &pbs.DeleteCredentialStoreRequest{Id: st.GetPublicId()})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
return st, clean
|
||||
}
|
||||
|
||||
successCases := []struct {
|
||||
name string
|
||||
req *pbs.UpdateCredentialStoreRequest
|
||||
res func(*pb.CredentialStore) *pb.CredentialStore
|
||||
}{
|
||||
{
|
||||
name: "name",
|
||||
req: &pbs.UpdateCredentialStoreRequest{
|
||||
UpdateMask: fieldmask("name"),
|
||||
Item: &pb.CredentialStore{
|
||||
Name: wrapperspb.String("new-name"),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialStore) *pb.CredentialStore {
|
||||
out := proto.Clone(in).(*pb.CredentialStore)
|
||||
out.Name = wrapperspb.String("new-name")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "description",
|
||||
req: &pbs.UpdateCredentialStoreRequest{
|
||||
UpdateMask: fieldmask("description"),
|
||||
Item: &pb.CredentialStore{
|
||||
Description: wrapperspb.String("new-description"),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialStore) *pb.CredentialStore {
|
||||
out := proto.Clone(in).(*pb.CredentialStore)
|
||||
out.Description = wrapperspb.String("new-description")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "name-and-description",
|
||||
req: &pbs.UpdateCredentialStoreRequest{
|
||||
UpdateMask: fieldmask("name", "description"),
|
||||
Item: &pb.CredentialStore{
|
||||
Name: wrapperspb.String("new-name"),
|
||||
Description: wrapperspb.String("new-description"),
|
||||
},
|
||||
},
|
||||
res: func(in *pb.CredentialStore) *pb.CredentialStore {
|
||||
out := proto.Clone(in).(*pb.CredentialStore)
|
||||
out.Name = wrapperspb.String("new-name")
|
||||
out.Description = wrapperspb.String("new-description")
|
||||
return out
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range successCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
st, cleanup := freshStore()
|
||||
defer cleanup()
|
||||
|
||||
if tc.req.Item.GetVersion() == 0 {
|
||||
tc.req.Item.Version = 1
|
||||
}
|
||||
if tc.req.GetId() == "" {
|
||||
tc.req.Id = st.GetPublicId()
|
||||
}
|
||||
resToChange, err := s.GetCredentialStore(ctx, &pbs.GetCredentialStoreRequest{Id: st.GetPublicId()})
|
||||
require.NoError(err)
|
||||
want := &pbs.UpdateCredentialStoreResponse{Item: tc.res(resToChange.GetItem())}
|
||||
|
||||
got, gErr := s.UpdateCredentialStore(ctx, tc.req)
|
||||
require.NoError(gErr)
|
||||
require.NotNil(got)
|
||||
|
||||
gotUpdateTime := got.GetItem().GetUpdatedTime()
|
||||
created := st.GetCreateTime().GetTimestamp()
|
||||
assert.True(gotUpdateTime.AsTime().After(created.AsTime()), "Should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, created)
|
||||
|
||||
want.Item.UpdatedTime = got.Item.UpdatedTime
|
||||
|
||||
assert.EqualValues(2, got.Item.Version)
|
||||
want.Item.Version = 2
|
||||
|
||||
assert.Empty(cmp.Diff(got, want, protocmp.Transform()))
|
||||
})
|
||||
}
|
||||
|
||||
// cant update read only fields
|
||||
st, cleanup := freshStore()
|
||||
defer cleanup()
|
||||
|
||||
roCases := []struct {
|
||||
path string
|
||||
item *pb.CredentialStore
|
||||
matcher func(t *testing.T, e error) // When not set defaults to checking against InvalidArgument Error
|
||||
}{
|
||||
{
|
||||
path: "type",
|
||||
item: &pb.CredentialStore{Type: "something"},
|
||||
},
|
||||
{
|
||||
path: "scope_id",
|
||||
item: &pb.CredentialStore{ScopeId: "global"},
|
||||
},
|
||||
{
|
||||
path: "updated_time",
|
||||
item: &pb.CredentialStore{UpdatedTime: timestamppb.Now()},
|
||||
},
|
||||
{
|
||||
path: "created_time",
|
||||
item: &pb.CredentialStore{UpdatedTime: timestamppb.Now()},
|
||||
},
|
||||
{
|
||||
path: "authorized_actions",
|
||||
item: &pb.CredentialStore{AuthorizedActions: append(testAuthorizedActions, "another")},
|
||||
},
|
||||
}
|
||||
for _, tc := range roCases {
|
||||
t.Run(fmt.Sprintf("ReadOnlyField/%s", tc.path), func(t *testing.T) {
|
||||
req := &pbs.UpdateCredentialStoreRequest{
|
||||
Id: st.GetPublicId(),
|
||||
Item: tc.item,
|
||||
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{tc.path}},
|
||||
}
|
||||
req.Item.Version = st.Version
|
||||
|
||||
got, gErr := s.UpdateCredentialStore(ctx, req)
|
||||
assert.Error(t, gErr)
|
||||
matcher := tc.matcher
|
||||
if matcher == nil {
|
||||
matcher = func(t *testing.T, e error) {
|
||||
assert.Truef(t, errors.Is(gErr, handlers.ApiErrorWithCode(codes.InvalidArgument)), "got error %v, wanted invalid argument", gErr)
|
||||
}
|
||||
}
|
||||
matcher(t, gErr)
|
||||
assert.Nil(t, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package targets
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
credstatic "github.com/hashicorp/boundary/internal/credential/static"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
serverpb "github.com/hashicorp/boundary/internal/gen/controller/servers/services"
|
||||
"github.com/hashicorp/boundary/internal/session"
|
||||
"github.com/hashicorp/boundary/internal/types/subtypes"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
// dynamicToWorkerCredential converts the strongly typed credential.Dynamic into
|
||||
// a session.Credential suitable for passing to a Boundary worker.
|
||||
func dynamicToWorkerCredential(ctx context.Context, cred credential.Dynamic) (session.Credential, error) {
|
||||
const op = "targets.dynamicToWorkerCredential"
|
||||
var workerCred *serverpb.Credential
|
||||
switch c := cred.(type) {
|
||||
case credential.UsernamePassword:
|
||||
workerCred = &serverpb.Credential{
|
||||
Credential: &serverpb.Credential_UserPassword{
|
||||
UserPassword: &serverpb.UserPassword{
|
||||
Username: c.Username(),
|
||||
Password: string(c.Password()),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("unsupported credential %T", c))
|
||||
}
|
||||
|
||||
data, err := proto.Marshal(workerCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("marshalling dynamic secret to proto"))
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func dynamicToSessionCredential(ctx context.Context, cred credential.Dynamic) (*pb.SessionCredential, error) {
|
||||
const op = "targets.dynamicToSessionCredential"
|
||||
l := cred.Library()
|
||||
secret := cred.Secret()
|
||||
// TODO: Access the json directly from the vault response instead of re-marshalling it.
|
||||
jSecret, err := json.Marshal(secret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("marshalling secret to json"))
|
||||
}
|
||||
var sSecret *structpb.Struct
|
||||
switch secret.(type) {
|
||||
case map[string]interface{}:
|
||||
// In this case we actually have to re-decode it. The proto wrappers
|
||||
// choke on json.Number and at the time I'm writing this I don't
|
||||
// have time to write a walk function to dig through with reflect
|
||||
// and find all json.Numbers and replace them. So we eat the
|
||||
// inefficiency. So note that we are specifically _not_ using a
|
||||
// decoder with UseNumber here.
|
||||
var dSecret map[string]interface{}
|
||||
if err := json.Unmarshal(jSecret, &dSecret); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("decoding json for proto marshaling"))
|
||||
}
|
||||
sSecret, err = structpb.NewStruct(dSecret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("creating proto struct for secret"))
|
||||
}
|
||||
}
|
||||
|
||||
var credType string
|
||||
var credData *structpb.Struct
|
||||
if l.CredentialType() != credential.UnspecifiedType {
|
||||
credType = string(l.CredentialType())
|
||||
|
||||
switch c := cred.(type) {
|
||||
case credential.UsernamePassword:
|
||||
credData, err = handlers.ProtoToStruct(
|
||||
&pb.UserPasswordCredential{
|
||||
Username: c.Username(),
|
||||
Password: string(c.Password()),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("creating proto struct for credential"))
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("unsupported credential %T", c))
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.SessionCredential{
|
||||
CredentialSource: &pb.CredentialSource{
|
||||
Id: l.GetPublicId(),
|
||||
Name: l.GetName(),
|
||||
Description: l.GetDescription(),
|
||||
CredentialStoreId: l.GetStoreId(),
|
||||
Type: subtypes.SubtypeFromId(credentialDomain, l.GetPublicId()).String(),
|
||||
CredentialType: credType,
|
||||
},
|
||||
Secret: &pb.SessionSecret{
|
||||
Raw: base64.StdEncoding.EncodeToString(jSecret),
|
||||
Decoded: sSecret,
|
||||
},
|
||||
Credential: credData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// staticToWorkerCredential converts the credential.Static into
|
||||
// a session.Credential suitable for passing to a Boundary worker.
|
||||
func staticToWorkerCredential(ctx context.Context, cred credential.Static) (session.Credential, error) {
|
||||
const op = "targets.staticToWorkerCredential"
|
||||
var workerCred *serverpb.Credential
|
||||
switch c := cred.(type) {
|
||||
case credstatic.UsernamePasswordCredential:
|
||||
workerCred = &serverpb.Credential{
|
||||
Credential: &serverpb.Credential_UserPassword{
|
||||
UserPassword: &serverpb.UserPassword{
|
||||
Username: c.GetUsername(),
|
||||
Password: string(c.GetPassword()),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("unsupported credential %T", c))
|
||||
}
|
||||
|
||||
data, err := proto.Marshal(workerCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("marshalling dynamic secret to proto"))
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func staticToSessionCredential(ctx context.Context, cred credential.Static) (*pb.SessionCredential, error) {
|
||||
const op = "targets.staticToSessionCredential"
|
||||
|
||||
var credType string
|
||||
var credData *structpb.Struct
|
||||
var secret map[string]interface{}
|
||||
switch c := cred.(type) {
|
||||
case *credstatic.UsernamePasswordCredential:
|
||||
var err error
|
||||
credType = string(credential.UsernamePasswordType)
|
||||
credData, err = handlers.ProtoToStruct(
|
||||
&pb.UserPasswordCredential{
|
||||
Username: c.GetUsername(),
|
||||
Password: string(c.GetPassword()),
|
||||
},
|
||||
)
|
||||
secret = map[string]interface{}{
|
||||
"username": c.GetUsername(),
|
||||
"password": string(c.GetPassword()),
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("creating proto struct for static credential"))
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("unsupported credential %T", c))
|
||||
}
|
||||
|
||||
jSecret, err := json.Marshal(secret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("marshalling static secret to json"))
|
||||
}
|
||||
sSecret, err := structpb.NewStruct(secret)
|
||||
|
||||
return &pb.SessionCredential{
|
||||
CredentialSource: &pb.CredentialSource{
|
||||
Id: cred.GetPublicId(),
|
||||
Name: cred.GetName(),
|
||||
Description: cred.GetDescription(),
|
||||
CredentialStoreId: cred.GetStoreId(),
|
||||
Type: credstatic.Subtype.String(),
|
||||
CredentialType: credType,
|
||||
},
|
||||
Secret: &pb.SessionSecret{
|
||||
Raw: base64.StdEncoding.EncodeToString(jSecret),
|
||||
Decoded: sSecret,
|
||||
},
|
||||
Credential: credData,
|
||||
}, nil
|
||||
}
|
||||
@@ -17,9 +17,15 @@ type Attributes interface {
|
||||
|
||||
// Options create target.Options to be used to create a target.Target.
|
||||
Options() []target.Option
|
||||
|
||||
// Vet validates the Attributes and returns a map of fields to error messages
|
||||
// if any fields are invalid.
|
||||
Vet() map[string]string
|
||||
|
||||
// VetForUpdate validates the Attributes for an updated resource with the
|
||||
// provided mask paths and returns a map of fields to error messages if any
|
||||
// fields are invalid.
|
||||
VetForUpdate([]string) map[string]string
|
||||
}
|
||||
|
||||
type attributeFunc func(interface{}) Attributes
|
||||
|
||||
@@ -2,16 +2,17 @@ package targets
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
stderrors "errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/globals"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
credstatic "github.com/hashicorp/boundary/internal/credential/static"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/common"
|
||||
@@ -20,7 +21,6 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/db/timestamp"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
serverpb "github.com/hashicorp/boundary/internal/gen/controller/servers/services"
|
||||
"github.com/hashicorp/boundary/internal/host"
|
||||
"github.com/hashicorp/boundary/internal/host/plugin"
|
||||
"github.com/hashicorp/boundary/internal/host/static"
|
||||
@@ -41,14 +41,14 @@ import (
|
||||
"github.com/mr-tron/base58"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
const (
|
||||
credentialDomain = "credential"
|
||||
hostDomain = "host"
|
||||
credentialDomain = "credential"
|
||||
hostDomain = "host"
|
||||
missingPortErrStr = "missing port in address"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -65,9 +65,6 @@ var (
|
||||
action.AddHostSources,
|
||||
action.SetHostSources,
|
||||
action.RemoveHostSources,
|
||||
action.AddCredentialLibraries,
|
||||
action.SetCredentialLibraries,
|
||||
action.RemoveCredentialLibraries,
|
||||
action.AddCredentialSources,
|
||||
action.SetCredentialSources,
|
||||
action.RemoveCredentialSources,
|
||||
@@ -93,6 +90,7 @@ type Service struct {
|
||||
pluginHostRepoFn common.PluginHostRepoFactory
|
||||
staticHostRepoFn common.StaticRepoFactory
|
||||
vaultCredRepoFn common.VaultCredentialRepoFactory
|
||||
staticCredRepoFn common.StaticCredentialRepoFactory
|
||||
kmsCache *kms.Kms
|
||||
}
|
||||
|
||||
@@ -107,6 +105,7 @@ func NewService(
|
||||
pluginHostRepoFn common.PluginHostRepoFactory,
|
||||
staticHostRepoFn common.StaticRepoFactory,
|
||||
vaultCredRepoFn common.VaultCredentialRepoFactory,
|
||||
staticCredRepoFn common.StaticCredentialRepoFactory,
|
||||
) (Service, error) {
|
||||
const op = "targets.NewService"
|
||||
if repoFn == nil {
|
||||
@@ -130,6 +129,9 @@ func NewService(
|
||||
if vaultCredRepoFn == nil {
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing vault credential repository")
|
||||
}
|
||||
if staticCredRepoFn == nil {
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing static credential repository")
|
||||
}
|
||||
return Service{
|
||||
repoFn: repoFn,
|
||||
iamRepoFn: iamRepoFn,
|
||||
@@ -138,6 +140,7 @@ func NewService(
|
||||
pluginHostRepoFn: pluginHostRepoFn,
|
||||
staticHostRepoFn: staticHostRepoFn,
|
||||
vaultCredRepoFn: vaultCredRepoFn,
|
||||
staticCredRepoFn: staticCredRepoFn,
|
||||
kmsCache: kmsCache,
|
||||
}, nil
|
||||
}
|
||||
@@ -486,7 +489,7 @@ func (s Service) AddTargetHostSources(ctx context.Context, req *pbs.AddTargetHos
|
||||
if err := validateAddHostSourcesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.AddHostSets)
|
||||
authResults := s.authResult(ctx, req.GetId(), action.AddHostSources)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
@@ -524,7 +527,7 @@ func (s Service) SetTargetHostSources(ctx context.Context, req *pbs.SetTargetHos
|
||||
if err := validateSetHostSourcesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.SetHostSets)
|
||||
authResults := s.authResult(ctx, req.GetId(), action.SetHostSources)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
@@ -557,12 +560,12 @@ func (s Service) SetTargetHostSources(ctx context.Context, req *pbs.SetTargetHos
|
||||
|
||||
// RemoveTargetHostSources implements the interface pbs.TargetServiceServer.
|
||||
func (s Service) RemoveTargetHostSources(ctx context.Context, req *pbs.RemoveTargetHostSourcesRequest) (*pbs.RemoveTargetHostSourcesResponse, error) {
|
||||
const op = "targets.(Service).RemoveTargetHostSets"
|
||||
const op = "targets.(Service).RemoveTargetHostSources"
|
||||
|
||||
if err := validateRemoveHostSourcesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.RemoveHostSets)
|
||||
authResults := s.authResult(ctx, req.GetId(), action.RemoveHostSources)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
@@ -593,120 +596,6 @@ func (s Service) RemoveTargetHostSources(ctx context.Context, req *pbs.RemoveTar
|
||||
return &pbs.RemoveTargetHostSourcesResponse{Item: item}, nil
|
||||
}
|
||||
|
||||
// DEPRECATED: AddTargetCredentialLibraries implements the interface pbs.TargetServiceServer.
|
||||
func (s Service) AddTargetCredentialLibraries(ctx context.Context, req *pbs.AddTargetCredentialLibrariesRequest) (*pbs.AddTargetCredentialLibrariesResponse, error) {
|
||||
const op = "targets.(Service).AddTargetCredentialLibraries"
|
||||
|
||||
if err := validateAddLibrariesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.AddCredentialLibraries)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
t, ts, cl, err := s.addCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), nil, req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outputFields, ok := requests.OutputFields(ctx)
|
||||
if !ok {
|
||||
return nil, errors.New(ctx, errors.Internal, op, "no request context found")
|
||||
}
|
||||
|
||||
outputOpts := make([]handlers.Option, 0, 3)
|
||||
outputOpts = append(outputOpts, handlers.WithOutputFields(&outputFields))
|
||||
if outputFields.Has(globals.ScopeField) {
|
||||
outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedActionsField) {
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, t.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
|
||||
item, err := toProto(ctx, t, ts, cl, outputOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pbs.AddTargetCredentialLibrariesResponse{Item: item}, nil
|
||||
}
|
||||
|
||||
// DEPRECATED: SetTargetCredentialLibraries implements the interface pbs.TargetServiceServer.
|
||||
func (s Service) SetTargetCredentialLibraries(ctx context.Context, req *pbs.SetTargetCredentialLibrariesRequest) (*pbs.SetTargetCredentialLibrariesResponse, error) {
|
||||
const op = "targets.(Service).SetTargetCredentialLibraries"
|
||||
|
||||
if err := validateSetLibrariesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.SetCredentialLibraries)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
t, ts, cl, err := s.setCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), nil, req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outputFields, ok := requests.OutputFields(ctx)
|
||||
if !ok {
|
||||
return nil, errors.New(ctx, errors.Internal, op, "no request context found")
|
||||
}
|
||||
|
||||
outputOpts := make([]handlers.Option, 0, 3)
|
||||
outputOpts = append(outputOpts, handlers.WithOutputFields(&outputFields))
|
||||
if outputFields.Has(globals.ScopeField) {
|
||||
outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedActionsField) {
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, t.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
|
||||
item, err := toProto(ctx, t, ts, cl, outputOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pbs.SetTargetCredentialLibrariesResponse{Item: item}, nil
|
||||
}
|
||||
|
||||
// DEPRECATED: RemoveTargetCredentialLibraries implements the interface pbs.TargetServiceServer.
|
||||
func (s Service) RemoveTargetCredentialLibraries(ctx context.Context, req *pbs.RemoveTargetCredentialLibrariesRequest) (*pbs.RemoveTargetCredentialLibrariesResponse, error) {
|
||||
const op = "targets.(Service).RemoveTargetCredentialLibraries"
|
||||
|
||||
if err := validateRemoveLibrariesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.RemoveCredentialLibraries)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
t, ts, cl, err := s.removeCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), nil, req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outputFields, ok := requests.OutputFields(ctx)
|
||||
if !ok {
|
||||
return nil, errors.New(ctx, errors.Internal, op, "no request context found")
|
||||
}
|
||||
|
||||
outputOpts := make([]handlers.Option, 0, 3)
|
||||
outputOpts = append(outputOpts, handlers.WithOutputFields(&outputFields))
|
||||
if outputFields.Has(globals.ScopeField) {
|
||||
outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedActionsField) {
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, t.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
|
||||
item, err := toProto(ctx, t, ts, cl, outputOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pbs.RemoveTargetCredentialLibrariesResponse{Item: item}, nil
|
||||
}
|
||||
|
||||
// AddTargetCredentialSources implements the interface pbs.TargetServiceServer.
|
||||
func (s Service) AddTargetCredentialSources(ctx context.Context, req *pbs.AddTargetCredentialSourcesRequest) (*pbs.AddTargetCredentialSourcesResponse, error) {
|
||||
const op = "targets.(Service).AddTargetCredentialSources"
|
||||
@@ -716,7 +605,12 @@ func (s Service) AddTargetCredentialSources(ctx context.Context, req *pbs.AddTar
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.AddCredentialSources)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
// TODO AddCredentialLibraries was deprecated but grant actions were never migrated
|
||||
// remove this check once actions have been migrated
|
||||
authResults = s.authResult(ctx, req.GetId(), action.AddCredentialLibraries)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
}
|
||||
t, ts, cl, err := s.addCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetEgressCredentialSourceIds(), req.GetVersion())
|
||||
if err != nil {
|
||||
@@ -754,7 +648,12 @@ func (s Service) SetTargetCredentialSources(ctx context.Context, req *pbs.SetTar
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.SetCredentialSources)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
// TODO SetCredentialLibraries was deprecated but grant actions were never migrated
|
||||
// remove this check once actions have been migrated
|
||||
authResults = s.authResult(ctx, req.GetId(), action.SetCredentialLibraries)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
}
|
||||
t, ts, cl, err := s.setCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetEgressCredentialSourceIds(), req.GetVersion())
|
||||
if err != nil {
|
||||
@@ -792,7 +691,12 @@ func (s Service) RemoveTargetCredentialSources(ctx context.Context, req *pbs.Rem
|
||||
}
|
||||
authResults := s.authResult(ctx, req.GetId(), action.RemoveCredentialSources)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
// TODO RemoveCredentialLibraries was deprecated but grant actions were never migrated
|
||||
// remove this check once actions have been migrated
|
||||
authResults = s.authResult(ctx, req.GetId(), action.RemoveCredentialLibraries)
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
}
|
||||
t, ts, cl, err := s.removeCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetEgressCredentialSourceIds(), req.GetVersion())
|
||||
if err != nil {
|
||||
@@ -869,7 +773,7 @@ func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSession
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t, hostSources, libs, err := repo.LookupTarget(ctx, t.GetPublicId())
|
||||
t, hostSources, credSources, err := repo.LookupTarget(ctx, t.GetPublicId())
|
||||
if err != nil {
|
||||
if errors.IsNotFoundError(err) {
|
||||
return nil, handlers.NotFoundErrorf("Target %q not found.", t.GetPublicId())
|
||||
@@ -978,25 +882,39 @@ func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSession
|
||||
chosenEndpoint = endpoints[rand.Intn(len(endpoints))]
|
||||
}
|
||||
|
||||
h, p, err := net.SplitHostPort(chosenEndpoint.Address)
|
||||
switch {
|
||||
case err != nil && strings.Contains(err.Error(), missingPortErrStr):
|
||||
if t.GetDefaultPort() == 0 {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("neither the selected host %q nor the target provides a port to use", chosenEndpoint.HostId))
|
||||
}
|
||||
h = chosenEndpoint.Address
|
||||
p = strconv.FormatUint(uint64(t.GetDefaultPort()), 10)
|
||||
case err != nil:
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error when parsing the chosen endpoints host address"))
|
||||
}
|
||||
// Generate the endpoint URL
|
||||
endpointUrl := &url.URL{
|
||||
Scheme: t.GetType().String(),
|
||||
}
|
||||
defaultPort := t.GetDefaultPort()
|
||||
if defaultPort != 0 {
|
||||
endpointUrl.Host = fmt.Sprintf("%s:%d", chosenEndpoint.Address, defaultPort)
|
||||
} else {
|
||||
endpointUrl.Host = chosenEndpoint.Address
|
||||
Host: net.JoinHostPort(h, p),
|
||||
}
|
||||
|
||||
var reqs []credential.Request
|
||||
var vaultReqs []credential.Request
|
||||
var staticIds []string
|
||||
var dynCreds []*session.DynamicCredential
|
||||
for _, l := range libs {
|
||||
reqs = append(reqs, credential.Request{
|
||||
SourceId: l.Id(),
|
||||
Purpose: l.CredentialPurpose(),
|
||||
})
|
||||
dynCreds = append(dynCreds, session.NewDynamicCredential(l.Id(), l.CredentialPurpose()))
|
||||
var staticCreds []*session.StaticCredential
|
||||
for _, cs := range credSources {
|
||||
switch cs.Type() {
|
||||
case target.LibraryCredentialSourceType:
|
||||
vaultReqs = append(vaultReqs, credential.Request{
|
||||
SourceId: cs.Id(),
|
||||
Purpose: cs.CredentialPurpose(),
|
||||
})
|
||||
dynCreds = append(dynCreds, session.NewDynamicCredential(cs.Id(), cs.CredentialPurpose()))
|
||||
case target.StaticCredentialSourceType:
|
||||
staticIds = append(staticIds, cs.Id())
|
||||
staticCreds = append(staticCreds, session.NewStaticCredential(cs.Id(), cs.CredentialPurpose()))
|
||||
}
|
||||
}
|
||||
|
||||
expTime := timestamppb.Now()
|
||||
@@ -1013,6 +931,7 @@ func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSession
|
||||
ConnectionLimit: t.GetSessionConnectionLimit(),
|
||||
WorkerFilter: t.GetWorkerFilter(),
|
||||
DynamicCredentials: dynCreds,
|
||||
StaticCredentials: staticCreds,
|
||||
}
|
||||
|
||||
sess, err := session.New(sessionComposition)
|
||||
@@ -1028,111 +947,82 @@ func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSession
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var cs []credential.Dynamic
|
||||
if len(reqs) > 0 {
|
||||
var dynamic []credential.Dynamic
|
||||
var staticCredsById map[string]credential.Static
|
||||
if len(vaultReqs) > 0 {
|
||||
credRepo, err := s.vaultCredRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
cs, err = credRepo.Issue(ctx, sess.GetPublicId(), reqs)
|
||||
dynamic, err = credRepo.Issue(ctx, sess.GetPublicId(), vaultReqs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
}
|
||||
|
||||
if len(staticIds) > 0 {
|
||||
credRepo, err := s.staticCredRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
// Remove duplicate requests
|
||||
staticIds = strutil.RemoveDuplicates(staticIds, false)
|
||||
creds, err := credRepo.Retrieve(ctx, t.GetScopeId(), staticIds)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
staticCredsById = make(map[string]credential.Static)
|
||||
for _, c := range creds {
|
||||
staticCredsById[c.GetPublicId()] = c
|
||||
}
|
||||
}
|
||||
|
||||
var creds []*pb.SessionCredential
|
||||
var workerCreds []session.Credential
|
||||
for _, cred := range cs {
|
||||
for _, cred := range dynamic {
|
||||
switch cred.Purpose() {
|
||||
case credential.EgressPurpose:
|
||||
m, err := credentialToProto(ctx, cred)
|
||||
c, err := dynamicToWorkerCredential(ctx, cred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
data, err := proto.Marshal(m)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("marshalling secret to proto"))
|
||||
}
|
||||
workerCreds = append(workerCreds, data)
|
||||
workerCreds = append(workerCreds, c)
|
||||
|
||||
case credential.ApplicationPurpose:
|
||||
l := cred.Library()
|
||||
secret := cred.Secret()
|
||||
// TODO: Access the json directly from the vault response instead of re-marshalling it.
|
||||
jSecret, err := json.Marshal(secret)
|
||||
c, err := dynamicToSessionCredential(ctx, cred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("marshalling secret to json"))
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
var sSecret *structpb.Struct
|
||||
switch secret.(type) {
|
||||
case map[string]interface{}:
|
||||
// In this case we actually have to re-decode it. The proto wrappers
|
||||
// choke on json.Number and at the time I'm writing this I don't
|
||||
// have time to write a walk function to dig through with reflect
|
||||
// and find all json.Numbers and replace them. So we eat the
|
||||
// inefficiency. So note that we are specifically _not_ using a
|
||||
// decoder with UseNumber here.
|
||||
var dSecret map[string]interface{}
|
||||
if err := json.Unmarshal(jSecret, &dSecret); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("decoding json for proto marshaling"))
|
||||
}
|
||||
sSecret, err = structpb.NewStruct(dSecret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("creating proto struct for secret"))
|
||||
}
|
||||
}
|
||||
|
||||
var credType string
|
||||
var credData *structpb.Struct
|
||||
if l.CredentialType() != credential.UnspecifiedType {
|
||||
credType = string(l.CredentialType())
|
||||
|
||||
switch c := cred.(type) {
|
||||
case credential.UserPassword:
|
||||
credData, err = handlers.ProtoToStruct(
|
||||
&pb.UserPasswordCredential{
|
||||
Username: c.Username(),
|
||||
Password: string(c.Password()),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("creating proto struct for credential"))
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unsupported credential type"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
creds = append(creds, &pb.SessionCredential{
|
||||
CredentialLibrary: &pb.CredentialLibrary{
|
||||
Id: l.GetPublicId(),
|
||||
Name: l.GetName(),
|
||||
Description: l.GetDescription(),
|
||||
CredentialStoreId: l.GetStoreId(),
|
||||
Type: subtypes.SubtypeFromId(credentialDomain, l.GetPublicId()).String(),
|
||||
},
|
||||
CredentialSource: &pb.CredentialSource{
|
||||
Id: l.GetPublicId(),
|
||||
Name: l.GetName(),
|
||||
Description: l.GetDescription(),
|
||||
CredentialStoreId: l.GetStoreId(),
|
||||
Type: subtypes.SubtypeFromId(credentialDomain, l.GetPublicId()).String(),
|
||||
CredentialType: credType,
|
||||
},
|
||||
Secret: &pb.SessionSecret{
|
||||
Raw: base64.StdEncoding.EncodeToString(jSecret),
|
||||
Decoded: sSecret,
|
||||
},
|
||||
Credential: credData,
|
||||
})
|
||||
creds = append(creds, c)
|
||||
|
||||
default:
|
||||
return nil, errors.New(ctx, errors.Unknown, op, fmt.Sprintf("unsupported credential purpose %s", cred.Purpose()))
|
||||
}
|
||||
}
|
||||
|
||||
for _, sc := range staticCreds {
|
||||
switch sc.CredentialPurpose {
|
||||
case string(credential.EgressPurpose):
|
||||
c, err := staticToWorkerCredential(ctx, staticCredsById[sc.CredentialStaticId])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
workerCreds = append(workerCreds, c)
|
||||
|
||||
case string(credential.ApplicationPurpose):
|
||||
c, err := staticToSessionCredential(ctx, staticCredsById[sc.CredentialStaticId])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
creds = append(creds, c)
|
||||
|
||||
default:
|
||||
return nil, errors.New(ctx, errors.Unknown, op, fmt.Sprintf("unsupported credential purpose %s", sc.CredentialPurpose))
|
||||
}
|
||||
}
|
||||
|
||||
if len(workerCreds) > 0 {
|
||||
// store credentials in repo, worker will request creds when a connection is established
|
||||
err = sessionRepo.AddSessionCredentials(ctx, sess.ScopeId, sess.PublicId, workerCreds)
|
||||
@@ -1166,7 +1056,7 @@ func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSession
|
||||
Scope: authResults.Scope,
|
||||
CreatedTime: sess.CreateTime.GetTimestamp(),
|
||||
Type: t.GetType().String(),
|
||||
AuthorizationToken: string(encodedMarshaledSad),
|
||||
AuthorizationToken: encodedMarshaledSad,
|
||||
UserId: authResults.UserId,
|
||||
HostId: chosenEndpoint.HostId,
|
||||
HostSetId: chosenEndpoint.SetId,
|
||||
@@ -1267,7 +1157,9 @@ func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []st
|
||||
if err != nil {
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to build target for update: %v.", err)
|
||||
}
|
||||
u.SetPublicId(ctx, id)
|
||||
if err := u.SetPublicId(ctx, id); err != nil {
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set target id: %v.", err)
|
||||
}
|
||||
|
||||
maskManager, err := subtypeRegistry.maskManager(subtype)
|
||||
if err != nil {
|
||||
@@ -1384,12 +1276,16 @@ func (s Service) addCredentialSourcesInRepo(ctx context.Context, targetId string
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
credLibs, err := createCredLibs(targetId, applicationIds, nil, egressIds)
|
||||
if err != nil {
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
|
||||
|
||||
var creds target.CredentialSources
|
||||
if len(applicationIds) > 0 {
|
||||
creds.ApplicationCredentialIds = strutil.RemoveDuplicates(applicationIds, false)
|
||||
}
|
||||
if len(egressIds) > 0 {
|
||||
creds.EgressCredentialIds = strutil.RemoveDuplicates(egressIds, false)
|
||||
}
|
||||
|
||||
out, hs, credSources, err := repo.AddTargetCredentialSources(ctx, targetId, version, credLibs)
|
||||
out, hs, credSources, err := repo.AddTargetCredentialSources(ctx, targetId, version, creds)
|
||||
if err != nil {
|
||||
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to add credential sources to target: %v.", err)
|
||||
@@ -1407,12 +1303,15 @@ func (s Service) setCredentialSourcesInRepo(ctx context.Context, targetId string
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
credLibs, err := createCredLibs(targetId, applicationIds, nil, egressIds)
|
||||
if err != nil {
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
|
||||
var ids target.CredentialSources
|
||||
if len(applicationIds) > 0 {
|
||||
ids.ApplicationCredentialIds = strutil.RemoveDuplicates(applicationIds, false)
|
||||
}
|
||||
if len(egressIds) > 0 {
|
||||
ids.EgressCredentialIds = strutil.RemoveDuplicates(egressIds, false)
|
||||
}
|
||||
|
||||
_, _, _, err = repo.SetTargetCredentialSources(ctx, targetId, version, credLibs)
|
||||
_, _, _, err = repo.SetTargetCredentialSources(ctx, targetId, version, ids)
|
||||
if err != nil {
|
||||
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
|
||||
@@ -1435,11 +1334,14 @@ func (s Service) removeCredentialSourcesInRepo(ctx context.Context, targetId str
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
credLibs, err := createCredLibs(targetId, applicationIds, nil, egressIds)
|
||||
if err != nil {
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
|
||||
var ids target.CredentialSources
|
||||
if len(applicationIds) > 0 {
|
||||
ids.ApplicationCredentialIds = strutil.RemoveDuplicates(applicationIds, false)
|
||||
}
|
||||
_, err = repo.DeleteTargetCredentialSources(ctx, targetId, version, credLibs)
|
||||
if len(egressIds) > 0 {
|
||||
ids.EgressCredentialIds = strutil.RemoveDuplicates(egressIds, false)
|
||||
}
|
||||
_, err = repo.DeleteTargetCredentialSources(ctx, targetId, version, ids)
|
||||
if err != nil {
|
||||
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to remove credential sources from target: %v.", err)
|
||||
@@ -1584,7 +1486,6 @@ func toProto(ctx context.Context, in target.Target, hostSources []target.HostSou
|
||||
|
||||
var appCredSources, egressCredSources []*pb.CredentialSource
|
||||
var appCredSourceIds, egressCredSourceIds []string
|
||||
var appCredLibraries []*pb.CredentialLibrary
|
||||
|
||||
for _, cs := range credSources {
|
||||
switch cs.CredentialPurpose() {
|
||||
@@ -1595,13 +1496,6 @@ func toProto(ctx context.Context, in target.Target, hostSources []target.HostSou
|
||||
CredentialStoreId: cs.CredentialStoreId(),
|
||||
})
|
||||
|
||||
// ApplicationCredentialLibrariesField is deprecated and should only be populated
|
||||
// for application purpose
|
||||
appCredLibraries = append(appCredLibraries, &pb.CredentialLibrary{
|
||||
Id: cs.Id(),
|
||||
CredentialStoreId: cs.CredentialStoreId(),
|
||||
})
|
||||
|
||||
case credential.EgressPurpose:
|
||||
egressCredSources = append(egressCredSources, &pb.CredentialSource{
|
||||
Id: cs.Id(),
|
||||
@@ -1614,15 +1508,9 @@ func toProto(ctx context.Context, in target.Target, hostSources []target.HostSou
|
||||
}
|
||||
}
|
||||
|
||||
if outputFields.Has(globals.ApplicationCredentialLibraryIdsField) {
|
||||
out.ApplicationCredentialLibraryIds = appCredSourceIds
|
||||
}
|
||||
if outputFields.Has(globals.ApplicationCredentialSourceIdsField) {
|
||||
out.ApplicationCredentialSourceIds = appCredSourceIds
|
||||
}
|
||||
if outputFields.Has(globals.ApplicationCredentialLibrariesField) {
|
||||
out.ApplicationCredentialLibraries = appCredLibraries
|
||||
}
|
||||
if outputFields.Has(globals.ApplicationCredentialSourcesField) {
|
||||
out.ApplicationCredentialSources = appCredSources
|
||||
}
|
||||
@@ -1702,7 +1590,8 @@ func validateCreateRequest(req *pbs.CreateTargetRequest) error {
|
||||
func validateUpdateRequest(req *pbs.UpdateTargetRequest) error {
|
||||
return handlers.ValidateUpdateRequest(req, req.GetItem(), func() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if handlers.MaskContains(req.GetUpdateMask().GetPaths(), globals.NameField) && req.GetItem().GetName().GetValue() == "" {
|
||||
paths := req.GetUpdateMask().GetPaths()
|
||||
if handlers.MaskContains(paths, globals.NameField) && req.GetItem().GetName().GetValue() == "" {
|
||||
badFields[globals.NameField] = "This field cannot be set to empty."
|
||||
}
|
||||
if req.GetItem().GetSessionConnectionLimit() != nil {
|
||||
@@ -1735,7 +1624,7 @@ func validateUpdateRequest(req *pbs.UpdateTargetRequest) error {
|
||||
if err != nil {
|
||||
badFields[globals.AttributesField] = "Attribute fields do not match the expected format."
|
||||
} else {
|
||||
for k, v := range a.Vet() {
|
||||
for k, v := range a.VetForUpdate(paths) {
|
||||
badFields[k] = v
|
||||
}
|
||||
}
|
||||
@@ -1901,72 +1790,6 @@ func validateRemoveHostSourcesRequest(req *pbs.RemoveTargetHostSourcesRequest) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAddLibrariesRequest(req *pbs.AddTargetCredentialLibrariesRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) {
|
||||
badFields[globals.IdField] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
badFields[globals.VersionField] = "Required field."
|
||||
}
|
||||
if len(req.GetApplicationCredentialLibraryIds()) == 0 {
|
||||
badFields[globals.ApplicationCredentialLibraryIdsField] = "Must be non-empty."
|
||||
}
|
||||
for _, cl := range req.GetApplicationCredentialLibraryIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
badFields[globals.ApplicationCredentialLibraryIdsField] = fmt.Sprintf("Incorrectly formatted credential library identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateSetLibrariesRequest(req *pbs.SetTargetCredentialLibrariesRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) {
|
||||
badFields[globals.IdField] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
badFields[globals.VersionField] = "Required field."
|
||||
}
|
||||
for _, cl := range req.GetApplicationCredentialLibraryIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
badFields[globals.ApplicationCredentialLibraryIdsField] = fmt.Sprintf("Incorrectly formatted credential library identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateRemoveLibrariesRequest(req *pbs.RemoveTargetCredentialLibrariesRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) {
|
||||
badFields[globals.IdField] = "Incorrectly formatted identifier."
|
||||
}
|
||||
if req.GetVersion() == 0 {
|
||||
badFields[globals.VersionField] = "Required field."
|
||||
}
|
||||
if len(req.GetApplicationCredentialLibraryIds()) == 0 {
|
||||
badFields[globals.ApplicationCredentialLibraryIdsField] = "Must be non-empty."
|
||||
}
|
||||
for _, cl := range req.GetApplicationCredentialLibraryIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
badFields[globals.ApplicationCredentialLibraryIdsField] = fmt.Sprintf("Incorrectly formatted credential library identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequest) error {
|
||||
badFields := map[string]string{}
|
||||
if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) {
|
||||
@@ -1980,13 +1803,13 @@ func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequ
|
||||
badFields[globals.EgressCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided."
|
||||
}
|
||||
for _, cl := range req.GetApplicationCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) {
|
||||
badFields[globals.ApplicationCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, cl := range req.GetEgressCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) {
|
||||
badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
@@ -2006,13 +1829,13 @@ func validateSetCredentialSourcesRequest(req *pbs.SetTargetCredentialSourcesRequ
|
||||
badFields[globals.VersionField] = "Required field."
|
||||
}
|
||||
for _, cl := range req.GetApplicationCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) {
|
||||
badFields[globals.ApplicationCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, cl := range req.GetEgressCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) {
|
||||
badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
@@ -2036,13 +1859,13 @@ func validateRemoveCredentialSourcesRequest(req *pbs.RemoveTargetCredentialSourc
|
||||
badFields[globals.EgressCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided."
|
||||
}
|
||||
for _, cl := range req.GetApplicationCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) {
|
||||
badFields[globals.ApplicationCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, cl := range req.GetEgressCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix, credstatic.CredentialPrefix) {
|
||||
badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
@@ -2094,45 +1917,6 @@ func validateAuthorizeSessionRequest(req *pbs.AuthorizeSessionRequest) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func createCredLibs(targetId string, applicationIds, ingressIds, egressIds []string) ([]*target.CredentialLibrary, error) {
|
||||
credLibs := make([]*target.CredentialLibrary, 0, len(applicationIds)+len(ingressIds)+len(egressIds))
|
||||
|
||||
byPurpose := map[credential.Purpose][]string{
|
||||
credential.ApplicationPurpose: strutil.RemoveDuplicates(applicationIds, false),
|
||||
credential.IngressPurpose: strutil.RemoveDuplicates(ingressIds, false),
|
||||
credential.EgressPurpose: strutil.RemoveDuplicates(egressIds, false),
|
||||
}
|
||||
for purpose, ids := range byPurpose {
|
||||
for _, id := range ids {
|
||||
l, err := target.NewCredentialLibrary(targetId, id, purpose)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
credLibs = append(credLibs, l)
|
||||
}
|
||||
}
|
||||
return credLibs, nil
|
||||
}
|
||||
|
||||
// credentialToProto converts the strongly typed credential.Credential into a known proto.Message.
|
||||
func credentialToProto(ctx context.Context, cred credential.Credential) (*serverpb.Credential, error) {
|
||||
const op = "targets.credentialToProto"
|
||||
switch c := cred.(type) {
|
||||
case credential.UserPassword:
|
||||
return &serverpb.Credential{
|
||||
Credential: &serverpb.Credential_UserPassword{
|
||||
UserPassword: &serverpb.UserPassword{
|
||||
Username: c.Username(),
|
||||
Password: string(c.Password()),
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
|
||||
default:
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("unsupported credential %T", c))
|
||||
}
|
||||
}
|
||||
|
||||
// workerList is a helper type to make the selection of workers clearer and more declarative.
|
||||
type workerList []*servers.Worker
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -10,6 +10,8 @@ import (
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets"
|
||||
)
|
||||
|
||||
const defaultPortField = "attributes.default_port"
|
||||
|
||||
type attribute struct {
|
||||
*pb.TcpTargetAttributes
|
||||
}
|
||||
@@ -24,8 +26,23 @@ func (a *attribute) Options() []target.Option {
|
||||
|
||||
func (a *attribute) Vet() map[string]string {
|
||||
badFields := map[string]string{}
|
||||
if a.GetDefaultPort() != nil && a.GetDefaultPort().GetValue() == 0 {
|
||||
badFields["attributes.default_port"] = "This optional field cannot be set to 0."
|
||||
if a.GetDefaultPort() == nil {
|
||||
badFields["attributes.default_port"] = "This field is required."
|
||||
} else if a.GetDefaultPort().GetValue() == 0 {
|
||||
badFields["attributes.default_port"] = "This field cannot be set to zero."
|
||||
}
|
||||
return badFields
|
||||
}
|
||||
|
||||
func (a *attribute) VetForUpdate(p []string) map[string]string {
|
||||
if !handlers.MaskContains(p, defaultPortField) {
|
||||
return nil
|
||||
}
|
||||
badFields := map[string]string{}
|
||||
if a.GetDefaultPort() == nil {
|
||||
badFields["attributes.default_port"] = "This field is required."
|
||||
} else if a.GetDefaultPort().GetValue() == 0 {
|
||||
badFields["attributes.default_port"] = "This cannot be set to zero."
|
||||
}
|
||||
return badFields
|
||||
}
|
||||
|
||||
@@ -75,17 +75,18 @@ func TestGet(t *testing.T) {
|
||||
copy(kmsAuthzActions, testAuthorizedActions)
|
||||
|
||||
wantKmsWorker := &pb.Worker{
|
||||
Id: kmsWorker.GetPublicId(),
|
||||
ScopeId: kmsWorker.GetScopeId(),
|
||||
Scope: &scopes.ScopeInfo{Id: kmsWorker.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"},
|
||||
CreatedTime: kmsWorker.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: kmsWorker.UpdateTime.GetTimestamp(),
|
||||
Version: kmsWorker.GetVersion(),
|
||||
Name: wrapperspb.String(kmsWorker.GetName()),
|
||||
Description: wrapperspb.String(kmsWorker.GetDescription()),
|
||||
Address: kmsWorker.GetAddress(),
|
||||
AuthorizedActions: strutil.StrListDelete(kmsAuthzActions, action.Update.String()),
|
||||
LastStatusTime: kmsWorker.GetLastStatusTime().GetTimestamp(),
|
||||
Id: kmsWorker.GetPublicId(),
|
||||
ScopeId: kmsWorker.GetScopeId(),
|
||||
Scope: &scopes.ScopeInfo{Id: kmsWorker.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"},
|
||||
CreatedTime: kmsWorker.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: kmsWorker.UpdateTime.GetTimestamp(),
|
||||
Version: kmsWorker.GetVersion(),
|
||||
Name: wrapperspb.String(kmsWorker.GetName()),
|
||||
Description: wrapperspb.String(kmsWorker.GetDescription()),
|
||||
Address: kmsWorker.GetAddress(),
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
AuthorizedActions: strutil.StrListDelete(kmsAuthzActions, action.Update.String()),
|
||||
LastStatusTime: kmsWorker.GetLastStatusTime().GetTimestamp(),
|
||||
CanonicalTags: map[string]*structpb.ListValue{
|
||||
"key": structListValue(t, "val"),
|
||||
},
|
||||
@@ -114,17 +115,18 @@ func TestGet(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
wantPkiWorker := &pb.Worker{
|
||||
Id: pkiWorker.GetPublicId(),
|
||||
ScopeId: pkiWorker.GetScopeId(),
|
||||
Scope: &scopes.ScopeInfo{Id: pkiWorker.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"},
|
||||
CreatedTime: pkiWorker.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: pkiWorker.UpdateTime.GetTimestamp(),
|
||||
Version: pkiWorker.GetVersion(),
|
||||
Name: wrapperspb.String(pkiWorker.GetName()),
|
||||
Description: wrapperspb.String(pkiWorker.GetDescription()),
|
||||
Address: pkiWorker.GetAddress(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
LastStatusTime: pkiWorker.GetLastStatusTime().GetTimestamp(),
|
||||
Id: pkiWorker.GetPublicId(),
|
||||
ScopeId: pkiWorker.GetScopeId(),
|
||||
Scope: &scopes.ScopeInfo{Id: pkiWorker.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"},
|
||||
CreatedTime: pkiWorker.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: pkiWorker.UpdateTime.GetTimestamp(),
|
||||
Version: pkiWorker.GetVersion(),
|
||||
Name: wrapperspb.String(pkiWorker.GetName()),
|
||||
Description: wrapperspb.String(pkiWorker.GetDescription()),
|
||||
Address: pkiWorker.GetAddress(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
LastStatusTime: pkiWorker.GetLastStatusTime().GetTimestamp(),
|
||||
CanonicalTags: map[string]*structpb.ListValue{
|
||||
"config": structListValue(t, "test"),
|
||||
},
|
||||
@@ -208,17 +210,18 @@ func TestList(t *testing.T) {
|
||||
kmsAuthzActions := make([]string, len(testAuthorizedActions))
|
||||
copy(kmsAuthzActions, testAuthorizedActions)
|
||||
wantKmsWorkers = append(wantKmsWorkers, &pb.Worker{
|
||||
Id: w.GetPublicId(),
|
||||
ScopeId: w.GetScopeId(),
|
||||
Scope: &scopes.ScopeInfo{Id: w.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"},
|
||||
CreatedTime: w.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: w.UpdateTime.GetTimestamp(),
|
||||
Version: w.GetVersion(),
|
||||
Name: wrapperspb.String(w.GetName()),
|
||||
AuthorizedActions: strutil.StrListDelete(kmsAuthzActions, action.Update.String()),
|
||||
Address: w.GetAddress(),
|
||||
Type: KmsWorkerType,
|
||||
LastStatusTime: w.GetLastStatusTime().GetTimestamp(),
|
||||
Id: w.GetPublicId(),
|
||||
ScopeId: w.GetScopeId(),
|
||||
Scope: &scopes.ScopeInfo{Id: w.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"},
|
||||
CreatedTime: w.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: w.UpdateTime.GetTimestamp(),
|
||||
Version: w.GetVersion(),
|
||||
Name: wrapperspb.String(w.GetName()),
|
||||
AuthorizedActions: strutil.StrListDelete(kmsAuthzActions, action.Update.String()),
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
Address: w.GetAddress(),
|
||||
Type: KmsWorkerType,
|
||||
LastStatusTime: w.GetLastStatusTime().GetTimestamp(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -226,17 +229,18 @@ func TestList(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
w := servers.TestPkiWorker(t, conn, wrap, servers.WithName(fmt.Sprintf("pki-worker%d", i)))
|
||||
wantPkiWorkers = append(wantPkiWorkers, &pb.Worker{
|
||||
Id: w.GetPublicId(),
|
||||
ScopeId: w.GetScopeId(),
|
||||
Scope: &scopes.ScopeInfo{Id: w.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"},
|
||||
CreatedTime: w.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: w.UpdateTime.GetTimestamp(),
|
||||
Version: w.GetVersion(),
|
||||
Name: wrapperspb.String(w.GetName()),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Address: w.GetAddress(),
|
||||
Type: PkiWorkerType,
|
||||
LastStatusTime: w.GetLastStatusTime().GetTimestamp(),
|
||||
Id: w.GetPublicId(),
|
||||
ScopeId: w.GetScopeId(),
|
||||
Scope: &scopes.ScopeInfo{Id: w.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"},
|
||||
CreatedTime: w.CreateTime.GetTimestamp(),
|
||||
UpdatedTime: w.UpdateTime.GetTimestamp(),
|
||||
Version: w.GetVersion(),
|
||||
Name: wrapperspb.String(w.GetName()),
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Address: w.GetAddress(),
|
||||
Type: PkiWorkerType,
|
||||
LastStatusTime: w.GetLastStatusTime().GetTimestamp(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -440,15 +444,16 @@ func TestUpdate(t *testing.T) {
|
||||
},
|
||||
res: &pbs.UpdateWorkerResponse{
|
||||
Item: &pb.Worker{
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Name: wrapperspb.String("name"),
|
||||
Description: wrapperspb.String("desc"),
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Name: wrapperspb.String("name"),
|
||||
Description: wrapperspb.String("desc"),
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -465,15 +470,16 @@ func TestUpdate(t *testing.T) {
|
||||
},
|
||||
res: &pbs.UpdateWorkerResponse{
|
||||
Item: &pb.Worker{
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Name: wrapperspb.String("name"),
|
||||
Description: wrapperspb.String("desc"),
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Name: wrapperspb.String("name"),
|
||||
Description: wrapperspb.String("desc"),
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -533,14 +539,15 @@ func TestUpdate(t *testing.T) {
|
||||
},
|
||||
res: &pbs.UpdateWorkerResponse{
|
||||
Item: &pb.Worker{
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Description: wrapperspb.String("default"),
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Description: wrapperspb.String("default"),
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -556,14 +563,15 @@ func TestUpdate(t *testing.T) {
|
||||
},
|
||||
res: &pbs.UpdateWorkerResponse{
|
||||
Item: &pb.Worker{
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Name: wrapperspb.String("default"),
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Name: wrapperspb.String("default"),
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -580,15 +588,16 @@ func TestUpdate(t *testing.T) {
|
||||
},
|
||||
res: &pbs.UpdateWorkerResponse{
|
||||
Item: &pb.Worker{
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Name: wrapperspb.String("updated"),
|
||||
Description: wrapperspb.String("default"),
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Name: wrapperspb.String("updated"),
|
||||
Description: wrapperspb.String("default"),
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -605,15 +614,16 @@ func TestUpdate(t *testing.T) {
|
||||
},
|
||||
res: &pbs.UpdateWorkerResponse{
|
||||
Item: &pb.Worker{
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Name: wrapperspb.String("default"),
|
||||
Description: wrapperspb.String("notignored"),
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
Id: wkr.GetPublicId(),
|
||||
ScopeId: wkr.GetScopeId(),
|
||||
Scope: expectedScope,
|
||||
Name: wrapperspb.String("default"),
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
Description: wrapperspb.String("notignored"),
|
||||
CreatedTime: wkr.GetCreateTime().GetTimestamp(),
|
||||
LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
Type: PkiWorkerType,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1235,11 +1245,12 @@ func TestCreateWorkerLed(t *testing.T) {
|
||||
},
|
||||
res: &pbs.CreateWorkerLedResponse{
|
||||
Item: &workers.Worker{
|
||||
ScopeId: scope.Global.String(),
|
||||
Name: &wrapperspb.StringValue{Value: "success"},
|
||||
Description: &wrapperspb.StringValue{Value: "success-description"},
|
||||
Version: 1,
|
||||
Type: PkiWorkerType,
|
||||
ScopeId: scope.Global.String(),
|
||||
Name: &wrapperspb.StringValue{Value: "success"},
|
||||
Description: &wrapperspb.StringValue{Value: "success-description"},
|
||||
ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0},
|
||||
Version: 1,
|
||||
Type: PkiWorkerType,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -29,6 +29,7 @@ begin;
|
||||
create trigger immutable_columns before update on target_credential_library
|
||||
for each row execute procedure immutable_columns('target_id', 'credential_library_id', 'credential_purpose', 'create_time');
|
||||
|
||||
-- replaced in 33/02_target.up.sql
|
||||
-- target_library provides the store id along with the other data stored in
|
||||
-- target_credential_library
|
||||
create view target_library
|
||||
|
||||
@@ -2,6 +2,7 @@ begin;
|
||||
|
||||
create table credential_type_enm (
|
||||
name text primary key
|
||||
-- This constraint is replaced in 32/01_credential_type.up.sql
|
||||
constraint only_predefined_credential_types_allowed
|
||||
check (
|
||||
name in (
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
begin;
|
||||
|
||||
-- drop constraint so we can migrate user_password to username_password
|
||||
alter table credential_type_enm
|
||||
drop constraint only_predefined_credential_types_allowed;
|
||||
|
||||
-- Next: we will update user_password to username_password
|
||||
update credential_type_enm
|
||||
set name = 'username_password'
|
||||
where name = 'user_password';
|
||||
|
||||
-- Add new constraint that only allows unspecified and new username_password
|
||||
-- This replaces the constraint defined in 2/02_credential_type.up.sql
|
||||
alter table credential_type_enm
|
||||
add constraint only_predefined_credential_types_allowed
|
||||
check (
|
||||
name in (
|
||||
'unspecified',
|
||||
'username_password'
|
||||
)
|
||||
);
|
||||
|
||||
commit;
|
||||
@@ -0,0 +1,118 @@
|
||||
begin;
|
||||
|
||||
create table credential_static_store (
|
||||
public_id wt_public_id primary key,
|
||||
scope_id wt_scope_id not null
|
||||
constraint iam_scope_fkey
|
||||
references iam_scope (public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
name wt_name,
|
||||
description wt_description,
|
||||
create_time wt_timestamp,
|
||||
update_time wt_timestamp,
|
||||
version wt_version,
|
||||
constraint credential_store_fkey
|
||||
foreign key (scope_id, public_id)
|
||||
references credential_store (scope_id, public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
constraint credential_static_store_scope_id_name_uq
|
||||
unique(scope_id, name)
|
||||
);
|
||||
comment on table credential_static_store is
|
||||
'credential_static_store is a table where each row is a resource that represents a static credential store. '
|
||||
'It is a credential_store subtype and an aggregate root.';
|
||||
|
||||
create trigger update_version_column after update on credential_static_store
|
||||
for each row execute procedure update_version_column();
|
||||
|
||||
create trigger update_time_column before update on credential_static_store
|
||||
for each row execute procedure update_time_column();
|
||||
|
||||
create trigger default_create_time_column before insert on credential_static_store
|
||||
for each row execute procedure default_create_time();
|
||||
|
||||
create trigger immutable_columns before update on credential_static_store
|
||||
for each row execute procedure immutable_columns('public_id', 'scope_id','create_time');
|
||||
|
||||
create trigger insert_credential_store_subtype before insert on credential_static_store
|
||||
for each row execute procedure insert_credential_store_subtype();
|
||||
|
||||
create trigger delete_credential_store_subtype after delete on credential_static_store
|
||||
for each row execute procedure delete_credential_store_subtype();
|
||||
|
||||
create table credential_static_username_password_credential (
|
||||
public_id wt_public_id primary key,
|
||||
store_id wt_public_id not null
|
||||
constraint credential_static_store_fkey
|
||||
references credential_static_store (public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
name wt_name,
|
||||
description wt_description,
|
||||
create_time wt_timestamp,
|
||||
update_time wt_timestamp,
|
||||
version wt_version,
|
||||
|
||||
username text not null
|
||||
constraint username_must_not_be_empty
|
||||
check(length(trim(username)) > 0),
|
||||
password_encrypted bytea not null
|
||||
constraint password_encrypted_must_not_be_empty
|
||||
check(length(password_encrypted) > 0),
|
||||
password_hmac bytea not null
|
||||
constraint password_hmac_must_not_be_empty
|
||||
check(length(password_hmac) > 0),
|
||||
key_id text not null
|
||||
constraint kms_data_key_version_fkey
|
||||
references kms_data_key_version (private_id)
|
||||
on delete restrict
|
||||
on update cascade,
|
||||
constraint credential_static_fkey
|
||||
foreign key (store_id, public_id)
|
||||
references credential_static (store_id, public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
|
||||
constraint credential_static_username_password_credential_store_id_name_uq
|
||||
unique(store_id, name),
|
||||
|
||||
-- The name of this constraint does not follow our naming conventions for
|
||||
-- unique constraints because it would be to long. The max length for
|
||||
-- identifiers in PostgreSQL is 63 characters.
|
||||
-- credential_static_username_password_credential_store_id_public_id_uq
|
||||
-- is 68 characters.
|
||||
--
|
||||
-- https://www.postgresql.org/docs/current/limits.html
|
||||
constraint credential_static_username_password_store_id_public_id_uq
|
||||
unique(store_id, public_id)
|
||||
);
|
||||
comment on table credential_static_username_password_credential is
|
||||
'credential_static_username_password_credential is a table where each row is a resource that represents a static username password credential. '
|
||||
'It is a credential_static subtype and an aggregate root.';
|
||||
|
||||
create trigger update_version_column after update on credential_static_username_password_credential
|
||||
for each row execute procedure update_version_column();
|
||||
|
||||
create trigger update_time_column before update on credential_static_username_password_credential
|
||||
for each row execute procedure update_time_column();
|
||||
|
||||
create trigger default_create_time_column before insert on credential_static_username_password_credential
|
||||
for each row execute procedure default_create_time();
|
||||
|
||||
create trigger immutable_columns before update on credential_static_username_password_credential
|
||||
for each row execute procedure immutable_columns('public_id', 'store_id','create_time');
|
||||
|
||||
create trigger insert_credential_static_subtype before insert on credential_static_username_password_credential
|
||||
for each row execute procedure insert_credential_static_subtype();
|
||||
|
||||
create trigger delete_credential_static_subtype after delete on credential_static_username_password_credential
|
||||
for each row execute procedure delete_credential_static_subtype();
|
||||
|
||||
insert into oplog_ticket (name, version)
|
||||
values
|
||||
('credential_static_store', 1),
|
||||
('credential_static_username_password_credential', 1);
|
||||
|
||||
commit;
|
||||
@@ -0,0 +1,82 @@
|
||||
begin;
|
||||
|
||||
-- target_static_credential does not follow the normal table naming convention of target_credential_static
|
||||
create table target_static_credential (
|
||||
target_id wt_public_id not null
|
||||
constraint target_fkey
|
||||
references target (public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
credential_static_id wt_public_id not null
|
||||
constraint credential_static_fkey
|
||||
references credential_static (public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
credential_purpose text not null
|
||||
constraint credential_purpose_enm_fkey
|
||||
references credential_purpose_enm (name)
|
||||
on delete restrict
|
||||
on update cascade,
|
||||
create_time wt_timestamp,
|
||||
primary key(target_id, credential_static_id, credential_purpose)
|
||||
);
|
||||
comment on table target_static_credential is
|
||||
'target_static_credential is a join table between the target, credential_static, and credential_purpose_enm tables. '
|
||||
'A row in the target_static_credential table represents the assignment of a static credential to a target for the specified purpose.';
|
||||
|
||||
create trigger default_create_time_column before insert on target_static_credential
|
||||
for each row execute procedure default_create_time();
|
||||
|
||||
create trigger immutable_columns before update on target_static_credential
|
||||
for each row execute procedure immutable_columns('target_id', 'credential_static_id', 'credential_purpose', 'create_time');
|
||||
|
||||
-- replaces view from 10/05_target.up.sql
|
||||
drop view target_library;
|
||||
-- target_credential_source provides the store id along with the other data stored in
|
||||
-- target_credential_library and target_static_credential
|
||||
create view target_credential_source
|
||||
as
|
||||
select
|
||||
tcl.target_id,
|
||||
tcl.credential_library_id as credential_source_id,
|
||||
tcl.credential_purpose,
|
||||
cl.store_id,
|
||||
'library' as type
|
||||
from
|
||||
target_credential_library tcl,
|
||||
credential_library cl
|
||||
where
|
||||
cl.public_id = tcl.credential_library_id
|
||||
union
|
||||
select
|
||||
tcs.target_id,
|
||||
tcs.credential_static_id as credential_source_id,
|
||||
tcs.credential_purpose,
|
||||
cst.store_id,
|
||||
'static' as type
|
||||
from
|
||||
target_static_credential tcs,
|
||||
credential_static cst
|
||||
where
|
||||
cst.public_id = tcs.credential_static_id;
|
||||
comment on view target_credential_source is
|
||||
'target_credential_source is a view where each row contains a credential source and the id of the parent credential store. '
|
||||
'No encrypted data is returned. This view can be used to retrieve data which will be returned external to boundary.';
|
||||
|
||||
create view credential_source_all_types
|
||||
as
|
||||
select
|
||||
public_id,
|
||||
'library' as type
|
||||
from
|
||||
credential_library
|
||||
union
|
||||
select
|
||||
public_id,
|
||||
'static' as type
|
||||
from
|
||||
credential_static;
|
||||
comment on view credential_source_all_types is
|
||||
'credential_source_all_types is a view where each row contains the credential source id and type.';
|
||||
|
||||
commit;
|
||||
@@ -0,0 +1,32 @@
|
||||
begin;
|
||||
|
||||
create table session_credential_static (
|
||||
session_id wt_public_id not null
|
||||
constraint session_fkey
|
||||
references session (public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
credential_static_id wt_public_id
|
||||
constraint credential_static_fkey
|
||||
references credential_static (public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
credential_purpose text not null
|
||||
constraint credential_purpose_fkey
|
||||
references credential_purpose_enm (name)
|
||||
on delete restrict
|
||||
on update cascade,
|
||||
primary key(session_id, credential_static_id, credential_purpose),
|
||||
create_time wt_timestamp
|
||||
);
|
||||
comment on table session_credential_dynamic is
|
||||
'session_credential_static is a join table between the session and static credential tables. '
|
||||
'It also contains the credential purpose the relationship represents.';
|
||||
|
||||
create trigger default_create_time_column before insert on session_credential_static
|
||||
for each row execute procedure default_create_time();
|
||||
|
||||
create trigger immutable_columns before update on session_credential_static
|
||||
for each row execute procedure immutable_columns('session_id', 'credential_static_id', 'credential_purpose', 'create_time');
|
||||
|
||||
commit;
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,111 @@
|
||||
package oss_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential/vault"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/db/common"
|
||||
"github.com/hashicorp/boundary/internal/db/schema"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/testing/dbtest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMigrations_user_password_Migration(t *testing.T) {
|
||||
const (
|
||||
priorMigration = 31002
|
||||
currentMigration = 32001
|
||||
)
|
||||
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
dialect := dbtest.Postgres
|
||||
|
||||
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, c())
|
||||
})
|
||||
d, err := common.SqlOpen(dialect, u)
|
||||
require.NoError(t, err)
|
||||
|
||||
// migration to the prior migration (before the one we want to test)
|
||||
m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
|
||||
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}),
|
||||
))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, m.ApplyMigrations(ctx))
|
||||
state, err := m.CurrentState(ctx)
|
||||
require.NoError(t, err)
|
||||
want := &schema.State{
|
||||
Initialized: true,
|
||||
Editions: []schema.EditionState{
|
||||
{
|
||||
Name: "oss",
|
||||
BinarySchemaVersion: priorMigration,
|
||||
DatabaseSchemaVersion: priorMigration,
|
||||
DatabaseSchemaState: schema.Equal,
|
||||
},
|
||||
},
|
||||
}
|
||||
require.Equal(t, want, state)
|
||||
|
||||
// get a connection
|
||||
dbType, err := db.StringToDbType(dialect)
|
||||
require.NoError(t, err)
|
||||
conn, err := db.Open(dbType, u)
|
||||
require.NoError(t, err)
|
||||
rw := db.New(conn)
|
||||
|
||||
rootWrapper := db.TestWrapper(t)
|
||||
iamRepo := iam.TestRepo(t, conn, rootWrapper)
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
|
||||
cs, err := vault.NewCredentialStore(prj.PublicId, "https://vault", []byte("token"))
|
||||
cs.PublicId = "csvlt_test1234"
|
||||
require.NoError(t, rw.Create(context.Background(), cs))
|
||||
|
||||
upLib, err := vault.NewCredentialLibrary(cs.PublicId, "vault_path", vault.WithMethod("GET"), vault.WithCredentialType("user_password"))
|
||||
upLib.PublicId = "clvlt_testuplib"
|
||||
require.NoError(t, rw.Create(context.Background(), upLib))
|
||||
|
||||
lib, err := vault.NewCredentialLibrary(cs.PublicId, "vault_path", vault.WithMethod("GET"))
|
||||
lib.PublicId = "clvlt_testlib"
|
||||
require.NoError(t, rw.Create(context.Background(), lib))
|
||||
|
||||
// now we're ready for the migration we want to test.
|
||||
m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
|
||||
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}),
|
||||
))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, m.ApplyMigrations(ctx))
|
||||
state, err = m.CurrentState(ctx)
|
||||
require.NoError(t, err)
|
||||
want = &schema.State{
|
||||
Initialized: true,
|
||||
Editions: []schema.EditionState{
|
||||
{
|
||||
Name: "oss",
|
||||
BinarySchemaVersion: currentMigration,
|
||||
DatabaseSchemaVersion: currentMigration,
|
||||
DatabaseSchemaState: schema.Equal,
|
||||
},
|
||||
},
|
||||
}
|
||||
require.Equal(t, want, state)
|
||||
|
||||
// Validate uplib was migrated to username_password
|
||||
err = rw.LookupByPublicId(context.Background(), upLib)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "username_password", upLib.GetCredentialType())
|
||||
|
||||
// Validate lib was left as unspecified
|
||||
err = rw.LookupByPublicId(context.Background(), lib)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "unspecified", lib.GetCredentialType())
|
||||
}
|
||||
@@ -346,11 +346,11 @@ begin;
|
||||
values
|
||||
('vs_______wvs', 'vl______wvl1', 'widget vault library', 'None', '/secrets', 'GET', 'unspecified'),
|
||||
('vs_______wvs', 'vl______wvl2', 'widget vault ssh', 'None', '/secrets/ssh/admin', 'GET', 'unspecified'),
|
||||
('vs_______wvs', 'vl______wvl3', 'widget vault kv one', 'None', '/secrets/kv/one', 'GET', 'user_password'),
|
||||
('vs_______wvs', 'vl______wvl4', 'widget vault kv two', 'None', '/secrets/kv/two', 'GET', 'user_password'),
|
||||
('vs_______wvs', 'vl______wvl5', 'widget vault kv three', 'None', '/secrets/kv/three', 'GET', 'user_password'),
|
||||
('vs_______wvs', 'vl______wvl6', 'widget vault kv four', 'None', '/secrets/kv/four', 'GET', 'user_password'),
|
||||
('vs_______wvs', 'vl______wvl7', 'widget vault kv five', 'None', '/secrets/kv/five', 'GET', 'user_password');
|
||||
('vs_______wvs', 'vl______wvl3', 'widget vault kv one', 'None', '/secrets/kv/one', 'GET', 'username_password'),
|
||||
('vs_______wvs', 'vl______wvl4', 'widget vault kv two', 'None', '/secrets/kv/two', 'GET', 'username_password'),
|
||||
('vs_______wvs', 'vl______wvl5', 'widget vault kv three', 'None', '/secrets/kv/three', 'GET', 'username_password'),
|
||||
('vs_______wvs', 'vl______wvl6', 'widget vault kv four', 'None', '/secrets/kv/four', 'GET', 'username_password'),
|
||||
('vs_______wvs', 'vl______wvl7', 'widget vault kv five', 'None', '/secrets/kv/five', 'GET', 'username_password');
|
||||
|
||||
insert into credential_vault_library_user_password_mapping_override
|
||||
(library_id)
|
||||
|
||||
@@ -11,19 +11,19 @@ begin;
|
||||
select is(count(*), 1::bigint) from credential_vault_library where public_id = 'vl______wvl1' and credential_type = 'unspecified';
|
||||
select is(count(*), 1::bigint) from credential_library where public_id = 'vl______wvl1' and credential_type = 'unspecified';
|
||||
|
||||
select is(count(*), 1::bigint) from credential_vault_library where public_id = 'vl______wvl3' and credential_type = 'user_password';
|
||||
select is(count(*), 1::bigint) from credential_library where public_id = 'vl______wvl3' and credential_type = 'user_password';
|
||||
select is(count(*), 1::bigint) from credential_vault_library where public_id = 'vl______wvl3' and credential_type = 'username_password';
|
||||
select is(count(*), 1::bigint) from credential_library where public_id = 'vl______wvl3' and credential_type = 'username_password';
|
||||
|
||||
-- validate the insert triggers
|
||||
prepare insert_vault_library as
|
||||
insert into credential_vault_library
|
||||
(store_id, public_id, vault_path, http_method, credential_type)
|
||||
values
|
||||
('vs_______wvs', 'vl_______tt1', '/secrets/kv', 'GET', 'user_password');
|
||||
('vs_______wvs', 'vl_______tt1', '/secrets/kv', 'GET', 'username_password');
|
||||
select lives_ok('insert_vault_library');
|
||||
|
||||
select is(count(*), 1::bigint) from credential_vault_library where public_id = 'vl_______tt1' and credential_type = 'user_password';
|
||||
select is(count(*), 1::bigint) from credential_library where public_id = 'vl_______tt1' and credential_type = 'user_password';
|
||||
select is(count(*), 1::bigint) from credential_vault_library where public_id = 'vl_______tt1' and credential_type = 'username_password';
|
||||
select is(count(*), 1::bigint) from credential_library where public_id = 'vl_______tt1' and credential_type = 'username_password';
|
||||
|
||||
-- validate the delete triggers
|
||||
prepare delete_vault_library as
|
||||
|
||||
+5
-5
@@ -26,11 +26,11 @@ begin;
|
||||
'select_private_libraries',
|
||||
$$VALUES
|
||||
('vl______wvl2', 'unspecified', null, null),
|
||||
('vl______wvl3', 'user_password', null, null),
|
||||
('vl______wvl4', 'user_password', null, null),
|
||||
('vl______wvl5', 'user_password', 'my_username', null),
|
||||
('vl______wvl6', 'user_password', null, 'my_password'),
|
||||
('vl______wvl7', 'user_password', 'my_username', 'my_password')$$
|
||||
('vl______wvl3', 'username_password', null, null),
|
||||
('vl______wvl4', 'username_password', null, null),
|
||||
('vl______wvl5', 'username_password', 'my_username', null),
|
||||
('vl______wvl6', 'username_password', null, 'my_password'),
|
||||
('vl______wvl7', 'username_password', 'my_username', 'my_password')$$
|
||||
);
|
||||
|
||||
-- validate the insert triggers
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
{
|
||||
"name": "controller.api.services.v1.CredentialLibraryService"
|
||||
},
|
||||
{
|
||||
"name": "controller.api.services.v1.CredentialService"
|
||||
},
|
||||
{
|
||||
"name": "controller.api.services.v1.CredentialStoreService"
|
||||
},
|
||||
@@ -911,6 +914,147 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/credentials": {
|
||||
"get": {
|
||||
"summary": "Lists all Credentials.",
|
||||
"operationId": "CredentialService_ListCredentials",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.services.v1.ListCredentialsResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "credential_store_id",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "filter",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"controller.api.services.v1.CredentialService"
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"summary": "Creates a single Credential.",
|
||||
"operationId": "CredentialService_CreateCredential",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.resources.credentials.v1.Credential"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "item",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.resources.credentials.v1.Credential"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"controller.api.services.v1.CredentialService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/credentials/{id}": {
|
||||
"get": {
|
||||
"summary": "Gets a single Credential.",
|
||||
"operationId": "CredentialService_GetCredential",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.resources.credentials.v1.Credential"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"controller.api.services.v1.CredentialService"
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Deletes a Credential",
|
||||
"operationId": "CredentialService_DeleteCredential",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.services.v1.DeleteCredentialResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"controller.api.services.v1.CredentialService"
|
||||
]
|
||||
},
|
||||
"patch": {
|
||||
"summary": "Updates a Credential.",
|
||||
"operationId": "CredentialService_UpdateCredential",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.resources.credentials.v1.Credential"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "item",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.resources.credentials.v1.Credential"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "update_mask",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"controller.api.services.v1.CredentialService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/groups": {
|
||||
"get": {
|
||||
"summary": "Lists all Groups.",
|
||||
@@ -2751,52 +2895,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/targets/{id}:add-credential-libraries": {
|
||||
"post": {
|
||||
"summary": "Deprecated: use AddTargetCredentialSources instead.",
|
||||
"operationId": "TargetService_AddTargetCredentialLibraries",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.resources.targets.v1.Target"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "Version is used to ensure this resource has not changed.\nThe mutation will fail if the version does not match the latest known good version."
|
||||
},
|
||||
"application_credential_library_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"controller.api.services.v1.TargetService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/targets/{id}:add-credential-sources": {
|
||||
"post": {
|
||||
"summary": "Adds existing Credential Sources to a Target.",
|
||||
@@ -2993,52 +3091,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/targets/{id}:remove-credential-libraries": {
|
||||
"post": {
|
||||
"summary": "Deprecated: use RemoveTargetCredentialSources instead.",
|
||||
"operationId": "TargetService_RemoveTargetCredentialLibraries",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.resources.targets.v1.Target"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "Version is used to ensure this resource has not changed.\nThe mutation will fail if the version does not match the latest known good version."
|
||||
},
|
||||
"application_credential_library_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"controller.api.services.v1.TargetService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/targets/{id}:remove-credential-sources": {
|
||||
"post": {
|
||||
"summary": "Removes Credential Sources from the Target.",
|
||||
@@ -3183,53 +3235,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/targets/{id}:set-credential-libraries": {
|
||||
"post": {
|
||||
"summary": "Deprecated: use SetTargetCredentialSources instead.",
|
||||
"operationId": "TargetService_SetTargetCredentialLibraries",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.resources.targets.v1.Target"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "Version is used to ensure this resource has not changed.\nThe mutation will fail if the version does not match the latest known good version."
|
||||
},
|
||||
"application_credential_library_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Sets the values for application_credential_library_ids. If any\ncredential_library_id field that is not set in the request will result in\nthose fields being cleared."
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"controller.api.services.v1.TargetService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/targets/{id}:set-credential-sources": {
|
||||
"post": {
|
||||
"summary": "Sets the Credential Sources on the Target.",
|
||||
@@ -4098,6 +4103,67 @@
|
||||
},
|
||||
"title": "CredentialLibrary contains all fields related to an Credential Library resource"
|
||||
},
|
||||
"controller.api.resources.credentials.v1.Credential": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Output only. The ID of the Credential.",
|
||||
"readOnly": true
|
||||
},
|
||||
"credential_store_id": {
|
||||
"type": "string",
|
||||
"description": "The ID of the Credential Store of which this Credential is a part."
|
||||
},
|
||||
"scope": {
|
||||
"$ref": "#/definitions/controller.api.resources.scopes.v1.ScopeInfo",
|
||||
"description": "Output only. Scope information for this Credential.",
|
||||
"readOnly": true
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Optional name for identification purposes."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Optional user-set description for identification purposes."
|
||||
},
|
||||
"created_time": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Output only. The time this resource was created.",
|
||||
"readOnly": true
|
||||
},
|
||||
"updated_time": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Output only. The time this resource was last updated.",
|
||||
"readOnly": true
|
||||
},
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "Version is used in mutation requests, after the initial creation, to ensure this resource has not changed.\nThe mutation will fail if the version does not match the latest known good version."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "The Credential type."
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"description": "The attributes that are applicable for the specific Credential type."
|
||||
},
|
||||
"authorized_actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Output only. The available actions on this resource for this user.",
|
||||
"readOnly": true
|
||||
}
|
||||
},
|
||||
"title": "Credential contains all fields related to an Credential resource"
|
||||
},
|
||||
"controller.api.resources.credentialstores.v1.CredentialStore": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -5046,35 +5112,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.resources.targets.v1.CredentialLibrary": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "The ID of the Credential Library."
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Output only. The name of the Credential Library.",
|
||||
"readOnly": true
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Output only. The description of the Credential Library.",
|
||||
"readOnly": true
|
||||
},
|
||||
"credential_store_id": {
|
||||
"type": "string",
|
||||
"description": "Output only. The Credential Store to which this Credential Library belongs.",
|
||||
"readOnly": true
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Output only. The type of the credential library.",
|
||||
"readOnly": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.resources.targets.v1.CredentialSource": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -5212,11 +5249,6 @@
|
||||
"description": "Output only. The credential source information.",
|
||||
"readOnly": true
|
||||
},
|
||||
"credential_library": {
|
||||
"$ref": "#/definitions/controller.api.resources.targets.v1.CredentialLibrary",
|
||||
"description": "Output only. The library which generated this credential. Deprecated: use credential_source instead.",
|
||||
"readOnly": true
|
||||
},
|
||||
"secret": {
|
||||
"$ref": "#/definitions/controller.api.resources.targets.v1.SessionSecret",
|
||||
"description": "Output only. The secret of this credential base64 encoded.",
|
||||
@@ -5338,22 +5370,6 @@
|
||||
"type": "string",
|
||||
"description": "Optional boolean expression to filter the workers that are allowed to satisfy this request."
|
||||
},
|
||||
"application_credential_library_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Output only. The IDs of the application credential library ids associated with this Target. Deprecated: use application_credential_source_ids instead.",
|
||||
"readOnly": true
|
||||
},
|
||||
"application_credential_libraries": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/controller.api.resources.targets.v1.CredentialLibrary"
|
||||
},
|
||||
"description": "Output only. The application credential libraries associated with this Target. Deprecated: use application_credential_sources instead.",
|
||||
"readOnly": true
|
||||
},
|
||||
"application_credential_source_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -5638,14 +5654,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.AddTargetCredentialLibrariesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"item": {
|
||||
"$ref": "#/definitions/controller.api.resources.targets.v1.Target"
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.AddTargetCredentialSourcesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -5760,6 +5768,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.CreateCredentialResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"uri": {
|
||||
"type": "string"
|
||||
},
|
||||
"item": {
|
||||
"$ref": "#/definitions/controller.api.resources.credentials.v1.Credential"
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.CreateCredentialStoreResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -5893,6 +5912,9 @@
|
||||
"controller.api.services.v1.DeleteCredentialLibraryResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"controller.api.services.v1.DeleteCredentialResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"controller.api.services.v1.DeleteCredentialStoreResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
@@ -5958,6 +5980,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.GetCredentialResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"item": {
|
||||
"$ref": "#/definitions/controller.api.resources.credentials.v1.Credential"
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.GetCredentialStoreResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6109,6 +6139,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.ListCredentialsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/controller.api.resources.credentials.v1.Credential"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.ListGroupsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6262,14 +6303,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.RemoveTargetCredentialLibrariesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"item": {
|
||||
"$ref": "#/definitions/controller.api.resources.targets.v1.Target"
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.RemoveTargetCredentialSourcesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6342,14 +6375,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.SetTargetCredentialLibrariesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"item": {
|
||||
"$ref": "#/definitions/controller.api.resources.targets.v1.Target"
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.SetTargetCredentialSourcesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6406,6 +6431,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.UpdateCredentialResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"item": {
|
||||
"$ref": "#/definitions/controller.api.resources.credentials.v1.Credential"
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.services.v1.UpdateCredentialStoreResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -0,0 +1,864 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc (unknown)
|
||||
// source: controller/api/services/v1/credential_service.proto
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"
|
||||
credentials "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentials"
|
||||
_ "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions"
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type GetCredentialRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
}
|
||||
|
||||
func (x *GetCredentialRequest) Reset() {
|
||||
*x = GetCredentialRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *GetCredentialRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetCredentialRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetCredentialRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetCredentialRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetCredentialRequest) Descriptor() ([]byte, []int) {
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *GetCredentialRequest) GetId() string {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GetCredentialResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Item *credentials.Credential `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
|
||||
}
|
||||
|
||||
func (x *GetCredentialResponse) Reset() {
|
||||
*x = GetCredentialResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *GetCredentialResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetCredentialResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetCredentialResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetCredentialResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetCredentialResponse) Descriptor() ([]byte, []int) {
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *GetCredentialResponse) GetItem() *credentials.Credential {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ListCredentialsRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
CredentialStoreId string `protobuf:"bytes,1,opt,name=credential_store_id,json=scope_id,proto3" json:"credential_store_id,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
Filter string `protobuf:"bytes,30,opt,name=filter,proto3" json:"filter,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
}
|
||||
|
||||
func (x *ListCredentialsRequest) Reset() {
|
||||
*x = ListCredentialsRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ListCredentialsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListCredentialsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ListCredentialsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListCredentialsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ListCredentialsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ListCredentialsRequest) GetCredentialStoreId() string {
|
||||
if x != nil {
|
||||
return x.CredentialStoreId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ListCredentialsRequest) GetFilter() string {
|
||||
if x != nil {
|
||||
return x.Filter
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ListCredentialsResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Items []*credentials.Credential `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListCredentialsResponse) Reset() {
|
||||
*x = ListCredentialsResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ListCredentialsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListCredentialsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ListCredentialsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListCredentialsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ListCredentialsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ListCredentialsResponse) GetItems() []*credentials.Credential {
|
||||
if x != nil {
|
||||
return x.Items
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateCredentialRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Item *credentials.Credential `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CreateCredentialRequest) Reset() {
|
||||
*x = CreateCredentialRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *CreateCredentialRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CreateCredentialRequest) ProtoMessage() {}
|
||||
|
||||
func (x *CreateCredentialRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CreateCredentialRequest.ProtoReflect.Descriptor instead.
|
||||
func (*CreateCredentialRequest) Descriptor() ([]byte, []int) {
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *CreateCredentialRequest) GetItem() *credentials.Credential {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateCredentialResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
Item *credentials.Credential `protobuf:"bytes,2,opt,name=item,proto3" json:"item,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CreateCredentialResponse) Reset() {
|
||||
*x = CreateCredentialResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *CreateCredentialResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CreateCredentialResponse) ProtoMessage() {}
|
||||
|
||||
func (x *CreateCredentialResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CreateCredentialResponse.ProtoReflect.Descriptor instead.
|
||||
func (*CreateCredentialResponse) Descriptor() ([]byte, []int) {
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *CreateCredentialResponse) GetUri() string {
|
||||
if x != nil {
|
||||
return x.Uri
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CreateCredentialResponse) GetItem() *credentials.Credential {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateCredentialRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
Item *credentials.Credential `protobuf:"bytes,2,opt,name=item,proto3" json:"item,omitempty"`
|
||||
UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,3,opt,name=update_mask,proto3" json:"update_mask,omitempty"`
|
||||
}
|
||||
|
||||
func (x *UpdateCredentialRequest) Reset() {
|
||||
*x = UpdateCredentialRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *UpdateCredentialRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UpdateCredentialRequest) ProtoMessage() {}
|
||||
|
||||
func (x *UpdateCredentialRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[6]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UpdateCredentialRequest.ProtoReflect.Descriptor instead.
|
||||
func (*UpdateCredentialRequest) Descriptor() ([]byte, []int) {
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *UpdateCredentialRequest) GetId() string {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UpdateCredentialRequest) GetItem() *credentials.Credential {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UpdateCredentialRequest) GetUpdateMask() *fieldmaskpb.FieldMask {
|
||||
if x != nil {
|
||||
return x.UpdateMask
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateCredentialResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Item *credentials.Credential `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
|
||||
}
|
||||
|
||||
func (x *UpdateCredentialResponse) Reset() {
|
||||
*x = UpdateCredentialResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *UpdateCredentialResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UpdateCredentialResponse) ProtoMessage() {}
|
||||
|
||||
func (x *UpdateCredentialResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[7]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UpdateCredentialResponse.ProtoReflect.Descriptor instead.
|
||||
func (*UpdateCredentialResponse) Descriptor() ([]byte, []int) {
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *UpdateCredentialResponse) GetItem() *credentials.Credential {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeleteCredentialRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" class:"public"` // @gotags: `class:"public"`
|
||||
}
|
||||
|
||||
func (x *DeleteCredentialRequest) Reset() {
|
||||
*x = DeleteCredentialRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *DeleteCredentialRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DeleteCredentialRequest) ProtoMessage() {}
|
||||
|
||||
func (x *DeleteCredentialRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[8]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DeleteCredentialRequest.ProtoReflect.Descriptor instead.
|
||||
func (*DeleteCredentialRequest) Descriptor() ([]byte, []int) {
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *DeleteCredentialRequest) GetId() string {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type DeleteCredentialResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *DeleteCredentialResponse) Reset() {
|
||||
*x = DeleteCredentialResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *DeleteCredentialResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DeleteCredentialResponse) ProtoMessage() {}
|
||||
|
||||
func (x *DeleteCredentialResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_api_services_v1_credential_service_proto_msgTypes[9]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DeleteCredentialResponse.ProtoReflect.Descriptor instead.
|
||||
func (*DeleteCredentialResponse) Descriptor() ([]byte, []int) {
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescGZIP(), []int{9}
|
||||
}
|
||||
|
||||
var File_controller_api_services_v1_credential_service_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_controller_api_services_v1_credential_service_proto_rawDesc = []byte{
|
||||
0x0a, 0x33, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69,
|
||||
0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x65,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
|
||||
0x31, 0x1a, 0x38, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70,
|
||||
0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x72, 0x65, 0x64,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f,
|
||||
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
|
||||
0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73,
|
||||
0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d,
|
||||
0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x26, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x72,
|
||||
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22,
|
||||
0x60, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x73, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x04, 0x69, 0x74, 0x65,
|
||||
0x6d, 0x22, 0x57, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x13, 0x63,
|
||||
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f,
|
||||
0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x1e, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x64, 0x0a, 0x17, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e,
|
||||
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43,
|
||||
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73,
|
||||
0x22, 0x62, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x04, 0x69,
|
||||
0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75,
|
||||
0x72, 0x63, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x04,
|
||||
0x69, 0x74, 0x65, 0x6d, 0x22, 0x75, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x72,
|
||||
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75,
|
||||
0x72, 0x69, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
|
||||
0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x65, 0x64,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xb0, 0x01, 0x0a, 0x17,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
|
||||
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
|
||||
0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x12, 0x3c, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73,
|
||||
0x6b, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x22, 0x63,
|
||||
0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74,
|
||||
0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
|
||||
0x63, 0x65, 0x73, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x04, 0x69,
|
||||
0x74, 0x65, 0x6d, 0x22, 0x29, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x72, 0x65,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
|
||||
0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1a,
|
||||
0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xbe, 0x07, 0x0a, 0x11, 0x43,
|
||||
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x12, 0xb6, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x61, 0x6c, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
|
||||
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x92, 0x41, 0x1b, 0x12, 0x19, 0x47, 0x65,
|
||||
0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x43, 0x72, 0x65, 0x64,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x14, 0x2f,
|
||||
0x76, 0x31, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2f, 0x7b,
|
||||
0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xae, 0x01, 0x0a, 0x0f, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x32, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43,
|
||||
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
|
||||
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x92, 0x41, 0x18, 0x12, 0x16, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
|
||||
0x6c, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x63,
|
||||
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0xc3, 0x01, 0x0a, 0x10, 0x43,
|
||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12,
|
||||
0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65,
|
||||
0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x92, 0x41, 0x1e, 0x12,
|
||||
0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c,
|
||||
0x65, 0x20, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2e, 0x82, 0xd3, 0xe4,
|
||||
0x93, 0x02, 0x1d, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x61, 0x6c, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x12, 0xc1, 0x01, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
|
||||
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x72,
|
||||
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x42, 0x92, 0x41, 0x17, 0x12, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61,
|
||||
0x20, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2e, 0x82, 0xd3, 0xe4, 0x93,
|
||||
0x02, 0x22, 0x32, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04,
|
||||
0x69, 0x74, 0x65, 0x6d, 0x12, 0xb4, 0x01, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43,
|
||||
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x72, 0x65,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65,
|
||||
0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x92, 0x41, 0x16, 0x12, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74,
|
||||
0x65, 0x73, 0x20, 0x61, 0x20, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x82,
|
||||
0xd3, 0xe4, 0x93, 0x02, 0x16, 0x2a, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x42, 0x5b, 0x5a, 0x4b, 0x67,
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63,
|
||||
0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0xa2, 0xe3, 0x29, 0x0a, 0x63, 0x72,
|
||||
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_controller_api_services_v1_credential_service_proto_rawDescOnce sync.Once
|
||||
file_controller_api_services_v1_credential_service_proto_rawDescData = file_controller_api_services_v1_credential_service_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_controller_api_services_v1_credential_service_proto_rawDescGZIP() []byte {
|
||||
file_controller_api_services_v1_credential_service_proto_rawDescOnce.Do(func() {
|
||||
file_controller_api_services_v1_credential_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_controller_api_services_v1_credential_service_proto_rawDescData)
|
||||
})
|
||||
return file_controller_api_services_v1_credential_service_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_controller_api_services_v1_credential_service_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
|
||||
var file_controller_api_services_v1_credential_service_proto_goTypes = []interface{}{
|
||||
(*GetCredentialRequest)(nil), // 0: controller.api.services.v1.GetCredentialRequest
|
||||
(*GetCredentialResponse)(nil), // 1: controller.api.services.v1.GetCredentialResponse
|
||||
(*ListCredentialsRequest)(nil), // 2: controller.api.services.v1.ListCredentialsRequest
|
||||
(*ListCredentialsResponse)(nil), // 3: controller.api.services.v1.ListCredentialsResponse
|
||||
(*CreateCredentialRequest)(nil), // 4: controller.api.services.v1.CreateCredentialRequest
|
||||
(*CreateCredentialResponse)(nil), // 5: controller.api.services.v1.CreateCredentialResponse
|
||||
(*UpdateCredentialRequest)(nil), // 6: controller.api.services.v1.UpdateCredentialRequest
|
||||
(*UpdateCredentialResponse)(nil), // 7: controller.api.services.v1.UpdateCredentialResponse
|
||||
(*DeleteCredentialRequest)(nil), // 8: controller.api.services.v1.DeleteCredentialRequest
|
||||
(*DeleteCredentialResponse)(nil), // 9: controller.api.services.v1.DeleteCredentialResponse
|
||||
(*credentials.Credential)(nil), // 10: controller.api.resources.credentials.v1.Credential
|
||||
(*fieldmaskpb.FieldMask)(nil), // 11: google.protobuf.FieldMask
|
||||
}
|
||||
var file_controller_api_services_v1_credential_service_proto_depIdxs = []int32{
|
||||
10, // 0: controller.api.services.v1.GetCredentialResponse.item:type_name -> controller.api.resources.credentials.v1.Credential
|
||||
10, // 1: controller.api.services.v1.ListCredentialsResponse.items:type_name -> controller.api.resources.credentials.v1.Credential
|
||||
10, // 2: controller.api.services.v1.CreateCredentialRequest.item:type_name -> controller.api.resources.credentials.v1.Credential
|
||||
10, // 3: controller.api.services.v1.CreateCredentialResponse.item:type_name -> controller.api.resources.credentials.v1.Credential
|
||||
10, // 4: controller.api.services.v1.UpdateCredentialRequest.item:type_name -> controller.api.resources.credentials.v1.Credential
|
||||
11, // 5: controller.api.services.v1.UpdateCredentialRequest.update_mask:type_name -> google.protobuf.FieldMask
|
||||
10, // 6: controller.api.services.v1.UpdateCredentialResponse.item:type_name -> controller.api.resources.credentials.v1.Credential
|
||||
0, // 7: controller.api.services.v1.CredentialService.GetCredential:input_type -> controller.api.services.v1.GetCredentialRequest
|
||||
2, // 8: controller.api.services.v1.CredentialService.ListCredentials:input_type -> controller.api.services.v1.ListCredentialsRequest
|
||||
4, // 9: controller.api.services.v1.CredentialService.CreateCredential:input_type -> controller.api.services.v1.CreateCredentialRequest
|
||||
6, // 10: controller.api.services.v1.CredentialService.UpdateCredential:input_type -> controller.api.services.v1.UpdateCredentialRequest
|
||||
8, // 11: controller.api.services.v1.CredentialService.DeleteCredential:input_type -> controller.api.services.v1.DeleteCredentialRequest
|
||||
1, // 12: controller.api.services.v1.CredentialService.GetCredential:output_type -> controller.api.services.v1.GetCredentialResponse
|
||||
3, // 13: controller.api.services.v1.CredentialService.ListCredentials:output_type -> controller.api.services.v1.ListCredentialsResponse
|
||||
5, // 14: controller.api.services.v1.CredentialService.CreateCredential:output_type -> controller.api.services.v1.CreateCredentialResponse
|
||||
7, // 15: controller.api.services.v1.CredentialService.UpdateCredential:output_type -> controller.api.services.v1.UpdateCredentialResponse
|
||||
9, // 16: controller.api.services.v1.CredentialService.DeleteCredential:output_type -> controller.api.services.v1.DeleteCredentialResponse
|
||||
12, // [12:17] is the sub-list for method output_type
|
||||
7, // [7:12] is the sub-list for method input_type
|
||||
7, // [7:7] is the sub-list for extension type_name
|
||||
7, // [7:7] is the sub-list for extension extendee
|
||||
0, // [0:7] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_controller_api_services_v1_credential_service_proto_init() }
|
||||
func file_controller_api_services_v1_credential_service_proto_init() {
|
||||
if File_controller_api_services_v1_credential_service_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_controller_api_services_v1_credential_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*GetCredentialRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_api_services_v1_credential_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*GetCredentialResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_api_services_v1_credential_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ListCredentialsRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_api_services_v1_credential_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ListCredentialsResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_api_services_v1_credential_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*CreateCredentialRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_api_services_v1_credential_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*CreateCredentialResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_api_services_v1_credential_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UpdateCredentialRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_api_services_v1_credential_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UpdateCredentialResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_api_services_v1_credential_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*DeleteCredentialRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_api_services_v1_credential_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*DeleteCredentialResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_controller_api_services_v1_credential_service_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 10,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_controller_api_services_v1_credential_service_proto_goTypes,
|
||||
DependencyIndexes: file_controller_api_services_v1_credential_service_proto_depIdxs,
|
||||
MessageInfos: file_controller_api_services_v1_credential_service_proto_msgTypes,
|
||||
}.Build()
|
||||
File_controller_api_services_v1_credential_service_proto = out.File
|
||||
file_controller_api_services_v1_credential_service_proto_rawDesc = nil
|
||||
file_controller_api_services_v1_credential_service_proto_goTypes = nil
|
||||
file_controller_api_services_v1_credential_service_proto_depIdxs = nil
|
||||
}
|
||||
@@ -0,0 +1,632 @@
|
||||
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||
// source: controller/api/services/v1/credential_service.proto
|
||||
|
||||
/*
|
||||
Package services is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// Suppress "imported and not used" errors
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
var _ = metadata.Join
|
||||
|
||||
func request_CredentialService_GetCredential_0(ctx context.Context, marshaler runtime.Marshaler, client CredentialServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GetCredentialRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := client.GetCredential(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_CredentialService_GetCredential_0(ctx context.Context, marshaler runtime.Marshaler, server CredentialServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GetCredentialRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := server.GetCredential(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_CredentialService_ListCredentials_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_CredentialService_ListCredentials_0(ctx context.Context, marshaler runtime.Marshaler, client CredentialServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ListCredentialsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_CredentialService_ListCredentials_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.ListCredentials(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_CredentialService_ListCredentials_0(ctx context.Context, marshaler runtime.Marshaler, server CredentialServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ListCredentialsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_CredentialService_ListCredentials_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.ListCredentials(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_CredentialService_CreateCredential_0(ctx context.Context, marshaler runtime.Marshaler, client CredentialServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq CreateCredentialRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.CreateCredential(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_CredentialService_CreateCredential_0(ctx context.Context, marshaler runtime.Marshaler, server CredentialServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq CreateCredentialRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.CreateCredential(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_CredentialService_UpdateCredential_0 = &utilities.DoubleArray{Encoding: map[string]int{"item": 0, "id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
|
||||
)
|
||||
|
||||
func request_CredentialService_UpdateCredential_0(ctx context.Context, marshaler runtime.Marshaler, client CredentialServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq UpdateCredentialRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 {
|
||||
if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Item); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
} else {
|
||||
protoReq.UpdateMask = fieldMask
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_CredentialService_UpdateCredential_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.UpdateCredential(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_CredentialService_UpdateCredential_0(ctx context.Context, marshaler runtime.Marshaler, server CredentialServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq UpdateCredentialRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Item); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if protoReq.UpdateMask == nil || len(protoReq.UpdateMask.GetPaths()) == 0 {
|
||||
if fieldMask, err := runtime.FieldMaskFromRequestBody(newReader(), protoReq.Item); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
} else {
|
||||
protoReq.UpdateMask = fieldMask
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_CredentialService_UpdateCredential_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.UpdateCredential(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_CredentialService_DeleteCredential_0(ctx context.Context, marshaler runtime.Marshaler, client CredentialServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq DeleteCredentialRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := client.DeleteCredential(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_CredentialService_DeleteCredential_0(ctx context.Context, marshaler runtime.Marshaler, server CredentialServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq DeleteCredentialRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := server.DeleteCredential(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterCredentialServiceHandlerServer registers the http handlers for service CredentialService to "mux".
|
||||
// UnaryRPC :call CredentialServiceServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterCredentialServiceHandlerFromEndpoint instead.
|
||||
func RegisterCredentialServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server CredentialServiceServer) error {
|
||||
|
||||
mux.Handle("GET", pattern_CredentialService_GetCredential_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.CredentialService/GetCredential", runtime.WithHTTPPathPattern("/v1/credentials/{id}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_CredentialService_GetCredential_0(ctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CredentialService_GetCredential_0(ctx, mux, outboundMarshaler, w, req, response_CredentialService_GetCredential_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_CredentialService_ListCredentials_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.CredentialService/ListCredentials", runtime.WithHTTPPathPattern("/v1/credentials"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_CredentialService_ListCredentials_0(ctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CredentialService_ListCredentials_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_CredentialService_CreateCredential_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.CredentialService/CreateCredential", runtime.WithHTTPPathPattern("/v1/credentials"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_CredentialService_CreateCredential_0(ctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CredentialService_CreateCredential_0(ctx, mux, outboundMarshaler, w, req, response_CredentialService_CreateCredential_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("PATCH", pattern_CredentialService_UpdateCredential_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.CredentialService/UpdateCredential", runtime.WithHTTPPathPattern("/v1/credentials/{id}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_CredentialService_UpdateCredential_0(ctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CredentialService_UpdateCredential_0(ctx, mux, outboundMarshaler, w, req, response_CredentialService_UpdateCredential_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_CredentialService_DeleteCredential_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.CredentialService/DeleteCredential", runtime.WithHTTPPathPattern("/v1/credentials/{id}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_CredentialService_DeleteCredential_0(ctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CredentialService_DeleteCredential_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterCredentialServiceHandlerFromEndpoint is same as RegisterCredentialServiceHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterCredentialServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.Dial(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterCredentialServiceHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterCredentialServiceHandler registers the http handlers for service CredentialService to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterCredentialServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
return RegisterCredentialServiceHandlerClient(ctx, mux, NewCredentialServiceClient(conn))
|
||||
}
|
||||
|
||||
// RegisterCredentialServiceHandlerClient registers the http handlers for service CredentialService
|
||||
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "CredentialServiceClient".
|
||||
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "CredentialServiceClient"
|
||||
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||
// "CredentialServiceClient" to call the correct interceptors.
|
||||
func RegisterCredentialServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client CredentialServiceClient) error {
|
||||
|
||||
mux.Handle("GET", pattern_CredentialService_GetCredential_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.CredentialService/GetCredential", runtime.WithHTTPPathPattern("/v1/credentials/{id}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_CredentialService_GetCredential_0(ctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CredentialService_GetCredential_0(ctx, mux, outboundMarshaler, w, req, response_CredentialService_GetCredential_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_CredentialService_ListCredentials_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.CredentialService/ListCredentials", runtime.WithHTTPPathPattern("/v1/credentials"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_CredentialService_ListCredentials_0(ctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CredentialService_ListCredentials_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_CredentialService_CreateCredential_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.CredentialService/CreateCredential", runtime.WithHTTPPathPattern("/v1/credentials"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_CredentialService_CreateCredential_0(ctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CredentialService_CreateCredential_0(ctx, mux, outboundMarshaler, w, req, response_CredentialService_CreateCredential_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("PATCH", pattern_CredentialService_UpdateCredential_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.CredentialService/UpdateCredential", runtime.WithHTTPPathPattern("/v1/credentials/{id}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_CredentialService_UpdateCredential_0(ctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CredentialService_UpdateCredential_0(ctx, mux, outboundMarshaler, w, req, response_CredentialService_UpdateCredential_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_CredentialService_DeleteCredential_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.CredentialService/DeleteCredential", runtime.WithHTTPPathPattern("/v1/credentials/{id}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_CredentialService_DeleteCredential_0(ctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_CredentialService_DeleteCredential_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type response_CredentialService_GetCredential_0 struct {
|
||||
proto.Message
|
||||
}
|
||||
|
||||
func (m response_CredentialService_GetCredential_0) XXX_ResponseBody() interface{} {
|
||||
response := m.Message.(*GetCredentialResponse)
|
||||
return response.Item
|
||||
}
|
||||
|
||||
type response_CredentialService_CreateCredential_0 struct {
|
||||
proto.Message
|
||||
}
|
||||
|
||||
func (m response_CredentialService_CreateCredential_0) XXX_ResponseBody() interface{} {
|
||||
response := m.Message.(*CreateCredentialResponse)
|
||||
return response.Item
|
||||
}
|
||||
|
||||
type response_CredentialService_UpdateCredential_0 struct {
|
||||
proto.Message
|
||||
}
|
||||
|
||||
func (m response_CredentialService_UpdateCredential_0) XXX_ResponseBody() interface{} {
|
||||
response := m.Message.(*UpdateCredentialResponse)
|
||||
return response.Item
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_CredentialService_GetCredential_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "credentials", "id"}, ""))
|
||||
|
||||
pattern_CredentialService_ListCredentials_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "credentials"}, ""))
|
||||
|
||||
pattern_CredentialService_CreateCredential_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "credentials"}, ""))
|
||||
|
||||
pattern_CredentialService_UpdateCredential_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "credentials", "id"}, ""))
|
||||
|
||||
pattern_CredentialService_DeleteCredential_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "credentials", "id"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_CredentialService_GetCredential_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_CredentialService_ListCredentials_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_CredentialService_CreateCredential_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_CredentialService_UpdateCredential_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_CredentialService_DeleteCredential_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
@@ -0,0 +1,287 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// CredentialServiceClient is the client API for CredentialService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type CredentialServiceClient interface {
|
||||
// GetCredential returns a stored Credential if present. The provided request
|
||||
// must include the Credential Store id. If missing, malformed or referencing a
|
||||
// non existing resource an error is returned.
|
||||
GetCredential(ctx context.Context, in *GetCredentialRequest, opts ...grpc.CallOption) (*GetCredentialResponse, error)
|
||||
// ListCredentials returns a list of stored Credentials which are in the
|
||||
// provided store. The request must include the Credential Store id and if missing,
|
||||
// malformed, or referencing a non existing scope, an error is returned.
|
||||
ListCredentials(ctx context.Context, in *ListCredentialsRequest, opts ...grpc.CallOption) (*ListCredentialsResponse, error)
|
||||
// CreateCredential creates and stores an Credential in boundary. The
|
||||
// provided request must include the credential_store_id in which the Credential
|
||||
// will be created. If the store id is missing, malformed or referencing a
|
||||
// non existing resource an error is returned. If a name is provided that is
|
||||
// in use in another Credential in the same store, an error is returned.
|
||||
CreateCredential(ctx context.Context, in *CreateCredentialRequest, opts ...grpc.CallOption) (*CreateCredentialResponse, error)
|
||||
// UpdateCredential updates an existing Credential in boundary. The provided
|
||||
// Credential must not have any read only fields set. The update mask must be
|
||||
// included in the request and contain at least 1 mutable field. To unset
|
||||
// a field's value, include the field in the update mask and don't set it
|
||||
// in the provided user. An error is returned if the Credential id is missing
|
||||
// or reference a non existing resource. An error is also returned if the
|
||||
// request attempts to update the name to one that is already in use by
|
||||
// another Credential in the parent scope.
|
||||
UpdateCredential(ctx context.Context, in *UpdateCredentialRequest, opts ...grpc.CallOption) (*UpdateCredentialResponse, error)
|
||||
// DeleteCredential removes an Credential from Boundary. If the Credential id
|
||||
// is malformed or not provided an error is returned.
|
||||
DeleteCredential(ctx context.Context, in *DeleteCredentialRequest, opts ...grpc.CallOption) (*DeleteCredentialResponse, error)
|
||||
}
|
||||
|
||||
type credentialServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewCredentialServiceClient(cc grpc.ClientConnInterface) CredentialServiceClient {
|
||||
return &credentialServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *credentialServiceClient) GetCredential(ctx context.Context, in *GetCredentialRequest, opts ...grpc.CallOption) (*GetCredentialResponse, error) {
|
||||
out := new(GetCredentialResponse)
|
||||
err := c.cc.Invoke(ctx, "/controller.api.services.v1.CredentialService/GetCredential", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *credentialServiceClient) ListCredentials(ctx context.Context, in *ListCredentialsRequest, opts ...grpc.CallOption) (*ListCredentialsResponse, error) {
|
||||
out := new(ListCredentialsResponse)
|
||||
err := c.cc.Invoke(ctx, "/controller.api.services.v1.CredentialService/ListCredentials", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *credentialServiceClient) CreateCredential(ctx context.Context, in *CreateCredentialRequest, opts ...grpc.CallOption) (*CreateCredentialResponse, error) {
|
||||
out := new(CreateCredentialResponse)
|
||||
err := c.cc.Invoke(ctx, "/controller.api.services.v1.CredentialService/CreateCredential", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *credentialServiceClient) UpdateCredential(ctx context.Context, in *UpdateCredentialRequest, opts ...grpc.CallOption) (*UpdateCredentialResponse, error) {
|
||||
out := new(UpdateCredentialResponse)
|
||||
err := c.cc.Invoke(ctx, "/controller.api.services.v1.CredentialService/UpdateCredential", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *credentialServiceClient) DeleteCredential(ctx context.Context, in *DeleteCredentialRequest, opts ...grpc.CallOption) (*DeleteCredentialResponse, error) {
|
||||
out := new(DeleteCredentialResponse)
|
||||
err := c.cc.Invoke(ctx, "/controller.api.services.v1.CredentialService/DeleteCredential", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// CredentialServiceServer is the server API for CredentialService service.
|
||||
// All implementations must embed UnimplementedCredentialServiceServer
|
||||
// for forward compatibility
|
||||
type CredentialServiceServer interface {
|
||||
// GetCredential returns a stored Credential if present. The provided request
|
||||
// must include the Credential Store id. If missing, malformed or referencing a
|
||||
// non existing resource an error is returned.
|
||||
GetCredential(context.Context, *GetCredentialRequest) (*GetCredentialResponse, error)
|
||||
// ListCredentials returns a list of stored Credentials which are in the
|
||||
// provided store. The request must include the Credential Store id and if missing,
|
||||
// malformed, or referencing a non existing scope, an error is returned.
|
||||
ListCredentials(context.Context, *ListCredentialsRequest) (*ListCredentialsResponse, error)
|
||||
// CreateCredential creates and stores an Credential in boundary. The
|
||||
// provided request must include the credential_store_id in which the Credential
|
||||
// will be created. If the store id is missing, malformed or referencing a
|
||||
// non existing resource an error is returned. If a name is provided that is
|
||||
// in use in another Credential in the same store, an error is returned.
|
||||
CreateCredential(context.Context, *CreateCredentialRequest) (*CreateCredentialResponse, error)
|
||||
// UpdateCredential updates an existing Credential in boundary. The provided
|
||||
// Credential must not have any read only fields set. The update mask must be
|
||||
// included in the request and contain at least 1 mutable field. To unset
|
||||
// a field's value, include the field in the update mask and don't set it
|
||||
// in the provided user. An error is returned if the Credential id is missing
|
||||
// or reference a non existing resource. An error is also returned if the
|
||||
// request attempts to update the name to one that is already in use by
|
||||
// another Credential in the parent scope.
|
||||
UpdateCredential(context.Context, *UpdateCredentialRequest) (*UpdateCredentialResponse, error)
|
||||
// DeleteCredential removes an Credential from Boundary. If the Credential id
|
||||
// is malformed or not provided an error is returned.
|
||||
DeleteCredential(context.Context, *DeleteCredentialRequest) (*DeleteCredentialResponse, error)
|
||||
mustEmbedUnimplementedCredentialServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedCredentialServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedCredentialServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedCredentialServiceServer) GetCredential(context.Context, *GetCredentialRequest) (*GetCredentialResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetCredential not implemented")
|
||||
}
|
||||
func (UnimplementedCredentialServiceServer) ListCredentials(context.Context, *ListCredentialsRequest) (*ListCredentialsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListCredentials not implemented")
|
||||
}
|
||||
func (UnimplementedCredentialServiceServer) CreateCredential(context.Context, *CreateCredentialRequest) (*CreateCredentialResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateCredential not implemented")
|
||||
}
|
||||
func (UnimplementedCredentialServiceServer) UpdateCredential(context.Context, *UpdateCredentialRequest) (*UpdateCredentialResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateCredential not implemented")
|
||||
}
|
||||
func (UnimplementedCredentialServiceServer) DeleteCredential(context.Context, *DeleteCredentialRequest) (*DeleteCredentialResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteCredential not implemented")
|
||||
}
|
||||
func (UnimplementedCredentialServiceServer) mustEmbedUnimplementedCredentialServiceServer() {}
|
||||
|
||||
// UnsafeCredentialServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to CredentialServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeCredentialServiceServer interface {
|
||||
mustEmbedUnimplementedCredentialServiceServer()
|
||||
}
|
||||
|
||||
func RegisterCredentialServiceServer(s grpc.ServiceRegistrar, srv CredentialServiceServer) {
|
||||
s.RegisterService(&CredentialService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _CredentialService_GetCredential_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetCredentialRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CredentialServiceServer).GetCredential(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/controller.api.services.v1.CredentialService/GetCredential",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CredentialServiceServer).GetCredential(ctx, req.(*GetCredentialRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _CredentialService_ListCredentials_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListCredentialsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CredentialServiceServer).ListCredentials(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/controller.api.services.v1.CredentialService/ListCredentials",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CredentialServiceServer).ListCredentials(ctx, req.(*ListCredentialsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _CredentialService_CreateCredential_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CreateCredentialRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CredentialServiceServer).CreateCredential(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/controller.api.services.v1.CredentialService/CreateCredential",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CredentialServiceServer).CreateCredential(ctx, req.(*CreateCredentialRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _CredentialService_UpdateCredential_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(UpdateCredentialRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CredentialServiceServer).UpdateCredential(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/controller.api.services.v1.CredentialService/UpdateCredential",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CredentialServiceServer).UpdateCredential(ctx, req.(*UpdateCredentialRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _CredentialService_DeleteCredential_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DeleteCredentialRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CredentialServiceServer).DeleteCredential(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/controller.api.services.v1.CredentialService/DeleteCredential",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CredentialServiceServer).DeleteCredential(ctx, req.(*DeleteCredentialRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// CredentialService_ServiceDesc is the grpc.ServiceDesc for CredentialService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var CredentialService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "controller.api.services.v1.CredentialService",
|
||||
HandlerType: (*CredentialServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetCredential",
|
||||
Handler: _CredentialService_GetCredential_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListCredentials",
|
||||
Handler: _CredentialService_ListCredentials_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CreateCredential",
|
||||
Handler: _CredentialService_CreateCredential_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "UpdateCredential",
|
||||
Handler: _CredentialService_UpdateCredential_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "DeleteCredential",
|
||||
Handler: _CredentialService_DeleteCredential_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "controller/api/services/v1/credential_service.proto",
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -781,210 +781,6 @@ func local_request_TargetService_RemoveTargetHostSources_0(ctx context.Context,
|
||||
|
||||
}
|
||||
|
||||
func request_TargetService_AddTargetCredentialLibraries_0(ctx context.Context, marshaler runtime.Marshaler, client TargetServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq AddTargetCredentialLibrariesRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := client.AddTargetCredentialLibraries(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_TargetService_AddTargetCredentialLibraries_0(ctx context.Context, marshaler runtime.Marshaler, server TargetServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq AddTargetCredentialLibrariesRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := server.AddTargetCredentialLibraries(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_TargetService_SetTargetCredentialLibraries_0(ctx context.Context, marshaler runtime.Marshaler, client TargetServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq SetTargetCredentialLibrariesRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := client.SetTargetCredentialLibraries(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_TargetService_SetTargetCredentialLibraries_0(ctx context.Context, marshaler runtime.Marshaler, server TargetServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq SetTargetCredentialLibrariesRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := server.SetTargetCredentialLibraries(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_TargetService_RemoveTargetCredentialLibraries_0(ctx context.Context, marshaler runtime.Marshaler, client TargetServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq RemoveTargetCredentialLibrariesRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := client.RemoveTargetCredentialLibraries(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_TargetService_RemoveTargetCredentialLibraries_0(ctx context.Context, marshaler runtime.Marshaler, server TargetServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq RemoveTargetCredentialLibrariesRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
|
||||
}
|
||||
|
||||
protoReq.Id, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
|
||||
}
|
||||
|
||||
msg, err := server.RemoveTargetCredentialLibraries(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_TargetService_AddTargetCredentialSources_0(ctx context.Context, marshaler runtime.Marshaler, client TargetServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq AddTargetCredentialSourcesRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
@@ -1483,78 +1279,6 @@ func RegisterTargetServiceHandlerServer(ctx context.Context, mux *runtime.ServeM
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_TargetService_AddTargetCredentialLibraries_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.TargetService/AddTargetCredentialLibraries", runtime.WithHTTPPathPattern("/v1/targets/{id}:add-credential-libraries"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_TargetService_AddTargetCredentialLibraries_0(ctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_TargetService_AddTargetCredentialLibraries_0(ctx, mux, outboundMarshaler, w, req, response_TargetService_AddTargetCredentialLibraries_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_TargetService_SetTargetCredentialLibraries_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.TargetService/SetTargetCredentialLibraries", runtime.WithHTTPPathPattern("/v1/targets/{id}:set-credential-libraries"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_TargetService_SetTargetCredentialLibraries_0(ctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_TargetService_SetTargetCredentialLibraries_0(ctx, mux, outboundMarshaler, w, req, response_TargetService_SetTargetCredentialLibraries_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_TargetService_RemoveTargetCredentialLibraries_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.TargetService/RemoveTargetCredentialLibraries", runtime.WithHTTPPathPattern("/v1/targets/{id}:remove-credential-libraries"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_TargetService_RemoveTargetCredentialLibraries_0(ctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_TargetService_RemoveTargetCredentialLibraries_0(ctx, mux, outboundMarshaler, w, req, response_TargetService_RemoveTargetCredentialLibraries_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_TargetService_AddTargetCredentialSources_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@@ -1920,69 +1644,6 @@ func RegisterTargetServiceHandlerClient(ctx context.Context, mux *runtime.ServeM
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_TargetService_AddTargetCredentialLibraries_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.TargetService/AddTargetCredentialLibraries", runtime.WithHTTPPathPattern("/v1/targets/{id}:add-credential-libraries"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_TargetService_AddTargetCredentialLibraries_0(ctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_TargetService_AddTargetCredentialLibraries_0(ctx, mux, outboundMarshaler, w, req, response_TargetService_AddTargetCredentialLibraries_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_TargetService_SetTargetCredentialLibraries_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.TargetService/SetTargetCredentialLibraries", runtime.WithHTTPPathPattern("/v1/targets/{id}:set-credential-libraries"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_TargetService_SetTargetCredentialLibraries_0(ctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_TargetService_SetTargetCredentialLibraries_0(ctx, mux, outboundMarshaler, w, req, response_TargetService_SetTargetCredentialLibraries_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_TargetService_RemoveTargetCredentialLibraries_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
ctx, err = runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.TargetService/RemoveTargetCredentialLibraries", runtime.WithHTTPPathPattern("/v1/targets/{id}:remove-credential-libraries"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_TargetService_RemoveTargetCredentialLibraries_0(ctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_TargetService_RemoveTargetCredentialLibraries_0(ctx, mux, outboundMarshaler, w, req, response_TargetService_RemoveTargetCredentialLibraries_0{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_TargetService_AddTargetCredentialSources_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@@ -2139,33 +1800,6 @@ func (m response_TargetService_RemoveTargetHostSources_0) XXX_ResponseBody() int
|
||||
return response.Item
|
||||
}
|
||||
|
||||
type response_TargetService_AddTargetCredentialLibraries_0 struct {
|
||||
proto.Message
|
||||
}
|
||||
|
||||
func (m response_TargetService_AddTargetCredentialLibraries_0) XXX_ResponseBody() interface{} {
|
||||
response := m.Message.(*AddTargetCredentialLibrariesResponse)
|
||||
return response.Item
|
||||
}
|
||||
|
||||
type response_TargetService_SetTargetCredentialLibraries_0 struct {
|
||||
proto.Message
|
||||
}
|
||||
|
||||
func (m response_TargetService_SetTargetCredentialLibraries_0) XXX_ResponseBody() interface{} {
|
||||
response := m.Message.(*SetTargetCredentialLibrariesResponse)
|
||||
return response.Item
|
||||
}
|
||||
|
||||
type response_TargetService_RemoveTargetCredentialLibraries_0 struct {
|
||||
proto.Message
|
||||
}
|
||||
|
||||
func (m response_TargetService_RemoveTargetCredentialLibraries_0) XXX_ResponseBody() interface{} {
|
||||
response := m.Message.(*RemoveTargetCredentialLibrariesResponse)
|
||||
return response.Item
|
||||
}
|
||||
|
||||
type response_TargetService_AddTargetCredentialSources_0 struct {
|
||||
proto.Message
|
||||
}
|
||||
@@ -2218,12 +1852,6 @@ var (
|
||||
|
||||
pattern_TargetService_RemoveTargetHostSources_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "targets", "id"}, "remove-host-sources"))
|
||||
|
||||
pattern_TargetService_AddTargetCredentialLibraries_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "targets", "id"}, "add-credential-libraries"))
|
||||
|
||||
pattern_TargetService_SetTargetCredentialLibraries_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "targets", "id"}, "set-credential-libraries"))
|
||||
|
||||
pattern_TargetService_RemoveTargetCredentialLibraries_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "targets", "id"}, "remove-credential-libraries"))
|
||||
|
||||
pattern_TargetService_AddTargetCredentialSources_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "targets", "id"}, "add-credential-sources"))
|
||||
|
||||
pattern_TargetService_SetTargetCredentialSources_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "targets", "id"}, "set-credential-sources"))
|
||||
@@ -2256,12 +1884,6 @@ var (
|
||||
|
||||
forward_TargetService_RemoveTargetHostSources_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_TargetService_AddTargetCredentialLibraries_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_TargetService_SetTargetCredentialLibraries_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_TargetService_RemoveTargetCredentialLibraries_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_TargetService_AddTargetCredentialSources_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_TargetService_SetTargetCredentialSources_0 = runtime.ForwardResponseMessage
|
||||
|
||||
@@ -94,33 +94,6 @@ type TargetServiceClient interface {
|
||||
// is returned if a Host Source is attempted to be removed from the Target
|
||||
// when the Target does not have the Host Set.
|
||||
RemoveTargetHostSources(ctx context.Context, in *RemoveTargetHostSourcesRequest, opts ...grpc.CallOption) (*RemoveTargetHostSourcesResponse, error)
|
||||
// Deprecated: Do not use.
|
||||
// AddTargetCredentialLibraries adds Credential Libraries to this Target.
|
||||
// The provided request must include the Target ID to which the Credential
|
||||
// Libraries will be added. All Credential Libraries added to the provided
|
||||
// Target must be a child of a Store that is in the same scope as this
|
||||
// Target. If the scope or Target IDs are missing, malformed, or reference
|
||||
// non-existing resources, an error is returned. An error is returned if a
|
||||
// Credential Library is attempted to be added to a target that is already
|
||||
// present on the Target.
|
||||
AddTargetCredentialLibraries(ctx context.Context, in *AddTargetCredentialLibrariesRequest, opts ...grpc.CallOption) (*AddTargetCredentialLibrariesResponse, error)
|
||||
// Deprecated: Do not use.
|
||||
// SetTargetCredentialLibraries sets the Target's Credential Libraries.
|
||||
// Any existing Credential Libraries on the Target are deleted if they are
|
||||
// not included in this request. The provided request must include the scope,
|
||||
// and the Target ID on which the Credential Libraries will be set. All
|
||||
// Credential Libraries in the request must be a child of a Store that is
|
||||
// in the same scope as the provided Target. If any IDs are missing,
|
||||
// malformed, or references a non-existing resource, an error is returned.
|
||||
SetTargetCredentialLibraries(ctx context.Context, in *SetTargetCredentialLibrariesRequest, opts ...grpc.CallOption) (*SetTargetCredentialLibrariesResponse, error)
|
||||
// Deprecated: Do not use.
|
||||
// RemoveTargetCredentialLibraries removes the Credential Libraries from the
|
||||
// specified Target. The provided request must include the Target ID for the
|
||||
// Target from which the Credential Libraries will be removed. If the ID is
|
||||
// missing, or malformed, an error is returned. An error is returned if a
|
||||
// Credential Library is attempted to be removed from the Target when the
|
||||
// Target does not have the Credential Library.
|
||||
RemoveTargetCredentialLibraries(ctx context.Context, in *RemoveTargetCredentialLibrariesRequest, opts ...grpc.CallOption) (*RemoveTargetCredentialLibrariesResponse, error)
|
||||
// AddTargetCredentialSources adds Credential Sources to this Target.
|
||||
// The provided request must include the Target ID to which the Credential
|
||||
// Sources will be added. All Credential Sources added to the provided
|
||||
@@ -263,36 +236,6 @@ func (c *targetServiceClient) RemoveTargetHostSources(ctx context.Context, in *R
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func (c *targetServiceClient) AddTargetCredentialLibraries(ctx context.Context, in *AddTargetCredentialLibrariesRequest, opts ...grpc.CallOption) (*AddTargetCredentialLibrariesResponse, error) {
|
||||
out := new(AddTargetCredentialLibrariesResponse)
|
||||
err := c.cc.Invoke(ctx, "/controller.api.services.v1.TargetService/AddTargetCredentialLibraries", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func (c *targetServiceClient) SetTargetCredentialLibraries(ctx context.Context, in *SetTargetCredentialLibrariesRequest, opts ...grpc.CallOption) (*SetTargetCredentialLibrariesResponse, error) {
|
||||
out := new(SetTargetCredentialLibrariesResponse)
|
||||
err := c.cc.Invoke(ctx, "/controller.api.services.v1.TargetService/SetTargetCredentialLibraries", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func (c *targetServiceClient) RemoveTargetCredentialLibraries(ctx context.Context, in *RemoveTargetCredentialLibrariesRequest, opts ...grpc.CallOption) (*RemoveTargetCredentialLibrariesResponse, error) {
|
||||
out := new(RemoveTargetCredentialLibrariesResponse)
|
||||
err := c.cc.Invoke(ctx, "/controller.api.services.v1.TargetService/RemoveTargetCredentialLibraries", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *targetServiceClient) AddTargetCredentialSources(ctx context.Context, in *AddTargetCredentialSourcesRequest, opts ...grpc.CallOption) (*AddTargetCredentialSourcesResponse, error) {
|
||||
out := new(AddTargetCredentialSourcesResponse)
|
||||
err := c.cc.Invoke(ctx, "/controller.api.services.v1.TargetService/AddTargetCredentialSources", in, out, opts...)
|
||||
@@ -400,33 +343,6 @@ type TargetServiceServer interface {
|
||||
// is returned if a Host Source is attempted to be removed from the Target
|
||||
// when the Target does not have the Host Set.
|
||||
RemoveTargetHostSources(context.Context, *RemoveTargetHostSourcesRequest) (*RemoveTargetHostSourcesResponse, error)
|
||||
// Deprecated: Do not use.
|
||||
// AddTargetCredentialLibraries adds Credential Libraries to this Target.
|
||||
// The provided request must include the Target ID to which the Credential
|
||||
// Libraries will be added. All Credential Libraries added to the provided
|
||||
// Target must be a child of a Store that is in the same scope as this
|
||||
// Target. If the scope or Target IDs are missing, malformed, or reference
|
||||
// non-existing resources, an error is returned. An error is returned if a
|
||||
// Credential Library is attempted to be added to a target that is already
|
||||
// present on the Target.
|
||||
AddTargetCredentialLibraries(context.Context, *AddTargetCredentialLibrariesRequest) (*AddTargetCredentialLibrariesResponse, error)
|
||||
// Deprecated: Do not use.
|
||||
// SetTargetCredentialLibraries sets the Target's Credential Libraries.
|
||||
// Any existing Credential Libraries on the Target are deleted if they are
|
||||
// not included in this request. The provided request must include the scope,
|
||||
// and the Target ID on which the Credential Libraries will be set. All
|
||||
// Credential Libraries in the request must be a child of a Store that is
|
||||
// in the same scope as the provided Target. If any IDs are missing,
|
||||
// malformed, or references a non-existing resource, an error is returned.
|
||||
SetTargetCredentialLibraries(context.Context, *SetTargetCredentialLibrariesRequest) (*SetTargetCredentialLibrariesResponse, error)
|
||||
// Deprecated: Do not use.
|
||||
// RemoveTargetCredentialLibraries removes the Credential Libraries from the
|
||||
// specified Target. The provided request must include the Target ID for the
|
||||
// Target from which the Credential Libraries will be removed. If the ID is
|
||||
// missing, or malformed, an error is returned. An error is returned if a
|
||||
// Credential Library is attempted to be removed from the Target when the
|
||||
// Target does not have the Credential Library.
|
||||
RemoveTargetCredentialLibraries(context.Context, *RemoveTargetCredentialLibrariesRequest) (*RemoveTargetCredentialLibrariesResponse, error)
|
||||
// AddTargetCredentialSources adds Credential Sources to this Target.
|
||||
// The provided request must include the Target ID to which the Credential
|
||||
// Sources will be added. All Credential Sources added to the provided
|
||||
@@ -494,15 +410,6 @@ func (UnimplementedTargetServiceServer) SetTargetHostSources(context.Context, *S
|
||||
func (UnimplementedTargetServiceServer) RemoveTargetHostSources(context.Context, *RemoveTargetHostSourcesRequest) (*RemoveTargetHostSourcesResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RemoveTargetHostSources not implemented")
|
||||
}
|
||||
func (UnimplementedTargetServiceServer) AddTargetCredentialLibraries(context.Context, *AddTargetCredentialLibrariesRequest) (*AddTargetCredentialLibrariesResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AddTargetCredentialLibraries not implemented")
|
||||
}
|
||||
func (UnimplementedTargetServiceServer) SetTargetCredentialLibraries(context.Context, *SetTargetCredentialLibrariesRequest) (*SetTargetCredentialLibrariesResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetTargetCredentialLibraries not implemented")
|
||||
}
|
||||
func (UnimplementedTargetServiceServer) RemoveTargetCredentialLibraries(context.Context, *RemoveTargetCredentialLibrariesRequest) (*RemoveTargetCredentialLibrariesResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RemoveTargetCredentialLibraries not implemented")
|
||||
}
|
||||
func (UnimplementedTargetServiceServer) AddTargetCredentialSources(context.Context, *AddTargetCredentialSourcesRequest) (*AddTargetCredentialSourcesResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AddTargetCredentialSources not implemented")
|
||||
}
|
||||
@@ -741,60 +648,6 @@ func _TargetService_RemoveTargetHostSources_Handler(srv interface{}, ctx context
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TargetService_AddTargetCredentialLibraries_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AddTargetCredentialLibrariesRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TargetServiceServer).AddTargetCredentialLibraries(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/controller.api.services.v1.TargetService/AddTargetCredentialLibraries",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TargetServiceServer).AddTargetCredentialLibraries(ctx, req.(*AddTargetCredentialLibrariesRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TargetService_SetTargetCredentialLibraries_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SetTargetCredentialLibrariesRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TargetServiceServer).SetTargetCredentialLibraries(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/controller.api.services.v1.TargetService/SetTargetCredentialLibraries",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TargetServiceServer).SetTargetCredentialLibraries(ctx, req.(*SetTargetCredentialLibrariesRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TargetService_RemoveTargetCredentialLibraries_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RemoveTargetCredentialLibrariesRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TargetServiceServer).RemoveTargetCredentialLibraries(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/controller.api.services.v1.TargetService/RemoveTargetCredentialLibraries",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TargetServiceServer).RemoveTargetCredentialLibraries(ctx, req.(*RemoveTargetCredentialLibrariesRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TargetService_AddTargetCredentialSources_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AddTargetCredentialSourcesRequest)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -904,18 +757,6 @@ var TargetService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "RemoveTargetHostSources",
|
||||
Handler: _TargetService_RemoveTargetHostSources_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "AddTargetCredentialLibraries",
|
||||
Handler: _TargetService_AddTargetCredentialLibraries_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SetTargetCredentialLibraries",
|
||||
Handler: _TargetService_SetTargetCredentialLibraries_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "RemoveTargetCredentialLibraries",
|
||||
Handler: _TargetService_RemoveTargetCredentialLibraries_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "AddTargetCredentialSources",
|
||||
Handler: _TargetService_AddTargetCredentialSources_Handler,
|
||||
|
||||
@@ -108,7 +108,7 @@ func Test_ActionParsingValidation(t *testing.T) {
|
||||
func Test_ValidateType(t *testing.T) {
|
||||
t.Parallel()
|
||||
var g Grant
|
||||
for i := resource.Unknown; i <= resource.CredentialLibrary; i++ {
|
||||
for i := resource.Unknown; i <= resource.Credential; i++ {
|
||||
g.typ = i
|
||||
if i == resource.Controller {
|
||||
assert.Error(t, g.validateType())
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package controller.api.resources.credentials.v1;
|
||||
|
||||
import "controller/api/resources/scopes/v1/scope.proto";
|
||||
import "controller/custom_options/v1/options.proto";
|
||||
import "google/api/visibility.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
|
||||
option go_package = "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentials;credentials";
|
||||
|
||||
// Credential contains all fields related to an Credential resource
|
||||
message Credential {
|
||||
// Output only. The ID of the Credential.
|
||||
string id = 10; // @gotags: `class:"public"`
|
||||
|
||||
// The ID of the Credential Store of which this Credential is a part.
|
||||
string credential_store_id = 20 [json_name = "credential_store_id"]; // @gotags: `class:"public"`
|
||||
|
||||
// Output only. Scope information for this Credential.
|
||||
resources.scopes.v1.ScopeInfo scope = 30;
|
||||
|
||||
// Optional name for identification purposes.
|
||||
google.protobuf.StringValue name = 40 [
|
||||
(custom_options.v1.generate_sdk_option) = true,
|
||||
(custom_options.v1.mask_mapping) = {
|
||||
this: "name"
|
||||
that: "Name"
|
||||
}
|
||||
]; // @gotags: `class:"public"`
|
||||
|
||||
// Optional user-set description for identification purposes.
|
||||
google.protobuf.StringValue description = 50 [
|
||||
(custom_options.v1.generate_sdk_option) = true,
|
||||
(custom_options.v1.mask_mapping) = {
|
||||
this: "description"
|
||||
that: "Description"
|
||||
}
|
||||
]; // @gotags: `class:"public"`
|
||||
|
||||
// Output only. The time this resource was created.
|
||||
google.protobuf.Timestamp created_time = 60 [json_name = "created_time"]; // @gotags: `class:"public"`
|
||||
|
||||
// Output only. The time this resource was last updated.
|
||||
google.protobuf.Timestamp updated_time = 70 [json_name = "updated_time"]; // @gotags: `class:"public"`
|
||||
|
||||
// Version is used in mutation requests, after the initial creation, to ensure this resource has not changed.
|
||||
// The mutation will fail if the version does not match the latest known good version.
|
||||
uint32 version = 80; // @gotags: `class:"public"`
|
||||
|
||||
// The Credential type.
|
||||
string type = 90; // @gotags: `class:"public"`
|
||||
|
||||
oneof attrs {
|
||||
// The attributes that are applicable for the specific Credential type.
|
||||
google.protobuf.Struct attributes = 100 [
|
||||
(custom_options.v1.generate_sdk_option) = true,
|
||||
(custom_options.v1.subtype) = "default"
|
||||
];
|
||||
UsernamePasswordAttributes username_password_attributes = 101 [
|
||||
(google.api.field_visibility).restriction = "INTERNAL",
|
||||
(custom_options.v1.generate_sdk_option) = true,
|
||||
(custom_options.v1.subtype) = "username_password"
|
||||
];
|
||||
}
|
||||
|
||||
// Output only. The available actions on this resource for this user.
|
||||
repeated string authorized_actions = 300 [json_name = "authorized_actions"]; // @gotags: `class:"public"`
|
||||
}
|
||||
|
||||
// The attributes of a UsernamePassword Credential.
|
||||
message UsernamePasswordAttributes {
|
||||
// The username associated with the credential.
|
||||
google.protobuf.StringValue username = 10 [
|
||||
(custom_options.v1.generate_sdk_option) = true,
|
||||
(custom_options.v1.mask_mapping) = {
|
||||
this: "attributes.username"
|
||||
that: "Username"
|
||||
}
|
||||
]; // @gotags: `class:"public"`
|
||||
|
||||
// Input only. The password associated with the credential.
|
||||
google.protobuf.StringValue password = 20 [
|
||||
json_name = "password",
|
||||
(custom_options.v1.generate_sdk_option) = true,
|
||||
(custom_options.v1.mask_mapping) = {
|
||||
this: "attributes.password"
|
||||
that: "Password"
|
||||
}
|
||||
]; // @gotags: `class:"secret"`
|
||||
|
||||
// Output only. The hmac value of the password.
|
||||
string password_hmac = 30 [
|
||||
json_name = "password_hmac",
|
||||
(custom_options.v1.mask_mapping) = {
|
||||
this: "attributes.password_hmac"
|
||||
that: "PasswordHmac"
|
||||
}
|
||||
]; // @gotags: `class:"public"`
|
||||
}
|
||||
@@ -47,23 +47,6 @@ message CredentialSource {
|
||||
string credential_type = 70; // @gotags: `class:"public"`
|
||||
}
|
||||
|
||||
message CredentialLibrary {
|
||||
// The ID of the Credential Library.
|
||||
string id = 10; // @gotags: `class:"public"`
|
||||
|
||||
// Output only. The name of the Credential Library.
|
||||
string name = 20; // @gotags: `class:"public"`
|
||||
|
||||
// Output only. The description of the Credential Library.
|
||||
string description = 30; // @gotags: `class:"public"`
|
||||
|
||||
// Output only. The Credential Store to which this Credential Library belongs.
|
||||
string credential_store_id = 40 [json_name = "credential_store_id"]; // @gotags: `class:"public"`
|
||||
|
||||
// Output only. The type of the credential library.
|
||||
string type = 60; // @gotags: `class:"public"`
|
||||
}
|
||||
|
||||
// The actual secret for a session credential.
|
||||
message SessionSecret {
|
||||
// Output only. The base64-encoded value representing the raw bytes from the
|
||||
@@ -79,15 +62,16 @@ message SessionCredential {
|
||||
// Output only. The credential source information.
|
||||
CredentialSource credential_source = 1;
|
||||
|
||||
// Output only. The library which generated this credential. Deprecated: use credential_source instead.
|
||||
CredentialLibrary credential_library = 10 [deprecated = true];
|
||||
|
||||
// Output only. The secret of this credential base64 encoded.
|
||||
SessionSecret secret = 20;
|
||||
|
||||
// Output only. The fields of the strongly typed credential, empty if the credential type of the
|
||||
// credential source is unspecified.
|
||||
google.protobuf.Struct credential = 40;
|
||||
|
||||
// Deprecated fields
|
||||
reserved "credential_library";
|
||||
reserved 10;
|
||||
}
|
||||
|
||||
// Target contains all fields related to a Target resource
|
||||
@@ -174,17 +158,6 @@ message Target {
|
||||
}
|
||||
]; // @gotags: `class:"public"`
|
||||
|
||||
// Output only. The IDs of the application credential library ids associated with this Target. Deprecated: use application_credential_source_ids instead.
|
||||
repeated string application_credential_library_ids = 150 [
|
||||
json_name = "application_credential_library_ids",
|
||||
deprecated = true
|
||||
]; // @gotags: `class:"public"`
|
||||
// Output only. The application credential libraries associated with this Target. Deprecated: use application_credential_sources instead.
|
||||
repeated CredentialLibrary application_credential_libraries = 180 [
|
||||
json_name = "application_credential_libraries",
|
||||
deprecated = true
|
||||
];
|
||||
|
||||
// Output only. The IDs of the application credential source ids associated with this Target.
|
||||
repeated string application_credential_source_ids = 400 [json_name = "application_credential_source_ids"]; // @gotags: `class:"public"`
|
||||
// Output only. The application credential sources associated with this Target.
|
||||
@@ -210,6 +183,10 @@ message Target {
|
||||
|
||||
// Output only. The available actions on this resource for this user.
|
||||
repeated string authorized_actions = 300 [json_name = "authorized_actions"]; // @gotags: `class:"public"`
|
||||
|
||||
// Deprecated fields
|
||||
reserved "application_credential_library_ids", "application_credential_libraries";
|
||||
reserved 150, 180;
|
||||
}
|
||||
|
||||
// TcpTargetAttributes contains attributes relevant to Targets of type "tcp"
|
||||
|
||||
Loaded 100 of 160 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user