Merge remote-tracking branch 'origin/main' into llb-byow

This commit is contained in:
Jeff Mitchell committed 2022-06-10 19:05:27 -04:00
commit 5d3facf561
56 files changed
+1455 -320

No files matched your search

+4 -4
View File
@@ -569,7 +569,7 @@ func (v verifier) performAuthCheck(ctx context.Context) (
}
retAcl = perms.NewACL(parsedGrants...)
aclResults = retAcl.Allowed(*v.res, v.act)
aclResults = retAcl.Allowed(*v.res, v.act, userId)
// We don't set authenticated above because setting this but not authorized
// is used for further permissions checks, such as during recursive listing.
// So we want to make sure any code relying on that has the full set of
@@ -619,7 +619,7 @@ func (r *VerifyResults) fetchActions(id string, typ resource.Type, availableActi
ret := make(action.ActionSet, 0, len(availableActions))
for _, act := range availableActions {
if r.v.acl.Allowed(*res, act).Authorized {
if r.v.acl.Allowed(*res, act, r.UserId).Authorized {
ret = append(ret, act)
}
}
@@ -637,7 +637,7 @@ func (r *VerifyResults) FetchOutputFields(res perms.Resource, act action.Type) p
return nil
}
return r.v.acl.Allowed(res, act).OutputFields
return r.v.acl.Allowed(res, act, r.UserId).OutputFields
}
// GetTokenFromRequest pulls the token from either the Authorization header or
@@ -675,7 +675,7 @@ func GetTokenFromRequest(ctx context.Context, kmsCache *kms.Kms, req *http.Reque
if receivedTokenType == AuthTokenTypeUnknown || fullToken == "" {
// We didn't find auth info or a client screwed up and put in a blank
// header instead of nothing at all, so return blank which will indicate
// the anonymouse user
// the anonymous user
return "", "", uint32(AuthTokenTypeUnknown)
}
+1 -1
View File
@@ -361,7 +361,7 @@ func (c *Controller) registerJobs() error {
if err := pluginhost.RegisterJobs(c.baseContext, c.scheduler, rw, rw, c.kms, c.conf.HostPlugins); err != nil {
return err
}
if err := session.RegisterJobs(c.baseContext, c.scheduler, rw, c.conf.StatusGracePeriodDuration); err != nil {
if err := session.RegisterJobs(c.baseContext, c.scheduler, rw, rw, c.kms, c.conf.StatusGracePeriodDuration); err != nil {
return err
}
if err := serversjob.RegisterJobs(c.baseContext, c.scheduler, rw, rw, c.kms); err != nil {
@@ -152,7 +152,7 @@ func (s Service) ListSessions(ctx context.Context, req *pbs.ListSessionsRequest)
RootScopeId: req.GetScopeId(),
Type: resource.Session,
Recursive: req.GetRecursive(),
AuthzProtectedEntityProvider: repo,
AuthzProtectedEntityProvider: session.ListForAuthzCheck(repo, session.WithTerminated(req.IncludeTerminated)),
ActionSet: IdActions,
},
)
@@ -232,6 +232,7 @@ func TestList(t *testing.T) {
conn, _ := db.TestSetup(t, "postgres")
wrap := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrap)
ctx := context.Background()
iamRepo := iam.TestRepo(t, conn, wrap)
@@ -260,16 +261,17 @@ func TestList(t *testing.T) {
hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0]
h := static.TestHosts(t, conn, hc.GetPublicId(), 1)[0]
static.TestSetMembers(t, conn, hs.GetPublicId(), []*static.Host{h})
tar := tcp.TestTarget(context.Background(), t, conn, pWithSessions.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()}))
tar := tcp.TestTarget(ctx, t, conn, pWithSessions.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()}))
hcOther := static.TestCatalogs(t, conn, pWithOtherSessions.GetPublicId(), 1)[0]
hsOther := static.TestSets(t, conn, hcOther.GetPublicId(), 1)[0]
hOther := static.TestHosts(t, conn, hcOther.GetPublicId(), 1)[0]
static.TestSetMembers(t, conn, hsOther.GetPublicId(), []*static.Host{hOther})
tarOther := tcp.TestTarget(context.Background(), t, conn, pWithOtherSessions.GetPublicId(), "test", target.WithHostSources([]string{hsOther.GetPublicId()}))
tarOther := tcp.TestTarget(ctx, t, conn, pWithOtherSessions.GetPublicId(), "test", target.WithHostSources([]string{hsOther.GetPublicId()}))
var wantSession []*pb.Session
var totalSession []*pb.Session
var wantIncludeTerminatedSessions []*pb.Session
for i := 0; i < 10; i++ {
sess := session.TestSession(t, conn, wrap, session.ComposedOf{
UserId: uId,
@@ -281,7 +283,7 @@ func TestList(t *testing.T) {
Endpoint: "tcp://127.0.0.1:22",
})
c := session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22, "127.0.0.2", 23, "127.0.0.1")
session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22, "127.0.0.2", 23, "127.0.0.1")
status, states := convertStates(sess.States)
@@ -304,17 +306,11 @@ func TestList(t *testing.T) {
Certificate: sess.Certificate,
Type: tcp.Subtype.String(),
AuthorizedActions: testAuthorizedActions,
Connections: []*pb.Connection{
{
ClientTcpAddress: c.ClientTcpAddress,
ClientTcpPort: c.ClientTcpPort,
EndpointTcpAddress: c.EndpointTcpAddress,
EndpointTcpPort: c.EndpointTcpPort,
},
},
Connections: []*pb.Connection{}, // connections should not be returned for list
})
totalSession = append(totalSession, wantSession[i])
wantIncludeTerminatedSessions = append(wantIncludeTerminatedSessions, wantSession[i])
sess = session.TestSession(t, conn, wrap, session.ComposedOf{
UserId: uIdOther,
@@ -326,7 +322,7 @@ func TestList(t *testing.T) {
Endpoint: "tcp://127.0.0.1:22",
})
c = session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22, "127.0.0.2", 23, "127.0.0.1")
session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22, "127.0.0.2", 23, "127.0.0.1")
status, states = convertStates(sess.States)
@@ -349,17 +345,57 @@ func TestList(t *testing.T) {
Certificate: sess.Certificate,
Type: tcp.Subtype.String(),
AuthorizedActions: testAuthorizedActions,
Connections: []*pb.Connection{
{
ClientTcpAddress: c.ClientTcpAddress,
ClientTcpPort: c.ClientTcpPort,
EndpointTcpAddress: c.EndpointTcpAddress,
EndpointTcpPort: c.EndpointTcpPort,
},
},
Connections: []*pb.Connection{}, // connections should not be returned for list
})
}
{
sess := session.TestSession(t, conn, wrap, session.ComposedOf{
UserId: uId,
HostId: h.GetPublicId(),
TargetId: tar.GetPublicId(),
HostSetId: hs.GetPublicId(),
AuthTokenId: at.GetPublicId(),
ScopeId: pWithSessions.GetPublicId(),
Endpoint: "tcp://127.0.0.1:22",
})
sess, err := sessRepo.CancelSession(ctx, sess.PublicId, sess.Version)
require.NoError(t, err)
terminated, err := sessRepo.TerminateCompletedSessions(ctx)
require.NoError(t, err)
require.Equal(t, 1, terminated)
sess, _, err = sessRepo.LookupSession(ctx, sess.PublicId)
require.NoError(t, err)
status, states := convertStates(sess.States)
expected := &pb.Session{
Id: sess.GetPublicId(),
ScopeId: pWithSessions.GetPublicId(),
AuthTokenId: at.GetPublicId(),
UserId: at.GetIamUserId(),
TargetId: sess.TargetId,
Endpoint: sess.Endpoint,
HostSetId: sess.HostSetId,
HostId: sess.HostId,
Version: sess.Version,
UpdatedTime: sess.UpdateTime.GetTimestamp(),
CreatedTime: sess.CreateTime.GetTimestamp(),
ExpirationTime: sess.ExpirationTime.GetTimestamp(),
Scope: &scopes.ScopeInfo{Id: pWithSessions.GetPublicId(), Type: scope.Project.String(), ParentScopeId: o.GetPublicId()},
Status: status,
States: states,
Certificate: sess.Certificate,
TerminationReason: sess.TerminationReason,
Type: tcp.Subtype.String(),
AuthorizedActions: testAuthorizedActions,
Connections: []*pb.Connection{}, // connections should not be returned for list
}
wantIncludeTerminatedSessions = append(wantIncludeTerminatedSessions, expected)
}
cases := []struct {
name string
req *pbs.ListSessionsRequest
@@ -371,6 +407,11 @@ func TestList(t *testing.T) {
req: &pbs.ListSessionsRequest{ScopeId: pWithSessions.GetPublicId()},
res: &pbs.ListSessionsResponse{Items: wantSession},
},
{
name: "List Many Include Terminated",
req: &pbs.ListSessionsRequest{ScopeId: pWithSessions.GetPublicId(), IncludeTerminated: true},
res: &pbs.ListSessionsResponse{Items: wantIncludeTerminatedSessions},
},
{
name: "List No Sessions",
req: &pbs.ListSessionsRequest{ScopeId: pNoSessions.GetPublicId()},
@@ -423,14 +464,8 @@ func TestList(t *testing.T) {
require.Equal(len(tc.res.GetItems()), len(got.GetItems()), "Didn't get expected number of sessions: %v", got.GetItems())
for i, wantSess := range tc.res.GetItems() {
assert.True(got.GetItems()[i].GetExpirationTime().AsTime().Sub(wantSess.GetExpirationTime().AsTime()) < 10*time.Millisecond)
assert.Equal(1, len(wantSess.GetConnections()))
assert.Equal(0, len(wantSess.GetConnections())) // no connections on list
wantSess.ExpirationTime = got.GetItems()[i].GetExpirationTime()
for _, c := range got.GetItems()[i].GetConnections() {
assert.Equal("127.0.0.1", c.ClientTcpAddress)
assert.Equal(uint32(22), c.ClientTcpPort)
assert.Equal("127.0.0.2", c.EndpointTcpAddress)
assert.Equal(uint32(23), c.EndpointTcpPort)
}
}
}
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListSessions(%q) got response %q, wanted %q", tc.req, got, tc.res)
@@ -1581,45 +1581,56 @@ func toProto(ctx context.Context, in target.Target, hostSources []target.HostSou
})
}
}
if outputFields.Has(globals.ApplicationCredentialLibraryIdsField) {
for _, cs := range credSources {
out.ApplicationCredentialLibraryIds = append(out.ApplicationCredentialLibraryIds, cs.Id())
var appCredSources, egressCredSources []*pb.CredentialSource
var appCredSourceIds, egressCredSourceIds []string
var appCredLibraries []*pb.CredentialLibrary
for _, cs := range credSources {
switch cs.CredentialPurpose() {
case credential.ApplicationPurpose:
appCredSourceIds = append(appCredSourceIds, cs.Id())
appCredSources = append(appCredSources, &pb.CredentialSource{
Id: cs.Id(),
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(),
CredentialStoreId: cs.CredentialStoreId(),
})
egressCredSourceIds = append(egressCredSourceIds, cs.Id())
default:
return nil, errors.New(ctx, errors.Internal, op, fmt.Sprintf("unrecognized purpose %q for credential source on target", cs.CredentialPurpose()))
}
}
if outputFields.Has(globals.ApplicationCredentialLibraryIdsField) {
out.ApplicationCredentialLibraryIds = appCredSourceIds
}
if outputFields.Has(globals.ApplicationCredentialSourceIdsField) {
for _, cs := range credSources {
out.ApplicationCredentialSourceIds = append(out.ApplicationCredentialSourceIds, cs.Id())
}
out.ApplicationCredentialSourceIds = appCredSourceIds
}
if outputFields.Has(globals.ApplicationCredentialLibrariesField) {
for _, cs := range credSources {
switch credential.Purpose(cs.CredentialPurpose()) {
case credential.ApplicationPurpose:
out.ApplicationCredentialLibraries = append(out.ApplicationCredentialLibraries, &pb.CredentialLibrary{
Id: cs.Id(),
CredentialStoreId: cs.CredentialStoreId(),
})
case credential.IngressPurpose, credential.EgressPurpose:
// TODO: When we support other purposes add them to different fields here.
default:
return nil, errors.New(ctx, errors.Internal, op, fmt.Sprintf("unrecognized purpose %q for credential source on target", cs.CredentialPurpose()))
}
}
out.ApplicationCredentialLibraries = appCredLibraries
}
if outputFields.Has(globals.ApplicationCredentialSourcesField) {
for _, cs := range credSources {
switch credential.Purpose(cs.CredentialPurpose()) {
case credential.ApplicationPurpose:
out.ApplicationCredentialSources = append(out.ApplicationCredentialSources, &pb.CredentialSource{
Id: cs.Id(),
CredentialStoreId: cs.CredentialStoreId(),
})
case credential.IngressPurpose, credential.EgressPurpose:
// TODO: When we support other purposes add them to different fields here.
default:
return nil, errors.New(ctx, errors.Internal, op, fmt.Sprintf("unrecognized purpose %q for credential source on target", cs.CredentialPurpose()))
}
}
out.ApplicationCredentialSources = appCredSources
}
if outputFields.Has(globals.EgressCredentialSourceIdsField) {
out.EgressCredentialSourceIds = egressCredSourceIds
}
if outputFields.Has(globals.EgressCredentialSourcesField) {
out.EgressCredentialSources = egressCredSources
}
if outputFields.Has(globals.AttributesField) {
if err := subtypeRegistry.setAttributes(in.GetType(), in, &out); err != nil {
+32 -2
View File
@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"net"
"strconv"
"strings"
@@ -373,6 +374,11 @@ type TestControllerOpts struct {
// If true, the controller will not be started
DisableAutoStart bool
// DisableEventing, if true the test controller will not create events
// You must not run the test in parallel (no calls to t.Parallel) since the
// this option relies on modifying the system wide default eventer.
DisableEventing bool
// DisableAuthorizationFailures will still cause authz checks to be
// performed but they won't cause 403 Forbidden. Useful for API-level
// testing to avoid a lot of faff.
@@ -543,8 +549,32 @@ func TestControllerConfig(t testing.TB, ctx context.Context, tc *TestController,
}
opts.Config.Controller.SchedulerRunJobInterval = opts.SchedulerRunJobInterval
if err := tc.b.SetupEventing(tc.b.Logger, tc.b.StderrLock, opts.Config.Controller.Name, base.WithEventerConfig(opts.Config.Eventing)); err != nil {
t.Fatal(err)
switch {
case opts.DisableEventing:
opts.Config.Eventing = &event.EventerConfig{
AuditEnabled: false,
ObservationsEnabled: false,
SysEventsEnabled: false,
}
testLogger := hclog.New(&hclog.LoggerOptions{
Mutex: tc.b.StderrLock,
Output: io.Discard,
})
e, err := event.NewEventer(
testLogger,
tc.b.StderrLock,
opts.Config.Controller.Name,
*opts.Config.Eventing,
)
if err != nil {
t.Fatal(err)
}
tc.b.Eventer = e
event.TestWithoutEventing(t) // this ensures the sys eventer will also stop eventing
default:
if err := tc.b.SetupEventing(tc.b.Logger, tc.b.StderrLock, opts.Config.Controller.Name, base.WithEventerConfig(opts.Config.Eventing)); err != nil {
t.Fatal(err)
}
}
// Initialize status grace period
@@ -1,7 +1,12 @@
package controller
import (
"bytes"
"io"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_TestController(t *testing.T) {
@@ -17,4 +22,44 @@ func Test_TestController(t *testing.T) {
defer tc1.Shutdown()
defer tc2.Shutdown()
})
t.Run("controller-without-eventing", func(t *testing.T) {
const op = "Test_TestWithoutEventing"
assert := assert.New(t)
// this isn't the best solution for capturing stdout but it works for now...
captureFn := func(fn func()) string {
old := os.Stdout
defer func() {
os.Stderr = old
}()
r, w, _ := os.Pipe()
os.Stderr = w
{
fn()
}
outC := make(chan string)
// copy the output in a separate goroutine so writing to stderr can't block indefinitely
go func() {
var buf bytes.Buffer
io.Copy(&buf, r)
outC <- buf.String()
}()
// back to normal state
w.Close()
return <-outC
}
assert.Empty(captureFn(func() {
tc := NewTestController(t, &TestControllerOpts{DisableEventing: true})
defer tc.Shutdown()
}))
assert.NotEmpty(captureFn(func() {
tc := NewTestController(t, nil)
defer tc.Shutdown()
}))
})
}