Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ Workflow Contracts define the structure and requirements for CI/CD attestations.
- **Actions**: Implement business logic in `internal/action/`
- **Policy Development**: Use `internal/policydevel/` for local policy testing
- **Default Endpoints**: Override with `-ldflags` at build time using `defaultCASAPI` and `defaultCPAPI` variables
- **Documentation**: After adding or modifying CLI commands, regenerate docs with `make generate` (runs `go generate ./...` which includes CLI docs)

### Artifact CAS Development
- **Storage Backends**: Implement new backends in `pkg/blobmanager/` with Provider interface
Expand Down
6 changes: 6 additions & 0 deletions app/cli/cmd/organization_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func newOrganizationUpdateCmd() *cobra.Command {
preventImplicitWorkflowCreation bool
restrictContractCreation bool
apiTokenMaxDaysInactive string
enableAIAgentCollector bool
)

cmd := &cobra.Command{
Expand All @@ -54,6 +55,10 @@ func newOrganizationUpdateCmd() *cobra.Command {
opts.RestrictContractCreation = &restrictContractCreation
}

if cmd.Flags().Changed("enable-ai-agent-collector") {
opts.EnableAIAgentCollector = &enableAIAgentCollector
}

if cmd.Flags().Changed("api-token-max-days-inactive") {
days, err := strconv.Atoi(apiTokenMaxDaysInactive)
if err != nil {
Expand Down Expand Up @@ -84,5 +89,6 @@ func newOrganizationUpdateCmd() *cobra.Command {
cmd.Flags().BoolVar(&preventImplicitWorkflowCreation, "prevent-implicit-workflow-creation", false, "prevent workflows and projects from being created implicitly during attestation init")
cmd.Flags().BoolVar(&restrictContractCreation, "restrict-contract-creation", false, "restrict contract creation (org-level and project-level) to only organization admins (owner/admin roles)")
cmd.Flags().StringVar(&apiTokenMaxDaysInactive, "api-token-max-days-inactive", "", "maximum days of inactivity before API tokens are auto-revoked (e.g. '90', '0' to disable)")
cmd.Flags().BoolVar(&enableAIAgentCollector, "enable-ai-agent-collector", false, "enable automatic AI agent config collection during attestation init")
return cmd
}
1 change: 1 addition & 0 deletions app/cli/documentation/cli-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2824,6 +2824,7 @@ Options
```
--api-token-max-days-inactive string maximum days of inactivity before API tokens are auto-revoked (e.g. '90', '0' to disable)
--block set the default policy violation blocking strategy
--enable-ai-agent-collector enable automatic AI agent config collection during attestation init
-h, --help help for update
--name string organization name
--policies-allowed-hostnames strings set the allowed hostnames for the policy engine
Expand Down
11 changes: 10 additions & 1 deletion app/cli/pkg/action/attestation_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"context"
"errors"
"fmt"
"slices"
"strconv"

"github.com/chainloop-dev/chainloop/app/cli/internal/token"
Expand Down Expand Up @@ -196,6 +197,7 @@ func (action *AttestationInit) Run(ctx context.Context, opts *AttestationInitRun
attestationID string
blockOnPolicyViolation bool
policiesAllowedHostnames []string
enableAIAgentCollector bool
// Timestamp Authority URL for new attestations
timestampAuthorityURL, signingCAName string
uiDashboardURL string
Expand Down Expand Up @@ -226,6 +228,7 @@ func (action *AttestationInit) Run(ctx context.Context, opts *AttestationInitRun
workflowMeta.Organization = result.GetOrganization()
blockOnPolicyViolation = result.GetBlockOnPolicyViolation()
policiesAllowedHostnames = result.GetPoliciesAllowedHostnames()
enableAIAgentCollector = result.GetEnableAiAgentCollector()
signingOpts := result.GetSigningOptions()
timestampAuthorityURL = signingOpts.GetTimestampAuthorityUrl()
signingCAName = signingOpts.GetSigningCa()
Expand Down Expand Up @@ -308,8 +311,9 @@ func (action *AttestationInit) Run(ctx context.Context, opts *AttestationInitRun
}

// Register and run auto-discovery collectors
// PR metadata is always collected; other collectors are opt-in via --collectors flag
// PR metadata is always collected; other collectors are opt-in via --collectors flag or org settings
collectors := []crafter.Collector{crafter.NewPRMetadataCollector(discoveredRunner)}
aiConfigRequested := slices.Contains(opts.Collectors, aiConfigCollectorName)
for _, name := range opts.Collectors {
switch name {
case aiConfigCollectorName:
Expand All @@ -318,6 +322,11 @@ func (action *AttestationInit) Run(ctx context.Context, opts *AttestationInitRun
action.Logger.Warn().Str("collector", name).Msg("unknown collector, skipping")
}
}
// Auto-enable AI agent config collector if the org setting is on and not already requested via CLI flag
if enableAIAgentCollector && !aiConfigRequested {
action.Logger.Debug().Msg("auto-enabling AI agent config collector from org setting")
collectors = append(collectors, crafter.NewAIAgentConfigCollector())
}
action.c.RegisterCollectors(collectors...)
action.c.RunCollectors(ctx, attestationID, casBackend)

Expand Down
2 changes: 2 additions & 0 deletions app/cli/pkg/action/membership_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type OrgItem struct {
PolicyAllowedHostnames []string `json:"policyAllowedHostnames,omitempty"`
PreventImplicitWorkflowCreation bool `json:"preventImplicitWorkflowCreation"`
APITokenMaxDaysInactive *string `json:"apiTokenMaxDaysInactive,omitempty"`
EnableAIAgentCollector bool `json:"enableAiAgentCollector"`
}

type MembershipItem struct {
Expand Down Expand Up @@ -138,6 +139,7 @@ func pbOrgItemToAction(in *pb.OrgItem) *OrgItem {
CreatedAt: toTimePtr(in.CreatedAt.AsTime()),
PolicyAllowedHostnames: in.PolicyAllowedHostnames,
PreventImplicitWorkflowCreation: in.PreventImplicitWorkflowCreation,
EnableAIAgentCollector: in.EnableAiAgentCollector,
}

if in.DefaultPolicyViolationStrategy == pb.OrgItem_POLICY_VIOLATION_BLOCKING_STRATEGY_BLOCK {
Expand Down
3 changes: 3 additions & 0 deletions app/cli/pkg/action/org_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ type NewOrgUpdateOpts struct {
// APITokenMaxDaysInactive is the maximum number of days a token can be inactive before auto-revocation.
// 0 means disabled.
APITokenMaxDaysInactive *int
// EnableAIAgentCollector enables automatic AI agent config collection during attestation init
EnableAIAgentCollector *bool
}

func (action *OrgUpdate) Run(ctx context.Context, name string, opts *NewOrgUpdateOpts) (*OrgItem, error) {
Expand All @@ -48,6 +50,7 @@ func (action *OrgUpdate) Run(ctx context.Context, name string, opts *NewOrgUpdat
BlockOnPolicyViolation: opts.BlockOnPolicyViolation,
PreventImplicitWorkflowCreation: opts.PreventImplicitWorkflowCreation,
RestrictContractCreationToOrgAdmins: opts.RestrictContractCreation,
EnableAiAgentCollector: opts.EnableAIAgentCollector,
}

if opts.PoliciesAllowedHostnames != nil {
Expand Down
21 changes: 16 additions & 5 deletions app/controlplane/api/controlplane/v1/organization.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions app/controlplane/api/controlplane/v1/organization.proto
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ message OrganizationServiceUpdateRequest {

// Maximum days of inactivity before API tokens are auto-revoked. Set to 0 to disable.
optional int32 api_token_max_days_inactive = 7;

// Enable automatic AI agent config collection during attestation init
optional bool enable_ai_agent_collector = 8;
}

message OrganizationServiceUpdateResponse {
Expand Down
19 changes: 15 additions & 4 deletions app/controlplane/api/controlplane/v1/response_messages.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions app/controlplane/api/controlplane/v1/response_messages.proto
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ message OrgItem {
bool restrict_contract_creation_to_org_admins = 8;
// Maximum days of inactivity before API tokens are auto-revoked. Absent if disabled.
optional int32 api_token_max_days_inactive = 9;
// Whether AI agent config collection is automatically enabled during attestation init
bool enable_ai_agent_collector = 10;

enum PolicyViolationBlockingStrategy {
POLICY_VIOLATION_BLOCKING_STRATEGY_UNSPECIFIED = 0;
Expand Down
20 changes: 15 additions & 5 deletions app/controlplane/api/controlplane/v1/workflow_run.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions app/controlplane/api/controlplane/v1/workflow_run.proto
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ message AttestationServiceInitResponse {
repeated string policies_allowed_hostnames = 6;
// URL pointing to the web dashboard. It might be empty if not available
string ui_dashboard_url = 7;
// Whether AI agent config collection is enabled at the org level
bool enable_ai_agent_collector = 8;
}

message SigningOptions {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading