Skip to content
Open
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
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ Code reviews are required for all submissions via GitHub pull requests.
- when adding new inedexes, make sure to update the generated sql migraiton files and make them CREATE INDEX CONCURRENTLY and set -- atlas:txmode none at the top
- after updating protos, make sure to run `buf format -w`
- Please avoid sycophantic commentary like ‘You’re absolutely correct!’ or ‘Brilliant idea!’
- For each file you modify, update the license header so the last year is the current year. For example, `Copyright 2023` becomes `Copyright 2023-2026`. If it already ends with the current year, no change needed. If there's no license header, create one with the current year.
- For each file you modify, update the license header so the last year is the current year. For example, `Copyright 2023` becomes `Copyright 2023-2026`. If it already ends with the current year, no change needed. New files should use only the current year (e.g., `Copyright 2026`), not a range.
- if you add any new dependency to a constructor, remember to run wire ./...
- when creating PR message, keep it high-level, what functionality was added, don't add info about testing, no icons, no info about how the message was generated.
- app/controlplane/api/gen/frontend/google/protobuf/descriptor.ts is a special case that we don't want to upgrade, so if it upgrades, put it back to main
Expand Down
4 changes: 4 additions & 0 deletions app/cli/cmd/organization_describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ func contextTableOutput(config *action.ConfigContextItem) error {
orgInfo += fmt.Sprintf("\nPolicy allowed hostnames: %v", strings.Join(m.Org.PolicyAllowedHostnames, ", "))
}

if m.Org.APITokenMaxDaysInactive != nil {
orgInfo += fmt.Sprintf("\nAPI token auto-revoke after: %s days inactive", *m.Org.APITokenMaxDaysInactive)
}

gt.AppendRow(table.Row{"Organization", orgInfo})
}

Expand Down
18 changes: 17 additions & 1 deletion app/cli/cmd/organization_update.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2023-2025 The Chainloop Authors.
// Copyright 2023-2026 The Chainloop Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,9 @@
package cmd

import (
"fmt"
"strconv"

"github.com/chainloop-dev/chainloop/app/cli/pkg/action"
"github.com/spf13/cobra"
)
Expand All @@ -27,6 +30,7 @@ func newOrganizationUpdateCmd() *cobra.Command {
policiesAllowedHostnames []string
preventImplicitWorkflowCreation bool
restrictContractCreation bool
apiTokenMaxDaysInactive string
)

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

if cmd.Flags().Changed("api-token-max-days-inactive") {
days, err := strconv.Atoi(apiTokenMaxDaysInactive)
if err != nil {
return fmt.Errorf("invalid value %q: must be a number of days (0 to disable)", apiTokenMaxDaysInactive)
}
if days < 0 || days > 365 {
return fmt.Errorf("api-token-max-days-inactive must be between 0 (disabled) and 365")
}
opts.APITokenMaxDaysInactive = &days
}

_, err := action.NewOrgUpdate(ActionOpts).Run(cmd.Context(), orgName, opts)
if err != nil {
return err
Expand All @@ -68,5 +83,6 @@ func newOrganizationUpdateCmd() *cobra.Command {
cmd.Flags().StringSliceVar(&policiesAllowedHostnames, "policies-allowed-hostnames", []string{}, "set the allowed hostnames for the policy engine")
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)")
return cmd
}
8 changes: 7 additions & 1 deletion app/cli/pkg/action/membership_list.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2024 The Chainloop Authors.
// Copyright 2024-2026 The Chainloop Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -35,6 +35,7 @@ type OrgItem struct {
PolicyViolationBlockingStrategy string `json:"policyViolationBlockingStrategy"`
PolicyAllowedHostnames []string `json:"policyAllowedHostnames,omitempty"`
PreventImplicitWorkflowCreation bool `json:"preventImplicitWorkflowCreation"`
APITokenMaxDaysInactive *string `json:"apiTokenMaxDaysInactive,omitempty"`
}

type MembershipItem struct {
Expand Down Expand Up @@ -145,6 +146,11 @@ func pbOrgItemToAction(in *pb.OrgItem) *OrgItem {
i.PolicyViolationBlockingStrategy = PolicyViolationBlockingStrategyAdvisory
}

if in.ApiTokenMaxDaysInactive != nil {
s := fmt.Sprintf("%d", in.GetApiTokenMaxDaysInactive())
i.APITokenMaxDaysInactive = &s
}

return i
}

Expand Down
15 changes: 14 additions & 1 deletion app/cli/pkg/action/org_update.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2023-2025 The Chainloop Authors.
// Copyright 2023-2026 The Chainloop Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,7 @@ package action

import (
"context"
"fmt"

pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1"
)
Expand All @@ -34,6 +35,9 @@ type NewOrgUpdateOpts struct {
PoliciesAllowedHostnames *[]string
PreventImplicitWorkflowCreation *bool
RestrictContractCreation *bool
// APITokenMaxDaysInactive is the maximum number of days a token can be inactive before auto-revocation.
// 0 means disabled.
APITokenMaxDaysInactive *int
}

func (action *OrgUpdate) Run(ctx context.Context, name string, opts *NewOrgUpdateOpts) (*OrgItem, error) {
Expand All @@ -51,6 +55,15 @@ func (action *OrgUpdate) Run(ctx context.Context, name string, opts *NewOrgUpdat
payload.UpdatePoliciesAllowedHostnames = true
}

if opts.APITokenMaxDaysInactive != nil {
v := *opts.APITokenMaxDaysInactive
if v < 0 || v > 365 {
return nil, fmt.Errorf("api_token_max_days_inactive must be between 0 and 365")
}
days := int32(v)
payload.ApiTokenMaxDaysInactive = &days
}

resp, err := client.Update(ctx, payload)
if err != nil {
return nil, err
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.

5 changes: 4 additions & 1 deletion app/controlplane/api/controlplane/v1/organization.proto
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2024-2025 The Chainloop Authors.
// Copyright 2024-2026 The Chainloop Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -99,6 +99,9 @@ message OrganizationServiceUpdateRequest {

// restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles)
optional bool restrict_contract_creation_to_org_admins = 6;

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

message OrganizationServiceUpdateResponse {
Expand Down
22 changes: 17 additions & 5 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.

4 changes: 3 additions & 1 deletion app/controlplane/api/controlplane/v1/response_messages.proto
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2024-2025 The Chainloop Authors.
// Copyright 2024-2026 The Chainloop Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -286,6 +286,8 @@ message OrgItem {
bool prevent_implicit_workflow_creation = 7;
// restrict_contract_creation_to_org_admins restricts contract creation (org-level and project-level) to only organization admins (owner/admin roles)
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;

enum PolicyViolationBlockingStrategy {
POLICY_VIOLATION_BLOCKING_STRATEGY_UNSPECIFIED = 0;
Expand Down

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

Loading
Loading