Skip to content

Commit fab67b4

Browse files
committed
prevent default contract creation as well
Signed-off-by: Sylwester Piskozub <sylwesterpiskozub@gmail.com>
1 parent 5e85aee commit fab67b4

4 files changed

Lines changed: 34 additions & 6 deletions

File tree

app/controlplane/cmd/wire_gen.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/internal/service/attestation.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ type AttestationService struct {
5959
projectVersionUseCase *biz.ProjectVersionUseCase
6060
projectUseCase *biz.ProjectUseCase
6161
signingUseCase *biz.SigningUseCase
62+
userUseCase *biz.UserUseCase
6263
}
6364

6465
type NewAttestationServiceOpts struct {
@@ -78,6 +79,7 @@ type NewAttestationServiceOpts struct {
7879
ProjectUC *biz.ProjectUseCase
7980
ProjectVersionUC *biz.ProjectVersionUseCase
8081
SigningUseCase *biz.SigningUseCase
82+
UserUC *biz.UserUseCase
8183
Opts []NewOpt
8284
}
8385

@@ -100,6 +102,7 @@ func NewAttestationService(opts *NewAttestationServiceOpts) *AttestationService
100102
projectUseCase: opts.ProjectUC,
101103
projectVersionUseCase: opts.ProjectVersionUC,
102104
signingUseCase: opts.SigningUseCase,
105+
userUseCase: opts.UserUC,
103106
}
104107
}
105108

@@ -748,14 +751,21 @@ func (s *AttestationService) FindOrCreateWorkflow(ctx context.Context, req *cpAP
748751
return &cpAPI.FindOrCreateWorkflowResponse{Result: bizWorkflowToPb(wf)}, nil
749752
}
750753

754+
// Get organization
755+
org, err := s.orgUseCase.FindByID(ctx, apiToken.OrgID)
756+
if err != nil {
757+
return nil, handleUseCaseErr(err, s.log)
758+
}
759+
751760
// the workflow does not exist, let's create it alongside its project and contract
752761
createOpts := &biz.WorkflowCreateOpts{
753-
OrgID: apiToken.OrgID,
754-
Name: req.GetWorkflowName(),
755-
Project: req.GetProjectName(),
756-
ContractName: req.GetContractName(),
757-
ContractBytes: req.GetContractBytes(),
758-
ImplicitCreation: true, // Mark as implicit creation from attestation init
762+
OrgID: apiToken.OrgID,
763+
Name: req.GetWorkflowName(),
764+
Project: req.GetProjectName(),
765+
ContractName: req.GetContractName(),
766+
ContractBytes: req.GetContractBytes(),
767+
ImplicitCreation: true, // Mark as implicit creation from attestation init
768+
OrgRestrictContractCreationToAdmins: org.RestrictContractCreationToOrgAdmins,
759769
}
760770

761771
// set project owner if RBAC is enabled
@@ -766,6 +776,14 @@ func (s *AttestationService) FindOrCreateWorkflow(ctx context.Context, req *cpAP
766776
return nil, handleUseCaseErr(err, s.log)
767777
}
768778
createOpts.Owner = &userID
779+
780+
// Check if user is an org admin
781+
membership, err := s.userUseCase.MembershipInOrg(ctx, user.ID, org.Name)
782+
783+
if err == nil && membership != nil {
784+
isAdmin := membership.Role.IsAdmin()
785+
createOpts.UserIsOrgAdmin = isAdmin
786+
}
769787
}
770788

771789
wf, err := s.workflowUseCase.Create(ctx, createOpts)

app/controlplane/pkg/biz/workflow.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ type WorkflowCreateOpts struct {
8181
Owner *uuid.UUID
8282
// ImplicitCreation indicates whether this workflow is being created implicitly via attestation init
8383
ImplicitCreation bool
84+
// UserIsOrgAdmin indicates whether the current user is an organization admin
85+
UserIsOrgAdmin bool
86+
// OrgRestrictContractCreationToAdmins is the organization's setting for restricting contract creation
87+
OrgRestrictContractCreationToAdmins bool
8488
}
8589

8690
type WorkflowUpdateOpts struct {

app/controlplane/pkg/data/workflow.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ func (r *WorkflowRepo) Create(ctx context.Context, opts *biz.WorkflowCreateOpts)
118118
contract, err := contractInOrg(ctx, r.data.DB, orgUUID, nil, &defaultContractName)
119119
if err != nil {
120120
if ent.IsNotFound(err) {
121+
// Check if contract creation is restricted to org admins
122+
if opts.OrgRestrictContractCreationToAdmins && !opts.UserIsOrgAdmin {
123+
return biz.NewErrUnauthorizedStr("only organization admins can create contracts")
124+
}
125+
121126
// Create a new contract associated with the workflow
122127
contract, _, err = r.contractRepo.addCreateToTx(ctx, tx, &biz.ContractCreateOpts{
123128
OrgID: orgUUID,

0 commit comments

Comments
 (0)