diff --git a/.envrc b/.envrc index bacbcba87..41628a3a9 100644 --- a/.envrc +++ b/.envrc @@ -1,6 +1,7 @@ -export TF_ACC=true -export TF_LOG=DEBUG +has nix && use flake dotenv_if_exists .env # You can create a .env file with your env vars for this project. You can also use .secrets if you are using act. See the line below. dotenv_if_exists .secrets # Used by [act](https://nektosact.com/) to load secrets into the pipelines strict_env env_vars_required SYSDIG_SECURE_API_TOKEN SYSDIG_MONITOR_API_TOKEN +export TF_ACC=true +export TF_LOG=DEBUG diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad96212de..aabcce23a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,9 @@ on: pull_request: branches: - master + merge_group: + branches: + - master jobs: build-multiarch: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5bbd4639b..ccc6f0c69 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,11 +7,9 @@ jobs: lint: name: Lint runs-on: ubuntu-latest - steps: - name: Check out code uses: actions/checkout@v4 - - name: Lint uses: golangci/golangci-lint-action@v8 with: @@ -20,75 +18,168 @@ jobs: test: name: Unit Tests runs-on: ubuntu-latest - steps: - name: Check out code uses: actions/checkout@v4 - - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: go.mod - - name: Test run: make test - test-sysdig-monitor: - name: Sysdig Monitor Acceptance Tests + # ============================================ + # Sysdig Secure - Dynamic Matrix + # ============================================ + list-sysdig-secure-tests: + name: List Secure Tests runs-on: ubuntu-latest needs: test - + outputs: + matrix: ${{ steps.list.outputs.matrix }} steps: - - name: Check out code - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + - id: list + run: | + files=$(grep -l "tf_acc_sysdig_secure" sysdig/*_test.go | xargs -I{} basename {} .go || echo "") + if [ -z "$files" ]; then + echo "matrix=[]" >> $GITHUB_OUTPUT + else + matrix=$(echo "$files" | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "matrix=$matrix" >> $GITHUB_OUTPUT + fi - - name: Set up Go - uses: actions/setup-go@v5 + test-sysdig-secure: + name: "Secure: ${{ matrix.file }}" + runs-on: ubuntu-latest + needs: list-sysdig-secure-tests + strategy: + fail-fast: true + max-parallel: 20 + matrix: + file: ${{ fromJson(needs.list-sysdig-secure-tests.outputs.matrix) }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: go-version-file: go.mod - - - name: Test - run: make testacc + - uses: hashicorp/setup-terraform@v3 + with: + terraform_wrapper: false + - name: Run tests from ${{ matrix.file }} + run: | + tests=$(grep -oh "func Test[A-Za-z0-9_]*" sysdig/${{ matrix.file }}.go | sed 's/func //' | tr '\n' '|' | sed 's/|$//') + if [ -n "$tests" ]; then + echo "Running tests: $tests" + CGO_ENABLED=1 TF_ACC=1 go test ./sysdig -v -tags=tf_acc_sysdig_secure -timeout 30m -race -run "^($tests)$" + else + echo "No tests found in file" + fi env: - TEST_SUITE: tf_acc_sysdig_monitor SYSDIG_MONITOR_API_TOKEN: ${{ secrets.KUBELAB_MONITOR_API_TOKEN }} SYSDIG_SECURE_API_TOKEN: ${{ secrets.KUBELAB_SECURE_API_TOKEN }} - test-sysdig-secure: - name: Sysdig Secure Acceptance Tests + sysdig-secure-result: + name: Sysdig Secure Tests Result + runs-on: ubuntu-latest + needs: [list-sysdig-secure-tests, test-sysdig-secure] + if: always() + steps: + - name: Check test results + run: | + if [ "${{ needs.test-sysdig-secure.result }}" == "success" ] || [ "${{ needs.test-sysdig-secure.result }}" == "skipped" ]; then + echo "All Sysdig Secure tests passed" + exit 0 + else + echo "Some Sysdig Secure tests failed" + exit 1 + fi + + # ============================================ + # Sysdig Monitor - Dynamic Matrix + # ============================================ + list-sysdig-monitor-tests: + name: List Monitor Tests runs-on: ubuntu-latest needs: test - + outputs: + matrix: ${{ steps.list.outputs.matrix }} steps: - - name: Check out code - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + - id: list + run: | + files=$(grep -l "tf_acc_sysdig_monitor" sysdig/*_test.go | xargs -I{} basename {} .go || echo "") + if [ -z "$files" ]; then + echo "matrix=[]" >> $GITHUB_OUTPUT + else + matrix=$(echo "$files" | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "matrix=$matrix" >> $GITHUB_OUTPUT + fi - - name: Set up Go - uses: actions/setup-go@v5 + test-sysdig-monitor: + name: "Monitor: ${{ matrix.file }}" + runs-on: ubuntu-latest + needs: list-sysdig-monitor-tests + strategy: + fail-fast: true + max-parallel: 20 + matrix: + file: ${{ fromJson(needs.list-sysdig-monitor-tests.outputs.matrix) }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: go-version-file: go.mod - - - name: Test - run: make testacc + - uses: hashicorp/setup-terraform@v3 + with: + terraform_wrapper: false + - name: Run tests from ${{ matrix.file }} + run: | + tests=$(grep -oh "func Test[A-Za-z0-9_]*" sysdig/${{ matrix.file }}.go | sed 's/func //' | tr '\n' '|' | sed 's/|$//') + if [ -n "$tests" ]; then + echo "Running tests: $tests" + CGO_ENABLED=1 TF_ACC=1 go test ./sysdig -v -tags=tf_acc_sysdig_monitor -timeout 30m -race -run "^($tests)$" + else + echo "No tests found in file" + fi env: - TEST_SUITE: tf_acc_sysdig_secure SYSDIG_MONITOR_API_TOKEN: ${{ secrets.KUBELAB_MONITOR_API_TOKEN }} SYSDIG_SECURE_API_TOKEN: ${{ secrets.KUBELAB_SECURE_API_TOKEN }} + sysdig-monitor-result: + name: Sysdig Monitor Tests Result + runs-on: ubuntu-latest + needs: [list-sysdig-monitor-tests, test-sysdig-monitor] + if: always() + steps: + - name: Check test results + run: | + if [ "${{ needs.test-sysdig-monitor.result }}" == "success" ] || [ "${{ needs.test-sysdig-monitor.result }}" == "skipped" ]; then + echo "All Sysdig Monitor tests passed" + exit 0 + else + echo "Some Sysdig Monitor tests failed" + exit 1 + fi + + # ============================================ + # IBM Monitor - Sequential (no parallelization) + # ============================================ test-ibm-monitor: name: IBM Monitor Acceptance Tests runs-on: ubuntu-latest needs: test - steps: - name: Check out code uses: actions/checkout@v4 - - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: go.mod - + - name: Set up Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_wrapper: false - name: Test run: make testacc env: @@ -99,20 +190,24 @@ jobs: SYSDIG_MONITOR_URL: "https://eu-gb.monitoring.cloud.ibm.com" IBM_EVENT_NOTIFICATION_INSTANCE_ID: ${{ secrets.IBM_EVENT_NOTIFICATION_INSTANCE_ID }} + # ============================================ + # IBM Secure - Sequential (no parallelization) + # ============================================ test-ibm-secure: name: IBM Secure Acceptance Tests runs-on: ubuntu-latest needs: test - steps: - name: Check out code uses: actions/checkout@v4 - - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: go.mod - + - name: Set up Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_wrapper: false - name: Test run: make testacc env: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 080f5b677..a2cbcd029 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,9 +26,4 @@ repos: pass_filenames: false entry: make test language: system - - id: testacc - name: testacc - pass_filenames: false - entry: make testacc - language: system diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..e78addebe --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,449 @@ +# AGENTS.md + +This file provides guidance to AI agents (Claude Code, Cursor, Copilot, etc.) when working with code in this repository. + +## Build and Development Commands + +```bash +# Build and install +make build # Compile provider to $GOPATH/bin +make install # Build and install to local Terraform plugins directory +make uninstall # Remove from local plugins directory + +# Code quality +make fmt # Format code with gofumpt +make fmtcheck # Verify code formatting +make lint # Run golangci-lint (1h timeout) + +# Testing +make test # Run unit tests (30s timeout, 4 parallel) +make testacc # Run acceptance tests (120min timeout, requires credentials) + +# Run specific test suite +TEST_SUITE=tf_acc_sysdig_monitor make testacc +TEST_SUITE=tf_acc_sysdig_secure make testacc +TEST_SUITE=tf_acc_ibm_monitor make testacc +TEST_SUITE=tf_acc_ibm_secure make testacc + +# Run a single test +go test ./sysdig -v -run TestAccResourceSysdigUser -tags=tf_acc_sysdig_secure -timeout 120m + +# Run with debug logging +TF_ACC=1 TF_LOG=DEBUG go test ./sysdig -v -tags=tf_acc_sysdig_secure -run TestAccMacro +``` + +## Required Environment Variables + +For acceptance tests (set in `.envrc` or `.env`): +```bash +SYSDIG_SECURE_API_TOKEN # Required for Secure tests +SYSDIG_MONITOR_API_TOKEN # Required for Monitor tests +TF_ACC=1 # Enable acceptance testing + +# IBM Cloud (optional) +SYSDIG_IBM_MONITOR_API_KEY +SYSDIG_IBM_MONITOR_INSTANCE_ID +SYSDIG_IBM_SECURE_API_KEY +SYSDIG_IBM_SECURE_INSTANCE_ID +``` + +## Architecture Overview + +Terraform provider for Sysdig Monitor and Sysdig Secure using Terraform Plugin SDK v2. + +### Directory Structure + +- `sysdig/` - Main provider package (resources, data sources, provider config) +- `sysdig/internal/client/v2/` - HTTP client layer for Sysdig API +- `website/docs/` - Terraform Registry documentation + +### File Naming Conventions + +- Resources: `sysdig/resource_sysdig__.go` +- Data sources: `sysdig/data_source_sysdig__.go` +- Tests: `sysdig/_test.go` (same package, co-located) +- Client implementations: `sysdig/internal/client/v2/.go` + +### Key Reference Files + +When implementing new resources, reference these files for patterns and utilities: + +| File | Purpose | +|------|---------| +| `sysdig/common.go` | ~60 predefined Schema key constants (`SchemaIDKey`, `SchemaTeamIDKey`, etc.) | +| `sysdig/schema.go` | Schema composition helpers, read-only schemas, `maps.Copy()` pattern | +| `sysdig/helpers.go` | Utility functions (`validateDiagFunc`, `parseAzureCreds`) | +| `sysdig/sysdig_clients.go` | Client interface and selection logic | +| `sysdig/resource_sysdig_secure_common_policy.go` | Secure policy patterns | +| `sysdig/resource_sysdig_monitor_alert_v2_common.go` | Alert V2 base implementation | +| `sysdig/resource_sysdig_monitor_notification_channel_common.go` | Notification channel patterns | + +## Resource Implementation Patterns + +### Schema Composition + +Resources use composable schema functions for shared fields: + +```go +// Alert resources compose multiple schema layers +Schema: createScopedSegmentedAlertV2Schema( + createAlertV2Schema( + map[string]*schema.Schema{ + "type_specific_field": { ... } + } + ) +) + +// Notification channels use shared base schema +Schema: createMonitorNotificationChannelSchema( + map[string]*schema.Schema{ + "channel_specific_field": { ... } + } +) +``` + +**Base schema functions** (in `sysdig/`): +- `createAlertV2Schema()` - Alert common fields +- `createScopedSegmentedAlertV2Schema()` - Scope and group_by +- `createRuleSchema()` - Secure rule common fields +- `createMonitorNotificationChannelSchema()` - Notification channel base +- `createSecureNotificationChannelSchema()` - Secure notification base + +### CRUD Implementation Pattern + +```go +func resourceSysdigXxxCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client, err := getXxxClient(meta.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + obj := buildXxxStruct(d) // ResourceData → Go struct + + created, err := client.CreateXxx(ctx, obj) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(strconv.Itoa(created.ID)) + return updateXxxState(d, &created) // Go struct → ResourceData +} +``` + +### State Management + +Two-function pattern for bidirectional mapping: +- `buildXxxStruct(d *schema.ResourceData)` - Terraform state → Go struct +- `updateXxxState(d *schema.ResourceData, obj *Type)` - Go struct → Terraform state + +### Version-Based Optimistic Locking + +All Update operations must include version for conflict detection: +```go +obj.Version = d.Get("version").(int) // Critical for updates +``` + +### Error Handling + +Handle "not found" gracefully in Read operations. When a resource no longer exists in the API, remove it from Terraform state instead of erroring (allows `terraform apply` to recreate it): +```go +// Pattern 1: Using typed errors +if err == v2.ErrAlertV2NotFound { + d.SetId("") // Remove from state + return nil // Don't error +} + +// Pattern 2: Using HTTP status codes +if statusCode == http.StatusNotFound { + d.SetId("") + return nil +} +``` + +### Timeouts + +Standard timeout configuration for CRUD operations: +```go +timeout := 5 * time.Minute + +Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(timeout), + Update: schema.DefaultTimeout(timeout), + Read: schema.DefaultTimeout(timeout), + Delete: schema.DefaultTimeout(timeout), +} +``` + +### Optional Fields with GetOk() + +Use `GetOk()` pattern for optional fields to distinguish between unset and zero values: +```go +if val, ok := d.GetOk("optional_field"); ok { + obj.OptionalField = val.(string) // Only set if explicitly configured +} +``` + +### Deprecating Fields + +Mark fields as deprecated with clear migration guidance: +```go +"old_field": { + Type: schema.TypeBool, + Optional: true, + Deprecated: "Use 'new_field' in the alert resource instead. This will be removed in a future version.", +} +``` + +### Read-Only Schema Helpers + +Use helper functions from `sysdig/schema.go` for consistent read-only fields: +```go +"computed_field": ReadOnlyIntSchema(), // Computed int field +"status": ReadOnlyStringSchema(), // Computed string field +"enabled": BoolSchema(), // Optional bool with default false +"active": BoolComputedSchema(), // Computed bool +``` + +## API Client Architecture + +### Interface Hierarchy + +``` +Common interface (users, teams, notification channels, agent access keys) + +SysdigCommon interface +├── Common +├── CustomRoleInterface, CustomRolePermissionInterface +├── GroupMappingInterface, GroupMappingConfigInterface +├── IPFiltersInterface, IPFilteringSettingsInterface +└── TeamServiceAccountInterface + +MonitorCommon interface (alerts, alertsV2, dashboards, silence rules, inhibition rules) + +SecureCommon interface (posture policies, posture zones, posture controls, posture accept risk, zones) + +SysdigMonitor interface +├── SysdigCommon +├── MonitorCommon +└── CloudAccountMonitorInterface + +SysdigSecure interface +├── SysdigCommon +├── SecureCommon +├── PolicyInterface, CompositePolicyInterface +├── RuleInterface, MacroInterface, ListInterface +├── CloudauthAccountSecureInterface, CloudauthAccountComponentSecureInterface, CloudauthAccountFeatureSecureInterface +├── OnboardingSecureInterface, OrganizationSecureInterface +└── VulnerabilityPolicyClient, VulnerabilityRuleBundleClient +``` + +### Client Types + +Provider auto-detects client type based on configured credentials: +- `SysdigMonitor` - Direct Sysdig Monitor API +- `SysdigSecure` - Direct Sysdig Secure API +- `IBMMonitor` - IBM Cloud Sysdig Monitor +- `IBMSecure` - IBM Cloud Sysdig Secure + +### SysdigClients Interface + +Resources access API clients through the `SysdigClients` interface (`sysdig/sysdig_clients.go`): + +```go +type SysdigClients interface { + sysdigMonitorClientV2() (v2.SysdigMonitor, error) + sysdigSecureClientV2() (v2.SysdigSecure, error) + ibmMonitorClient() (v2.IBMMonitor, error) + ibmSecureClient() (v2.IBMSecure, error) +} +``` + +Each resource implements a client getter function that selects the appropriate client based on configuration: +```go +func getAlertV2Client(c SysdigClients) (v2.AlertV2Interface, error) { + var client v2.AlertV2Interface + var err error + switch c.GetClientType() { + case IBMMonitor: + client, err = c.ibmMonitorClient() + default: + client, err = c.sysdigMonitorClientV2() + } + if err != nil { + return nil, err + } + return client, nil +} +``` + +### HTTP Client Features + +- Retryable HTTP with exponential backoff (max 5 retries) +- Retries on 5xx errors and 409 Conflict +- TLS verification can be disabled via `insecure_tls` +- Custom headers support via `extra_headers` + +### Authentication + +**Sysdig (Direct):** Bearer token in Authorization header +**IBM Cloud:** IAM token exchange with caching and auto-refresh + +## Testing Patterns + +### Build Tags + +Tests are organized by build tags: +- `unit` - Fast unit tests +- `tf_acc_sysdig_monitor` - Monitor acceptance tests +- `tf_acc_sysdig_secure` - Secure acceptance tests +- `tf_acc_ibm_monitor` - IBM Monitor tests +- `tf_acc_ibm_secure` - IBM Secure tests +- `tf_acc_onprem_monitor`, `tf_acc_onprem_secure` - On-prem tests + +### Acceptance Test Structure + +```go +//go:build tf_acc_sysdig_secure + +func TestAccResourceXxx(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: testConfig(randomName()), + }, + { + ResourceName: "sysdig_secure_xxx.test", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} +``` + +### Test Helpers (sysdig/common_test.go) + +- `preCheckAnyEnv(t, envs...)` - Validate environment variables +- `randomText(len)` - Generate random strings for unique names +- `sysdigOrIBMMonitorPreCheck(t)` - Check for either credential type + +## Development Workflow (TDD) + +Follow the **Red-Green-Refactor** cycle: + +1. **Red:** Write acceptance test first (it will fail) + - Create test file with appropriate build tag + - Define test cases covering create, update, import + - Run test to confirm it fails: `go test ./sysdig -v -run TestAccNewResource -tags=tf_acc_sysdig_secure` + +2. **Green:** Write minimum code to make test pass + - Implement resource schema and CRUD operations + - Add client interface if new API endpoints needed + - Register in `provider.go` + - Run test until it passes + +3. **Refactor:** Clean up if needed + - Extract common patterns to shared functions + - Ensure code follows existing conventions + - Run `make fmt` and `make lint` + +**Prefer small commits** - commit after each complete Red-Green-Refactor cycle. Each commit should represent a single, atomic, working change. This makes code review easier and keeps a clean git history. + +## Adding New Resources + +1. **Write acceptance test first** in `sysdig/resource_sysdig___test.go` +2. **Create resource file:** `sysdig/resource_sysdig__.go` +3. **Implement schema** using composition pattern with existing base schemas +4. **Implement CRUD:** `CreateContext`, `ReadContext`, `UpdateContext`, `DeleteContext` +5. **Add client interface** in `sysdig/internal/client/v2/` if new API endpoints needed +6. **Register in provider:** Add to `ResourcesMap` in `sysdig/provider.go` +7. **Run tests until green:** Iterate until all tests pass +8. **Add documentation** in `website/docs/r/.md` + +## Documentation Conventions + +Documentation files in `website/docs/` follow a standard structure: + +### Resources (`website/docs/r/.md`) + +```markdown +--- +subcategory: "Sysdig Secure" # or "Sysdig Monitor" +layout: "sysdig" +page_title: "Sysdig: sysdig_secure_" +description: |- + Short description of the resource. +--- + +# Resource: sysdig_secure_ + +Longer description explaining what the resource does. + +## Example Usage + +\`\`\`terraform +resource "sysdig_secure_" "example" { + name = "example" + # ... required and common optional fields +} +\`\`\` + +## Argument Reference + +### Common Arguments +* `name` - (Required) The name of the resource. + +### Type-Specific Arguments +* `specific_field` - (Optional) Description. Default: `value`. + +### Nested Schema for `block_name` +* `nested_field` - (Required) Description. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: +* `id` - The ID of the resource. +* `version` - The current version of the resource. + +## Import + +Resource can be imported using the ID: + +\`\`\` +$ terraform import sysdig_secure_.example 12345 +\`\`\` +``` + +### Data Sources (`website/docs/d/.md`) + +Same structure but without Import section and with read-only field descriptions. + +## CI/CD Pipeline + +### PR Checks +- Multi-architecture build (darwin, linux, windows, freebsd, openbsd, solaris) +- golangci-lint (30min timeout in CI, 1h timeout in local GNUmakefile) +- Unit tests +- Acceptance tests (Monitor, Secure, IBM suites in parallel) +- Provider documentation validation (tfproviderdocs) +- CodeQL security analysis + +### Release Process +- Tag with `v*` pattern triggers release +- GoReleaser builds multi-platform binaries +- GPG signing of checksums +- Automatic GitHub Release creation + +## PR Guidelines + +- Use [Conventional Commit](https://www.conventionalcommits.org/) format + - Example: `feat(secure-policy): Add runbook to policy resources` +- Update CODEOWNERS for new resource areas +- Include acceptance tests +- Update documentation in `website/docs/` diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..f6aa6c026 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,3 @@ +# CLAUDE.md + +@AGENTS.md diff --git a/CODEOWNERS b/CODEOWNERS index 44024a8a0..ea066153d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,26 +1,26 @@ -* @airadier @tembleking @mateobur +* @sysdiglabs/sysdig-training # Fargate workload agent -*fargate* @airadier @tembleking @mateobur @marojor @francesco-racciatti @pgcrooks-sysdig @gnosek +*fargate* @sysdiglabs/sysdig-training @marojor @francesco-racciatti @pgcrooks-sysdig @gnosek # compliance -*benchmark* @airadier @tembleking @mateobur @haresh-suresh @nkraemer-sysdig +*benchmark* @sysdiglabs/sysdig-training @haresh-suresh @nkraemer-sysdig # monitor -*monitor*alert* @airadier @tembleking @mateobur @michelevergnano @dkutsanov @antonio-cuomo @dbonf @vojindj @DagDigg @Shadow649 -*monitor*dashboard* @airadier @tembleking @mateobur @rossifrancesco -*monitor*groupmapping* @airadier @tembleking @mateobur @shadow649 -*notification_channel* @airadier @tembleking @mateobur @michelevergnano @dkutsanov @antonio-cuomo @dbonf @vojindj @DagDigg @Shadow649 -*inhibition_rule* @airadier @tembleking @mateobur @michelevergnano @dkutsanov @antonio-cuomo @dbonf @vojindj @DagDigg @Shadow649 -*silence_rule* @airadier @tembleking @mateobur @michelevergnano @dkutsanov @antonio-cuomo @dbonf @vojindj @DagDigg @Shadow649 +*monitor*alert* @sysdiglabs/sysdig-training @michelevergnano @dkutsanov @antonio-cuomo @dbonf @vojindj @DagDigg @Shadow649 +*monitor*dashboard* @sysdiglabs/sysdig-training @rossifrancesco +*monitor*groupmapping* @sysdiglabs/sysdig-training @shadow649 +*notification_channel* @sysdiglabs/sysdig-training @michelevergnano @dkutsanov @antonio-cuomo @dbonf @vojindj @DagDigg @Shadow649 +*inhibition_rule* @sysdiglabs/sysdig-training @michelevergnano @dkutsanov @antonio-cuomo @dbonf @vojindj @DagDigg @Shadow649 +*silence_rule* @sysdiglabs/sysdig-training @michelevergnano @dkutsanov @antonio-cuomo @dbonf @vojindj @DagDigg @Shadow649 # policies/rules -*secure*policy* @airadier @tembleking @mateobur @rosenbloomb-sysdig @ombellare @miguelgordo @ivanlysiuk-sysdig @daniel-almeida @jbainbridgesysdig +*secure*policy* @sysdiglabs/sysdig-training @rosenbloomb-sysdig @ombellare @miguelgordo @ivanlysiuk-sysdig @daniel-almeida @jbainbridgesysdig # internal components -/sysdig/internal/client/v2/client.go @airadier @tembleking @mateobur @filiptubic @mbarbieri @draraksysdig -/sysdig/internal/client/v2/config.go @airadier @tembleking @mateobur @filiptubic @mbarbieri @draraksysdig -/sysdig/internal/client/v2/ibm.go @airadier @tembleking @mateobur @filiptubic @mbarbieri @draraksysdig -/sysdig/internal/client/v2/agentaccesskey.go @airadier @tembleking @mateobur @igoreulalio @filiptubic @mbarbieri @draraksysdig -/main.go @airadier @tembleking @mateobur @filiptubic @mbarbieri @draraksysdig -/.goreleaser.yml @airadier @tembleking @mateobur @filiptubic @mbarbieri @draraksysdig -/.github/ @airadier @tembleking @mateobur @filiptubic @mbarbieri @draraksysdig +/sysdig/internal/client/v2/client.go @sysdiglabs/sysdig-training @filiptubic @mbarbieri @draraksysdig +/sysdig/internal/client/v2/config.go @sysdiglabs/sysdig-training @filiptubic @mbarbieri @draraksysdig +/sysdig/internal/client/v2/ibm.go @sysdiglabs/sysdig-training @filiptubic @mbarbieri @draraksysdig +/sysdig/internal/client/v2/agentaccesskey.go @sysdiglabs/sysdig-training @igoreulalio @filiptubic @mbarbieri @draraksysdig +/main.go @sysdiglabs/sysdig-training @filiptubic @mbarbieri @draraksysdig +/.goreleaser.yml @sysdiglabs/sysdig-training @filiptubic @mbarbieri @draraksysdig +/.github/ @sysdiglabs/sysdig-training @filiptubic @mbarbieri @draraksysdig diff --git a/examples/serverless-agent/ecs-fargate/README.md b/examples/serverless-agent/ecs-fargate/README.md new file mode 100644 index 000000000..06b9ee3f0 --- /dev/null +++ b/examples/serverless-agent/ecs-fargate/README.md @@ -0,0 +1,35 @@ +# Workload with Serverless Workload Agent +This example deploys a cluster running a workload application secured by the Serverless Workload Agent. +The workload used is [falcosecurity/event-generator](https://github.com/falcosecurity/event-generator), which produces synthetic suspicious actions that will trigger Sysdig managed policies. + + +## Prerequisites +The following prerequisites are required to deploy this sample: +- `VPC ID`, the ID of an already existing VPC +- `Subnet ID`, the ID of an already existing Subnet within the VPC above + + +## Usage +``` +$ terraform init +$ terraform apply +``` + + +## Components +| **Component** | **Name** | **Description** | +|--------------------|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------| +| ECS Cluster | `-cluster` | The cluster containing the ECS Service below. | +| ECS Service | `-service` | The service running the TaskDefinition below. | +| ECS TaskDefinition | `-task-definition` | The task definition including a workload container being secured by the Serverless Agent. | +| ECS SecurityGroup | `-security-group` | The security group ensuring connectivity to the Serverless Agent. This security group has no restrictions applied and is intended for testing only. | + + +## Files +| **File** | **Description** | +|----------------|----------------------------------------------------------------------------------------------------------| +| `output.tf` | Contains the reference to the cluster, service, and task revision being deployed. | +| `providers.tf` | Contains the configuration parameters for the providers. | +| `resources.tf` | Contains the resources to deploy, including the task definition being secured with the Serverless Agent. | +| `variables.tf` | Contains the configuration parameters for AWS and the Serverless Agent. | +| `versions.tf` | Defines the version of the providers. | diff --git a/examples/serverless-agent/fargate/workload-legacy/output.tf b/examples/serverless-agent/ecs-fargate/output.tf similarity index 100% rename from examples/serverless-agent/fargate/workload-legacy/output.tf rename to examples/serverless-agent/ecs-fargate/output.tf diff --git a/examples/serverless-agent/fargate/workload-legacy/providers.tf b/examples/serverless-agent/ecs-fargate/providers.tf similarity index 100% rename from examples/serverless-agent/fargate/workload-legacy/providers.tf rename to examples/serverless-agent/ecs-fargate/providers.tf diff --git a/examples/serverless-agent/fargate/workload/instrumented_load.tf b/examples/serverless-agent/ecs-fargate/resources.tf similarity index 74% rename from examples/serverless-agent/fargate/workload/instrumented_load.tf rename to examples/serverless-agent/ecs-fargate/resources.tf index 0b6f1370c..15c834e66 100644 --- a/examples/serverless-agent/fargate/workload/instrumented_load.tf +++ b/examples/serverless-agent/ecs-fargate/resources.tf @@ -7,20 +7,7 @@ data "sysdig_fargate_workload_agent" "containers_instrumented" { "logConfiguration" : { "logDriver" : "awslogs", "options" : { - "awslogs-group" : aws_cloudwatch_log_group.instrumented_logs.name, - "awslogs-region" : var.region, - "awslogs-stream-prefix" : "task" - }, - } - }, - { - "name" : "event-gen-2", - "image" : "falcosecurity/event-generator", - "command" : ["run", "syscall", "--all", "--loop"], - "logConfiguration" : { - "logDriver" : "awslogs", - "options" : { - "awslogs-group" : aws_cloudwatch_log_group.instrumented_logs.name, + "awslogs-group" : aws_cloudwatch_log_group.logs.name, "awslogs-region" : var.region, "awslogs-stream-prefix" : "task" }, @@ -35,19 +22,19 @@ data "sysdig_fargate_workload_agent" "containers_instrumented" { collector_port = var.collector_port log_configuration { - group = aws_cloudwatch_log_group.instrumented_logs.name + group = aws_cloudwatch_log_group.logs.name stream_prefix = "instrumentation" region = var.region } } resource "aws_ecs_task_definition" "task_definition" { - family = "${var.prefix}-instrumented-task-definition" + family = "${var.prefix}-task-definition" task_role_arn = aws_iam_role.task_role.arn execution_role_arn = aws_iam_role.execution_role.arn - cpu = "256" - memory = "512" + cpu = "512" + memory = "1024" network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] pid_mode = "task" @@ -57,10 +44,10 @@ resource "aws_ecs_task_definition" "task_definition" { resource "aws_ecs_cluster" "cluster" { - name = "${var.prefix}-instrumented-workload" + name = "${var.prefix}-cluster" } -resource "aws_cloudwatch_log_group" "instrumented_logs" { +resource "aws_cloudwatch_log_group" "logs" { } data "aws_iam_policy_document" "assume_role_policy" { @@ -106,7 +93,7 @@ data "aws_iam_policy_document" "task_policy" { } resource "aws_ecs_service" "service" { - name = "${var.prefix}-instrumented-service" + name = "${var.prefix}-service" cluster = aws_ecs_cluster.cluster.id task_definition = aws_ecs_task_definition.task_definition.arn @@ -115,7 +102,7 @@ resource "aws_ecs_service" "service" { platform_version = "1.4.0" network_configuration { - subnets = [var.subnet_1, var.subnet_2] + subnets = [var.subnet] security_groups = [aws_security_group.security_group.id] assign_public_ip = true } @@ -126,7 +113,7 @@ resource "aws_security_group" "security_group" { vpc_id = var.vpc_id } -resource "aws_security_group_rule" "orchestrator_agent_ingress_rule" { +resource "aws_security_group_rule" "ingress_rule" { type = "ingress" protocol = "tcp" from_port = 0 @@ -135,7 +122,7 @@ resource "aws_security_group_rule" "orchestrator_agent_ingress_rule" { security_group_id = aws_security_group.security_group.id } -resource "aws_security_group_rule" "orchestrator_agent_egress_rule" { +resource "aws_security_group_rule" "egress_rule" { type = "egress" protocol = "all" from_port = 0 diff --git a/examples/serverless-agent/fargate/workload/variables.tf b/examples/serverless-agent/ecs-fargate/variables.tf similarity index 78% rename from examples/serverless-agent/fargate/workload/variables.tf rename to examples/serverless-agent/ecs-fargate/variables.tf index ba6abf0ce..b0440445b 100644 --- a/examples/serverless-agent/fargate/workload/variables.tf +++ b/examples/serverless-agent/ecs-fargate/variables.tf @@ -9,20 +9,15 @@ variable "profile" { } variable "region" { - description = "AWS Region for deployment" - default = "us-east-1" + description = "AWS Region for deployment, for example: us-east-1" } -variable "subnet_1" { - description = "Subnet-1 Id" -} - -variable "subnet_2" { - description = "Subnet-2 Id" +variable "vpc_id" { + description = "VPC Id (for example: vpc-1234567890abcde)" } -variable "vpc_id" { - description = "VPC Id" +variable "subnet" { + description = "Subnet Id (for example: subnet-1234567890abcde)" } variable "tags" { @@ -33,7 +28,7 @@ variable "tags" { variable "replicas" { description = "Number of workload replicas to run" - default = 2 + default = 1 } # Serverless Agent Configuration diff --git a/examples/serverless-agent/fargate/orchestrator/versions.tf b/examples/serverless-agent/ecs-fargate/versions.tf similarity index 56% rename from examples/serverless-agent/fargate/orchestrator/versions.tf rename to examples/serverless-agent/ecs-fargate/versions.tf index 37120d0a4..95a1aa035 100644 --- a/examples/serverless-agent/fargate/orchestrator/versions.tf +++ b/examples/serverless-agent/ecs-fargate/versions.tf @@ -4,15 +4,11 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 5.35.0" - } - local = { - source = "hashicorp/local" - version = "~> 2.4.1" + version = "~>6.32.0" } sysdig = { source = "sysdiglabs/sysdig" - version = "~> 1.24.5" + version = "~>3.4.0" } } } \ No newline at end of file diff --git a/examples/serverless-agent/fargate/orchestrator/README.md b/examples/serverless-agent/fargate/orchestrator/README.md deleted file mode 100644 index c528b975e..000000000 --- a/examples/serverless-agent/fargate/orchestrator/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Serverless Orchestrator Agent - -This example deploys an AWS ECS Fargate cluster to run the Serverless Orchestrator Agent. This Agent acts as a proxy between the Collector and many Serverless Workload Agents. - -## Prerequisites - -The following AWS prerequisites are required to deploy this cluster: -- VPC -- 2 subnets - -## Components - -The cluster will be called `-cluster` and will deploy the following: -- 1 Service (called `OrchestratorAgent`) - - 1 Task (with the latest version of the Serverless Orchestrator Agent) -- Network Load balancer -- Cloudwatch log group -- Security group - -## Layout -| **File** | **Purpose** | -| --- | --- | -| `main.tf` | AWS provider configuration | -| `orchestrator.tf` | Orchestrator cluster definition | -| `output.tf` | Defines the output variables | -| `variables.tf` | AWS and Agent configuration | -| `versions.tf` | Defines TF provider versions | diff --git a/examples/serverless-agent/fargate/orchestrator/orchestrator.tf b/examples/serverless-agent/fargate/orchestrator/orchestrator.tf deleted file mode 100644 index 102d96042..000000000 --- a/examples/serverless-agent/fargate/orchestrator/orchestrator.tf +++ /dev/null @@ -1,36 +0,0 @@ -module "fargate-orchestrator-agent" { - source = "sysdiglabs/fargate-orchestrator-agent/aws" - version = "0.5.0" - - vpc_id = var.vpc_id - subnets = [var.subnet_1, var.subnet_2] - - access_key = var.access_key - - collector_host = var.collector_host - collector_port = var.collector_port - - name = var.prefix - agent_image = var.agent_orchestrator_image - - # True if the VPC uses an InternetGateway, false otherwise - assign_public_ip = true - - tags = var.tags -} - - -data "aws_ecs_cluster" "fargate-orchestrator" { - depends_on = [ - module.fargate-orchestrator-agent - ] - cluster_name = "${var.prefix}-cluster" -} - -data "aws_ecs_service" "orchestrator-service" { - depends_on = [ - module.fargate-orchestrator-agent - ] - service_name = "OrchestratorAgent" - cluster_arn = data.aws_ecs_cluster.fargate-orchestrator.arn -} diff --git a/examples/serverless-agent/fargate/orchestrator/output.tf b/examples/serverless-agent/fargate/orchestrator/output.tf deleted file mode 100644 index 0088749df..000000000 --- a/examples/serverless-agent/fargate/orchestrator/output.tf +++ /dev/null @@ -1,11 +0,0 @@ -output "orchestrator_cluster_name" { - value = data.aws_ecs_cluster.fargate-orchestrator.cluster_name -} - -output "orchestrator_cluster_arn" { - value = data.aws_ecs_cluster.fargate-orchestrator.arn -} - -output "orchestrator_service_arn" { - value = data.aws_ecs_service.orchestrator-service.arn -} diff --git a/examples/serverless-agent/fargate/orchestrator/providers.tf b/examples/serverless-agent/fargate/orchestrator/providers.tf deleted file mode 100644 index f6f28cca8..000000000 --- a/examples/serverless-agent/fargate/orchestrator/providers.tf +++ /dev/null @@ -1,4 +0,0 @@ -provider "aws" { - region = var.region - profile = var.profile -} diff --git a/examples/serverless-agent/fargate/orchestrator/variables.tf b/examples/serverless-agent/fargate/orchestrator/variables.tf deleted file mode 100644 index 92af8fc9f..000000000 --- a/examples/serverless-agent/fargate/orchestrator/variables.tf +++ /dev/null @@ -1,51 +0,0 @@ -# AWS configuration -variable "prefix" { - description = "All resources created by Terraform have this prefix prepended to them" -} - -variable "profile" { - description = "AWS profile name" - type = string -} - -variable "region" { - description = "AWS Region for deployment" - default = "us-east-1" -} - -variable "subnet_1" { - description = "Subnet-1 Id" -} - -variable "subnet_2" { - description = "Subnet-2 Id" -} - -variable "vpc_id" { - description = "VPC Id" -} - -variable "tags" { - type = map(string) - description = "Tags to assign to resources in module" - default = {} -} - -# Serverless Agent Configuration -variable "access_key" { - description = "Sysdig Agent access key" -} - -variable "agent_orchestrator_image" { - description = "Orchestrator Agent image to use" - default = "quay.io/sysdig/orchestrator-agent:latest" -} - -variable "collector_host" { - description = "Collector host where agent will send the data" -} - -variable "collector_port" { - description = "Collector port where agent will send the data" - default = "6443" -} diff --git a/examples/serverless-agent/fargate/workload-legacy/README.md b/examples/serverless-agent/fargate/workload-legacy/README.md deleted file mode 100644 index a221da511..000000000 --- a/examples/serverless-agent/fargate/workload-legacy/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Workload with Serverless Workload Agent - -This example deploys a cluster with a workload and the Serverless Workload Agent as a sidecar to secure the workload. - -The Workload Agent will use an Orchestrator Agent as a proxy to the Sysdig Collector. - -## Prerequisites - -The following prerequisites are required to deploy this cluster: -- Orchestrator Agent deployed -- VPC -- 2 subnets - -## Components - -The cluster will be called `-instrumented-workload` and will deploy the following: -- 1 Service (called `-instrumented-workload` and will deploy the following: -- 1 Service (called `= %d, got %d", minCount, count) + } + return nil + } +} + func ruleStatefulCountDataSource() string { return fmt.Sprintf(` %s diff --git a/sysdig/data_source_sysdig_user_test.go b/sysdig/data_source_sysdig_user_test.go index 4e66800f3..7743c5c6b 100644 --- a/sysdig/data_source_sysdig_user_test.go +++ b/sysdig/data_source_sysdig_user_test.go @@ -3,8 +3,10 @@ package sysdig_test import ( + "fmt" "testing" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -12,6 +14,7 @@ import ( ) func TestAccDataUser(t *testing.T) { + randomSuffix := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) resource.ParallelTest(t, resource.TestCase{ PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), ProviderFactories: map[string]func() (*schema.Provider, error){ @@ -21,21 +24,21 @@ func TestAccDataUser(t *testing.T) { }, Steps: []resource.TestStep{ { - Config: getUser(), + Config: getUser(randomSuffix), }, }, }) } -func getUser() string { - return ` +func getUser(suffix string) string { + return fmt.Sprintf(` resource "sysdig_user" "sample" { - email = "terraform-test+user@sysdig.com" + email = "terraform-test+user-%s@sysdig.com" } data "sysdig_user" "me" { depends_on = ["sysdig_user.sample"] email = sysdig_user.sample.email } -` +`, suffix) } diff --git a/sysdig/internal/client/v2/alerts_v2.go b/sysdig/internal/client/v2/alerts_v2.go index 556696640..3fd100a0c 100644 --- a/sysdig/internal/client/v2/alerts_v2.go +++ b/sysdig/internal/client/v2/alerts_v2.go @@ -43,8 +43,9 @@ const ( ) const ( - AlertLinkV2TypeDashboard AlertLinkV2Type = "dashboard" - AlertLinkV2TypeRunbook AlertLinkV2Type = "runbook" + AlertLinkV2TypeDashboard AlertLinkV2Type = "dashboard" + AlertLinkV2TypeDashboardTemplate AlertLinkV2Type = "dashboardTemplate" + AlertLinkV2TypeRunbook AlertLinkV2Type = "runbook" ) var labelCache struct { diff --git a/sysdig/internal/client/v2/cloudauth/go/cloud_account.pb.go b/sysdig/internal/client/v2/cloudauth/go/cloudauth_cloud_account.pb.go similarity index 92% rename from sysdig/internal/client/v2/cloudauth/go/cloud_account.pb.go rename to sysdig/internal/client/v2/cloudauth/go/cloudauth_cloud_account.pb.go index 0c5a874fe..ba543220d 100644 --- a/sysdig/internal/client/v2/cloudauth/go/cloud_account.pb.go +++ b/sysdig/internal/client/v2/cloudauth/go/cloudauth_cloud_account.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.6 -// protoc v4.24.2 +// protoc-gen-go v1.36.11 +// protoc v6.33.5 // source: cloudauth_cloud_account.proto package cloudauthproto @@ -531,6 +531,7 @@ type CloudAccount struct { // // *CloudAccount_Ibm ProviderDetails isCloudAccount_ProviderDetails `protobuf_oneof:"provider_details"` + ParentUuid string `protobuf:"bytes,22,opt,name=parent_uuid,json=parentUuid,proto3" json:"parent_uuid,omitempty"` // UUID/CRN of the direct parent organizational group; empty if directly under the root unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -721,6 +722,13 @@ func (x *CloudAccount) GetIbm() *IBMCloudAccount { return nil } +func (x *CloudAccount) GetParentUuid() string { + if x != nil { + return x.ParentUuid + } + return "" +} + type isCloudAccount_ProviderDetails interface { isCloudAccount_ProviderDetails() } @@ -1445,6 +1453,124 @@ func (x *CloudOrganization) GetAutomaticOnboarding() bool { return false } +// OrganizationalGroup captures metadata for cloud organizational structures +// Supports AWS Organizations OUs, Azure Management Groups, GCP Folders, IBM Account Groups +type OrganizationalGroup struct { + state protoimpl.MessageState `protogen:"open.v1"` + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // Primary key (IBM CRN, AWS ARN, Azure Resource ID, GCP Resource Name) + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // Human-readable name (e.g., "Production OU", "account-AA") + OrganizationUuid string `protobuf:"bytes,3,opt,name=organization_uuid,json=organizationUuid,proto3" json:"organization_uuid,omitempty"` // Organization UUID (parent organization) + ParentUuid string `protobuf:"bytes,4,opt,name=parent_uuid,json=parentUuid,proto3" json:"parent_uuid,omitempty"` // Parent group UUID (empty/null for root-level groups) + Provider Provider `protobuf:"varint,5,opt,name=provider,proto3,enum=cloudauthproto.Provider" json:"provider,omitempty"` // Cloud provider enum (PROVIDER_AWS, PROVIDER_AZURE, etc.) + Metadata *structpb.Struct `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata,omitempty"` // Provider-specific metadata (JSONB storage) + CustomerId uint64 `protobuf:"varint,7,opt,name=customer_id,json=customerId,proto3" json:"customer_id,omitempty"` // Customer ID for multi-tenancy isolation + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` // Creation timestamp + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` // Last update timestamp + Verbosity Verbosity `protobuf:"varint,10,opt,name=verbosity,proto3,enum=cloudauthproto.Verbosity" json:"verbosity,omitempty"` // Verbosity level for nested loading control + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OrganizationalGroup) Reset() { + *x = OrganizationalGroup{} + mi := &file_cloudauth_cloud_account_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OrganizationalGroup) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OrganizationalGroup) ProtoMessage() {} + +func (x *OrganizationalGroup) ProtoReflect() protoreflect.Message { + mi := &file_cloudauth_cloud_account_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OrganizationalGroup.ProtoReflect.Descriptor instead. +func (*OrganizationalGroup) Descriptor() ([]byte, []int) { + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{9} +} + +func (x *OrganizationalGroup) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *OrganizationalGroup) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *OrganizationalGroup) GetOrganizationUuid() string { + if x != nil { + return x.OrganizationUuid + } + return "" +} + +func (x *OrganizationalGroup) GetParentUuid() string { + if x != nil { + return x.ParentUuid + } + return "" +} + +func (x *OrganizationalGroup) GetProvider() Provider { + if x != nil { + return x.Provider + } + return Provider_PROVIDER_UNSPECIFIED +} + +func (x *OrganizationalGroup) GetMetadata() *structpb.Struct { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *OrganizationalGroup) GetCustomerId() uint64 { + if x != nil { + return x.CustomerId + } + return 0 +} + +func (x *OrganizationalGroup) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *OrganizationalGroup) GetUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.UpdatedAt + } + return nil +} + +func (x *OrganizationalGroup) GetVerbosity() Verbosity { + if x != nil { + return x.Verbosity + } + return Verbosity_VERBOSITY_UNSPECIFIED +} + // FeatureComponents enumerates all components available to a feature type FeatureComponents struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1463,7 +1589,7 @@ type FeatureComponents struct { func (x *FeatureComponents) Reset() { *x = FeatureComponents{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[9] + mi := &file_cloudauth_cloud_account_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1475,7 +1601,7 @@ func (x *FeatureComponents) String() string { func (*FeatureComponents) ProtoMessage() {} func (x *FeatureComponents) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[9] + mi := &file_cloudauth_cloud_account_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1488,7 +1614,7 @@ func (x *FeatureComponents) ProtoReflect() protoreflect.Message { // Deprecated: Use FeatureComponents.ProtoReflect.Descriptor instead. func (*FeatureComponents) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{9} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{10} } func (x *FeatureComponents) GetCloudConnector() *AccountComponent { @@ -1581,7 +1707,7 @@ type AccountComponent struct { func (x *AccountComponent) Reset() { *x = AccountComponent{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[10] + mi := &file_cloudauth_cloud_account_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1593,7 +1719,7 @@ func (x *AccountComponent) String() string { func (*AccountComponent) ProtoMessage() {} func (x *AccountComponent) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[10] + mi := &file_cloudauth_cloud_account_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1606,7 +1732,7 @@ func (x *AccountComponent) ProtoReflect() protoreflect.Message { // Deprecated: Use AccountComponent.ProtoReflect.Descriptor instead. func (*AccountComponent) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{10} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{11} } func (x *AccountComponent) GetType() Component { @@ -1812,7 +1938,7 @@ type CloudConnectorMetadata struct { func (x *CloudConnectorMetadata) Reset() { *x = CloudConnectorMetadata{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[11] + mi := &file_cloudauth_cloud_account_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1824,7 +1950,7 @@ func (x *CloudConnectorMetadata) String() string { func (*CloudConnectorMetadata) ProtoMessage() {} func (x *CloudConnectorMetadata) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[11] + mi := &file_cloudauth_cloud_account_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1837,7 +1963,7 @@ func (x *CloudConnectorMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use CloudConnectorMetadata.ProtoReflect.Descriptor instead. func (*CloudConnectorMetadata) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{11} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{12} } func (x *CloudConnectorMetadata) GetProvider() isCloudConnectorMetadata_Provider { @@ -1912,7 +2038,7 @@ type TrustedRoleMetadata struct { func (x *TrustedRoleMetadata) Reset() { *x = TrustedRoleMetadata{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[12] + mi := &file_cloudauth_cloud_account_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1924,7 +2050,7 @@ func (x *TrustedRoleMetadata) String() string { func (*TrustedRoleMetadata) ProtoMessage() {} func (x *TrustedRoleMetadata) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[12] + mi := &file_cloudauth_cloud_account_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1937,7 +2063,7 @@ func (x *TrustedRoleMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use TrustedRoleMetadata.ProtoReflect.Descriptor instead. func (*TrustedRoleMetadata) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{12} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{13} } func (x *TrustedRoleMetadata) GetProvider() isTrustedRoleMetadata_Provider { @@ -2025,7 +2151,7 @@ type EventBridgeMetadata struct { func (x *EventBridgeMetadata) Reset() { *x = EventBridgeMetadata{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[13] + mi := &file_cloudauth_cloud_account_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2037,7 +2163,7 @@ func (x *EventBridgeMetadata) String() string { func (*EventBridgeMetadata) ProtoMessage() {} func (x *EventBridgeMetadata) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[13] + mi := &file_cloudauth_cloud_account_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2050,7 +2176,7 @@ func (x *EventBridgeMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use EventBridgeMetadata.ProtoReflect.Descriptor instead. func (*EventBridgeMetadata) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{13} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14} } func (x *EventBridgeMetadata) GetProvider() isEventBridgeMetadata_Provider { @@ -2110,7 +2236,7 @@ type ServicePrincipalMetadata struct { func (x *ServicePrincipalMetadata) Reset() { *x = ServicePrincipalMetadata{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[14] + mi := &file_cloudauth_cloud_account_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2122,7 +2248,7 @@ func (x *ServicePrincipalMetadata) String() string { func (*ServicePrincipalMetadata) ProtoMessage() {} func (x *ServicePrincipalMetadata) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[14] + mi := &file_cloudauth_cloud_account_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2135,7 +2261,7 @@ func (x *ServicePrincipalMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicePrincipalMetadata.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15} } func (x *ServicePrincipalMetadata) GetProvider() isServicePrincipalMetadata_Provider { @@ -2226,7 +2352,7 @@ type WebhookDatasourceMetadata struct { func (x *WebhookDatasourceMetadata) Reset() { *x = WebhookDatasourceMetadata{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[15] + mi := &file_cloudauth_cloud_account_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2238,7 +2364,7 @@ func (x *WebhookDatasourceMetadata) String() string { func (*WebhookDatasourceMetadata) ProtoMessage() {} func (x *WebhookDatasourceMetadata) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[15] + mi := &file_cloudauth_cloud_account_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2251,7 +2377,7 @@ func (x *WebhookDatasourceMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use WebhookDatasourceMetadata.ProtoReflect.Descriptor instead. func (*WebhookDatasourceMetadata) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16} } func (x *WebhookDatasourceMetadata) GetProvider() isWebhookDatasourceMetadata_Provider { @@ -2338,7 +2464,7 @@ type CryptoKeyMetadata struct { func (x *CryptoKeyMetadata) Reset() { *x = CryptoKeyMetadata{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[16] + mi := &file_cloudauth_cloud_account_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2350,7 +2476,7 @@ func (x *CryptoKeyMetadata) String() string { func (*CryptoKeyMetadata) ProtoMessage() {} func (x *CryptoKeyMetadata) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[16] + mi := &file_cloudauth_cloud_account_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2363,7 +2489,7 @@ func (x *CryptoKeyMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use CryptoKeyMetadata.ProtoReflect.Descriptor instead. func (*CryptoKeyMetadata) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{17} } func (x *CryptoKeyMetadata) GetProvider() isCryptoKeyMetadata_Provider { @@ -2406,7 +2532,7 @@ type CloudLogsMetadata struct { func (x *CloudLogsMetadata) Reset() { *x = CloudLogsMetadata{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[17] + mi := &file_cloudauth_cloud_account_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2418,7 +2544,7 @@ func (x *CloudLogsMetadata) String() string { func (*CloudLogsMetadata) ProtoMessage() {} func (x *CloudLogsMetadata) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[17] + mi := &file_cloudauth_cloud_account_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2431,7 +2557,7 @@ func (x *CloudLogsMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use CloudLogsMetadata.ProtoReflect.Descriptor instead. func (*CloudLogsMetadata) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{17} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{18} } func (x *CloudLogsMetadata) GetProvider() isCloudLogsMetadata_Provider { @@ -2487,7 +2613,7 @@ type CloudResponderMetadata struct { func (x *CloudResponderMetadata) Reset() { *x = CloudResponderMetadata{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[18] + mi := &file_cloudauth_cloud_account_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2499,7 +2625,7 @@ func (x *CloudResponderMetadata) String() string { func (*CloudResponderMetadata) ProtoMessage() {} func (x *CloudResponderMetadata) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[18] + mi := &file_cloudauth_cloud_account_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2512,7 +2638,7 @@ func (x *CloudResponderMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use CloudResponderMetadata.ProtoReflect.Descriptor instead. func (*CloudResponderMetadata) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{18} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{19} } func (x *CloudResponderMetadata) GetProvider() isCloudResponderMetadata_Provider { @@ -2542,15 +2668,16 @@ type CloudResponderMetadata_Aws struct { func (*CloudResponderMetadata_Aws) isCloudResponderMetadata_Provider() {} type CloudResponderRolesMetadata struct { - state protoimpl.MessageState `protogen:"open.v1"` - Roles []*TrustedRoleMetadata `protobuf:"bytes,1,rep,name=roles,proto3" json:"roles,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Roles []*TrustedRoleMetadata `protobuf:"bytes,1,rep,name=roles,proto3" json:"roles,omitempty"` + ValidationRole *TrustedRoleMetadata `protobuf:"bytes,2,opt,name=validation_role,json=validationRole,proto3" json:"validation_role,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CloudResponderRolesMetadata) Reset() { *x = CloudResponderRolesMetadata{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[19] + mi := &file_cloudauth_cloud_account_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2562,7 +2689,7 @@ func (x *CloudResponderRolesMetadata) String() string { func (*CloudResponderRolesMetadata) ProtoMessage() {} func (x *CloudResponderRolesMetadata) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[19] + mi := &file_cloudauth_cloud_account_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2575,7 +2702,7 @@ func (x *CloudResponderRolesMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use CloudResponderRolesMetadata.ProtoReflect.Descriptor instead. func (*CloudResponderRolesMetadata) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{19} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{20} } func (x *CloudResponderRolesMetadata) GetRoles() []*TrustedRoleMetadata { @@ -2585,6 +2712,13 @@ func (x *CloudResponderRolesMetadata) GetRoles() []*TrustedRoleMetadata { return nil } +func (x *CloudResponderRolesMetadata) GetValidationRole() *TrustedRoleMetadata { + if x != nil { + return x.ValidationRole + } + return nil +} + type CloudConnectorMetadata_AWS struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -2593,7 +2727,7 @@ type CloudConnectorMetadata_AWS struct { func (x *CloudConnectorMetadata_AWS) Reset() { *x = CloudConnectorMetadata_AWS{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[21] + mi := &file_cloudauth_cloud_account_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2605,7 +2739,7 @@ func (x *CloudConnectorMetadata_AWS) String() string { func (*CloudConnectorMetadata_AWS) ProtoMessage() {} func (x *CloudConnectorMetadata_AWS) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[21] + mi := &file_cloudauth_cloud_account_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2618,7 +2752,7 @@ func (x *CloudConnectorMetadata_AWS) ProtoReflect() protoreflect.Message { // Deprecated: Use CloudConnectorMetadata_AWS.ProtoReflect.Descriptor instead. func (*CloudConnectorMetadata_AWS) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{11, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{12, 0} } type CloudConnectorMetadata_Azure struct { @@ -2629,7 +2763,7 @@ type CloudConnectorMetadata_Azure struct { func (x *CloudConnectorMetadata_Azure) Reset() { *x = CloudConnectorMetadata_Azure{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[22] + mi := &file_cloudauth_cloud_account_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2641,7 +2775,7 @@ func (x *CloudConnectorMetadata_Azure) String() string { func (*CloudConnectorMetadata_Azure) ProtoMessage() {} func (x *CloudConnectorMetadata_Azure) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[22] + mi := &file_cloudauth_cloud_account_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2654,7 +2788,7 @@ func (x *CloudConnectorMetadata_Azure) ProtoReflect() protoreflect.Message { // Deprecated: Use CloudConnectorMetadata_Azure.ProtoReflect.Descriptor instead. func (*CloudConnectorMetadata_Azure) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{11, 1} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{12, 1} } type CloudConnectorMetadata_GCP struct { @@ -2665,7 +2799,7 @@ type CloudConnectorMetadata_GCP struct { func (x *CloudConnectorMetadata_GCP) Reset() { *x = CloudConnectorMetadata_GCP{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[23] + mi := &file_cloudauth_cloud_account_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2677,7 +2811,7 @@ func (x *CloudConnectorMetadata_GCP) String() string { func (*CloudConnectorMetadata_GCP) ProtoMessage() {} func (x *CloudConnectorMetadata_GCP) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[23] + mi := &file_cloudauth_cloud_account_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2690,7 +2824,7 @@ func (x *CloudConnectorMetadata_GCP) ProtoReflect() protoreflect.Message { // Deprecated: Use CloudConnectorMetadata_GCP.ProtoReflect.Descriptor instead. func (*CloudConnectorMetadata_GCP) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{11, 2} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{12, 2} } type TrustedRoleMetadata_AWS struct { @@ -2702,7 +2836,7 @@ type TrustedRoleMetadata_AWS struct { func (x *TrustedRoleMetadata_AWS) Reset() { *x = TrustedRoleMetadata_AWS{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[24] + mi := &file_cloudauth_cloud_account_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2714,7 +2848,7 @@ func (x *TrustedRoleMetadata_AWS) String() string { func (*TrustedRoleMetadata_AWS) ProtoMessage() {} func (x *TrustedRoleMetadata_AWS) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[24] + mi := &file_cloudauth_cloud_account_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2727,7 +2861,7 @@ func (x *TrustedRoleMetadata_AWS) ProtoReflect() protoreflect.Message { // Deprecated: Use TrustedRoleMetadata_AWS.ProtoReflect.Descriptor instead. func (*TrustedRoleMetadata_AWS) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{12, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{13, 0} } func (x *TrustedRoleMetadata_AWS) GetRoleName() string { @@ -2746,7 +2880,7 @@ type TrustedRoleMetadata_GCP struct { func (x *TrustedRoleMetadata_GCP) Reset() { *x = TrustedRoleMetadata_GCP{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[25] + mi := &file_cloudauth_cloud_account_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2758,7 +2892,7 @@ func (x *TrustedRoleMetadata_GCP) String() string { func (*TrustedRoleMetadata_GCP) ProtoMessage() {} func (x *TrustedRoleMetadata_GCP) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[25] + mi := &file_cloudauth_cloud_account_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2771,7 +2905,7 @@ func (x *TrustedRoleMetadata_GCP) ProtoReflect() protoreflect.Message { // Deprecated: Use TrustedRoleMetadata_GCP.ProtoReflect.Descriptor instead. func (*TrustedRoleMetadata_GCP) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{12, 1} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{13, 1} } func (x *TrustedRoleMetadata_GCP) GetRoleName() string { @@ -2790,7 +2924,7 @@ type TrustedRoleMetadata_Azure struct { func (x *TrustedRoleMetadata_Azure) Reset() { *x = TrustedRoleMetadata_Azure{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[26] + mi := &file_cloudauth_cloud_account_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2802,7 +2936,7 @@ func (x *TrustedRoleMetadata_Azure) String() string { func (*TrustedRoleMetadata_Azure) ProtoMessage() {} func (x *TrustedRoleMetadata_Azure) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[26] + mi := &file_cloudauth_cloud_account_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2815,7 +2949,7 @@ func (x *TrustedRoleMetadata_Azure) ProtoReflect() protoreflect.Message { // Deprecated: Use TrustedRoleMetadata_Azure.ProtoReflect.Descriptor instead. func (*TrustedRoleMetadata_Azure) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{12, 2} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{13, 2} } func (x *TrustedRoleMetadata_Azure) GetRoleName() string { @@ -2834,7 +2968,7 @@ type TrustedRoleMetadata_IBMCloud struct { func (x *TrustedRoleMetadata_IBMCloud) Reset() { *x = TrustedRoleMetadata_IBMCloud{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[27] + mi := &file_cloudauth_cloud_account_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2846,7 +2980,7 @@ func (x *TrustedRoleMetadata_IBMCloud) String() string { func (*TrustedRoleMetadata_IBMCloud) ProtoMessage() {} func (x *TrustedRoleMetadata_IBMCloud) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[27] + mi := &file_cloudauth_cloud_account_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2859,7 +2993,7 @@ func (x *TrustedRoleMetadata_IBMCloud) ProtoReflect() protoreflect.Message { // Deprecated: Use TrustedRoleMetadata_IBMCloud.ProtoReflect.Descriptor instead. func (*TrustedRoleMetadata_IBMCloud) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{12, 3} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{13, 3} } func (x *TrustedRoleMetadata_IBMCloud) GetRoleName() string { @@ -2880,7 +3014,7 @@ type EventBridgeMetadata_AWS struct { func (x *EventBridgeMetadata_AWS) Reset() { *x = EventBridgeMetadata_AWS{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[28] + mi := &file_cloudauth_cloud_account_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2892,7 +3026,7 @@ func (x *EventBridgeMetadata_AWS) String() string { func (*EventBridgeMetadata_AWS) ProtoMessage() {} func (x *EventBridgeMetadata_AWS) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[28] + mi := &file_cloudauth_cloud_account_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2905,7 +3039,7 @@ func (x *EventBridgeMetadata_AWS) ProtoReflect() protoreflect.Message { // Deprecated: Use EventBridgeMetadata_AWS.ProtoReflect.Descriptor instead. func (*EventBridgeMetadata_AWS) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{13, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 0} } func (x *EventBridgeMetadata_AWS) GetRoleName() string { @@ -2939,7 +3073,7 @@ type EventBridgeMetadata_Azure struct { func (x *EventBridgeMetadata_Azure) Reset() { *x = EventBridgeMetadata_Azure{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[29] + mi := &file_cloudauth_cloud_account_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2951,7 +3085,7 @@ func (x *EventBridgeMetadata_Azure) String() string { func (*EventBridgeMetadata_Azure) ProtoMessage() {} func (x *EventBridgeMetadata_Azure) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[29] + mi := &file_cloudauth_cloud_account_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2964,7 +3098,7 @@ func (x *EventBridgeMetadata_Azure) ProtoReflect() protoreflect.Message { // Deprecated: Use EventBridgeMetadata_Azure.ProtoReflect.Descriptor instead. func (*EventBridgeMetadata_Azure) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{13, 1} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 1} } func (x *EventBridgeMetadata_Azure) GetEventHubMetadata() *EventBridgeMetadata_Azure_EventHubMetadata { @@ -2992,7 +3126,7 @@ type EventBridgeMetadata_Azure_EventHubMetadata struct { func (x *EventBridgeMetadata_Azure_EventHubMetadata) Reset() { *x = EventBridgeMetadata_Azure_EventHubMetadata{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[30] + mi := &file_cloudauth_cloud_account_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3004,7 +3138,7 @@ func (x *EventBridgeMetadata_Azure_EventHubMetadata) String() string { func (*EventBridgeMetadata_Azure_EventHubMetadata) ProtoMessage() {} func (x *EventBridgeMetadata_Azure_EventHubMetadata) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[30] + mi := &file_cloudauth_cloud_account_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3017,7 +3151,7 @@ func (x *EventBridgeMetadata_Azure_EventHubMetadata) ProtoReflect() protoreflect // Deprecated: Use EventBridgeMetadata_Azure_EventHubMetadata.ProtoReflect.Descriptor instead. func (*EventBridgeMetadata_Azure_EventHubMetadata) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{13, 1, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 1, 0} } func (x *EventBridgeMetadata_Azure_EventHubMetadata) GetEventHubName() string { @@ -3053,7 +3187,7 @@ type ServicePrincipalMetadata_GCP struct { func (x *ServicePrincipalMetadata_GCP) Reset() { *x = ServicePrincipalMetadata_GCP{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[31] + mi := &file_cloudauth_cloud_account_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3065,7 +3199,7 @@ func (x *ServicePrincipalMetadata_GCP) String() string { func (*ServicePrincipalMetadata_GCP) ProtoMessage() {} func (x *ServicePrincipalMetadata_GCP) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[31] + mi := &file_cloudauth_cloud_account_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3078,7 +3212,7 @@ func (x *ServicePrincipalMetadata_GCP) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicePrincipalMetadata_GCP.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_GCP) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 0} } func (x *ServicePrincipalMetadata_GCP) GetKey() *ServicePrincipalMetadata_GCP_Key { @@ -3118,7 +3252,7 @@ type ServicePrincipalMetadata_Okta struct { func (x *ServicePrincipalMetadata_Okta) Reset() { *x = ServicePrincipalMetadata_Okta{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[32] + mi := &file_cloudauth_cloud_account_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3130,7 +3264,7 @@ func (x *ServicePrincipalMetadata_Okta) String() string { func (*ServicePrincipalMetadata_Okta) ProtoMessage() {} func (x *ServicePrincipalMetadata_Okta) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[32] + mi := &file_cloudauth_cloud_account_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3143,7 +3277,7 @@ func (x *ServicePrincipalMetadata_Okta) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicePrincipalMetadata_Okta.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_Okta) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 1} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 1} } func (x *ServicePrincipalMetadata_Okta) GetOauthApp() *ServicePrincipalMetadata_Okta_OAuthApp { @@ -3163,7 +3297,7 @@ type ServicePrincipalMetadata_Azure struct { func (x *ServicePrincipalMetadata_Azure) Reset() { *x = ServicePrincipalMetadata_Azure{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[33] + mi := &file_cloudauth_cloud_account_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3175,7 +3309,7 @@ func (x *ServicePrincipalMetadata_Azure) String() string { func (*ServicePrincipalMetadata_Azure) ProtoMessage() {} func (x *ServicePrincipalMetadata_Azure) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[33] + mi := &file_cloudauth_cloud_account_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3188,7 +3322,7 @@ func (x *ServicePrincipalMetadata_Azure) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicePrincipalMetadata_Azure.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_Azure) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 2} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 2} } func (x *ServicePrincipalMetadata_Azure) GetActiveDirectoryServicePrincipal() *ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal { @@ -3215,7 +3349,7 @@ type ServicePrincipalMetadata_OracleCloud struct { func (x *ServicePrincipalMetadata_OracleCloud) Reset() { *x = ServicePrincipalMetadata_OracleCloud{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[34] + mi := &file_cloudauth_cloud_account_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3227,7 +3361,7 @@ func (x *ServicePrincipalMetadata_OracleCloud) String() string { func (*ServicePrincipalMetadata_OracleCloud) ProtoMessage() {} func (x *ServicePrincipalMetadata_OracleCloud) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[34] + mi := &file_cloudauth_cloud_account_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3240,7 +3374,7 @@ func (x *ServicePrincipalMetadata_OracleCloud) ProtoReflect() protoreflect.Messa // Deprecated: Use ServicePrincipalMetadata_OracleCloud.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_OracleCloud) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 3} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 3} } func (x *ServicePrincipalMetadata_OracleCloud) GetApiKey() *ServicePrincipalMetadata_OracleCloud_ApiKey { @@ -3276,7 +3410,7 @@ type ServicePrincipalMetadata_GCP_Key struct { func (x *ServicePrincipalMetadata_GCP_Key) Reset() { *x = ServicePrincipalMetadata_GCP_Key{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[35] + mi := &file_cloudauth_cloud_account_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3288,7 +3422,7 @@ func (x *ServicePrincipalMetadata_GCP_Key) String() string { func (*ServicePrincipalMetadata_GCP_Key) ProtoMessage() {} func (x *ServicePrincipalMetadata_GCP_Key) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[35] + mi := &file_cloudauth_cloud_account_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3301,7 +3435,7 @@ func (x *ServicePrincipalMetadata_GCP_Key) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicePrincipalMetadata_GCP_Key.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_GCP_Key) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 0, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 0, 0} } func (x *ServicePrincipalMetadata_GCP_Key) GetType() string { @@ -3392,7 +3526,7 @@ type ServicePrincipalMetadata_GCP_WorkloadIdentityFederation struct { func (x *ServicePrincipalMetadata_GCP_WorkloadIdentityFederation) Reset() { *x = ServicePrincipalMetadata_GCP_WorkloadIdentityFederation{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[36] + mi := &file_cloudauth_cloud_account_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3404,7 +3538,7 @@ func (x *ServicePrincipalMetadata_GCP_WorkloadIdentityFederation) String() strin func (*ServicePrincipalMetadata_GCP_WorkloadIdentityFederation) ProtoMessage() {} func (x *ServicePrincipalMetadata_GCP_WorkloadIdentityFederation) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[36] + mi := &file_cloudauth_cloud_account_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3417,7 +3551,7 @@ func (x *ServicePrincipalMetadata_GCP_WorkloadIdentityFederation) ProtoReflect() // Deprecated: Use ServicePrincipalMetadata_GCP_WorkloadIdentityFederation.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_GCP_WorkloadIdentityFederation) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 0, 1} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 0, 1} } func (x *ServicePrincipalMetadata_GCP_WorkloadIdentityFederation) GetPoolId() string { @@ -3452,7 +3586,7 @@ type ServicePrincipalMetadata_Okta_OAuthApp struct { func (x *ServicePrincipalMetadata_Okta_OAuthApp) Reset() { *x = ServicePrincipalMetadata_Okta_OAuthApp{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[37] + mi := &file_cloudauth_cloud_account_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3464,7 +3598,7 @@ func (x *ServicePrincipalMetadata_Okta_OAuthApp) String() string { func (*ServicePrincipalMetadata_Okta_OAuthApp) ProtoMessage() {} func (x *ServicePrincipalMetadata_Okta_OAuthApp) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[37] + mi := &file_cloudauth_cloud_account_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3477,7 +3611,7 @@ func (x *ServicePrincipalMetadata_Okta_OAuthApp) ProtoReflect() protoreflect.Mes // Deprecated: Use ServicePrincipalMetadata_Okta_OAuthApp.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_Okta_OAuthApp) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 1, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 1, 0} } func (x *ServicePrincipalMetadata_Okta_OAuthApp) GetOktaUrl() string { @@ -3519,7 +3653,7 @@ type ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal struct { func (x *ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal) Reset() { *x = ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[38] + mi := &file_cloudauth_cloud_account_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3531,7 +3665,7 @@ func (x *ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal) String( func (*ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal) ProtoMessage() {} func (x *ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[38] + mi := &file_cloudauth_cloud_account_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3544,7 +3678,7 @@ func (x *ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal) ProtoRe // Deprecated: Use ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 2, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 2, 0} } func (x *ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal) GetAccountEnabled() bool { @@ -3617,7 +3751,7 @@ type ServicePrincipalMetadata_Azure_Oauth2PermissionGrant struct { func (x *ServicePrincipalMetadata_Azure_Oauth2PermissionGrant) Reset() { *x = ServicePrincipalMetadata_Azure_Oauth2PermissionGrant{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[39] + mi := &file_cloudauth_cloud_account_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3629,7 +3763,7 @@ func (x *ServicePrincipalMetadata_Azure_Oauth2PermissionGrant) String() string { func (*ServicePrincipalMetadata_Azure_Oauth2PermissionGrant) ProtoMessage() {} func (x *ServicePrincipalMetadata_Azure_Oauth2PermissionGrant) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[39] + mi := &file_cloudauth_cloud_account_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3642,7 +3776,7 @@ func (x *ServicePrincipalMetadata_Azure_Oauth2PermissionGrant) ProtoReflect() pr // Deprecated: Use ServicePrincipalMetadata_Azure_Oauth2PermissionGrant.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_Azure_Oauth2PermissionGrant) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 2, 1} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 2, 1} } func (x *ServicePrincipalMetadata_Azure_Oauth2PermissionGrant) GetClientId() string { @@ -3703,7 +3837,7 @@ type ServicePrincipalMetadata_OracleCloud_ApiKey struct { func (x *ServicePrincipalMetadata_OracleCloud_ApiKey) Reset() { *x = ServicePrincipalMetadata_OracleCloud_ApiKey{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[40] + mi := &file_cloudauth_cloud_account_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3715,7 +3849,7 @@ func (x *ServicePrincipalMetadata_OracleCloud_ApiKey) String() string { func (*ServicePrincipalMetadata_OracleCloud_ApiKey) ProtoMessage() {} func (x *ServicePrincipalMetadata_OracleCloud_ApiKey) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[40] + mi := &file_cloudauth_cloud_account_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3728,7 +3862,7 @@ func (x *ServicePrincipalMetadata_OracleCloud_ApiKey) ProtoReflect() protoreflec // Deprecated: Use ServicePrincipalMetadata_OracleCloud_ApiKey.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_OracleCloud_ApiKey) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 3, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 3, 0} } func (x *ServicePrincipalMetadata_OracleCloud_ApiKey) GetFingerprint() string { @@ -3796,7 +3930,7 @@ type ServicePrincipalMetadata_OracleCloud_Policy struct { func (x *ServicePrincipalMetadata_OracleCloud_Policy) Reset() { *x = ServicePrincipalMetadata_OracleCloud_Policy{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[41] + mi := &file_cloudauth_cloud_account_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3808,7 +3942,7 @@ func (x *ServicePrincipalMetadata_OracleCloud_Policy) String() string { func (*ServicePrincipalMetadata_OracleCloud_Policy) ProtoMessage() {} func (x *ServicePrincipalMetadata_OracleCloud_Policy) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[41] + mi := &file_cloudauth_cloud_account_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3821,7 +3955,7 @@ func (x *ServicePrincipalMetadata_OracleCloud_Policy) ProtoReflect() protoreflec // Deprecated: Use ServicePrincipalMetadata_OracleCloud_Policy.ProtoReflect.Descriptor instead. func (*ServicePrincipalMetadata_OracleCloud_Policy) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{14, 3, 1} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 3, 1} } func (x *ServicePrincipalMetadata_OracleCloud_Policy) GetPolicyId() string { @@ -3840,7 +3974,7 @@ type WebhookDatasourceMetadata_Okta struct { func (x *WebhookDatasourceMetadata_Okta) Reset() { *x = WebhookDatasourceMetadata_Okta{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[42] + mi := &file_cloudauth_cloud_account_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3852,7 +3986,7 @@ func (x *WebhookDatasourceMetadata_Okta) String() string { func (*WebhookDatasourceMetadata_Okta) ProtoMessage() {} func (x *WebhookDatasourceMetadata_Okta) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[42] + mi := &file_cloudauth_cloud_account_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3865,7 +3999,7 @@ func (x *WebhookDatasourceMetadata_Okta) ProtoReflect() protoreflect.Message { // Deprecated: Use WebhookDatasourceMetadata_Okta.ProtoReflect.Descriptor instead. func (*WebhookDatasourceMetadata_Okta) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16, 0} } func (x *WebhookDatasourceMetadata_Okta) GetWebhookDatasource() *WebhookDatasourceMetadata_Okta_WebhookDatasource { @@ -3884,7 +4018,7 @@ type WebhookDatasourceMetadata_Github struct { func (x *WebhookDatasourceMetadata_Github) Reset() { *x = WebhookDatasourceMetadata_Github{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[43] + mi := &file_cloudauth_cloud_account_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3896,7 +4030,7 @@ func (x *WebhookDatasourceMetadata_Github) String() string { func (*WebhookDatasourceMetadata_Github) ProtoMessage() {} func (x *WebhookDatasourceMetadata_Github) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[43] + mi := &file_cloudauth_cloud_account_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3909,7 +4043,7 @@ func (x *WebhookDatasourceMetadata_Github) ProtoReflect() protoreflect.Message { // Deprecated: Use WebhookDatasourceMetadata_Github.ProtoReflect.Descriptor instead. func (*WebhookDatasourceMetadata_Github) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 1} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16, 1} } func (x *WebhookDatasourceMetadata_Github) GetWebhookDatasource() *WebhookDatasourceMetadata_Github_WebhookDatasource { @@ -3929,7 +4063,7 @@ type WebhookDatasourceMetadata_Gcp struct { func (x *WebhookDatasourceMetadata_Gcp) Reset() { *x = WebhookDatasourceMetadata_Gcp{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[44] + mi := &file_cloudauth_cloud_account_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3941,7 +4075,7 @@ func (x *WebhookDatasourceMetadata_Gcp) String() string { func (*WebhookDatasourceMetadata_Gcp) ProtoMessage() {} func (x *WebhookDatasourceMetadata_Gcp) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[44] + mi := &file_cloudauth_cloud_account_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3954,7 +4088,7 @@ func (x *WebhookDatasourceMetadata_Gcp) ProtoReflect() protoreflect.Message { // Deprecated: Use WebhookDatasourceMetadata_Gcp.ProtoReflect.Descriptor instead. func (*WebhookDatasourceMetadata_Gcp) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 2} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16, 2} } func (x *WebhookDatasourceMetadata_Gcp) GetWebhookDatasource() *WebhookDatasourceMetadata_Gcp_WebhookDatasource { @@ -3980,7 +4114,7 @@ type WebhookDatasourceMetadata_AWS struct { func (x *WebhookDatasourceMetadata_AWS) Reset() { *x = WebhookDatasourceMetadata_AWS{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[45] + mi := &file_cloudauth_cloud_account_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3992,7 +4126,7 @@ func (x *WebhookDatasourceMetadata_AWS) String() string { func (*WebhookDatasourceMetadata_AWS) ProtoMessage() {} func (x *WebhookDatasourceMetadata_AWS) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[45] + mi := &file_cloudauth_cloud_account_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4005,7 +4139,7 @@ func (x *WebhookDatasourceMetadata_AWS) ProtoReflect() protoreflect.Message { // Deprecated: Use WebhookDatasourceMetadata_AWS.ProtoReflect.Descriptor instead. func (*WebhookDatasourceMetadata_AWS) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 3} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16, 3} } func (x *WebhookDatasourceMetadata_AWS) GetWebhookDatasource() *WebhookDatasourceMetadata_AWS_WebhookDatasource { @@ -4027,7 +4161,7 @@ type WebhookDatasourceMetadata_Okta_WebhookDatasource struct { func (x *WebhookDatasourceMetadata_Okta_WebhookDatasource) Reset() { *x = WebhookDatasourceMetadata_Okta_WebhookDatasource{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[46] + mi := &file_cloudauth_cloud_account_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4039,7 +4173,7 @@ func (x *WebhookDatasourceMetadata_Okta_WebhookDatasource) String() string { func (*WebhookDatasourceMetadata_Okta_WebhookDatasource) ProtoMessage() {} func (x *WebhookDatasourceMetadata_Okta_WebhookDatasource) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[46] + mi := &file_cloudauth_cloud_account_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4052,7 +4186,7 @@ func (x *WebhookDatasourceMetadata_Okta_WebhookDatasource) ProtoReflect() protor // Deprecated: Use WebhookDatasourceMetadata_Okta_WebhookDatasource.ProtoReflect.Descriptor instead. func (*WebhookDatasourceMetadata_Okta_WebhookDatasource) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 0, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16, 0, 0} } func (x *WebhookDatasourceMetadata_Okta_WebhookDatasource) GetHookId() string { @@ -4095,7 +4229,7 @@ type WebhookDatasourceMetadata_Github_WebhookDatasource struct { func (x *WebhookDatasourceMetadata_Github_WebhookDatasource) Reset() { *x = WebhookDatasourceMetadata_Github_WebhookDatasource{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[47] + mi := &file_cloudauth_cloud_account_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4107,7 +4241,7 @@ func (x *WebhookDatasourceMetadata_Github_WebhookDatasource) String() string { func (*WebhookDatasourceMetadata_Github_WebhookDatasource) ProtoMessage() {} func (x *WebhookDatasourceMetadata_Github_WebhookDatasource) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[47] + mi := &file_cloudauth_cloud_account_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4120,7 +4254,7 @@ func (x *WebhookDatasourceMetadata_Github_WebhookDatasource) ProtoReflect() prot // Deprecated: Use WebhookDatasourceMetadata_Github_WebhookDatasource.ProtoReflect.Descriptor instead. func (*WebhookDatasourceMetadata_Github_WebhookDatasource) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 1, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16, 1, 0} } func (x *WebhookDatasourceMetadata_Github_WebhookDatasource) GetHookId() int64 { @@ -4164,7 +4298,7 @@ type WebhookDatasourceMetadata_Gcp_WebhookDatasource struct { func (x *WebhookDatasourceMetadata_Gcp_WebhookDatasource) Reset() { *x = WebhookDatasourceMetadata_Gcp_WebhookDatasource{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[48] + mi := &file_cloudauth_cloud_account_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4176,7 +4310,7 @@ func (x *WebhookDatasourceMetadata_Gcp_WebhookDatasource) String() string { func (*WebhookDatasourceMetadata_Gcp_WebhookDatasource) ProtoMessage() {} func (x *WebhookDatasourceMetadata_Gcp_WebhookDatasource) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[48] + mi := &file_cloudauth_cloud_account_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4189,7 +4323,7 @@ func (x *WebhookDatasourceMetadata_Gcp_WebhookDatasource) ProtoReflect() protore // Deprecated: Use WebhookDatasourceMetadata_Gcp_WebhookDatasource.ProtoReflect.Descriptor instead. func (*WebhookDatasourceMetadata_Gcp_WebhookDatasource) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 2, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16, 2, 0} } func (x *WebhookDatasourceMetadata_Gcp_WebhookDatasource) GetPubsubTopicName() string { @@ -4243,7 +4377,7 @@ type WebhookDatasourceMetadata_AWS_WebhookDatasource struct { func (x *WebhookDatasourceMetadata_AWS_WebhookDatasource) Reset() { *x = WebhookDatasourceMetadata_AWS_WebhookDatasource{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[49] + mi := &file_cloudauth_cloud_account_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4255,7 +4389,7 @@ func (x *WebhookDatasourceMetadata_AWS_WebhookDatasource) String() string { func (*WebhookDatasourceMetadata_AWS_WebhookDatasource) ProtoMessage() {} func (x *WebhookDatasourceMetadata_AWS_WebhookDatasource) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[49] + mi := &file_cloudauth_cloud_account_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4268,7 +4402,7 @@ func (x *WebhookDatasourceMetadata_AWS_WebhookDatasource) ProtoReflect() protore // Deprecated: Use WebhookDatasourceMetadata_AWS_WebhookDatasource.ProtoReflect.Descriptor instead. func (*WebhookDatasourceMetadata_AWS_WebhookDatasource) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{15, 3, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16, 3, 0} } func (x *WebhookDatasourceMetadata_AWS_WebhookDatasource) GetRoutingKey() string { @@ -4336,7 +4470,7 @@ type CryptoKeyMetadata_AWS struct { func (x *CryptoKeyMetadata_AWS) Reset() { *x = CryptoKeyMetadata_AWS{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[50] + mi := &file_cloudauth_cloud_account_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4348,7 +4482,7 @@ func (x *CryptoKeyMetadata_AWS) String() string { func (*CryptoKeyMetadata_AWS) ProtoMessage() {} func (x *CryptoKeyMetadata_AWS) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[50] + mi := &file_cloudauth_cloud_account_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4361,7 +4495,7 @@ func (x *CryptoKeyMetadata_AWS) ProtoReflect() protoreflect.Message { // Deprecated: Use CryptoKeyMetadata_AWS.ProtoReflect.Descriptor instead. func (*CryptoKeyMetadata_AWS) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{17, 0} } func (x *CryptoKeyMetadata_AWS) GetKms() *CryptoKeyMetadata_AWS_KMS { @@ -4381,7 +4515,7 @@ type CryptoKeyMetadata_AWS_KMS struct { func (x *CryptoKeyMetadata_AWS_KMS) Reset() { *x = CryptoKeyMetadata_AWS_KMS{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[51] + mi := &file_cloudauth_cloud_account_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4393,7 +4527,7 @@ func (x *CryptoKeyMetadata_AWS_KMS) String() string { func (*CryptoKeyMetadata_AWS_KMS) ProtoMessage() {} func (x *CryptoKeyMetadata_AWS_KMS) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[51] + mi := &file_cloudauth_cloud_account_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4406,7 +4540,7 @@ func (x *CryptoKeyMetadata_AWS_KMS) ProtoReflect() protoreflect.Message { // Deprecated: Use CryptoKeyMetadata_AWS_KMS.ProtoReflect.Descriptor instead. func (*CryptoKeyMetadata_AWS_KMS) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{16, 0, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{17, 0, 0} } func (x *CryptoKeyMetadata_AWS_KMS) GetAlias() string { @@ -4433,7 +4567,7 @@ type CloudLogsMetadata_AWS struct { func (x *CloudLogsMetadata_AWS) Reset() { *x = CloudLogsMetadata_AWS{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[52] + mi := &file_cloudauth_cloud_account_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4445,7 +4579,7 @@ func (x *CloudLogsMetadata_AWS) String() string { func (*CloudLogsMetadata_AWS) ProtoMessage() {} func (x *CloudLogsMetadata_AWS) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[52] + mi := &file_cloudauth_cloud_account_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4458,7 +4592,7 @@ func (x *CloudLogsMetadata_AWS) ProtoReflect() protoreflect.Message { // Deprecated: Use CloudLogsMetadata_AWS.ProtoReflect.Descriptor instead. func (*CloudLogsMetadata_AWS) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{17, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{18, 0} } func (x *CloudLogsMetadata_AWS) GetCloudtrailS3Bucket() *CloudLogsMetadata_AWS_CloudTrailS3Bucket { @@ -4484,7 +4618,7 @@ type CloudLogsMetadata_IBMCloud struct { func (x *CloudLogsMetadata_IBMCloud) Reset() { *x = CloudLogsMetadata_IBMCloud{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[53] + mi := &file_cloudauth_cloud_account_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4496,7 +4630,7 @@ func (x *CloudLogsMetadata_IBMCloud) String() string { func (*CloudLogsMetadata_IBMCloud) ProtoMessage() {} func (x *CloudLogsMetadata_IBMCloud) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[53] + mi := &file_cloudauth_cloud_account_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4509,7 +4643,7 @@ func (x *CloudLogsMetadata_IBMCloud) ProtoReflect() protoreflect.Message { // Deprecated: Use CloudLogsMetadata_IBMCloud.ProtoReflect.Descriptor instead. func (*CloudLogsMetadata_IBMCloud) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{17, 1} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{18, 1} } func (x *CloudLogsMetadata_IBMCloud) GetIbmActivityTracker() *CloudLogsMetadata_IBMCloud_IBMActivityTracker { @@ -4533,7 +4667,7 @@ type CloudLogsMetadata_AWS_CloudTrailS3Bucket struct { func (x *CloudLogsMetadata_AWS_CloudTrailS3Bucket) Reset() { *x = CloudLogsMetadata_AWS_CloudTrailS3Bucket{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[54] + mi := &file_cloudauth_cloud_account_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4545,7 +4679,7 @@ func (x *CloudLogsMetadata_AWS_CloudTrailS3Bucket) String() string { func (*CloudLogsMetadata_AWS_CloudTrailS3Bucket) ProtoMessage() {} func (x *CloudLogsMetadata_AWS_CloudTrailS3Bucket) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[54] + mi := &file_cloudauth_cloud_account_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4558,7 +4692,7 @@ func (x *CloudLogsMetadata_AWS_CloudTrailS3Bucket) ProtoReflect() protoreflect.M // Deprecated: Use CloudLogsMetadata_AWS_CloudTrailS3Bucket.ProtoReflect.Descriptor instead. func (*CloudLogsMetadata_AWS_CloudTrailS3Bucket) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{17, 0, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{18, 0, 0} } func (x *CloudLogsMetadata_AWS_CloudTrailS3Bucket) GetBucketArn() string { @@ -4619,7 +4753,7 @@ type CloudLogsMetadata_AWS_CloudTrailSNS struct { func (x *CloudLogsMetadata_AWS_CloudTrailSNS) Reset() { *x = CloudLogsMetadata_AWS_CloudTrailSNS{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[55] + mi := &file_cloudauth_cloud_account_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4631,7 +4765,7 @@ func (x *CloudLogsMetadata_AWS_CloudTrailSNS) String() string { func (*CloudLogsMetadata_AWS_CloudTrailSNS) ProtoMessage() {} func (x *CloudLogsMetadata_AWS_CloudTrailSNS) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[55] + mi := &file_cloudauth_cloud_account_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4644,7 +4778,7 @@ func (x *CloudLogsMetadata_AWS_CloudTrailSNS) ProtoReflect() protoreflect.Messag // Deprecated: Use CloudLogsMetadata_AWS_CloudTrailSNS.ProtoReflect.Descriptor instead. func (*CloudLogsMetadata_AWS_CloudTrailSNS) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{17, 0, 1} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{18, 0, 1} } func (x *CloudLogsMetadata_AWS_CloudTrailSNS) GetRoleName() string { @@ -4716,7 +4850,7 @@ type CloudLogsMetadata_IBMCloud_IBMActivityTracker struct { func (x *CloudLogsMetadata_IBMCloud_IBMActivityTracker) Reset() { *x = CloudLogsMetadata_IBMCloud_IBMActivityTracker{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[56] + mi := &file_cloudauth_cloud_account_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4728,7 +4862,7 @@ func (x *CloudLogsMetadata_IBMCloud_IBMActivityTracker) String() string { func (*CloudLogsMetadata_IBMCloud_IBMActivityTracker) ProtoMessage() {} func (x *CloudLogsMetadata_IBMCloud_IBMActivityTracker) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[56] + mi := &file_cloudauth_cloud_account_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4741,7 +4875,7 @@ func (x *CloudLogsMetadata_IBMCloud_IBMActivityTracker) ProtoReflect() protorefl // Deprecated: Use CloudLogsMetadata_IBMCloud_IBMActivityTracker.ProtoReflect.Descriptor instead. func (*CloudLogsMetadata_IBMCloud_IBMActivityTracker) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{17, 1, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{18, 1, 0} } func (x *CloudLogsMetadata_IBMCloud_IBMActivityTracker) GetServiceId() string { @@ -4788,7 +4922,7 @@ type CloudResponderMetadata_AWS struct { func (x *CloudResponderMetadata_AWS) Reset() { *x = CloudResponderMetadata_AWS{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[57] + mi := &file_cloudauth_cloud_account_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4800,7 +4934,7 @@ func (x *CloudResponderMetadata_AWS) String() string { func (*CloudResponderMetadata_AWS) ProtoMessage() {} func (x *CloudResponderMetadata_AWS) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[57] + mi := &file_cloudauth_cloud_account_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4813,7 +4947,7 @@ func (x *CloudResponderMetadata_AWS) ProtoReflect() protoreflect.Message { // Deprecated: Use CloudResponderMetadata_AWS.ProtoReflect.Descriptor instead. func (*CloudResponderMetadata_AWS) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{18, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{19, 0} } func (x *CloudResponderMetadata_AWS) GetResponderLambdas() *CloudResponderMetadata_AWS_ResponderLambdas { @@ -4824,17 +4958,18 @@ func (x *CloudResponderMetadata_AWS) GetResponderLambdas() *CloudResponderMetada } type CloudResponderMetadata_AWS_ResponderLambdas struct { - state protoimpl.MessageState `protogen:"open.v1"` - LambdaNames []string `protobuf:"bytes,1,rep,name=lambda_names,json=lambdaNames,proto3" json:"lambda_names,omitempty"` - Regions []string `protobuf:"bytes,2,rep,name=regions,proto3" json:"regions,omitempty"` - DelegateRoleName string `protobuf:"bytes,3,opt,name=delegate_role_name,json=delegateRoleName,proto3" json:"delegate_role_name,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + LambdaNames []string `protobuf:"bytes,1,rep,name=lambda_names,json=lambdaNames,proto3" json:"lambda_names,omitempty"` + Regions []string `protobuf:"bytes,2,rep,name=regions,proto3" json:"regions,omitempty"` + DelegateRoleName string `protobuf:"bytes,3,opt,name=delegate_role_name,json=delegateRoleName,proto3" json:"delegate_role_name,omitempty"` + ValidationRoleName string `protobuf:"bytes,4,opt,name=validation_role_name,json=validationRoleName,proto3" json:"validation_role_name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CloudResponderMetadata_AWS_ResponderLambdas) Reset() { *x = CloudResponderMetadata_AWS_ResponderLambdas{} - mi := &file_cloudauth_cloud_account_proto_msgTypes[58] + mi := &file_cloudauth_cloud_account_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4846,7 +4981,7 @@ func (x *CloudResponderMetadata_AWS_ResponderLambdas) String() string { func (*CloudResponderMetadata_AWS_ResponderLambdas) ProtoMessage() {} func (x *CloudResponderMetadata_AWS_ResponderLambdas) ProtoReflect() protoreflect.Message { - mi := &file_cloudauth_cloud_account_proto_msgTypes[58] + mi := &file_cloudauth_cloud_account_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4859,7 +4994,7 @@ func (x *CloudResponderMetadata_AWS_ResponderLambdas) ProtoReflect() protoreflec // Deprecated: Use CloudResponderMetadata_AWS_ResponderLambdas.ProtoReflect.Descriptor instead. func (*CloudResponderMetadata_AWS_ResponderLambdas) Descriptor() ([]byte, []int) { - return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{18, 0, 0} + return file_cloudauth_cloud_account_proto_rawDescGZIP(), []int{19, 0, 0} } func (x *CloudResponderMetadata_AWS_ResponderLambdas) GetLambdaNames() []string { @@ -4883,6 +5018,13 @@ func (x *CloudResponderMetadata_AWS_ResponderLambdas) GetDelegateRoleName() stri return "" } +func (x *CloudResponderMetadata_AWS_ResponderLambdas) GetValidationRoleName() string { + if x != nil { + return x.ValidationRoleName + } + return "" +} + var file_cloudauth_cloud_account_proto_extTypes = []protoimpl.ExtensionInfo{ { ExtendedType: (*descriptorpb.FieldOptions)(nil), @@ -4904,7 +5046,7 @@ var File_cloudauth_cloud_account_proto protoreflect.FileDescriptor const file_cloudauth_cloud_account_proto_rawDesc = "" + "\n" + - "\x1dcloudauth_cloud_account.proto\x12\x0ecloudauthproto\x1a google/protobuf/descriptor.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xaa\b\n" + + "\x1dcloudauth_cloud_account.proto\x12\x0ecloudauthproto\x1a google/protobuf/descriptor.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xcb\b\n" + "\fCloudAccount\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + "\vcustomer_id\x18\x02 \x01(\x04R\n" + @@ -4935,7 +5077,9 @@ const file_cloudauth_cloud_account_proto_rawDesc = "" + "\x14regulatory_framework\x18\x12 \x01(\x0e2#.cloudauthproto.RegulatoryFrameworkR\x13regulatoryFramework\x12P\n" + "\x12provider_partition\x18\x13 \x01(\x0e2!.cloudauthproto.ProviderPartitionR\x11providerPartition\x128\n" + "\x18organizational_unit_path\x18\x14 \x01(\tR\x16organizationalUnitPath\x123\n" + - "\x03ibm\x18\x15 \x01(\v2\x1f.cloudauthproto.IBMCloudAccountH\x00R\x03ibmB\x12\n" + + "\x03ibm\x18\x15 \x01(\v2\x1f.cloudauthproto.IBMCloudAccountH\x00R\x03ibm\x12\x1f\n" + + "\vparent_uuid\x18\x16 \x01(\tR\n" + + "parentUuidB\x12\n" + "\x10provider_details\"#\n" + "\x0fIBMCloudAccount\x12\x10\n" + "\x03crn\x18\x01 \x01(\tR\x03crn\"\xd9\a\n" + @@ -5019,7 +5163,23 @@ const file_cloudauth_cloud_account_proto_rawDesc = "" + "\x17included_cloud_accounts\x18\x11 \x03(\tR\x15includedCloudAccounts\x126\n" + "\x17excluded_cloud_accounts\x18\x12 \x03(\tR\x15excludedCloudAccounts\x120\n" + "\x14organization_root_id\x18\x13 \x01(\tR\x12organizationRootId\x121\n" + - "\x14automatic_onboarding\x18\x14 \x01(\bR\x13automaticOnboarding\"\x87\a\n" + + "\x14automatic_onboarding\x18\x14 \x01(\bR\x13automaticOnboarding\"\xc6\x03\n" + + "\x13OrganizationalGroup\x12\x12\n" + + "\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12+\n" + + "\x11organization_uuid\x18\x03 \x01(\tR\x10organizationUuid\x12\x1f\n" + + "\vparent_uuid\x18\x04 \x01(\tR\n" + + "parentUuid\x124\n" + + "\bprovider\x18\x05 \x01(\x0e2\x18.cloudauthproto.ProviderR\bprovider\x123\n" + + "\bmetadata\x18\x06 \x01(\v2\x17.google.protobuf.StructR\bmetadata\x12\x1f\n" + + "\vcustomer_id\x18\a \x01(\x04R\n" + + "customerId\x129\n" + + "\n" + + "created_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x129\n" + + "\n" + + "updated_at\x18\t \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\x127\n" + + "\tverbosity\x18\n" + + " \x01(\x0e2\x19.cloudauthproto.VerbosityR\tverbosity\"\x87\a\n" + "\x11FeatureComponents\x12N\n" + "\x0fcloud_connector\x18\x01 \x01(\v2 .cloudauthproto.AccountComponentH\x00R\x0ecloudConnector\x88\x01\x01\x12H\n" + "\fevent_bridge\x18\x02 \x01(\v2 .cloudauthproto.AccountComponentH\x01R\veventBridge\x88\x01\x01\x12H\n" + @@ -5271,19 +5431,21 @@ const file_cloudauth_cloud_account_proto_rawDesc = "" + "bucket_crn\x18\x04 \x01(\tR\tbucketCrn\x12#\n" + "\ringestion_url\x18\x05 \x01(\tR\fingestionUrlB\n" + "\n" + - "\bprovider\"\xd5\x02\n" + + "\bprovider\"\x88\x03\n" + "\x16CloudResponderMetadata\x12>\n" + - "\x03aws\x18\x01 \x01(\v2*.cloudauthproto.CloudResponderMetadata.AWSH\x00R\x03aws\x1a\xee\x01\n" + + "\x03aws\x18\x01 \x01(\v2*.cloudauthproto.CloudResponderMetadata.AWSH\x00R\x03aws\x1a\xa1\x02\n" + "\x03AWS\x12h\n" + - "\x11responder_lambdas\x18\x01 \x01(\v2;.cloudauthproto.CloudResponderMetadata.AWS.ResponderLambdasR\x10responderLambdas\x1a}\n" + + "\x11responder_lambdas\x18\x01 \x01(\v2;.cloudauthproto.CloudResponderMetadata.AWS.ResponderLambdasR\x10responderLambdas\x1a\xaf\x01\n" + "\x10ResponderLambdas\x12!\n" + "\flambda_names\x18\x01 \x03(\tR\vlambdaNames\x12\x18\n" + "\aregions\x18\x02 \x03(\tR\aregions\x12,\n" + - "\x12delegate_role_name\x18\x03 \x01(\tR\x10delegateRoleNameB\n" + + "\x12delegate_role_name\x18\x03 \x01(\tR\x10delegateRoleName\x120\n" + + "\x14validation_role_name\x18\x04 \x01(\tR\x12validationRoleNameB\n" + "\n" + - "\bprovider\"X\n" + + "\bprovider\"\xa6\x01\n" + "\x1bCloudResponderRolesMetadata\x129\n" + - "\x05roles\x18\x01 \x03(\v2#.cloudauthproto.TrustedRoleMetadataR\x05roles*\xb5\x01\n" + + "\x05roles\x18\x01 \x03(\v2#.cloudauthproto.TrustedRoleMetadataR\x05roles\x12L\n" + + "\x0fvalidation_role\x18\x02 \x01(\v2#.cloudauthproto.TrustedRoleMetadataR\x0evalidationRole*\xb5\x01\n" + "\bProvider\x12\x18\n" + "\x14PROVIDER_UNSPECIFIED\x10\x00\x12\x10\n" + "\fPROVIDER_AWS\x10\x01\x12\x12\n" + @@ -5363,7 +5525,7 @@ func file_cloudauth_cloud_account_proto_rawDescGZIP() []byte { } var file_cloudauth_cloud_account_proto_enumTypes = make([]protoimpl.EnumInfo, 8) -var file_cloudauth_cloud_account_proto_msgTypes = make([]protoimpl.MessageInfo, 59) +var file_cloudauth_cloud_account_proto_msgTypes = make([]protoimpl.MessageInfo, 60) var file_cloudauth_cloud_account_proto_goTypes = []any{ (Provider)(0), // 0: cloudauthproto.Provider (Feature)(0), // 1: cloudauthproto.Feature @@ -5382,67 +5544,69 @@ var file_cloudauth_cloud_account_proto_goTypes = []any{ (*ValidationWarning)(nil), // 14: cloudauthproto.ValidationWarning (*Validation)(nil), // 15: cloudauthproto.Validation (*CloudOrganization)(nil), // 16: cloudauthproto.CloudOrganization - (*FeatureComponents)(nil), // 17: cloudauthproto.FeatureComponents - (*AccountComponent)(nil), // 18: cloudauthproto.AccountComponent - (*CloudConnectorMetadata)(nil), // 19: cloudauthproto.CloudConnectorMetadata - (*TrustedRoleMetadata)(nil), // 20: cloudauthproto.TrustedRoleMetadata - (*EventBridgeMetadata)(nil), // 21: cloudauthproto.EventBridgeMetadata - (*ServicePrincipalMetadata)(nil), // 22: cloudauthproto.ServicePrincipalMetadata - (*WebhookDatasourceMetadata)(nil), // 23: cloudauthproto.WebhookDatasourceMetadata - (*CryptoKeyMetadata)(nil), // 24: cloudauthproto.CryptoKeyMetadata - (*CloudLogsMetadata)(nil), // 25: cloudauthproto.CloudLogsMetadata - (*CloudResponderMetadata)(nil), // 26: cloudauthproto.CloudResponderMetadata - (*CloudResponderRolesMetadata)(nil), // 27: cloudauthproto.CloudResponderRolesMetadata - nil, // 28: cloudauthproto.AccountFeature.FlagsEntry - (*CloudConnectorMetadata_AWS)(nil), // 29: cloudauthproto.CloudConnectorMetadata.AWS - (*CloudConnectorMetadata_Azure)(nil), // 30: cloudauthproto.CloudConnectorMetadata.Azure - (*CloudConnectorMetadata_GCP)(nil), // 31: cloudauthproto.CloudConnectorMetadata.GCP - (*TrustedRoleMetadata_AWS)(nil), // 32: cloudauthproto.TrustedRoleMetadata.AWS - (*TrustedRoleMetadata_GCP)(nil), // 33: cloudauthproto.TrustedRoleMetadata.GCP - (*TrustedRoleMetadata_Azure)(nil), // 34: cloudauthproto.TrustedRoleMetadata.Azure - (*TrustedRoleMetadata_IBMCloud)(nil), // 35: cloudauthproto.TrustedRoleMetadata.IBMCloud - (*EventBridgeMetadata_AWS)(nil), // 36: cloudauthproto.EventBridgeMetadata.AWS - (*EventBridgeMetadata_Azure)(nil), // 37: cloudauthproto.EventBridgeMetadata.Azure - (*EventBridgeMetadata_Azure_EventHubMetadata)(nil), // 38: cloudauthproto.EventBridgeMetadata.Azure.EventHubMetadata - (*ServicePrincipalMetadata_GCP)(nil), // 39: cloudauthproto.ServicePrincipalMetadata.GCP - (*ServicePrincipalMetadata_Okta)(nil), // 40: cloudauthproto.ServicePrincipalMetadata.Okta - (*ServicePrincipalMetadata_Azure)(nil), // 41: cloudauthproto.ServicePrincipalMetadata.Azure - (*ServicePrincipalMetadata_OracleCloud)(nil), // 42: cloudauthproto.ServicePrincipalMetadata.OracleCloud - (*ServicePrincipalMetadata_GCP_Key)(nil), // 43: cloudauthproto.ServicePrincipalMetadata.GCP.Key - (*ServicePrincipalMetadata_GCP_WorkloadIdentityFederation)(nil), // 44: cloudauthproto.ServicePrincipalMetadata.GCP.WorkloadIdentityFederation - (*ServicePrincipalMetadata_Okta_OAuthApp)(nil), // 45: cloudauthproto.ServicePrincipalMetadata.Okta.OAuthApp - (*ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal)(nil), // 46: cloudauthproto.ServicePrincipalMetadata.Azure.ActiveDirectoryServicePrincipal - (*ServicePrincipalMetadata_Azure_Oauth2PermissionGrant)(nil), // 47: cloudauthproto.ServicePrincipalMetadata.Azure.Oauth2PermissionGrant - (*ServicePrincipalMetadata_OracleCloud_ApiKey)(nil), // 48: cloudauthproto.ServicePrincipalMetadata.OracleCloud.ApiKey - (*ServicePrincipalMetadata_OracleCloud_Policy)(nil), // 49: cloudauthproto.ServicePrincipalMetadata.OracleCloud.Policy - (*WebhookDatasourceMetadata_Okta)(nil), // 50: cloudauthproto.WebhookDatasourceMetadata.Okta - (*WebhookDatasourceMetadata_Github)(nil), // 51: cloudauthproto.WebhookDatasourceMetadata.Github - (*WebhookDatasourceMetadata_Gcp)(nil), // 52: cloudauthproto.WebhookDatasourceMetadata.Gcp - (*WebhookDatasourceMetadata_AWS)(nil), // 53: cloudauthproto.WebhookDatasourceMetadata.AWS - (*WebhookDatasourceMetadata_Okta_WebhookDatasource)(nil), // 54: cloudauthproto.WebhookDatasourceMetadata.Okta.WebhookDatasource - (*WebhookDatasourceMetadata_Github_WebhookDatasource)(nil), // 55: cloudauthproto.WebhookDatasourceMetadata.Github.WebhookDatasource - (*WebhookDatasourceMetadata_Gcp_WebhookDatasource)(nil), // 56: cloudauthproto.WebhookDatasourceMetadata.Gcp.WebhookDatasource - (*WebhookDatasourceMetadata_AWS_WebhookDatasource)(nil), // 57: cloudauthproto.WebhookDatasourceMetadata.AWS.WebhookDatasource - (*CryptoKeyMetadata_AWS)(nil), // 58: cloudauthproto.CryptoKeyMetadata.AWS - (*CryptoKeyMetadata_AWS_KMS)(nil), // 59: cloudauthproto.CryptoKeyMetadata.AWS.KMS - (*CloudLogsMetadata_AWS)(nil), // 60: cloudauthproto.CloudLogsMetadata.AWS - (*CloudLogsMetadata_IBMCloud)(nil), // 61: cloudauthproto.CloudLogsMetadata.IBMCloud - (*CloudLogsMetadata_AWS_CloudTrailS3Bucket)(nil), // 62: cloudauthproto.CloudLogsMetadata.AWS.CloudTrailS3Bucket - (*CloudLogsMetadata_AWS_CloudTrailSNS)(nil), // 63: cloudauthproto.CloudLogsMetadata.AWS.CloudTrailSNS - (*CloudLogsMetadata_IBMCloud_IBMActivityTracker)(nil), // 64: cloudauthproto.CloudLogsMetadata.IBMCloud.IBMActivityTracker - (*CloudResponderMetadata_AWS)(nil), // 65: cloudauthproto.CloudResponderMetadata.AWS - (*CloudResponderMetadata_AWS_ResponderLambdas)(nil), // 66: cloudauthproto.CloudResponderMetadata.AWS.ResponderLambdas - (*timestamppb.Timestamp)(nil), // 67: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 68: google.protobuf.Duration - (*structpb.Value)(nil), // 69: google.protobuf.Value - (*descriptorpb.FieldOptions)(nil), // 70: google.protobuf.FieldOptions + (*OrganizationalGroup)(nil), // 17: cloudauthproto.OrganizationalGroup + (*FeatureComponents)(nil), // 18: cloudauthproto.FeatureComponents + (*AccountComponent)(nil), // 19: cloudauthproto.AccountComponent + (*CloudConnectorMetadata)(nil), // 20: cloudauthproto.CloudConnectorMetadata + (*TrustedRoleMetadata)(nil), // 21: cloudauthproto.TrustedRoleMetadata + (*EventBridgeMetadata)(nil), // 22: cloudauthproto.EventBridgeMetadata + (*ServicePrincipalMetadata)(nil), // 23: cloudauthproto.ServicePrincipalMetadata + (*WebhookDatasourceMetadata)(nil), // 24: cloudauthproto.WebhookDatasourceMetadata + (*CryptoKeyMetadata)(nil), // 25: cloudauthproto.CryptoKeyMetadata + (*CloudLogsMetadata)(nil), // 26: cloudauthproto.CloudLogsMetadata + (*CloudResponderMetadata)(nil), // 27: cloudauthproto.CloudResponderMetadata + (*CloudResponderRolesMetadata)(nil), // 28: cloudauthproto.CloudResponderRolesMetadata + nil, // 29: cloudauthproto.AccountFeature.FlagsEntry + (*CloudConnectorMetadata_AWS)(nil), // 30: cloudauthproto.CloudConnectorMetadata.AWS + (*CloudConnectorMetadata_Azure)(nil), // 31: cloudauthproto.CloudConnectorMetadata.Azure + (*CloudConnectorMetadata_GCP)(nil), // 32: cloudauthproto.CloudConnectorMetadata.GCP + (*TrustedRoleMetadata_AWS)(nil), // 33: cloudauthproto.TrustedRoleMetadata.AWS + (*TrustedRoleMetadata_GCP)(nil), // 34: cloudauthproto.TrustedRoleMetadata.GCP + (*TrustedRoleMetadata_Azure)(nil), // 35: cloudauthproto.TrustedRoleMetadata.Azure + (*TrustedRoleMetadata_IBMCloud)(nil), // 36: cloudauthproto.TrustedRoleMetadata.IBMCloud + (*EventBridgeMetadata_AWS)(nil), // 37: cloudauthproto.EventBridgeMetadata.AWS + (*EventBridgeMetadata_Azure)(nil), // 38: cloudauthproto.EventBridgeMetadata.Azure + (*EventBridgeMetadata_Azure_EventHubMetadata)(nil), // 39: cloudauthproto.EventBridgeMetadata.Azure.EventHubMetadata + (*ServicePrincipalMetadata_GCP)(nil), // 40: cloudauthproto.ServicePrincipalMetadata.GCP + (*ServicePrincipalMetadata_Okta)(nil), // 41: cloudauthproto.ServicePrincipalMetadata.Okta + (*ServicePrincipalMetadata_Azure)(nil), // 42: cloudauthproto.ServicePrincipalMetadata.Azure + (*ServicePrincipalMetadata_OracleCloud)(nil), // 43: cloudauthproto.ServicePrincipalMetadata.OracleCloud + (*ServicePrincipalMetadata_GCP_Key)(nil), // 44: cloudauthproto.ServicePrincipalMetadata.GCP.Key + (*ServicePrincipalMetadata_GCP_WorkloadIdentityFederation)(nil), // 45: cloudauthproto.ServicePrincipalMetadata.GCP.WorkloadIdentityFederation + (*ServicePrincipalMetadata_Okta_OAuthApp)(nil), // 46: cloudauthproto.ServicePrincipalMetadata.Okta.OAuthApp + (*ServicePrincipalMetadata_Azure_ActiveDirectoryServicePrincipal)(nil), // 47: cloudauthproto.ServicePrincipalMetadata.Azure.ActiveDirectoryServicePrincipal + (*ServicePrincipalMetadata_Azure_Oauth2PermissionGrant)(nil), // 48: cloudauthproto.ServicePrincipalMetadata.Azure.Oauth2PermissionGrant + (*ServicePrincipalMetadata_OracleCloud_ApiKey)(nil), // 49: cloudauthproto.ServicePrincipalMetadata.OracleCloud.ApiKey + (*ServicePrincipalMetadata_OracleCloud_Policy)(nil), // 50: cloudauthproto.ServicePrincipalMetadata.OracleCloud.Policy + (*WebhookDatasourceMetadata_Okta)(nil), // 51: cloudauthproto.WebhookDatasourceMetadata.Okta + (*WebhookDatasourceMetadata_Github)(nil), // 52: cloudauthproto.WebhookDatasourceMetadata.Github + (*WebhookDatasourceMetadata_Gcp)(nil), // 53: cloudauthproto.WebhookDatasourceMetadata.Gcp + (*WebhookDatasourceMetadata_AWS)(nil), // 54: cloudauthproto.WebhookDatasourceMetadata.AWS + (*WebhookDatasourceMetadata_Okta_WebhookDatasource)(nil), // 55: cloudauthproto.WebhookDatasourceMetadata.Okta.WebhookDatasource + (*WebhookDatasourceMetadata_Github_WebhookDatasource)(nil), // 56: cloudauthproto.WebhookDatasourceMetadata.Github.WebhookDatasource + (*WebhookDatasourceMetadata_Gcp_WebhookDatasource)(nil), // 57: cloudauthproto.WebhookDatasourceMetadata.Gcp.WebhookDatasource + (*WebhookDatasourceMetadata_AWS_WebhookDatasource)(nil), // 58: cloudauthproto.WebhookDatasourceMetadata.AWS.WebhookDatasource + (*CryptoKeyMetadata_AWS)(nil), // 59: cloudauthproto.CryptoKeyMetadata.AWS + (*CryptoKeyMetadata_AWS_KMS)(nil), // 60: cloudauthproto.CryptoKeyMetadata.AWS.KMS + (*CloudLogsMetadata_AWS)(nil), // 61: cloudauthproto.CloudLogsMetadata.AWS + (*CloudLogsMetadata_IBMCloud)(nil), // 62: cloudauthproto.CloudLogsMetadata.IBMCloud + (*CloudLogsMetadata_AWS_CloudTrailS3Bucket)(nil), // 63: cloudauthproto.CloudLogsMetadata.AWS.CloudTrailS3Bucket + (*CloudLogsMetadata_AWS_CloudTrailSNS)(nil), // 64: cloudauthproto.CloudLogsMetadata.AWS.CloudTrailSNS + (*CloudLogsMetadata_IBMCloud_IBMActivityTracker)(nil), // 65: cloudauthproto.CloudLogsMetadata.IBMCloud.IBMActivityTracker + (*CloudResponderMetadata_AWS)(nil), // 66: cloudauthproto.CloudResponderMetadata.AWS + (*CloudResponderMetadata_AWS_ResponderLambdas)(nil), // 67: cloudauthproto.CloudResponderMetadata.AWS.ResponderLambdas + (*timestamppb.Timestamp)(nil), // 68: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 69: google.protobuf.Duration + (*structpb.Value)(nil), // 70: google.protobuf.Value + (*structpb.Struct)(nil), // 71: google.protobuf.Struct + (*descriptorpb.FieldOptions)(nil), // 72: google.protobuf.FieldOptions } var file_cloudauth_cloud_account_proto_depIdxs = []int32{ 0, // 0: cloudauthproto.CloudAccount.provider:type_name -> cloudauthproto.Provider 10, // 1: cloudauthproto.CloudAccount.feature:type_name -> cloudauthproto.AccountFeatures - 67, // 2: cloudauthproto.CloudAccount.created_at:type_name -> google.protobuf.Timestamp - 67, // 3: cloudauthproto.CloudAccount.updated_at:type_name -> google.protobuf.Timestamp - 18, // 4: cloudauthproto.CloudAccount.components:type_name -> cloudauthproto.AccountComponent + 68, // 2: cloudauthproto.CloudAccount.created_at:type_name -> google.protobuf.Timestamp + 68, // 3: cloudauthproto.CloudAccount.updated_at:type_name -> google.protobuf.Timestamp + 19, // 4: cloudauthproto.CloudAccount.components:type_name -> cloudauthproto.AccountComponent 15, // 5: cloudauthproto.CloudAccount.validation:type_name -> cloudauthproto.Validation 2, // 6: cloudauthproto.CloudAccount.verbosity:type_name -> cloudauthproto.Verbosity 3, // 7: cloudauthproto.CloudAccount.regulatory_framework:type_name -> cloudauthproto.RegulatoryFramework @@ -5459,96 +5623,102 @@ var file_cloudauth_cloud_account_proto_depIdxs = []int32{ 11, // 18: cloudauthproto.AccountFeatures.secure_sensitive_content_posture:type_name -> cloudauthproto.AccountFeature 11, // 19: cloudauthproto.AccountFeatures.secure_response_actions:type_name -> cloudauthproto.AccountFeature 1, // 20: cloudauthproto.AccountFeature.type:type_name -> cloudauthproto.Feature - 67, // 21: cloudauthproto.AccountFeature.created_at:type_name -> google.protobuf.Timestamp + 68, // 21: cloudauthproto.AccountFeature.created_at:type_name -> google.protobuf.Timestamp 15, // 22: cloudauthproto.AccountFeature.validation:type_name -> cloudauthproto.Validation - 28, // 23: cloudauthproto.AccountFeature.flags:type_name -> cloudauthproto.AccountFeature.FlagsEntry - 68, // 24: cloudauthproto.ValidationStep.duration:type_name -> google.protobuf.Duration + 29, // 23: cloudauthproto.AccountFeature.flags:type_name -> cloudauthproto.AccountFeature.FlagsEntry + 69, // 24: cloudauthproto.ValidationStep.duration:type_name -> google.protobuf.Duration 13, // 25: cloudauthproto.ValidationStep.error:type_name -> cloudauthproto.ValidationError 14, // 26: cloudauthproto.ValidationStep.warning:type_name -> cloudauthproto.ValidationWarning 6, // 27: cloudauthproto.ValidationStep.stage:type_name -> cloudauthproto.ValidationStage - 67, // 28: cloudauthproto.ValidationStep.updated_at:type_name -> google.protobuf.Timestamp - 69, // 29: cloudauthproto.ValidationError.detail:type_name -> google.protobuf.Value - 69, // 30: cloudauthproto.ValidationWarning.detail:type_name -> google.protobuf.Value + 68, // 28: cloudauthproto.ValidationStep.updated_at:type_name -> google.protobuf.Timestamp + 70, // 29: cloudauthproto.ValidationError.detail:type_name -> google.protobuf.Value + 70, // 30: cloudauthproto.ValidationWarning.detail:type_name -> google.protobuf.Value 5, // 31: cloudauthproto.Validation.result:type_name -> cloudauthproto.ValidationResult - 67, // 32: cloudauthproto.Validation.timestamp:type_name -> google.protobuf.Timestamp + 68, // 32: cloudauthproto.Validation.timestamp:type_name -> google.protobuf.Timestamp 12, // 33: cloudauthproto.Validation.steps:type_name -> cloudauthproto.ValidationStep 6, // 34: cloudauthproto.Validation.disposition:type_name -> cloudauthproto.ValidationStage 8, // 35: cloudauthproto.CloudOrganization.accounts:type_name -> cloudauthproto.CloudAccount - 67, // 36: cloudauthproto.CloudOrganization.created_at:type_name -> google.protobuf.Timestamp - 67, // 37: cloudauthproto.CloudOrganization.updated_at:type_name -> google.protobuf.Timestamp + 68, // 36: cloudauthproto.CloudOrganization.created_at:type_name -> google.protobuf.Timestamp + 68, // 37: cloudauthproto.CloudOrganization.updated_at:type_name -> google.protobuf.Timestamp 0, // 38: cloudauthproto.CloudOrganization.provider:type_name -> cloudauthproto.Provider 15, // 39: cloudauthproto.CloudOrganization.validation:type_name -> cloudauthproto.Validation 2, // 40: cloudauthproto.CloudOrganization.verbosity:type_name -> cloudauthproto.Verbosity 8, // 41: cloudauthproto.CloudOrganization.management_account:type_name -> cloudauthproto.CloudAccount - 18, // 42: cloudauthproto.FeatureComponents.cloud_connector:type_name -> cloudauthproto.AccountComponent - 18, // 43: cloudauthproto.FeatureComponents.event_bridge:type_name -> cloudauthproto.AccountComponent - 18, // 44: cloudauthproto.FeatureComponents.trusted_role:type_name -> cloudauthproto.AccountComponent - 18, // 45: cloudauthproto.FeatureComponents.service_principal:type_name -> cloudauthproto.AccountComponent - 18, // 46: cloudauthproto.FeatureComponents.webhook_datasource:type_name -> cloudauthproto.AccountComponent - 18, // 47: cloudauthproto.FeatureComponents.crypto_key:type_name -> cloudauthproto.AccountComponent - 18, // 48: cloudauthproto.FeatureComponents.cloud_logs:type_name -> cloudauthproto.AccountComponent - 18, // 49: cloudauthproto.FeatureComponents.cloud_responder:type_name -> cloudauthproto.AccountComponent - 18, // 50: cloudauthproto.FeatureComponents.cloud_responder_roles:type_name -> cloudauthproto.AccountComponent - 7, // 51: cloudauthproto.AccountComponent.type:type_name -> cloudauthproto.Component - 67, // 52: cloudauthproto.AccountComponent.created_at:type_name -> google.protobuf.Timestamp - 67, // 53: cloudauthproto.AccountComponent.updated_at:type_name -> google.protobuf.Timestamp - 15, // 54: cloudauthproto.AccountComponent.validation:type_name -> cloudauthproto.Validation - 19, // 55: cloudauthproto.AccountComponent.cloud_connector_metadata:type_name -> cloudauthproto.CloudConnectorMetadata - 20, // 56: cloudauthproto.AccountComponent.trusted_role_metadata:type_name -> cloudauthproto.TrustedRoleMetadata - 21, // 57: cloudauthproto.AccountComponent.event_bridge_metadata:type_name -> cloudauthproto.EventBridgeMetadata - 22, // 58: cloudauthproto.AccountComponent.service_principal_metadata:type_name -> cloudauthproto.ServicePrincipalMetadata - 23, // 59: cloudauthproto.AccountComponent.webhook_datasource_metadata:type_name -> cloudauthproto.WebhookDatasourceMetadata - 24, // 60: cloudauthproto.AccountComponent.crypto_key_metadata:type_name -> cloudauthproto.CryptoKeyMetadata - 25, // 61: cloudauthproto.AccountComponent.cloud_logs_metadata:type_name -> cloudauthproto.CloudLogsMetadata - 26, // 62: cloudauthproto.AccountComponent.cloud_responder_metadata:type_name -> cloudauthproto.CloudResponderMetadata - 27, // 63: cloudauthproto.AccountComponent.cloud_responder_roles_metadata:type_name -> cloudauthproto.CloudResponderRolesMetadata - 29, // 64: cloudauthproto.CloudConnectorMetadata.aws:type_name -> cloudauthproto.CloudConnectorMetadata.AWS - 30, // 65: cloudauthproto.CloudConnectorMetadata.azure:type_name -> cloudauthproto.CloudConnectorMetadata.Azure - 31, // 66: cloudauthproto.CloudConnectorMetadata.gcp:type_name -> cloudauthproto.CloudConnectorMetadata.GCP - 32, // 67: cloudauthproto.TrustedRoleMetadata.aws:type_name -> cloudauthproto.TrustedRoleMetadata.AWS - 34, // 68: cloudauthproto.TrustedRoleMetadata.azure:type_name -> cloudauthproto.TrustedRoleMetadata.Azure - 33, // 69: cloudauthproto.TrustedRoleMetadata.gcp:type_name -> cloudauthproto.TrustedRoleMetadata.GCP - 35, // 70: cloudauthproto.TrustedRoleMetadata.ibmcloud:type_name -> cloudauthproto.TrustedRoleMetadata.IBMCloud - 36, // 71: cloudauthproto.EventBridgeMetadata.aws:type_name -> cloudauthproto.EventBridgeMetadata.AWS - 37, // 72: cloudauthproto.EventBridgeMetadata.azure:type_name -> cloudauthproto.EventBridgeMetadata.Azure - 39, // 73: cloudauthproto.ServicePrincipalMetadata.gcp:type_name -> cloudauthproto.ServicePrincipalMetadata.GCP - 40, // 74: cloudauthproto.ServicePrincipalMetadata.okta:type_name -> cloudauthproto.ServicePrincipalMetadata.Okta - 41, // 75: cloudauthproto.ServicePrincipalMetadata.azure:type_name -> cloudauthproto.ServicePrincipalMetadata.Azure - 42, // 76: cloudauthproto.ServicePrincipalMetadata.oci:type_name -> cloudauthproto.ServicePrincipalMetadata.OracleCloud - 50, // 77: cloudauthproto.WebhookDatasourceMetadata.okta:type_name -> cloudauthproto.WebhookDatasourceMetadata.Okta - 51, // 78: cloudauthproto.WebhookDatasourceMetadata.github:type_name -> cloudauthproto.WebhookDatasourceMetadata.Github - 52, // 79: cloudauthproto.WebhookDatasourceMetadata.gcp:type_name -> cloudauthproto.WebhookDatasourceMetadata.Gcp - 53, // 80: cloudauthproto.WebhookDatasourceMetadata.aws:type_name -> cloudauthproto.WebhookDatasourceMetadata.AWS - 58, // 81: cloudauthproto.CryptoKeyMetadata.aws:type_name -> cloudauthproto.CryptoKeyMetadata.AWS - 60, // 82: cloudauthproto.CloudLogsMetadata.aws:type_name -> cloudauthproto.CloudLogsMetadata.AWS - 61, // 83: cloudauthproto.CloudLogsMetadata.ibmcloud:type_name -> cloudauthproto.CloudLogsMetadata.IBMCloud - 65, // 84: cloudauthproto.CloudResponderMetadata.aws:type_name -> cloudauthproto.CloudResponderMetadata.AWS - 20, // 85: cloudauthproto.CloudResponderRolesMetadata.roles:type_name -> cloudauthproto.TrustedRoleMetadata - 38, // 86: cloudauthproto.EventBridgeMetadata.Azure.event_hub_metadata:type_name -> cloudauthproto.EventBridgeMetadata.Azure.EventHubMetadata - 41, // 87: cloudauthproto.EventBridgeMetadata.Azure.service_principal:type_name -> cloudauthproto.ServicePrincipalMetadata.Azure - 43, // 88: cloudauthproto.ServicePrincipalMetadata.GCP.key:type_name -> cloudauthproto.ServicePrincipalMetadata.GCP.Key - 44, // 89: cloudauthproto.ServicePrincipalMetadata.GCP.workload_identity_federation:type_name -> cloudauthproto.ServicePrincipalMetadata.GCP.WorkloadIdentityFederation - 45, // 90: cloudauthproto.ServicePrincipalMetadata.Okta.oauth_app:type_name -> cloudauthproto.ServicePrincipalMetadata.Okta.OAuthApp - 46, // 91: cloudauthproto.ServicePrincipalMetadata.Azure.active_directory_service_principal:type_name -> cloudauthproto.ServicePrincipalMetadata.Azure.ActiveDirectoryServicePrincipal - 47, // 92: cloudauthproto.ServicePrincipalMetadata.Azure.oauth2_permission_grants:type_name -> cloudauthproto.ServicePrincipalMetadata.Azure.Oauth2PermissionGrant - 48, // 93: cloudauthproto.ServicePrincipalMetadata.OracleCloud.api_key:type_name -> cloudauthproto.ServicePrincipalMetadata.OracleCloud.ApiKey - 49, // 94: cloudauthproto.ServicePrincipalMetadata.OracleCloud.policy:type_name -> cloudauthproto.ServicePrincipalMetadata.OracleCloud.Policy - 54, // 95: cloudauthproto.WebhookDatasourceMetadata.Okta.webhook_datasource:type_name -> cloudauthproto.WebhookDatasourceMetadata.Okta.WebhookDatasource - 55, // 96: cloudauthproto.WebhookDatasourceMetadata.Github.webhook_datasource:type_name -> cloudauthproto.WebhookDatasourceMetadata.Github.WebhookDatasource - 56, // 97: cloudauthproto.WebhookDatasourceMetadata.Gcp.webhook_datasource:type_name -> cloudauthproto.WebhookDatasourceMetadata.Gcp.WebhookDatasource - 39, // 98: cloudauthproto.WebhookDatasourceMetadata.Gcp.service_principal:type_name -> cloudauthproto.ServicePrincipalMetadata.GCP - 57, // 99: cloudauthproto.WebhookDatasourceMetadata.AWS.webhook_datasource:type_name -> cloudauthproto.WebhookDatasourceMetadata.AWS.WebhookDatasource - 59, // 100: cloudauthproto.CryptoKeyMetadata.AWS.kms:type_name -> cloudauthproto.CryptoKeyMetadata.AWS.KMS - 62, // 101: cloudauthproto.CloudLogsMetadata.AWS.cloudtrail_s3_bucket:type_name -> cloudauthproto.CloudLogsMetadata.AWS.CloudTrailS3Bucket - 63, // 102: cloudauthproto.CloudLogsMetadata.AWS.cloudtrail_sns:type_name -> cloudauthproto.CloudLogsMetadata.AWS.CloudTrailSNS - 64, // 103: cloudauthproto.CloudLogsMetadata.IBMCloud.ibm_activity_tracker:type_name -> cloudauthproto.CloudLogsMetadata.IBMCloud.IBMActivityTracker - 66, // 104: cloudauthproto.CloudResponderMetadata.AWS.responder_lambdas:type_name -> cloudauthproto.CloudResponderMetadata.AWS.ResponderLambdas - 70, // 105: cloudauthproto.encryption:extendee -> google.protobuf.FieldOptions - 106, // [106:106] is the sub-list for method output_type - 106, // [106:106] is the sub-list for method input_type - 106, // [106:106] is the sub-list for extension type_name - 105, // [105:106] is the sub-list for extension extendee - 0, // [0:105] is the sub-list for field type_name + 0, // 42: cloudauthproto.OrganizationalGroup.provider:type_name -> cloudauthproto.Provider + 71, // 43: cloudauthproto.OrganizationalGroup.metadata:type_name -> google.protobuf.Struct + 68, // 44: cloudauthproto.OrganizationalGroup.created_at:type_name -> google.protobuf.Timestamp + 68, // 45: cloudauthproto.OrganizationalGroup.updated_at:type_name -> google.protobuf.Timestamp + 2, // 46: cloudauthproto.OrganizationalGroup.verbosity:type_name -> cloudauthproto.Verbosity + 19, // 47: cloudauthproto.FeatureComponents.cloud_connector:type_name -> cloudauthproto.AccountComponent + 19, // 48: cloudauthproto.FeatureComponents.event_bridge:type_name -> cloudauthproto.AccountComponent + 19, // 49: cloudauthproto.FeatureComponents.trusted_role:type_name -> cloudauthproto.AccountComponent + 19, // 50: cloudauthproto.FeatureComponents.service_principal:type_name -> cloudauthproto.AccountComponent + 19, // 51: cloudauthproto.FeatureComponents.webhook_datasource:type_name -> cloudauthproto.AccountComponent + 19, // 52: cloudauthproto.FeatureComponents.crypto_key:type_name -> cloudauthproto.AccountComponent + 19, // 53: cloudauthproto.FeatureComponents.cloud_logs:type_name -> cloudauthproto.AccountComponent + 19, // 54: cloudauthproto.FeatureComponents.cloud_responder:type_name -> cloudauthproto.AccountComponent + 19, // 55: cloudauthproto.FeatureComponents.cloud_responder_roles:type_name -> cloudauthproto.AccountComponent + 7, // 56: cloudauthproto.AccountComponent.type:type_name -> cloudauthproto.Component + 68, // 57: cloudauthproto.AccountComponent.created_at:type_name -> google.protobuf.Timestamp + 68, // 58: cloudauthproto.AccountComponent.updated_at:type_name -> google.protobuf.Timestamp + 15, // 59: cloudauthproto.AccountComponent.validation:type_name -> cloudauthproto.Validation + 20, // 60: cloudauthproto.AccountComponent.cloud_connector_metadata:type_name -> cloudauthproto.CloudConnectorMetadata + 21, // 61: cloudauthproto.AccountComponent.trusted_role_metadata:type_name -> cloudauthproto.TrustedRoleMetadata + 22, // 62: cloudauthproto.AccountComponent.event_bridge_metadata:type_name -> cloudauthproto.EventBridgeMetadata + 23, // 63: cloudauthproto.AccountComponent.service_principal_metadata:type_name -> cloudauthproto.ServicePrincipalMetadata + 24, // 64: cloudauthproto.AccountComponent.webhook_datasource_metadata:type_name -> cloudauthproto.WebhookDatasourceMetadata + 25, // 65: cloudauthproto.AccountComponent.crypto_key_metadata:type_name -> cloudauthproto.CryptoKeyMetadata + 26, // 66: cloudauthproto.AccountComponent.cloud_logs_metadata:type_name -> cloudauthproto.CloudLogsMetadata + 27, // 67: cloudauthproto.AccountComponent.cloud_responder_metadata:type_name -> cloudauthproto.CloudResponderMetadata + 28, // 68: cloudauthproto.AccountComponent.cloud_responder_roles_metadata:type_name -> cloudauthproto.CloudResponderRolesMetadata + 30, // 69: cloudauthproto.CloudConnectorMetadata.aws:type_name -> cloudauthproto.CloudConnectorMetadata.AWS + 31, // 70: cloudauthproto.CloudConnectorMetadata.azure:type_name -> cloudauthproto.CloudConnectorMetadata.Azure + 32, // 71: cloudauthproto.CloudConnectorMetadata.gcp:type_name -> cloudauthproto.CloudConnectorMetadata.GCP + 33, // 72: cloudauthproto.TrustedRoleMetadata.aws:type_name -> cloudauthproto.TrustedRoleMetadata.AWS + 35, // 73: cloudauthproto.TrustedRoleMetadata.azure:type_name -> cloudauthproto.TrustedRoleMetadata.Azure + 34, // 74: cloudauthproto.TrustedRoleMetadata.gcp:type_name -> cloudauthproto.TrustedRoleMetadata.GCP + 36, // 75: cloudauthproto.TrustedRoleMetadata.ibmcloud:type_name -> cloudauthproto.TrustedRoleMetadata.IBMCloud + 37, // 76: cloudauthproto.EventBridgeMetadata.aws:type_name -> cloudauthproto.EventBridgeMetadata.AWS + 38, // 77: cloudauthproto.EventBridgeMetadata.azure:type_name -> cloudauthproto.EventBridgeMetadata.Azure + 40, // 78: cloudauthproto.ServicePrincipalMetadata.gcp:type_name -> cloudauthproto.ServicePrincipalMetadata.GCP + 41, // 79: cloudauthproto.ServicePrincipalMetadata.okta:type_name -> cloudauthproto.ServicePrincipalMetadata.Okta + 42, // 80: cloudauthproto.ServicePrincipalMetadata.azure:type_name -> cloudauthproto.ServicePrincipalMetadata.Azure + 43, // 81: cloudauthproto.ServicePrincipalMetadata.oci:type_name -> cloudauthproto.ServicePrincipalMetadata.OracleCloud + 51, // 82: cloudauthproto.WebhookDatasourceMetadata.okta:type_name -> cloudauthproto.WebhookDatasourceMetadata.Okta + 52, // 83: cloudauthproto.WebhookDatasourceMetadata.github:type_name -> cloudauthproto.WebhookDatasourceMetadata.Github + 53, // 84: cloudauthproto.WebhookDatasourceMetadata.gcp:type_name -> cloudauthproto.WebhookDatasourceMetadata.Gcp + 54, // 85: cloudauthproto.WebhookDatasourceMetadata.aws:type_name -> cloudauthproto.WebhookDatasourceMetadata.AWS + 59, // 86: cloudauthproto.CryptoKeyMetadata.aws:type_name -> cloudauthproto.CryptoKeyMetadata.AWS + 61, // 87: cloudauthproto.CloudLogsMetadata.aws:type_name -> cloudauthproto.CloudLogsMetadata.AWS + 62, // 88: cloudauthproto.CloudLogsMetadata.ibmcloud:type_name -> cloudauthproto.CloudLogsMetadata.IBMCloud + 66, // 89: cloudauthproto.CloudResponderMetadata.aws:type_name -> cloudauthproto.CloudResponderMetadata.AWS + 21, // 90: cloudauthproto.CloudResponderRolesMetadata.roles:type_name -> cloudauthproto.TrustedRoleMetadata + 21, // 91: cloudauthproto.CloudResponderRolesMetadata.validation_role:type_name -> cloudauthproto.TrustedRoleMetadata + 39, // 92: cloudauthproto.EventBridgeMetadata.Azure.event_hub_metadata:type_name -> cloudauthproto.EventBridgeMetadata.Azure.EventHubMetadata + 42, // 93: cloudauthproto.EventBridgeMetadata.Azure.service_principal:type_name -> cloudauthproto.ServicePrincipalMetadata.Azure + 44, // 94: cloudauthproto.ServicePrincipalMetadata.GCP.key:type_name -> cloudauthproto.ServicePrincipalMetadata.GCP.Key + 45, // 95: cloudauthproto.ServicePrincipalMetadata.GCP.workload_identity_federation:type_name -> cloudauthproto.ServicePrincipalMetadata.GCP.WorkloadIdentityFederation + 46, // 96: cloudauthproto.ServicePrincipalMetadata.Okta.oauth_app:type_name -> cloudauthproto.ServicePrincipalMetadata.Okta.OAuthApp + 47, // 97: cloudauthproto.ServicePrincipalMetadata.Azure.active_directory_service_principal:type_name -> cloudauthproto.ServicePrincipalMetadata.Azure.ActiveDirectoryServicePrincipal + 48, // 98: cloudauthproto.ServicePrincipalMetadata.Azure.oauth2_permission_grants:type_name -> cloudauthproto.ServicePrincipalMetadata.Azure.Oauth2PermissionGrant + 49, // 99: cloudauthproto.ServicePrincipalMetadata.OracleCloud.api_key:type_name -> cloudauthproto.ServicePrincipalMetadata.OracleCloud.ApiKey + 50, // 100: cloudauthproto.ServicePrincipalMetadata.OracleCloud.policy:type_name -> cloudauthproto.ServicePrincipalMetadata.OracleCloud.Policy + 55, // 101: cloudauthproto.WebhookDatasourceMetadata.Okta.webhook_datasource:type_name -> cloudauthproto.WebhookDatasourceMetadata.Okta.WebhookDatasource + 56, // 102: cloudauthproto.WebhookDatasourceMetadata.Github.webhook_datasource:type_name -> cloudauthproto.WebhookDatasourceMetadata.Github.WebhookDatasource + 57, // 103: cloudauthproto.WebhookDatasourceMetadata.Gcp.webhook_datasource:type_name -> cloudauthproto.WebhookDatasourceMetadata.Gcp.WebhookDatasource + 40, // 104: cloudauthproto.WebhookDatasourceMetadata.Gcp.service_principal:type_name -> cloudauthproto.ServicePrincipalMetadata.GCP + 58, // 105: cloudauthproto.WebhookDatasourceMetadata.AWS.webhook_datasource:type_name -> cloudauthproto.WebhookDatasourceMetadata.AWS.WebhookDatasource + 60, // 106: cloudauthproto.CryptoKeyMetadata.AWS.kms:type_name -> cloudauthproto.CryptoKeyMetadata.AWS.KMS + 63, // 107: cloudauthproto.CloudLogsMetadata.AWS.cloudtrail_s3_bucket:type_name -> cloudauthproto.CloudLogsMetadata.AWS.CloudTrailS3Bucket + 64, // 108: cloudauthproto.CloudLogsMetadata.AWS.cloudtrail_sns:type_name -> cloudauthproto.CloudLogsMetadata.AWS.CloudTrailSNS + 65, // 109: cloudauthproto.CloudLogsMetadata.IBMCloud.ibm_activity_tracker:type_name -> cloudauthproto.CloudLogsMetadata.IBMCloud.IBMActivityTracker + 67, // 110: cloudauthproto.CloudResponderMetadata.AWS.responder_lambdas:type_name -> cloudauthproto.CloudResponderMetadata.AWS.ResponderLambdas + 72, // 111: cloudauthproto.encryption:extendee -> google.protobuf.FieldOptions + 112, // [112:112] is the sub-list for method output_type + 112, // [112:112] is the sub-list for method input_type + 112, // [112:112] is the sub-list for extension type_name + 111, // [111:112] is the sub-list for extension extendee + 0, // [0:111] is the sub-list for field type_name } func init() { file_cloudauth_cloud_account_proto_init() } @@ -5560,8 +5730,8 @@ func file_cloudauth_cloud_account_proto_init() { (*CloudAccount_Ibm)(nil), } file_cloudauth_cloud_account_proto_msgTypes[4].OneofWrappers = []any{} - file_cloudauth_cloud_account_proto_msgTypes[9].OneofWrappers = []any{} - file_cloudauth_cloud_account_proto_msgTypes[10].OneofWrappers = []any{ + file_cloudauth_cloud_account_proto_msgTypes[10].OneofWrappers = []any{} + file_cloudauth_cloud_account_proto_msgTypes[11].OneofWrappers = []any{ (*AccountComponent_CloudConnectorMetadata)(nil), (*AccountComponent_TrustedRoleMetadata)(nil), (*AccountComponent_EventBridgeMetadata)(nil), @@ -5572,41 +5742,41 @@ func file_cloudauth_cloud_account_proto_init() { (*AccountComponent_CloudResponderMetadata)(nil), (*AccountComponent_CloudResponderRolesMetadata)(nil), } - file_cloudauth_cloud_account_proto_msgTypes[11].OneofWrappers = []any{ + file_cloudauth_cloud_account_proto_msgTypes[12].OneofWrappers = []any{ (*CloudConnectorMetadata_Aws)(nil), (*CloudConnectorMetadata_Azure_)(nil), (*CloudConnectorMetadata_Gcp)(nil), } - file_cloudauth_cloud_account_proto_msgTypes[12].OneofWrappers = []any{ + file_cloudauth_cloud_account_proto_msgTypes[13].OneofWrappers = []any{ (*TrustedRoleMetadata_Aws)(nil), (*TrustedRoleMetadata_Azure_)(nil), (*TrustedRoleMetadata_Gcp)(nil), (*TrustedRoleMetadata_Ibmcloud)(nil), } - file_cloudauth_cloud_account_proto_msgTypes[13].OneofWrappers = []any{ + file_cloudauth_cloud_account_proto_msgTypes[14].OneofWrappers = []any{ (*EventBridgeMetadata_Aws)(nil), (*EventBridgeMetadata_Azure_)(nil), } - file_cloudauth_cloud_account_proto_msgTypes[14].OneofWrappers = []any{ + file_cloudauth_cloud_account_proto_msgTypes[15].OneofWrappers = []any{ (*ServicePrincipalMetadata_Gcp)(nil), (*ServicePrincipalMetadata_Okta_)(nil), (*ServicePrincipalMetadata_Azure_)(nil), (*ServicePrincipalMetadata_Oci)(nil), } - file_cloudauth_cloud_account_proto_msgTypes[15].OneofWrappers = []any{ + file_cloudauth_cloud_account_proto_msgTypes[16].OneofWrappers = []any{ (*WebhookDatasourceMetadata_Okta_)(nil), (*WebhookDatasourceMetadata_Github_)(nil), (*WebhookDatasourceMetadata_Gcp_)(nil), (*WebhookDatasourceMetadata_Aws)(nil), } - file_cloudauth_cloud_account_proto_msgTypes[16].OneofWrappers = []any{ + file_cloudauth_cloud_account_proto_msgTypes[17].OneofWrappers = []any{ (*CryptoKeyMetadata_Aws)(nil), } - file_cloudauth_cloud_account_proto_msgTypes[17].OneofWrappers = []any{ + file_cloudauth_cloud_account_proto_msgTypes[18].OneofWrappers = []any{ (*CloudLogsMetadata_Aws)(nil), (*CloudLogsMetadata_Ibmcloud)(nil), } - file_cloudauth_cloud_account_proto_msgTypes[18].OneofWrappers = []any{ + file_cloudauth_cloud_account_proto_msgTypes[19].OneofWrappers = []any{ (*CloudResponderMetadata_Aws)(nil), } type x struct{} @@ -5615,7 +5785,7 @@ func file_cloudauth_cloud_account_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_cloudauth_cloud_account_proto_rawDesc), len(file_cloudauth_cloud_account_proto_rawDesc)), NumEnums: 8, - NumMessages: 59, + NumMessages: 60, NumExtensions: 1, NumServices: 0, }, diff --git a/sysdig/internal/client/v2/model.go b/sysdig/internal/client/v2/model.go index b8112995e..fb796aee6 100644 --- a/sysdig/internal/client/v2/model.go +++ b/sysdig/internal/client/v2/model.go @@ -86,14 +86,21 @@ type teamWrapper struct { Team Team `json:"team"` } +type Customer struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + ExternalID string `json:"externalId,omitempty"` +} + type User struct { - ID int `json:"id,omitempty"` - Version int `json:"version,omitempty"` - SystemRole string `json:"systemRole,omitempty"` - Email string `json:"username"` - FirstName string `json:"firstName,omitempty"` - LastName string `json:"lastName,omitempty"` - CurrentTeam *int `json:"currentTeam"` + ID int `json:"id,omitempty"` + Version int `json:"version,omitempty"` + SystemRole string `json:"systemRole,omitempty"` + Email string `json:"username"` + FirstName string `json:"firstName,omitempty"` + LastName string `json:"lastName,omitempty"` + CurrentTeam *int `json:"currentTeam"` + Customer *Customer `json:"customer,omitempty"` } type userWrapper struct { @@ -766,6 +773,7 @@ type AlertV2ConfigMetric struct { GroupAggregation string `json:"groupAggregation"` TimeAggregation string `json:"timeAggregation"` Metric AlertMetricDescriptorV2 `json:"metric"` + MetricID string `json:"metricId,omitempty"` // Legacy API field, used as fallback when Metric.ID is empty NoDataBehaviour string `json:"noDataBehaviour"` Range int `json:"range"` @@ -1201,3 +1209,109 @@ type ZoneScope struct { TargetType string `json:"targetType"` Rules string `json:"rules"` } + +// SSO OpenID Connect configuration - combines base SSO fields with OpenID-specific config +type SSOOpenID struct { + // Response-only identification fields + ID int `json:"id,omitempty"` + Version int `json:"version,omitempty"` + DateCreated string `json:"dateCreated,omitempty"` + LastUpdated string `json:"lastUpdated,omitempty"` + + // Base SSO fields (root level in API) + Product string `json:"product,omitempty"` + IsActive bool `json:"isActive"` + CreateUserOnLogin bool `json:"createUserOnLogin"` + IsSingleLogoutEnabled bool `json:"isSingleLogoutEnabled"` + IsGroupMappingEnabled bool `json:"isGroupMappingEnabled"` + GroupMappingAttributeName string `json:"groupMappingAttributeName,omitempty"` + IntegrationName string `json:"integrationName,omitempty"` + + // OpenID-specific config (nested in "config" in API) + Config *SSOOpenIDConfig `json:"config,omitempty"` +} + +// SSOOpenIDConfig contains OpenID-specific fields that go inside the "config" block +type SSOOpenIDConfig struct { + Type string `json:"type"` // "OPENID" + IssuerURL string `json:"issuerUrl"` + ClientID string `json:"clientId"` + ClientSecret string `json:"clientSecret,omitempty"` + IsMetadataDiscoveryEnabled bool `json:"isMetadataDiscoveryEnabled"` + Metadata *OpenIDMetadata `json:"metadata,omitempty"` + GroupAttributeName string `json:"groupAttributeName,omitempty"` + IsAdditionalScopesCheckEnabled bool `json:"isAdditionalScopesCheckEnabled"` + AdditionalScopes []string `json:"additionalScopes,omitempty"` +} + +type OpenIDMetadata struct { + Issuer string `json:"issuer"` + AuthorizationEndpoint string `json:"authorizationEndpoint"` + TokenEndpoint string `json:"tokenEndpoint"` + JwksURI string `json:"jwksUri"` + TokenAuthMethod string `json:"tokenAuthMethod"` + EndSessionEndpoint string `json:"endSessionEndpoint,omitempty"` + UserInfoEndpoint string `json:"userInfoEndpoint,omitempty"` +} + +// SSO SAML configuration - combines base SSO fields with SAML-specific config +type SSOSaml struct { + // Response-only identification fields + ID int `json:"id,omitempty"` + Version int `json:"version,omitempty"` + DateCreated string `json:"dateCreated,omitempty"` + LastUpdated string `json:"lastUpdated,omitempty"` + + // Base SSO fields (root level in API) + Product string `json:"product,omitempty"` + IsActive bool `json:"isActive"` + CreateUserOnLogin bool `json:"createUserOnLogin"` + IsSingleLogoutEnabled bool `json:"isSingleLogoutEnabled"` + IsGroupMappingEnabled bool `json:"isGroupMappingEnabled"` + GroupMappingAttributeName string `json:"groupMappingAttributeName,omitempty"` + IntegrationName string `json:"integrationName,omitempty"` + + // SAML-specific config (nested in "config" in API) + Config *SSOSamlConfig `json:"config,omitempty"` +} + +// SSOSamlConfig contains SAML-specific fields that go inside the "config" block +type SSOSamlConfig struct { + Type string `json:"type"` // "SAML" + MetadataURL string `json:"metadataUrl,omitempty"` + MetadataXML string `json:"metadataXml,omitempty"` + EmailParameter string `json:"emailParameter"` + IsSignatureValidationEnabled *bool `json:"isSignatureValidationEnabled,omitempty"` + IsSignedAssertionEnabled *bool `json:"isSignedAssertionEnabled,omitempty"` + IsDestinationVerificationEnabled *bool `json:"isDestinationVerificationEnabled,omitempty"` + IsEncryptionSupportEnabled *bool `json:"isEncryptionSupportEnabled,omitempty"` +} + +// SSO Group Mapping (Platform API) +type SSOGroupMapping struct { + ID int `json:"id,omitempty"` + GroupName string `json:"groupName"` + StandardTeamRole string `json:"standardTeamRole,omitempty"` + CustomTeamRoleID int `json:"customTeamRoleId,omitempty"` + IsAdmin bool `json:"isAdmin"` + TeamMap *SSOGroupMappingTeamMap `json:"teamMap"` + Weight int `json:"weight,omitempty"` +} + +type SSOGroupMappingTeamMap struct { + IsForAllTeams bool `json:"isForAllTeams"` + TeamIDs []int `json:"teamIds,omitempty"` +} + +// SSO Group Mapping Settings (Platform API) +type SSOGroupMappingSettings struct { + NoMappingStrategy string `json:"noMappingStrategy"` + DifferentRolesSameTeamStrategy string `json:"differentRolesSameTeamStrategy"` + NoMappingsErrorRedirectURL string `json:"noMappingsErrorRedirectUrl,omitempty"` +} + +// SSO Global Settings (Platform API) +type SSOGlobalSettings struct { + Product string `json:"product,omitempty"` + IsPasswordLoginEnabled bool `json:"isPasswordLoginEnabled"` +} diff --git a/sysdig/internal/client/v2/sso_global_settings.go b/sysdig/internal/client/v2/sso_global_settings.go new file mode 100644 index 000000000..88559ede7 --- /dev/null +++ b/sysdig/internal/client/v2/sso_global_settings.go @@ -0,0 +1,68 @@ +package v2 + +import ( + "context" + "errors" + "fmt" + "net/http" +) + +var ErrSSOGlobalSettingsNotFound = errors.New("SSO global settings not found") + +const ( + ssoGlobalSettingsPath = "%s/platform/v1/global-sso-settings/%s" +) + +type SSOGlobalSettingsInterface interface { + Base + GetSSOGlobalSettings(ctx context.Context, product string) (*SSOGlobalSettings, error) + UpdateSSOGlobalSettings(ctx context.Context, product string, settings *SSOGlobalSettings) (*SSOGlobalSettings, error) +} + +func (c *Client) GetSSOGlobalSettings(ctx context.Context, product string) (result *SSOGlobalSettings, err error) { + response, err := c.requester.Request(ctx, http.MethodGet, c.ssoGlobalSettingsURL(product), nil) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode == http.StatusNotFound { + return nil, ErrSSOGlobalSettingsNotFound + } + if response.StatusCode != http.StatusOK { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOGlobalSettings](response.Body) +} + +func (c *Client) UpdateSSOGlobalSettings(ctx context.Context, product string, settings *SSOGlobalSettings) (result *SSOGlobalSettings, err error) { + payload, err := Marshal(settings) + if err != nil { + return nil, err + } + + response, err := c.requester.Request(ctx, http.MethodPut, c.ssoGlobalSettingsURL(product), payload) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOGlobalSettings](response.Body) +} + +func (c *Client) ssoGlobalSettingsURL(product string) string { + return fmt.Sprintf(ssoGlobalSettingsPath, c.config.url, product) +} diff --git a/sysdig/internal/client/v2/sso_group_mapping.go b/sysdig/internal/client/v2/sso_group_mapping.go new file mode 100644 index 000000000..958f927d3 --- /dev/null +++ b/sysdig/internal/client/v2/sso_group_mapping.go @@ -0,0 +1,126 @@ +package v2 + +import ( + "context" + "errors" + "fmt" + "net/http" +) + +var ErrSSOGroupMappingNotFound = errors.New("SSO group mapping not found") + +const ( + createSSOGroupMappingPath = "%s/platform/v1/group-mappings" + getSSOGroupMappingPath = "%s/platform/v1/group-mappings/%d" + updateSSOGroupMappingPath = "%s/platform/v1/group-mappings/%d" + deleteSSOGroupMappingPath = "%s/platform/v1/group-mappings/%d" +) + +type SSOGroupMappingInterface interface { + Base + CreateSSOGroupMapping(ctx context.Context, gm *SSOGroupMapping) (*SSOGroupMapping, error) + GetSSOGroupMapping(ctx context.Context, id int) (*SSOGroupMapping, error) + UpdateSSOGroupMapping(ctx context.Context, id int, gm *SSOGroupMapping) (*SSOGroupMapping, error) + DeleteSSOGroupMapping(ctx context.Context, id int) error +} + +func (c *Client) CreateSSOGroupMapping(ctx context.Context, gm *SSOGroupMapping) (result *SSOGroupMapping, err error) { + payload, err := Marshal(gm) + if err != nil { + return nil, err + } + + response, err := c.requester.Request(ctx, http.MethodPost, c.createSSOGroupMappingURL(), payload) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOGroupMapping](response.Body) +} + +func (c *Client) GetSSOGroupMapping(ctx context.Context, id int) (result *SSOGroupMapping, err error) { + response, err := c.requester.Request(ctx, http.MethodGet, c.getSSOGroupMappingURL(id), nil) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode == http.StatusNotFound { + return nil, ErrSSOGroupMappingNotFound + } + if response.StatusCode != http.StatusOK { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOGroupMapping](response.Body) +} + +func (c *Client) UpdateSSOGroupMapping(ctx context.Context, id int, gm *SSOGroupMapping) (result *SSOGroupMapping, err error) { + payload, err := Marshal(gm) + if err != nil { + return nil, err + } + + response, err := c.requester.Request(ctx, http.MethodPut, c.updateSSOGroupMappingURL(id), payload) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOGroupMapping](response.Body) +} + +func (c *Client) DeleteSSOGroupMapping(ctx context.Context, id int) (err error) { + response, err := c.requester.Request(ctx, http.MethodDelete, c.deleteSSOGroupMappingURL(id), nil) + if err != nil { + return err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK && response.StatusCode != http.StatusNotFound { + return c.ErrorFromResponse(response) + } + + return nil +} + +func (c *Client) createSSOGroupMappingURL() string { + return fmt.Sprintf(createSSOGroupMappingPath, c.config.url) +} + +func (c *Client) getSSOGroupMappingURL(id int) string { + return fmt.Sprintf(getSSOGroupMappingPath, c.config.url, id) +} + +func (c *Client) updateSSOGroupMappingURL(id int) string { + return fmt.Sprintf(updateSSOGroupMappingPath, c.config.url, id) +} + +func (c *Client) deleteSSOGroupMappingURL(id int) string { + return fmt.Sprintf(deleteSSOGroupMappingPath, c.config.url, id) +} diff --git a/sysdig/internal/client/v2/sso_group_mapping_settings.go b/sysdig/internal/client/v2/sso_group_mapping_settings.go new file mode 100644 index 000000000..f76600d98 --- /dev/null +++ b/sysdig/internal/client/v2/sso_group_mapping_settings.go @@ -0,0 +1,72 @@ +package v2 + +import ( + "context" + "errors" + "fmt" + "net/http" +) + +var ErrSSOGroupMappingSettingsNotFound = errors.New("SSO group mapping settings not found") + +const ( + ssoGroupMappingSettingsPath = "%s/platform/v1/group-mappings-settings" +) + +type SSOGroupMappingSettingsInterface interface { + Base + GetSSOGroupMappingSettings(ctx context.Context) (*SSOGroupMappingSettings, error) + UpdateSSOGroupMappingSettings(ctx context.Context, settings *SSOGroupMappingSettings) (*SSOGroupMappingSettings, error) +} + +func (c *Client) GetSSOGroupMappingSettings(ctx context.Context) (result *SSOGroupMappingSettings, err error) { + response, err := c.requester.Request(ctx, http.MethodGet, c.getSSOGroupMappingSettingsURL(), nil) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode == http.StatusNotFound { + return nil, ErrSSOGroupMappingSettingsNotFound + } + if response.StatusCode != http.StatusOK { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOGroupMappingSettings](response.Body) +} + +func (c *Client) UpdateSSOGroupMappingSettings(ctx context.Context, settings *SSOGroupMappingSettings) (result *SSOGroupMappingSettings, err error) { + payload, err := Marshal(settings) + if err != nil { + return nil, err + } + + response, err := c.requester.Request(ctx, http.MethodPut, c.updateSSOGroupMappingSettingsURL(), payload) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOGroupMappingSettings](response.Body) +} + +func (c *Client) getSSOGroupMappingSettingsURL() string { + return fmt.Sprintf(ssoGroupMappingSettingsPath, c.config.url) +} + +func (c *Client) updateSSOGroupMappingSettingsURL() string { + return fmt.Sprintf(ssoGroupMappingSettingsPath, c.config.url) +} diff --git a/sysdig/internal/client/v2/sso_openid.go b/sysdig/internal/client/v2/sso_openid.go new file mode 100644 index 000000000..655e45ecd --- /dev/null +++ b/sysdig/internal/client/v2/sso_openid.go @@ -0,0 +1,147 @@ +package v2 + +import ( + "context" + "errors" + "fmt" + "net/http" +) + +var ErrSSOOpenIDNotFound = errors.New("SSO OpenID configuration not found") + +const ( + createSSOOpenIDPath = "%s/platform/v1/sso-settings/" + getSSOOpenIDPath = "%s/platform/v1/sso-settings/%d" + updateSSOOpenIDPath = "%s/platform/v1/sso-settings/%d" + deleteSSOOpenIDPath = "%s/platform/v1/sso-settings/%d" + + createSystemSSOOpenIDPath = "%s/platform/v1/system-sso-settings/" + getSystemSSOOpenIDPath = "%s/platform/v1/system-sso-settings/%d" + updateSystemSSOOpenIDPath = "%s/platform/v1/system-sso-settings/%d" + deleteSystemSSOOpenIDPath = "%s/platform/v1/system-sso-settings/%d" +) + +type SSOOpenIDInterface interface { + Base + CreateSSOOpenID(ctx context.Context, isSystem bool, sso *SSOOpenID) (*SSOOpenID, error) + GetSSOOpenID(ctx context.Context, isSystem bool, id int) (*SSOOpenID, error) + UpdateSSOOpenID(ctx context.Context, isSystem bool, id int, sso *SSOOpenID) (*SSOOpenID, error) + DeleteSSOOpenID(ctx context.Context, isSystem bool, id int) error +} + +func (c *Client) CreateSSOOpenID(ctx context.Context, isSystem bool, sso *SSOOpenID) (result *SSOOpenID, err error) { + payload, err := Marshal(sso) + if err != nil { + return nil, err + } + + response, err := c.requester.Request(ctx, http.MethodPost, c.createSSOOpenIDURL(isSystem), payload) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOOpenID](response.Body) +} + +func (c *Client) GetSSOOpenID(ctx context.Context, isSystem bool, id int) (result *SSOOpenID, err error) { + response, err := c.requester.Request(ctx, http.MethodGet, c.getSSOOpenIDURL(isSystem, id), nil) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode == http.StatusNotFound { + return nil, ErrSSOOpenIDNotFound + } + if response.StatusCode != http.StatusOK { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOOpenID](response.Body) +} + +func (c *Client) UpdateSSOOpenID(ctx context.Context, isSystem bool, id int, sso *SSOOpenID) (result *SSOOpenID, err error) { + payload, err := Marshal(sso) + if err != nil { + return nil, err + } + + response, err := c.requester.Request(ctx, http.MethodPut, c.updateSSOOpenIDURL(isSystem, id), payload) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOOpenID](response.Body) +} + +func (c *Client) DeleteSSOOpenID(ctx context.Context, isSystem bool, id int) (err error) { + response, err := c.requester.Request(ctx, http.MethodDelete, c.deleteSSOOpenIDURL(isSystem, id), nil) + if err != nil { + return err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK && response.StatusCode != http.StatusNotFound { + return c.ErrorFromResponse(response) + } + + return nil +} + +func (c *Client) createSSOOpenIDURL(isSystem bool) string { + path := createSSOOpenIDPath + if isSystem { + path = createSystemSSOOpenIDPath + } + return fmt.Sprintf(path, c.config.url) +} + +func (c *Client) getSSOOpenIDURL(isSystem bool, id int) string { + path := getSSOOpenIDPath + if isSystem { + path = getSystemSSOOpenIDPath + } + return fmt.Sprintf(path, c.config.url, id) +} + +func (c *Client) updateSSOOpenIDURL(isSystem bool, id int) string { + path := updateSSOOpenIDPath + if isSystem { + path = updateSystemSSOOpenIDPath + } + return fmt.Sprintf(path, c.config.url, id) +} + +func (c *Client) deleteSSOOpenIDURL(isSystem bool, id int) string { + path := deleteSSOOpenIDPath + if isSystem { + path = deleteSystemSSOOpenIDPath + } + return fmt.Sprintf(path, c.config.url, id) +} diff --git a/sysdig/internal/client/v2/sso_saml.go b/sysdig/internal/client/v2/sso_saml.go new file mode 100644 index 000000000..33fbfb10c --- /dev/null +++ b/sysdig/internal/client/v2/sso_saml.go @@ -0,0 +1,147 @@ +package v2 + +import ( + "context" + "errors" + "fmt" + "net/http" +) + +var ErrSSOSamlNotFound = errors.New("SSO SAML configuration not found") + +const ( + createSSOSamlPath = "%s/platform/v1/sso-settings/" + getSSOSamlPath = "%s/platform/v1/sso-settings/%d" + updateSSOSamlPath = "%s/platform/v1/sso-settings/%d" + deleteSSOSamlPath = "%s/platform/v1/sso-settings/%d" + + createSystemSSOSamlPath = "%s/platform/v1/system-sso-settings/" + getSystemSSOSamlPath = "%s/platform/v1/system-sso-settings/%d" + updateSystemSSOSamlPath = "%s/platform/v1/system-sso-settings/%d" + deleteSystemSSOSamlPath = "%s/platform/v1/system-sso-settings/%d" +) + +type SSOSamlInterface interface { + Base + CreateSSOSaml(ctx context.Context, isSystem bool, sso *SSOSaml) (*SSOSaml, error) + GetSSOSaml(ctx context.Context, isSystem bool, id int) (*SSOSaml, error) + UpdateSSOSaml(ctx context.Context, isSystem bool, id int, sso *SSOSaml) (*SSOSaml, error) + DeleteSSOSaml(ctx context.Context, isSystem bool, id int) error +} + +func (c *Client) CreateSSOSaml(ctx context.Context, isSystem bool, sso *SSOSaml) (result *SSOSaml, err error) { + payload, err := Marshal(sso) + if err != nil { + return nil, err + } + + response, err := c.requester.Request(ctx, http.MethodPost, c.createSSOSamlURL(isSystem), payload) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOSaml](response.Body) +} + +func (c *Client) GetSSOSaml(ctx context.Context, isSystem bool, id int) (result *SSOSaml, err error) { + response, err := c.requester.Request(ctx, http.MethodGet, c.getSSOSamlURL(isSystem, id), nil) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode == http.StatusNotFound { + return nil, ErrSSOSamlNotFound + } + if response.StatusCode != http.StatusOK { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOSaml](response.Body) +} + +func (c *Client) UpdateSSOSaml(ctx context.Context, isSystem bool, id int, sso *SSOSaml) (result *SSOSaml, err error) { + payload, err := Marshal(sso) + if err != nil { + return nil, err + } + + response, err := c.requester.Request(ctx, http.MethodPut, c.updateSSOSamlURL(isSystem, id), payload) + if err != nil { + return nil, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK { + return nil, c.ErrorFromResponse(response) + } + + return Unmarshal[*SSOSaml](response.Body) +} + +func (c *Client) DeleteSSOSaml(ctx context.Context, isSystem bool, id int) (err error) { + response, err := c.requester.Request(ctx, http.MethodDelete, c.deleteSSOSamlURL(isSystem, id), nil) + if err != nil { + return err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK && response.StatusCode != http.StatusNotFound { + return c.ErrorFromResponse(response) + } + + return nil +} + +func (c *Client) createSSOSamlURL(isSystem bool) string { + path := createSSOSamlPath + if isSystem { + path = createSystemSSOSamlPath + } + return fmt.Sprintf(path, c.config.url) +} + +func (c *Client) getSSOSamlURL(isSystem bool, id int) string { + path := getSSOSamlPath + if isSystem { + path = getSystemSSOSamlPath + } + return fmt.Sprintf(path, c.config.url, id) +} + +func (c *Client) updateSSOSamlURL(isSystem bool, id int) string { + path := updateSSOSamlPath + if isSystem { + path = updateSystemSSOSamlPath + } + return fmt.Sprintf(path, c.config.url, id) +} + +func (c *Client) deleteSSOSamlURL(isSystem bool, id int) string { + path := deleteSSOSamlPath + if isSystem { + path = deleteSystemSSOSamlPath + } + return fmt.Sprintf(path, c.config.url, id) +} diff --git a/sysdig/internal/client/v2/sysdig.go b/sysdig/internal/client/v2/sysdig.go index 3316182a2..24428f285 100644 --- a/sysdig/internal/client/v2/sysdig.go +++ b/sysdig/internal/client/v2/sysdig.go @@ -25,6 +25,11 @@ type SysdigCommon interface { GroupMappingInterface IPFilteringSettingsInterface IPFiltersInterface + SSOGlobalSettingsInterface + SSOGroupMappingInterface + SSOGroupMappingSettingsInterface + SSOOpenIDInterface + SSOSamlInterface TeamServiceAccountInterface } diff --git a/sysdig/provider.go b/sysdig/provider.go index 694a47c97..93464333c 100644 --- a/sysdig/provider.go +++ b/sysdig/provider.go @@ -115,14 +115,19 @@ func (p *SysdigProvider) Provider() *schema.Provider { }, }, ResourcesMap: map[string]*schema.Resource{ - "sysdig_agent_access_key": resourceSysdigAgentAccessKey(), - "sysdig_custom_role": resourceSysdigCustomRole(), - "sysdig_group_mapping": resourceSysdigGroupMapping(), - "sysdig_group_mapping_config": resourceSysdigGroupMappingConfig(), - "sysdig_ip_filter": resourceSysdigIPFilter(), - "sysdig_ip_filtering_settings": resourceSysdigIPFilteringSettings(), - "sysdig_team_service_account": resourceSysdigTeamServiceAccount(), - "sysdig_user": resourceSysdigUser(), + "sysdig_agent_access_key": resourceSysdigAgentAccessKey(), + "sysdig_custom_role": resourceSysdigCustomRole(), + "sysdig_group_mapping": resourceSysdigGroupMapping(), + "sysdig_group_mapping_config": resourceSysdigGroupMappingConfig(), + "sysdig_ip_filter": resourceSysdigIPFilter(), + "sysdig_ip_filtering_settings": resourceSysdigIPFilteringSettings(), + "sysdig_sso_global_settings": resourceSysdigSSOGlobalSettings(), + "sysdig_sso_group_mapping": resourceSysdigSSOGroupMapping(), + "sysdig_sso_group_mapping_settings": resourceSysdigSSOGroupMappingSettings(), + "sysdig_sso_openid": resourceSysdigSSOOpenID(), + "sysdig_sso_saml": resourceSysdigSSOSaml(), + "sysdig_team_service_account": resourceSysdigTeamServiceAccount(), + "sysdig_user": resourceSysdigUser(), "sysdig_monitor_alert_v2_change": resourceSysdigMonitorAlertV2Change(), "sysdig_monitor_alert_v2_downtime": resourceSysdigMonitorAlertV2Downtime(), diff --git a/sysdig/resource_sysdig_group_mapping.go b/sysdig/resource_sysdig_group_mapping.go index 9168466f0..b2a40d370 100644 --- a/sysdig/resource_sysdig_group_mapping.go +++ b/sysdig/resource_sysdig_group_mapping.go @@ -14,10 +14,11 @@ func resourceSysdigGroupMapping() *schema.Resource { timeout := 5 * time.Minute return &schema.Resource{ - ReadContext: resourceSysdigGroupMappingRead, - CreateContext: resourceSysdigGroupMappingCreate, - UpdateContext: resourceSysdigGroupMappingUpdate, - DeleteContext: resourceSysdigGroupMappingDelete, + ReadContext: resourceSysdigGroupMappingRead, + CreateContext: resourceSysdigGroupMappingCreate, + UpdateContext: resourceSysdigGroupMappingUpdate, + DeleteContext: resourceSysdigGroupMappingDelete, + DeprecationMessage: "Use sysdig_sso_group_mapping instead. This resource will be removed in a future version.", Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, diff --git a/sysdig/resource_sysdig_group_mapping_config.go b/sysdig/resource_sysdig_group_mapping_config.go index 7538c1c9f..404b4d829 100644 --- a/sysdig/resource_sysdig_group_mapping_config.go +++ b/sysdig/resource_sysdig_group_mapping_config.go @@ -12,10 +12,11 @@ import ( func resourceSysdigGroupMappingConfig() *schema.Resource { timeout := 5 * time.Minute return &schema.Resource{ - ReadContext: resourceSysdigGroupMappingConfigRead, - CreateContext: resourceSysdigGroupMappingConfigCreate, - UpdateContext: resourceSysdigGroupMappingConfigUpdate, - DeleteContext: resourceSysdigGroupMappingConfigDelete, + ReadContext: resourceSysdigGroupMappingConfigRead, + CreateContext: resourceSysdigGroupMappingConfigCreate, + UpdateContext: resourceSysdigGroupMappingConfigUpdate, + DeleteContext: resourceSysdigGroupMappingConfigDelete, + DeprecationMessage: "Use sysdig_sso_group_mapping_settings instead. This resource will be removed in a future version.", Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, diff --git a/sysdig/resource_sysdig_monitor_alert_v2_change_test.go b/sysdig/resource_sysdig_monitor_alert_v2_change_test.go index 140c5a6cf..cac9f2277 100644 --- a/sysdig/resource_sysdig_monitor_alert_v2_change_test.go +++ b/sysdig/resource_sysdig_monitor_alert_v2_change_test.go @@ -57,6 +57,18 @@ func TestAccAlertV2Change(t *testing.T) { { Config: alertV2ChangeWithUnreportedAlertNotificationsRetentionSec(rText()), }, + { + Config: alertV2ChangeWithNotEqualOperator(rText()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("sysdig_monitor_alert_v2_change.sample", "operator", "!="), + ), + }, + { + Config: alertV2ChangeWithEqualOperator(rText()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("sysdig_monitor_alert_v2_change.sample", "operator", "="), + ), + }, { Config: alertV2ChangeWithWarningThreshold(rText()), }, @@ -314,6 +326,36 @@ resource "sysdig_monitor_alert_v2_change" "sample" { `, name) } +func alertV2ChangeWithNotEqualOperator(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_change" "sample" { + name = "TERRAFORM TEST - CHANGE %s" + metric = "sysdig_container_cpu_used_percent" + group_aggregation = "avg" + time_aggregation = "avg" + operator = "!=" + threshold = 50 + shorter_time_range_seconds = 300 + longer_time_range_seconds = 3600 +} +`, name) +} + +func alertV2ChangeWithEqualOperator(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_change" "sample" { + name = "TERRAFORM TEST - CHANGE %s" + metric = "sysdig_container_cpu_used_percent" + group_aggregation = "avg" + time_aggregation = "avg" + operator = "=" + threshold = 50 + shorter_time_range_seconds = 300 + longer_time_range_seconds = 3600 +} +`, name) +} + func alertV2ChangeWithWarningThreshold(name string) string { return fmt.Sprintf(` resource "sysdig_monitor_notification_channel_email" "nc_email1" { diff --git a/sysdig/resource_sysdig_monitor_alert_v2_common.go b/sysdig/resource_sysdig_monitor_alert_v2_common.go index c3c3057d8..259e90a6b 100644 --- a/sysdig/resource_sysdig_monitor_alert_v2_common.go +++ b/sysdig/resource_sysdig_monitor_alert_v2_common.go @@ -216,6 +216,7 @@ func AlertV2SeverityValues() []string { func AlertLinkV2TypeValues() []string { return []string{ string(v2.AlertLinkV2TypeDashboard), + string(v2.AlertLinkV2TypeDashboardTemplate), string(v2.AlertLinkV2TypeRunbook), } } diff --git a/sysdig/resource_sysdig_monitor_alert_v2_event_test.go b/sysdig/resource_sysdig_monitor_alert_v2_event_test.go index d68d5c85c..40c4251e7 100644 --- a/sysdig/resource_sysdig_monitor_alert_v2_event_test.go +++ b/sysdig/resource_sysdig_monitor_alert_v2_event_test.go @@ -36,6 +36,18 @@ func TestAccAlertV2Event(t *testing.T) { { Config: alertV2EventWithScrambledSources(rText()), }, + { + Config: alertV2EventWithNotEqualOperator(rText()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("sysdig_monitor_alert_v2_event.sample", "operator", "!="), + ), + }, + { + Config: alertV2EventWithEqualOperator(rText()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("sysdig_monitor_alert_v2_event.sample", "operator", "="), + ), + }, { Config: alertV2EventWithWarningThreshold(rText()), }, @@ -138,6 +150,50 @@ resource "sysdig_monitor_alert_v2_event" "sample" { `, name) } +func alertV2EventWithNotEqualOperator(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_event" "sample" { + + name = "TERRAFORM TEST - EVENTV2 %s" + filter = "xxx" + operator = "!=" + threshold = 50 + + scope { + label = "kube_cluster_name" + operator = "in" + values = ["thom-cluster1", "demo-env-prom"] + } + + range_seconds = 600 + +} + +`, name) +} + +func alertV2EventWithEqualOperator(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_event" "sample" { + + name = "TERRAFORM TEST - EVENTV2 %s" + filter = "xxx" + operator = "=" + threshold = 50 + + scope { + label = "kube_cluster_name" + operator = "in" + values = ["thom-cluster1", "demo-env-prom"] + } + + range_seconds = 600 + +} + +`, name) +} + func alertV2EventWithWarningThreshold(name string) string { return fmt.Sprintf(` resource "sysdig_monitor_alert_v2_event" "sample" { diff --git a/sysdig/resource_sysdig_monitor_alert_v2_metric.go b/sysdig/resource_sysdig_monitor_alert_v2_metric.go index 593d8bee0..b60ffdc5a 100644 --- a/sysdig/resource_sysdig_monitor_alert_v2_metric.go +++ b/sysdig/resource_sysdig_monitor_alert_v2_metric.go @@ -59,8 +59,9 @@ func resourceSysdigMonitorAlertV2Metric() *schema.Resource { Default: "", }, "metric": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, "time_aggregation": { Type: schema.TypeString, @@ -274,7 +275,11 @@ func updateAlertV2MetricState(d *schema.ResourceData, alert *v2.AlertV2Metric) e _ = d.Set("group_aggregation", alert.Config.GroupAggregation) - _ = d.Set("metric", alert.Config.Metric.ID) + metricID := alert.Config.Metric.ID + if metricID == "" { + metricID = alert.Config.MetricID + } + _ = d.Set("metric", metricID) _ = d.Set("no_data_behaviour", alert.Config.NoDataBehaviour) diff --git a/sysdig/resource_sysdig_monitor_alert_v2_metric_test.go b/sysdig/resource_sysdig_monitor_alert_v2_metric_test.go index be5094d88..6bd873845 100644 --- a/sysdig/resource_sysdig_monitor_alert_v2_metric_test.go +++ b/sysdig/resource_sysdig_monitor_alert_v2_metric_test.go @@ -4,6 +4,7 @@ package sysdig_test import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" @@ -84,6 +85,18 @@ func TestAccAlertV2Metric(t *testing.T) { { Config: alertV2MetricWithLabels(rText()), }, + { + Config: alertV2MetricWithNotEqualOperator(rText()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("sysdig_monitor_alert_v2_metric.sample", "operator", "!="), + ), + }, + { + Config: alertV2MetricWithEqualOperator(rText()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("sysdig_monitor_alert_v2_metric.sample", "operator", "="), + ), + }, { Config: alertV2MetricWithWarningThreshold(rText()), }, @@ -96,6 +109,39 @@ func TestAccAlertV2Metric(t *testing.T) { }) } +func TestAccAlertV2MetricRejectsEmptyMetric(t *testing.T) { + rText := func() string { return acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) } + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigIBMMonitorAPIKeyEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: alertV2MetricWithEmptyMetric(rText()), + ExpectError: regexp.MustCompile(`expected "metric" to not be an empty string`), + }, + }, + }) +} + +func alertV2MetricWithEmptyMetric(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_metric" "sample" { + name = "TERRAFORM TEST - METRICV2 %s" + metric = "" + group_aggregation = "avg" + time_aggregation = "avg" + operator = ">=" + threshold = 50 + range_seconds = 600 +} +`, name) +} + func alertV2Metric(name string) string { return fmt.Sprintf(` resource "sysdig_monitor_alert_v2_metric" "sample" { @@ -469,6 +515,10 @@ resource "sysdig_monitor_alert_v2_metric" "sample" { type = "dashboard" id = sysdig_monitor_dashboard.dashboard.id } + link { + type = "dashboardTemplate" + id = "view.promcat.mysql" + } } `, name, name, name) } @@ -526,6 +576,38 @@ resource "sysdig_monitor_alert_v2_metric" "sample" { `, name) } +func alertV2MetricWithNotEqualOperator(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_metric" "sample" { + + name = "TERRAFORM TEST - METRICV2 %s" + metric = "sysdig_container_cpu_used_percent" + group_aggregation = "avg" + time_aggregation = "avg" + operator = "!=" + threshold = 50 + range_seconds = 600 + +} +`, name) +} + +func alertV2MetricWithEqualOperator(name string) string { + return fmt.Sprintf(` +resource "sysdig_monitor_alert_v2_metric" "sample" { + + name = "TERRAFORM TEST - METRICV2 %s" + metric = "sysdig_container_cpu_used_percent" + group_aggregation = "avg" + time_aggregation = "avg" + operator = "=" + threshold = 50 + range_seconds = 600 + +} +`, name) +} + func alertV2MetricWithWarningThreshold(name string) string { return fmt.Sprintf(` resource "sysdig_monitor_notification_channel_email" "nc_email1" { diff --git a/sysdig/resource_sysdig_secure_cloud_auth_account.go b/sysdig/resource_sysdig_secure_cloud_auth_account.go index ebc931f58..1c96a57e3 100644 --- a/sysdig/resource_sysdig_secure_cloud_auth_account.go +++ b/sysdig/resource_sysdig_secure_cloud_auth_account.go @@ -101,7 +101,7 @@ func resourceSysdigSecureCloudauthAccount() *schema.Resource { Required: true, }, SchemaComponents: { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, @@ -335,7 +335,7 @@ func setAccountFeature(accountFeatures *cloudauth.AccountFeatures, fieldName str case SchemaEnabled: target.Elem().FieldByName("Enabled").SetBool(value.(bool)) case SchemaComponents: - for _, componentID := range value.([]any) { + for _, componentID := range value.(*schema.Set).List() { target.Elem().FieldByName("Components").Set(reflect.Append(target.Elem().FieldByName("Components"), reflect.ValueOf(componentID.(string)))) } } diff --git a/sysdig/resource_sysdig_secure_cloud_auth_account_feature.go b/sysdig/resource_sysdig_secure_cloud_auth_account_feature.go index 6aa033545..87974cfe8 100644 --- a/sysdig/resource_sysdig_secure_cloud_auth_account_feature.go +++ b/sysdig/resource_sysdig_secure_cloud_auth_account_feature.go @@ -51,7 +51,7 @@ func getAccountFeatureSchema() map[string]*schema.Schema { Required: true, }, SchemaComponents: { - Type: schema.TypeList, + Type: schema.TypeSet, Required: true, Elem: &schema.Schema{ Type: schema.TypeString, @@ -184,7 +184,7 @@ func validateCloudauthAccountFeatureUpdate(existingFeature *v2.CloudauthAccountF func getFeatureComponentsList(data *schema.ResourceData) []string { componentsList := []string{} - componentsResourceList := data.Get(SchemaComponents).([]any) + componentsResourceList := data.Get(SchemaComponents).(*schema.Set).List() for _, componentID := range componentsResourceList { componentsList = append(componentsList, componentID.(string)) } diff --git a/sysdig/resource_sysdig_secure_cloud_auth_account_test.go b/sysdig/resource_sysdig_secure_cloud_auth_account_test.go index 406abcd9a..527c35c97 100644 --- a/sysdig/resource_sysdig_secure_cloud_auth_account_test.go +++ b/sysdig/resource_sysdig_secure_cloud_auth_account_test.go @@ -1,4 +1,4 @@ -//go:build tf_acc_sysdig_secure || tf_acc_sysdig_common +//go:build tf_acc_sysdig_secure package sysdig_test @@ -574,7 +574,6 @@ func TestAccAWSSecureCloudAuthAccountResponseActions(t *testing.T) { }, }, }) - } func TestAccAWSSecureCloudAccountThreatDetection(t *testing.T) { diff --git a/sysdig/resource_sysdig_secure_managed_ruleset_test.go b/sysdig/resource_sysdig_secure_managed_ruleset_test.go index 98dbdce94..dcd5fcf53 100644 --- a/sysdig/resource_sysdig_secure_managed_ruleset_test.go +++ b/sysdig/resource_sysdig_secure_managed_ruleset_test.go @@ -7,7 +7,6 @@ import ( "os" "testing" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -15,7 +14,7 @@ import ( ) func TestAccManagedRuleset(t *testing.T) { - rText := func() string { return acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) } + rText := randomText(10) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -30,7 +29,7 @@ func TestAccManagedRuleset(t *testing.T) { }, Steps: []resource.TestStep{ { - Config: managedRulesetWithoutNotificationChannels(), + Config: managedRulesetWithoutNotificationChannels(rText), }, { ResourceName: "sysdig_secure_managed_ruleset.sample", @@ -38,16 +37,16 @@ func TestAccManagedRuleset(t *testing.T) { ImportStateVerify: true, }, { - Config: managedRulesetWithoutActions(rText()), + Config: managedRulesetWithoutActions(rText), }, { - Config: managedRuleset(rText()), + Config: managedRuleset(rText), }, { - Config: managedRulesetWithMinimumConfiguration(), + Config: managedRulesetWithMinimumConfiguration(rText), }, { - Config: managedRulesetWithKillAction(), + Config: managedRulesetWithKillAction(rText), Destroy: true, }, }, @@ -58,7 +57,7 @@ func managedRuleset(name string) string { return fmt.Sprintf(` %s resource "sysdig_secure_managed_ruleset" "sample" { - name = "Sysdig Runtime Threat Detection (Copy)" + name = "Sysdig Runtime Threat Detection - %s" description = "Test Description" inherited_from { name = "Sysdig Runtime Threat Detection" @@ -77,17 +76,17 @@ resource "sysdig_secure_managed_ruleset" "sample" { name = "testcapture" } } - + notification_channels = [sysdig_secure_notification_channel_email.sample_email.id] } - `, secureNotificationChannelEmailWithName(name)) + `, secureNotificationChannelEmailWithName(name), name) } func managedRulesetWithoutActions(name string) string { return fmt.Sprintf(` %s resource "sysdig_secure_managed_ruleset" "sample" { - name = "Sysdig Runtime Threat Detection (Copy)" + name = "Sysdig Runtime Threat Detection - %s" description = "Test Description" inherited_from { name = "Sysdig Runtime Threat Detection" @@ -99,16 +98,16 @@ resource "sysdig_secure_managed_ruleset" "sample" { runbook = "https://sysdig.com" actions {} - + notification_channels = [sysdig_secure_notification_channel_email.sample_email.id] } - `, secureNotificationChannelEmailWithName(name)) + `, secureNotificationChannelEmailWithName(name), name) } -func managedRulesetWithoutNotificationChannels() string { - return ` +func managedRulesetWithoutNotificationChannels(name string) string { + return fmt.Sprintf(` resource "sysdig_secure_managed_ruleset" "sample" { - name = "Sysdig Runtime Threat Detection (Copy)" + name = "Sysdig Runtime Threat Detection - %s" description = "Test Description" inherited_from { name = "Sysdig Runtime Threat Detection" @@ -126,27 +125,27 @@ resource "sysdig_secure_managed_ruleset" "sample" { seconds_after_event = 10 name = "testcapture" } - } -}` + } +}`, name) } -func managedRulesetWithMinimumConfiguration() string { - return ` +func managedRulesetWithMinimumConfiguration(name string) string { + return fmt.Sprintf(` resource "sysdig_secure_managed_ruleset" "sample" { - name = "Sysdig Runtime Threat Detection (Copy)" + name = "Sysdig Runtime Threat Detection - %s" description = "Test Description" inherited_from { name = "Sysdig Runtime Threat Detection" type = "falco" } enabled = true -}` +}`, name) } -func managedRulesetWithKillAction() string { - return ` +func managedRulesetWithKillAction(name string) string { + return fmt.Sprintf(` resource "sysdig_secure_managed_ruleset" "sample" { - name = "Sysdig Runtime Threat Detection (Copy)" + name = "Sysdig Runtime Threat Detection - %s" description = "Test Description" inherited_from { name = "Sysdig Runtime Threat Detection" @@ -160,5 +159,5 @@ resource "sysdig_secure_managed_ruleset" "sample" { actions { container = "kill" } -}` +}`, name) } diff --git a/sysdig/resource_sysdig_secure_posture_zone_test.go b/sysdig/resource_sysdig_secure_posture_zone_test.go index f504da9d8..94f405b7a 100644 --- a/sysdig/resource_sysdig_secure_posture_zone_test.go +++ b/sysdig/resource_sysdig_secure_posture_zone_test.go @@ -66,10 +66,15 @@ resource "sysdig_secure_posture_zone" "z1" { func securePostureZoneWithPolicies(name string) string { return fmt.Sprintf(` -data "sysdig_secure_posture_policies" "all" {} +resource "sysdig_secure_posture_policy" "test" { + name = "%s-policy" + description = "test policy for posture zone" + is_active = true + type = "Unknown" +} resource "sysdig_secure_posture_zone" "z1" { - name = "%s" - policy_ids = [data.sysdig_secure_posture_policies.all.policies[0].id] -}`, name) + name = "%s" + policy_ids = [sysdig_secure_posture_policy.test.id] +}`, name, name) } diff --git a/sysdig/resource_sysdig_secure_rule_falco_test.go b/sysdig/resource_sysdig_secure_rule_falco_test.go index 8e0b17d79..476294a75 100644 --- a/sysdig/resource_sysdig_secure_rule_falco_test.go +++ b/sysdig/resource_sysdig_secure_rule_falco_test.go @@ -443,23 +443,12 @@ resource "sysdig_secure_rule_falco" "falco_rule_with_exceptions" { comps = ["in", "="] values = jsonencode([ [["sysdig", "sysdiglabs"], "falco"] ]) } - exceptions { - name = "subjects_equal" - fields = ["ka.req.binding.subjects", "ka.req.binding.role"] - comps = ["=", "="] - values = jsonencode([ ["foo", "bar"] ]) - } exceptions { name = "only_one_field" fields = ["ka.req.binding.subjects"] comps = ["in"] values = jsonencode([["foo"]]) } - exceptions { - name = "only_one_field_without_comps" - fields = ["ka.req.binding.subjects"] - values = jsonencode([["foo"]]) - } } `, name) } diff --git a/sysdig/resource_sysdig_secure_team.go b/sysdig/resource_sysdig_secure_team.go index 069cc2b93..cec6f40a7 100644 --- a/sysdig/resource_sysdig_secure_team.go +++ b/sysdig/resource_sysdig_secure_team.go @@ -31,11 +31,11 @@ func resourceSysdigSecureTeam() *schema.Resource { allZonesPlan := plan[SchemaAllZones] var nonEmptyZoneIDs bool - if !zoneIDsPlan.IsNull() && len(zoneIDsPlan.AsValueSlice()) > 0 { + if !zoneIDsPlan.IsNull() && zoneIDsPlan.IsKnown() && len(zoneIDsPlan.AsValueSlice()) > 0 { nonEmptyZoneIDs = true } - if nonEmptyZoneIDs && allZonesPlan.True() { + if nonEmptyZoneIDs && allZonesPlan.IsKnown() && allZonesPlan.True() { return fmt.Errorf("if %s is enabled, %s must be omitted", SchemaAllZones, SchemaZonesIDsKey) } diff --git a/sysdig/resource_sysdig_sso_global_settings.go b/sysdig/resource_sysdig_sso_global_settings.go new file mode 100644 index 000000000..266a89aaa --- /dev/null +++ b/sysdig/resource_sysdig_sso_global_settings.go @@ -0,0 +1,130 @@ +package sysdig + +import ( + "context" + "time" + + v2 "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceSysdigSSOGlobalSettings() *schema.Resource { + timeout := 5 * time.Minute + + return &schema.Resource{ + CreateContext: resourceSysdigSSOGlobalSettingsCreate, + ReadContext: resourceSysdigSSOGlobalSettingsRead, + UpdateContext: resourceSysdigSSOGlobalSettingsUpdate, + DeleteContext: resourceSysdigSSOGlobalSettingsDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(timeout), + Update: schema.DefaultTimeout(timeout), + Read: schema.DefaultTimeout(timeout), + Delete: schema.DefaultTimeout(timeout), + }, + Schema: map[string]*schema.Schema{ + "product": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"monitor", "secure"}, false), + }, + "is_password_login_enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + } +} + +func resourceSysdigSSOGlobalSettingsCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + product := d.Get("product").(string) + settings := ssoGlobalSettingsFromResourceData(d) + + _, err = client.UpdateSSOGlobalSettings(ctx, product, settings) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(product) + + return resourceSysdigSSOGlobalSettingsRead(ctx, d, m) +} + +func resourceSysdigSSOGlobalSettingsRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + product := d.Id() + + settings, err := client.GetSSOGlobalSettings(ctx, product) + if err != nil { + if err == v2.ErrSSOGlobalSettingsNotFound { + d.SetId("") + return nil + } + return diag.FromErr(err) + } + + err = ssoGlobalSettingsToResourceData(settings, d) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceSysdigSSOGlobalSettingsUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + product := d.Id() + settings := ssoGlobalSettingsFromResourceData(d) + + _, err = client.UpdateSSOGlobalSettings(ctx, product, settings) + if err != nil { + return diag.FromErr(err) + } + + return resourceSysdigSSOGlobalSettingsRead(ctx, d, m) +} + +func resourceSysdigSSOGlobalSettingsDelete(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { + return nil +} + +func ssoGlobalSettingsFromResourceData(d *schema.ResourceData) *v2.SSOGlobalSettings { + return &v2.SSOGlobalSettings{ + IsPasswordLoginEnabled: d.Get("is_password_login_enabled").(bool), + } +} + +func ssoGlobalSettingsToResourceData(settings *v2.SSOGlobalSettings, d *schema.ResourceData) error { + // Product may not be returned in API response; use ID (which is the product name) + product := settings.Product + if product == "" { + product = d.Id() + } + if err := d.Set("product", product); err != nil { + return err + } + if err := d.Set("is_password_login_enabled", settings.IsPasswordLoginEnabled); err != nil { + return err + } + + return nil +} diff --git a/sysdig/resource_sysdig_sso_global_settings_test.go b/sysdig/resource_sysdig_sso_global_settings_test.go new file mode 100644 index 000000000..67472885d --- /dev/null +++ b/sysdig/resource_sysdig_sso_global_settings_test.go @@ -0,0 +1,64 @@ +//go:build tf_acc_sysdig_monitor || tf_acc_sysdig_secure || tf_acc_onprem_monitor || tf_acc_onprem_secure + +package sysdig_test + +import ( + "fmt" + "testing" + + "github.com/draios/terraform-provider-sysdig/sysdig" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func TestAccSSOGlobalSettings(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoGlobalSettingsConfig("monitor", true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_global_settings.test", + "product", + "monitor", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_global_settings.test", + "is_password_login_enabled", + "true", + ), + ), + }, + { + Config: ssoGlobalSettingsConfig("monitor", false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_global_settings.test", + "is_password_login_enabled", + "false", + ), + ), + }, + { + ResourceName: "sysdig_sso_global_settings.test", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func ssoGlobalSettingsConfig(product string, isPasswordLoginEnabled bool) string { + return fmt.Sprintf(` +resource "sysdig_sso_global_settings" "test" { + product = "%s" + is_password_login_enabled = %t +} +`, product, isPasswordLoginEnabled) +} diff --git a/sysdig/resource_sysdig_sso_group_mapping.go b/sysdig/resource_sysdig_sso_group_mapping.go new file mode 100644 index 000000000..ac25d6059 --- /dev/null +++ b/sysdig/resource_sysdig_sso_group_mapping.go @@ -0,0 +1,244 @@ +package sysdig + +import ( + "context" + "fmt" + "strconv" + "time" + + v2 "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceSysdigSSOGroupMapping() *schema.Resource { + timeout := 5 * time.Minute + + return &schema.Resource{ + CreateContext: resourceSysdigSSOGroupMappingCreate, + ReadContext: resourceSysdigSSOGroupMappingRead, + UpdateContext: resourceSysdigSSOGroupMappingUpdate, + DeleteContext: resourceSysdigSSOGroupMappingDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(timeout), + Update: schema.DefaultTimeout(timeout), + Read: schema.DefaultTimeout(timeout), + Delete: schema.DefaultTimeout(timeout), + }, + CustomizeDiff: func(ctx context.Context, diff *schema.ResourceDiff, meta any) error { + teamMaps := diff.Get("team_map").([]any) + if len(teamMaps) > 0 { + teamMap := teamMaps[0].(map[string]any) + isForAllTeams := teamMap["is_for_all_teams"].(bool) + teamIDs := teamMap["team_ids"].([]any) + if !isForAllTeams && len(teamIDs) == 0 { + return fmt.Errorf("team_ids must be set when is_for_all_teams is false") + } + } + + return nil + }, + Schema: map[string]*schema.Schema{ + "group_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 256), + }, + "standard_team_role": { + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"custom_team_role_id"}, + AtLeastOneOf: []string{"standard_team_role", "custom_team_role_id"}, + }, + "custom_team_role_id": { + Type: schema.TypeInt, + Optional: true, + ConflictsWith: []string{"standard_team_role"}, + AtLeastOneOf: []string{"standard_team_role", "custom_team_role_id"}, + }, + "is_admin": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "team_map": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_for_all_teams": { + Type: schema.TypeBool, + Required: true, + }, + "team_ids": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + }, + "weight": { + Type: schema.TypeInt, + Optional: true, + Default: 32767, + ValidateFunc: validation.IntBetween(1, 32767), + }, + }, + } +} + +func resourceSysdigSSOGroupMappingCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + gm := ssoGroupMappingFromResourceData(d) + + created, err := client.CreateSSOGroupMapping(ctx, gm) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(strconv.Itoa(created.ID)) + + return resourceSysdigSSOGroupMappingRead(ctx, d, m) +} + +func resourceSysdigSSOGroupMappingRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + gm, err := client.GetSSOGroupMapping(ctx, id) + if err != nil { + if err == v2.ErrSSOGroupMappingNotFound { + d.SetId("") + return nil + } + return diag.FromErr(err) + } + + err = ssoGroupMappingToResourceData(gm, d) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceSysdigSSOGroupMappingUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + gm := ssoGroupMappingFromResourceData(d) + + _, err = client.UpdateSSOGroupMapping(ctx, id, gm) + if err != nil { + return diag.FromErr(err) + } + + return resourceSysdigSSOGroupMappingRead(ctx, d, m) +} + +func resourceSysdigSSOGroupMappingDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + err = client.DeleteSSOGroupMapping(ctx, id) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func ssoGroupMappingFromResourceData(d *schema.ResourceData) *v2.SSOGroupMapping { + gm := &v2.SSOGroupMapping{ + GroupName: d.Get("group_name").(string), + IsAdmin: d.Get("is_admin").(bool), + Weight: d.Get("weight").(int), + } + + if v, ok := d.GetOk("standard_team_role"); ok { + gm.StandardTeamRole = v.(string) + } + + if v, ok := d.GetOk("custom_team_role_id"); ok { + gm.CustomTeamRoleID = v.(int) + } + + teamMaps := d.Get("team_map").([]any) + if len(teamMaps) > 0 { + teamMap := teamMaps[0].(map[string]any) + teamIDsInterface := teamMap["team_ids"].([]any) + teamIDs := make([]int, len(teamIDsInterface)) + for i, id := range teamIDsInterface { + teamIDs[i] = id.(int) + } + gm.TeamMap = &v2.SSOGroupMappingTeamMap{ + IsForAllTeams: teamMap["is_for_all_teams"].(bool), + TeamIDs: teamIDs, + } + } + + return gm +} + +func ssoGroupMappingToResourceData(gm *v2.SSOGroupMapping, d *schema.ResourceData) error { + if err := d.Set("group_name", gm.GroupName); err != nil { + return err + } + if err := d.Set("standard_team_role", gm.StandardTeamRole); err != nil { + return err + } + if err := d.Set("custom_team_role_id", gm.CustomTeamRoleID); err != nil { + return err + } + if err := d.Set("is_admin", gm.IsAdmin); err != nil { + return err + } + if err := d.Set("weight", gm.Weight); err != nil { + return err + } + + if gm.TeamMap != nil { + teamMap := map[string]any{ + "is_for_all_teams": gm.TeamMap.IsForAllTeams, + "team_ids": gm.TeamMap.TeamIDs, + } + if err := d.Set("team_map", []map[string]any{teamMap}); err != nil { + return err + } + } + + return nil +} diff --git a/sysdig/resource_sysdig_sso_group_mapping_settings.go b/sysdig/resource_sysdig_sso_group_mapping_settings.go new file mode 100644 index 000000000..e5eed7ab0 --- /dev/null +++ b/sysdig/resource_sysdig_sso_group_mapping_settings.go @@ -0,0 +1,159 @@ +package sysdig + +import ( + "context" + "fmt" + "time" + + v2 "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceSysdigSSOGroupMappingSettings() *schema.Resource { + timeout := 5 * time.Minute + + return &schema.Resource{ + CreateContext: resourceSysdigSSOGroupMappingSettingsCreate, + ReadContext: resourceSysdigSSOGroupMappingSettingsRead, + UpdateContext: resourceSysdigSSOGroupMappingSettingsUpdate, + DeleteContext: resourceSysdigSSOGroupMappingSettingsDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(timeout), + Update: schema.DefaultTimeout(timeout), + Read: schema.DefaultTimeout(timeout), + Delete: schema.DefaultTimeout(timeout), + }, + CustomizeDiff: func(ctx context.Context, diff *schema.ResourceDiff, meta any) error { + strategy := diff.Get("no_mapping_strategy").(string) + redirectURL, hasRedirectURL := diff.GetOk("no_mappings_error_redirect_url") + + if strategy == "NO_MAPPINGS_ERROR_REDIRECT" && (!hasRedirectURL || redirectURL.(string) == "") { + return fmt.Errorf("no_mappings_error_redirect_url must be set when no_mapping_strategy is NO_MAPPINGS_ERROR_REDIRECT") + } + + if strategy != "NO_MAPPINGS_ERROR_REDIRECT" && hasRedirectURL && redirectURL.(string) != "" { + return fmt.Errorf("no_mappings_error_redirect_url can only be set when no_mapping_strategy is NO_MAPPINGS_ERROR_REDIRECT") + } + + return nil + }, + Schema: map[string]*schema.Schema{ + "no_mapping_strategy": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "UNAUTHORIZED", + "DEFAULT_TEAM_DEFAULT_ROLE", + "NO_MAPPINGS_ERROR_REDIRECT", + }, false), + }, + "different_roles_same_team_strategy": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "UNAUTHORIZED", + "HIGHEST_ROLE", + "LOWEST_ROLE", + }, false), + }, + "no_mappings_error_redirect_url": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(0, 2048), + }, + }, + } +} + +func resourceSysdigSSOGroupMappingSettingsCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + settings := ssoGroupMappingSettingsFromResourceData(d) + + _, err = client.UpdateSSOGroupMappingSettings(ctx, settings) + if err != nil { + return diag.FromErr(err) + } + + d.SetId("sso_group_mapping_settings") + + return resourceSysdigSSOGroupMappingSettingsRead(ctx, d, m) +} + +func resourceSysdigSSOGroupMappingSettingsRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + settings, err := client.GetSSOGroupMappingSettings(ctx) + if err != nil { + if err == v2.ErrSSOGroupMappingSettingsNotFound { + d.SetId("") + return nil + } + return diag.FromErr(err) + } + + err = ssoGroupMappingSettingsToResourceData(settings, d) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceSysdigSSOGroupMappingSettingsUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + settings := ssoGroupMappingSettingsFromResourceData(d) + + _, err = client.UpdateSSOGroupMappingSettings(ctx, settings) + if err != nil { + return diag.FromErr(err) + } + + return resourceSysdigSSOGroupMappingSettingsRead(ctx, d, m) +} + +func resourceSysdigSSOGroupMappingSettingsDelete(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { + return nil +} + +func ssoGroupMappingSettingsFromResourceData(d *schema.ResourceData) *v2.SSOGroupMappingSettings { + settings := &v2.SSOGroupMappingSettings{ + NoMappingStrategy: d.Get("no_mapping_strategy").(string), + DifferentRolesSameTeamStrategy: d.Get("different_roles_same_team_strategy").(string), + } + + if v, ok := d.GetOk("no_mappings_error_redirect_url"); ok { + settings.NoMappingsErrorRedirectURL = v.(string) + } + + return settings +} + +func ssoGroupMappingSettingsToResourceData(settings *v2.SSOGroupMappingSettings, d *schema.ResourceData) error { + if err := d.Set("no_mapping_strategy", settings.NoMappingStrategy); err != nil { + return err + } + if err := d.Set("different_roles_same_team_strategy", settings.DifferentRolesSameTeamStrategy); err != nil { + return err + } + if err := d.Set("no_mappings_error_redirect_url", settings.NoMappingsErrorRedirectURL); err != nil { + return err + } + + return nil +} diff --git a/sysdig/resource_sysdig_sso_group_mapping_settings_test.go b/sysdig/resource_sysdig_sso_group_mapping_settings_test.go new file mode 100644 index 000000000..30cbbda2c --- /dev/null +++ b/sysdig/resource_sysdig_sso_group_mapping_settings_test.go @@ -0,0 +1,97 @@ +//go:build tf_acc_sysdig_monitor || tf_acc_sysdig_secure || tf_acc_onprem_monitor || tf_acc_onprem_secure + +package sysdig_test + +import ( + "testing" + + "github.com/draios/terraform-provider-sysdig/sysdig" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func TestAccSSOGroupMappingSettings(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoGroupMappingSettingsConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping_settings.test", + "no_mapping_strategy", + "UNAUTHORIZED", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping_settings.test", + "different_roles_same_team_strategy", + "UNAUTHORIZED", + ), + ), + }, + { + Config: ssoGroupMappingSettingsUpdatedConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping_settings.test", + "no_mapping_strategy", + "DEFAULT_TEAM_DEFAULT_ROLE", + ), + ), + }, + { + ResourceName: "sysdig_sso_group_mapping_settings.test", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: ssoGroupMappingSettingsRedirectConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping_settings.test", + "no_mapping_strategy", + "NO_MAPPINGS_ERROR_REDIRECT", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping_settings.test", + "no_mappings_error_redirect_url", + "https://example.com/error", + ), + ), + }, + }, + }) +} + +func ssoGroupMappingSettingsConfig() string { + return ` +resource "sysdig_sso_group_mapping_settings" "test" { + no_mapping_strategy = "UNAUTHORIZED" + different_roles_same_team_strategy = "UNAUTHORIZED" +} +` +} + +func ssoGroupMappingSettingsUpdatedConfig() string { + return ` +resource "sysdig_sso_group_mapping_settings" "test" { + no_mapping_strategy = "DEFAULT_TEAM_DEFAULT_ROLE" + different_roles_same_team_strategy = "UNAUTHORIZED" +} +` +} + +func ssoGroupMappingSettingsRedirectConfig() string { + return ` +resource "sysdig_sso_group_mapping_settings" "test" { + no_mapping_strategy = "NO_MAPPINGS_ERROR_REDIRECT" + different_roles_same_team_strategy = "UNAUTHORIZED" + no_mappings_error_redirect_url = "https://example.com/error" +} +` +} diff --git a/sysdig/resource_sysdig_sso_group_mapping_test.go b/sysdig/resource_sysdig_sso_group_mapping_test.go new file mode 100644 index 000000000..b3b8daddf --- /dev/null +++ b/sysdig/resource_sysdig_sso_group_mapping_test.go @@ -0,0 +1,185 @@ +//go:build tf_acc_sysdig_monitor || tf_acc_sysdig_secure || tf_acc_onprem_monitor || tf_acc_onprem_secure + +package sysdig_test + +import ( + "fmt" + "testing" + + "github.com/draios/terraform-provider-sysdig/sysdig" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func TestAccSSOGroupMappingAllTeams(t *testing.T) { + groupName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoGroupMappingAllTeamsConfig(groupName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping.test", + "group_name", + groupName, + ), + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping.test", + "is_admin", + "false", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping.test", + "team_map.0.is_for_all_teams", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping.test", + "weight", + "10", + ), + ), + }, + { + ResourceName: "sysdig_sso_group_mapping.test", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSSOGroupMappingUpdate(t *testing.T) { + groupName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoGroupMappingAllTeamsConfig(groupName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping.test", + "group_name", + groupName, + ), + ), + }, + { + Config: ssoGroupMappingAllTeamsUpdatedConfig(groupName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping.test", + "group_name", + fmt.Sprintf("%s-updated", groupName), + ), + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping.test", + "is_admin", + "true", + ), + ), + }, + }, + }) +} + +func TestAccSSOGroupMappingCustomRole(t *testing.T) { + groupName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoGroupMappingCustomRoleConfig(groupName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping.test_custom", + "group_name", + groupName, + ), + resource.TestCheckResourceAttrSet( + "sysdig_sso_group_mapping.test_custom", + "custom_team_role_id", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_group_mapping.test_custom", + "team_map.0.is_for_all_teams", + "true", + ), + ), + }, + }, + }) +} + +func ssoGroupMappingAllTeamsConfig(groupName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_group_mapping" "test" { + group_name = "%s" + standard_team_role = "ROLE_TEAM_STANDARD" + is_admin = false + + team_map { + is_for_all_teams = true + } + + weight = 10 +} +`, groupName) +} + +func ssoGroupMappingAllTeamsUpdatedConfig(groupName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_group_mapping" "test" { + group_name = "%s-updated" + standard_team_role = "ROLE_TEAM_MANAGER" + is_admin = true + + team_map { + is_for_all_teams = true + } + + weight = 10 +} +`, groupName) +} + +func ssoGroupMappingCustomRoleConfig(groupName string) string { + return fmt.Sprintf(` +resource "sysdig_custom_role" "test_role" { + name = "%[1]s-custom-role" + description = "Test custom role for SSO group mapping" + permissions { + monitor_permissions = ["token.view", "api-token.read"] + } +} + +resource "sysdig_sso_group_mapping" "test_custom" { + group_name = "%[1]s" + custom_team_role_id = sysdig_custom_role.test_role.id + + team_map { + is_for_all_teams = true + } +} +`, groupName) +} diff --git a/sysdig/resource_sysdig_sso_openid.go b/sysdig/resource_sysdig_sso_openid.go new file mode 100644 index 000000000..709ecdaa2 --- /dev/null +++ b/sysdig/resource_sysdig_sso_openid.go @@ -0,0 +1,441 @@ +package sysdig + +import ( + "context" + "fmt" + "strconv" + "strings" + "time" + + v2 "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceSysdigSSOOpenID() *schema.Resource { + timeout := 5 * time.Minute + + return &schema.Resource{ + ReadContext: resourceSysdigSSOOpenIDRead, + CreateContext: resourceSysdigSSOOpenIDCreate, + UpdateContext: resourceSysdigSSOOpenIDUpdate, + DeleteContext: resourceSysdigSSOOpenIDDelete, + Importer: &schema.ResourceImporter{ + StateContext: importSSOOpenIDState, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(timeout), + Update: schema.DefaultTimeout(timeout), + Read: schema.DefaultTimeout(timeout), + Delete: schema.DefaultTimeout(timeout), + }, + CustomizeDiff: validateSSOOpenIDMetadata, + Schema: map[string]*schema.Schema{ + // Required fields + "issuer_url": { + Type: schema.TypeString, + Required: true, + Description: "The OpenID Connect issuer URL (e.g., https://accounts.google.com)", + }, + "client_id": { + Type: schema.TypeString, + Required: true, + Description: "The OAuth 2.0 client ID", + }, + "client_secret": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + Description: "The OAuth 2.0 client secret", + }, + + // Optional base SSO fields + "is_system": { + Type: schema.TypeBool, + Optional: true, + Default: false, + ForceNew: true, + Description: "Whether this is a system SSO configuration (Only applicable to on-prem installations)", + }, + "product": { + Type: schema.TypeString, + Optional: true, + Default: "secure", + ValidateFunc: validation.StringInSlice([]string{"monitor", "secure"}, false), + Description: "The Sysdig product (monitor or secure)", + }, + "is_active": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: "Whether the SSO configuration is active", + }, + "create_user_on_login": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether to create a new user upon first login", + }, + "is_single_logout_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether single logout is enabled", + }, + "is_group_mapping_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether group mapping is enabled", + }, + "group_mapping_attribute_name": { + Type: schema.TypeString, + Optional: true, + Default: "groups", + Description: "The attribute name for group mapping", + }, + "integration_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "A name to distinguish different SSO integrations (cannot be changed after creation)", + }, + + // OpenID specific optional fields + "is_metadata_discovery_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: "Whether to use automatic metadata discovery from the issuer URL", + }, + "is_additional_scopes_check_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether additional scopes check is enabled", + }, + "additional_scopes": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "Additional OAuth scopes to request", + }, + + // Metadata block (required if is_metadata_discovery_enabled = false) + "metadata": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "issuer": { + Type: schema.TypeString, + Required: true, + Description: "The issuer identifier", + }, + "authorization_endpoint": { + Type: schema.TypeString, + Required: true, + Description: "The authorization endpoint URL", + }, + "token_endpoint": { + Type: schema.TypeString, + Required: true, + Description: "The token endpoint URL", + }, + "jwks_uri": { + Type: schema.TypeString, + Required: true, + Description: "The JWKS URI for token verification", + }, + "token_auth_method": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"CLIENT_SECRET_BASIC", "CLIENT_SECRET_POST"}, false), + Description: "The token authentication method (CLIENT_SECRET_BASIC or CLIENT_SECRET_POST)", + }, + "end_session_endpoint": { + Type: schema.TypeString, + Optional: true, + Description: "The end session endpoint URL for logout", + }, + "user_info_endpoint": { + Type: schema.TypeString, + Optional: true, + Description: "The user info endpoint URL", + }, + }, + }, + Description: "Manual metadata configuration (required when is_metadata_discovery_enabled is false)", + }, + + // Computed field + "version": { + Type: schema.TypeInt, + Computed: true, + Description: "The version of the SSO configuration (used for optimistic locking)", + }, + }, + } +} + +func validateSSOOpenIDMetadata(_ context.Context, diff *schema.ResourceDiff, _ any) error { + isMetadataDiscoveryEnabled := diff.Get("is_metadata_discovery_enabled").(bool) + metadata := diff.Get("metadata").([]any) + + if !isMetadataDiscoveryEnabled && len(metadata) == 0 { + return fmt.Errorf("metadata block is required when is_metadata_discovery_enabled is false") + } + + return nil +} + +func importSSOOpenIDState(_ context.Context, d *schema.ResourceData, _ any) ([]*schema.ResourceData, error) { + importID := d.Id() + if strings.HasPrefix(importID, "system/") { + if err := d.Set("is_system", true); err != nil { + return nil, err + } + d.SetId(strings.TrimPrefix(importID, "system/")) + } else { + if err := d.Set("is_system", false); err != nil { + return nil, err + } + } + return []*schema.ResourceData{d}, nil +} + +func resourceSysdigSSOOpenIDRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + isSystem := d.Get("is_system").(bool) + + sso, err := client.GetSSOOpenID(ctx, isSystem, id) + if err != nil { + if err == v2.ErrSSOOpenIDNotFound { + d.SetId("") + return nil + } + return diag.FromErr(err) + } + + return ssoOpenIDToResourceData(sso, d) +} + +func resourceSysdigSSOOpenIDCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + isSystem := d.Get("is_system").(bool) + sso := ssoOpenIDFromResourceData(d) + + created, err := client.CreateSSOOpenID(ctx, isSystem, sso) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(strconv.Itoa(created.ID)) + + return resourceSysdigSSOOpenIDRead(ctx, d, m) +} + +func resourceSysdigSSOOpenIDUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + isSystem := d.Get("is_system").(bool) + sso := ssoOpenIDFromResourceData(d) + sso.ID = id + sso.Version = d.Get("version").(int) + + _, err = client.UpdateSSOOpenID(ctx, isSystem, id, sso) + if err != nil { + return diag.FromErr(err) + } + + return resourceSysdigSSOOpenIDRead(ctx, d, m) +} + +func resourceSysdigSSOOpenIDDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + isSystem := d.Get("is_system").(bool) + + // API requires disabling SSO config before deletion + // We need to build the object from ResourceData to include client_secret + // (which is not returned by GET but is required for PUT) + if d.Get("is_active").(bool) { + sso := ssoOpenIDFromResourceData(d) + sso.ID = id + sso.Version = d.Get("version").(int) + sso.IsActive = false + + _, err = client.UpdateSSOOpenID(ctx, isSystem, id, sso) + if err != nil { + return diag.Errorf("failed to disable SSO config before deletion: %s", err) + } + } + + err = client.DeleteSSOOpenID(ctx, isSystem, id) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func ssoOpenIDFromResourceData(d *schema.ResourceData) *v2.SSOOpenID { + // Build the OpenID-specific config (nested in API "config" field) + config := &v2.SSOOpenIDConfig{ + Type: "OPENID", + IssuerURL: d.Get("issuer_url").(string), + ClientID: d.Get("client_id").(string), + ClientSecret: d.Get("client_secret").(string), + IsMetadataDiscoveryEnabled: d.Get("is_metadata_discovery_enabled").(bool), + IsAdditionalScopesCheckEnabled: d.Get("is_additional_scopes_check_enabled").(bool), + } + + // Handle additional scopes + if v, ok := d.GetOk("additional_scopes"); ok { + scopesInterface := v.([]any) + scopes := make([]string, len(scopesInterface)) + for i, s := range scopesInterface { + scopes[i] = s.(string) + } + config.AdditionalScopes = scopes + } + + // Handle metadata block + if v, ok := d.GetOk("metadata"); ok { + metadataList := v.([]any) + if len(metadataList) > 0 { + metadata := metadataList[0].(map[string]any) + config.Metadata = &v2.OpenIDMetadata{ + Issuer: metadata["issuer"].(string), + AuthorizationEndpoint: metadata["authorization_endpoint"].(string), + TokenEndpoint: metadata["token_endpoint"].(string), + JwksURI: metadata["jwks_uri"].(string), + TokenAuthMethod: metadata["token_auth_method"].(string), + EndSessionEndpoint: metadata["end_session_endpoint"].(string), + UserInfoEndpoint: metadata["user_info_endpoint"].(string), + } + } + } + + // Build the main SSO object with base fields at root level + sso := &v2.SSOOpenID{ + Product: d.Get("product").(string), + IsActive: d.Get("is_active").(bool), + CreateUserOnLogin: d.Get("create_user_on_login").(bool), + IsSingleLogoutEnabled: d.Get("is_single_logout_enabled").(bool), + IsGroupMappingEnabled: d.Get("is_group_mapping_enabled").(bool), + GroupMappingAttributeName: d.Get("group_mapping_attribute_name").(string), + IntegrationName: d.Get("integration_name").(string), + Config: config, + } + + return sso +} + +func ssoOpenIDToResourceData(sso *v2.SSOOpenID, d *schema.ResourceData) diag.Diagnostics { + var diags diag.Diagnostics + + // Set base SSO fields (root level in API) + if err := d.Set("product", sso.Product); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_active", sso.IsActive); err != nil { + return diag.FromErr(err) + } + if err := d.Set("create_user_on_login", sso.CreateUserOnLogin); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_single_logout_enabled", sso.IsSingleLogoutEnabled); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_group_mapping_enabled", sso.IsGroupMappingEnabled); err != nil { + return diag.FromErr(err) + } + if err := d.Set("group_mapping_attribute_name", sso.GroupMappingAttributeName); err != nil { + return diag.FromErr(err) + } + if err := d.Set("integration_name", sso.IntegrationName); err != nil { + return diag.FromErr(err) + } + if err := d.Set("version", sso.Version); err != nil { + return diag.FromErr(err) + } + + // Set OpenID-specific fields from nested config + if sso.Config != nil { + if err := d.Set("issuer_url", sso.Config.IssuerURL); err != nil { + return diag.FromErr(err) + } + if err := d.Set("client_id", sso.Config.ClientID); err != nil { + return diag.FromErr(err) + } + // Note: client_secret is not returned by the API, so we don't set it here + // to avoid diff issues with the sensitive value + + if err := d.Set("is_metadata_discovery_enabled", sso.Config.IsMetadataDiscoveryEnabled); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_additional_scopes_check_enabled", sso.Config.IsAdditionalScopesCheckEnabled); err != nil { + return diag.FromErr(err) + } + // Only set additional_scopes if API returns them (preserves user-configured values) + if sso.Config.AdditionalScopes != nil { + if err := d.Set("additional_scopes", sso.Config.AdditionalScopes); err != nil { + return diag.FromErr(err) + } + } + + // Handle metadata block + if sso.Config.Metadata != nil { + metadata := []map[string]any{ + { + "issuer": sso.Config.Metadata.Issuer, + "authorization_endpoint": sso.Config.Metadata.AuthorizationEndpoint, + "token_endpoint": sso.Config.Metadata.TokenEndpoint, + "jwks_uri": sso.Config.Metadata.JwksURI, + "token_auth_method": sso.Config.Metadata.TokenAuthMethod, + "end_session_endpoint": sso.Config.Metadata.EndSessionEndpoint, + "user_info_endpoint": sso.Config.Metadata.UserInfoEndpoint, + }, + } + if err := d.Set("metadata", metadata); err != nil { + return diag.FromErr(err) + } + } + } + + return diags +} diff --git a/sysdig/resource_sysdig_sso_openid_onprem_test.go b/sysdig/resource_sysdig_sso_openid_onprem_test.go new file mode 100644 index 000000000..392b1f326 --- /dev/null +++ b/sysdig/resource_sysdig_sso_openid_onprem_test.go @@ -0,0 +1,301 @@ +//go:build tf_acc_onprem_monitor || tf_acc_onprem_secure + +package sysdig_test + +import ( + "fmt" + "testing" + + "github.com/draios/terraform-provider-sysdig/sysdig" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccSSOOpenIDOnprem_Basic(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoOpenIDOnpremBasicConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "is_system", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "issuer_url", + "https://accounts.google.com", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "client_id", + "test-client-id", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "integration_name", + integrationName, + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "is_active", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "is_metadata_discovery_enabled", + "true", + ), + resource.TestCheckResourceAttrSet( + "sysdig_sso_openid.test", + "version", + ), + ), + }, + { + ResourceName: "sysdig_sso_openid.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"client_secret"}, + ImportStateIdFunc: func(s *terraform.State) (string, error) { + return "system/" + s.RootModule().Resources["sysdig_sso_openid.test"].Primary.ID, nil + }, + }, + }, + }) +} + +func TestAccSSOOpenIDOnprem_WithMetadata(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoOpenIDOnpremWithMetadataConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "is_system", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "is_metadata_discovery_enabled", + "false", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "metadata.0.issuer", + "https://idp.example.com", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "metadata.0.authorization_endpoint", + "https://idp.example.com/oauth2/authorize", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "metadata.0.token_endpoint", + "https://idp.example.com/oauth2/token", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "metadata.0.jwks_uri", + "https://idp.example.com/.well-known/jwks.json", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "metadata.0.token_auth_method", + "CLIENT_SECRET_BASIC", + ), + ), + }, + { + ResourceName: "sysdig_sso_openid.test_metadata", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"client_secret"}, + ImportStateIdFunc: func(s *terraform.State) (string, error) { + return "system/" + s.RootModule().Resources["sysdig_sso_openid.test_metadata"].Primary.ID, nil + }, + }, + }, + }) +} + +func TestAccSSOOpenIDOnprem_Update(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoOpenIDOnpremBasicConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "integration_name", + integrationName, + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "is_group_mapping_enabled", + "false", + ), + ), + }, + { + Config: ssoOpenIDOnpremUpdatedConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "integration_name", + integrationName, // integration_name cannot be updated (ForceNew) + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "is_group_mapping_enabled", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "group_mapping_attribute_name", + "custom_groups", + ), + ), + }, + }, + }) +} + +func TestAccSSOOpenIDOnprem_WithAdditionalScopes(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoOpenIDOnpremWithAdditionalScopesConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_scopes", + "is_system", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_scopes", + "is_additional_scopes_check_enabled", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_scopes", + "additional_scopes.#", + "2", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_scopes", + "additional_scopes.0", + "groups", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_scopes", + "additional_scopes.1", + "roles", + ), + ), + }, + }, + }) +} + +func ssoOpenIDOnpremBasicConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_openid" "test" { + is_system = true + issuer_url = "https://accounts.google.com" + client_id = "test-client-id" + client_secret = "test-client-secret" + integration_name = "%s" + is_active = true +} +`, integrationName) +} + +func ssoOpenIDOnpremUpdatedConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_openid" "test" { + is_system = true + issuer_url = "https://accounts.google.com" + client_id = "test-client-id" + client_secret = "test-client-secret" + integration_name = "%s" + is_active = true + is_group_mapping_enabled = true + group_mapping_attribute_name = "custom_groups" +} +`, integrationName) +} + +func ssoOpenIDOnpremWithMetadataConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_openid" "test_metadata" { + is_system = true + issuer_url = "https://idp.example.com" + client_id = "test-client-id" + client_secret = "test-client-secret" + integration_name = "%s" + is_metadata_discovery_enabled = false + + metadata { + issuer = "https://idp.example.com" + authorization_endpoint = "https://idp.example.com/oauth2/authorize" + token_endpoint = "https://idp.example.com/oauth2/token" + jwks_uri = "https://idp.example.com/.well-known/jwks.json" + token_auth_method = "CLIENT_SECRET_BASIC" + end_session_endpoint = "https://idp.example.com/oauth2/logout" + user_info_endpoint = "https://idp.example.com/userinfo" + } +} +`, integrationName) +} + +func ssoOpenIDOnpremWithAdditionalScopesConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_openid" "test_scopes" { + is_system = true + issuer_url = "https://accounts.google.com" + client_id = "test-client-id" + client_secret = "test-client-secret" + integration_name = "%s" + is_additional_scopes_check_enabled = true + additional_scopes = ["groups", "roles"] +} +`, integrationName) +} diff --git a/sysdig/resource_sysdig_sso_openid_test.go b/sysdig/resource_sysdig_sso_openid_test.go new file mode 100644 index 000000000..375c4a1f4 --- /dev/null +++ b/sysdig/resource_sysdig_sso_openid_test.go @@ -0,0 +1,275 @@ +//go:build tf_acc_sysdig_monitor || tf_acc_sysdig_secure + +package sysdig_test + +import ( + "fmt" + "testing" + + "github.com/draios/terraform-provider-sysdig/sysdig" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func TestAccSSOOpenID_Basic(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoOpenIDBasicConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "issuer_url", + "https://accounts.google.com", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "client_id", + "test-client-id", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "integration_name", + integrationName, + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "is_active", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "is_metadata_discovery_enabled", + "true", + ), + resource.TestCheckResourceAttrSet( + "sysdig_sso_openid.test", + "version", + ), + ), + }, + { + ResourceName: "sysdig_sso_openid.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"client_secret"}, + }, + }, + }) +} + +func TestAccSSOOpenID_WithMetadata(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoOpenIDWithMetadataConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "is_metadata_discovery_enabled", + "false", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "metadata.0.issuer", + "https://idp.example.com", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "metadata.0.authorization_endpoint", + "https://idp.example.com/oauth2/authorize", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "metadata.0.token_endpoint", + "https://idp.example.com/oauth2/token", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "metadata.0.jwks_uri", + "https://idp.example.com/.well-known/jwks.json", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_metadata", + "metadata.0.token_auth_method", + "CLIENT_SECRET_BASIC", + ), + ), + }, + { + ResourceName: "sysdig_sso_openid.test_metadata", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"client_secret"}, + }, + }, + }) +} + +func TestAccSSOOpenID_Update(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoOpenIDBasicConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "integration_name", + integrationName, + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "is_group_mapping_enabled", + "false", + ), + ), + }, + { + Config: ssoOpenIDUpdatedConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "integration_name", + integrationName, // integration_name cannot be updated (ForceNew) + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "is_group_mapping_enabled", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test", + "group_mapping_attribute_name", + "custom_groups", + ), + ), + }, + }, + }) +} + +func TestAccSSOOpenID_WithAdditionalScopes(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoOpenIDWithAdditionalScopesConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_scopes", + "is_additional_scopes_check_enabled", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_scopes", + "additional_scopes.#", + "2", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_scopes", + "additional_scopes.0", + "groups", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_openid.test_scopes", + "additional_scopes.1", + "roles", + ), + ), + }, + }, + }) +} + +func ssoOpenIDBasicConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_openid" "test" { + issuer_url = "https://accounts.google.com" + client_id = "test-client-id" + client_secret = "test-client-secret" + integration_name = "%s" + is_active = true +} +`, integrationName) +} + +func ssoOpenIDUpdatedConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_openid" "test" { + issuer_url = "https://accounts.google.com" + client_id = "test-client-id" + client_secret = "test-client-secret" + integration_name = "%s" + is_active = true + is_group_mapping_enabled = true + group_mapping_attribute_name = "custom_groups" +} +`, integrationName) +} + +func ssoOpenIDWithMetadataConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_openid" "test_metadata" { + issuer_url = "https://idp.example.com" + client_id = "test-client-id" + client_secret = "test-client-secret" + integration_name = "%s" + is_metadata_discovery_enabled = false + + metadata { + issuer = "https://idp.example.com" + authorization_endpoint = "https://idp.example.com/oauth2/authorize" + token_endpoint = "https://idp.example.com/oauth2/token" + jwks_uri = "https://idp.example.com/.well-known/jwks.json" + token_auth_method = "CLIENT_SECRET_BASIC" + end_session_endpoint = "https://idp.example.com/oauth2/logout" + user_info_endpoint = "https://idp.example.com/userinfo" + } +} +`, integrationName) +} + +func ssoOpenIDWithAdditionalScopesConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_openid" "test_scopes" { + issuer_url = "https://accounts.google.com" + client_id = "test-client-id" + client_secret = "test-client-secret" + integration_name = "%s" + is_additional_scopes_check_enabled = true + additional_scopes = ["groups", "roles"] +} +`, integrationName) +} diff --git a/sysdig/resource_sysdig_sso_saml.go b/sysdig/resource_sysdig_sso_saml.go new file mode 100644 index 000000000..5abd70c84 --- /dev/null +++ b/sysdig/resource_sysdig_sso_saml.go @@ -0,0 +1,361 @@ +package sysdig + +import ( + "context" + "strconv" + "strings" + "time" + + v2 "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceSysdigSSOSaml() *schema.Resource { + timeout := 5 * time.Minute + + return &schema.Resource{ + ReadContext: resourceSysdigSSOSamlRead, + CreateContext: resourceSysdigSSOSamlCreate, + UpdateContext: resourceSysdigSSOSamlUpdate, + DeleteContext: resourceSysdigSSOSamlDelete, + Importer: &schema.ResourceImporter{ + StateContext: importSSOSamlState, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(timeout), + Update: schema.DefaultTimeout(timeout), + Read: schema.DefaultTimeout(timeout), + Delete: schema.DefaultTimeout(timeout), + }, + Schema: map[string]*schema.Schema{ + // SAML metadata - mutually exclusive + "metadata_url": { + Type: schema.TypeString, + Optional: true, + Description: "The URL to fetch SAML metadata from the IdP", + ExactlyOneOf: []string{"metadata_url", "metadata_xml"}, + }, + "metadata_xml": { + Type: schema.TypeString, + Optional: true, + Description: "The raw SAML metadata XML from the IdP", + ExactlyOneOf: []string{"metadata_url", "metadata_xml"}, + }, + + // Required field + "email_parameter": { + Type: schema.TypeString, + Required: true, + Description: "The SAML attribute name that contains the user's email address", + }, + + // Optional base SSO fields (shared with OpenID) + "is_system": { + Type: schema.TypeBool, + Optional: true, + Default: false, + ForceNew: true, + Description: "Whether this is a system SSO configuration (Only applicable to on-prem installations)", + }, + "product": { + Type: schema.TypeString, + Optional: true, + Default: "secure", + ValidateFunc: validation.StringInSlice([]string{"monitor", "secure"}, false), + Description: "The Sysdig product (monitor or secure)", + }, + "is_active": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: "Whether the SSO configuration is active", + }, + "create_user_on_login": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether to create a new user upon first login", + }, + "is_single_logout_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether single logout is enabled", + }, + "is_group_mapping_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether group mapping is enabled", + }, + "group_mapping_attribute_name": { + Type: schema.TypeString, + Optional: true, + Default: "groups", + Description: "The SAML attribute name for group mapping", + }, + "integration_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "A name to distinguish different SSO integrations (cannot be changed after creation)", + }, + + // SAML specific optional fields (security) + "is_signature_validation_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: "Whether SAML response signature validation is enabled", + }, + "is_signed_assertion_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: "Whether signed SAML assertions are required", + }, + "is_destination_verification_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: "Whether destination verification is enabled", + }, + "is_encryption_support_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether encryption support is enabled", + }, + + // Computed field + "version": { + Type: schema.TypeInt, + Computed: true, + Description: "The version of the SSO configuration (used for optimistic locking)", + }, + }, + } +} + +func importSSOSamlState(_ context.Context, d *schema.ResourceData, _ any) ([]*schema.ResourceData, error) { + importID := d.Id() + if strings.HasPrefix(importID, "system/") { + if err := d.Set("is_system", true); err != nil { + return nil, err + } + d.SetId(strings.TrimPrefix(importID, "system/")) + } else { + if err := d.Set("is_system", false); err != nil { + return nil, err + } + } + return []*schema.ResourceData{d}, nil +} + +func resourceSysdigSSOSamlRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + isSystem := d.Get("is_system").(bool) + + sso, err := client.GetSSOSaml(ctx, isSystem, id) + if err != nil { + if err == v2.ErrSSOSamlNotFound { + d.SetId("") + return nil + } + return diag.FromErr(err) + } + + return ssoSamlToResourceData(sso, d) +} + +func resourceSysdigSSOSamlCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + isSystem := d.Get("is_system").(bool) + sso := ssoSamlFromResourceData(d) + + created, err := client.CreateSSOSaml(ctx, isSystem, sso) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(strconv.Itoa(created.ID)) + + return resourceSysdigSSOSamlRead(ctx, d, m) +} + +func resourceSysdigSSOSamlUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + isSystem := d.Get("is_system").(bool) + sso := ssoSamlFromResourceData(d) + sso.ID = id + sso.Version = d.Get("version").(int) + + _, err = client.UpdateSSOSaml(ctx, isSystem, id, sso) + if err != nil { + return diag.FromErr(err) + } + + return resourceSysdigSSOSamlRead(ctx, d, m) +} + +func resourceSysdigSSOSamlDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + client, err := m.(SysdigClients).sysdigCommonClientV2() + if err != nil { + return diag.FromErr(err) + } + + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + isSystem := d.Get("is_system").(bool) + + // API requires disabling SSO config before deletion + if d.Get("is_active").(bool) { + sso := ssoSamlFromResourceData(d) + sso.ID = id + sso.Version = d.Get("version").(int) + sso.IsActive = false + + _, err = client.UpdateSSOSaml(ctx, isSystem, id, sso) + if err != nil { + return diag.Errorf("failed to disable SSO config before deletion: %s", err) + } + } + + err = client.DeleteSSOSaml(ctx, isSystem, id) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func ssoSamlFromResourceData(d *schema.ResourceData) *v2.SSOSaml { + // Build the SAML-specific config (nested in API "config" field) + config := &v2.SSOSamlConfig{ + Type: "SAML", + MetadataURL: d.Get("metadata_url").(string), + MetadataXML: d.Get("metadata_xml").(string), + EmailParameter: d.Get("email_parameter").(string), + } + + // Handle SAML security fields (using pointers to distinguish unset from false) + isSignatureValidationEnabled := d.Get("is_signature_validation_enabled").(bool) + config.IsSignatureValidationEnabled = &isSignatureValidationEnabled + + isSignedAssertionEnabled := d.Get("is_signed_assertion_enabled").(bool) + config.IsSignedAssertionEnabled = &isSignedAssertionEnabled + + isDestinationVerificationEnabled := d.Get("is_destination_verification_enabled").(bool) + config.IsDestinationVerificationEnabled = &isDestinationVerificationEnabled + + isEncryptionSupportEnabled := d.Get("is_encryption_support_enabled").(bool) + config.IsEncryptionSupportEnabled = &isEncryptionSupportEnabled + + // Build the main SSO object with base fields at root level + sso := &v2.SSOSaml{ + Product: d.Get("product").(string), + IsActive: d.Get("is_active").(bool), + CreateUserOnLogin: d.Get("create_user_on_login").(bool), + IsSingleLogoutEnabled: d.Get("is_single_logout_enabled").(bool), + IsGroupMappingEnabled: d.Get("is_group_mapping_enabled").(bool), + GroupMappingAttributeName: d.Get("group_mapping_attribute_name").(string), + IntegrationName: d.Get("integration_name").(string), + Config: config, + } + + return sso +} + +func ssoSamlToResourceData(sso *v2.SSOSaml, d *schema.ResourceData) diag.Diagnostics { + var diags diag.Diagnostics + + // Set base SSO fields (root level in API) + if err := d.Set("product", sso.Product); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_active", sso.IsActive); err != nil { + return diag.FromErr(err) + } + if err := d.Set("create_user_on_login", sso.CreateUserOnLogin); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_single_logout_enabled", sso.IsSingleLogoutEnabled); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_group_mapping_enabled", sso.IsGroupMappingEnabled); err != nil { + return diag.FromErr(err) + } + if err := d.Set("group_mapping_attribute_name", sso.GroupMappingAttributeName); err != nil { + return diag.FromErr(err) + } + if err := d.Set("integration_name", sso.IntegrationName); err != nil { + return diag.FromErr(err) + } + if err := d.Set("version", sso.Version); err != nil { + return diag.FromErr(err) + } + + // Set SAML-specific fields from nested config + if sso.Config != nil { + if err := d.Set("metadata_url", sso.Config.MetadataURL); err != nil { + return diag.FromErr(err) + } + if err := d.Set("metadata_xml", sso.Config.MetadataXML); err != nil { + return diag.FromErr(err) + } + if err := d.Set("email_parameter", sso.Config.EmailParameter); err != nil { + return diag.FromErr(err) + } + + // Handle SAML security fields + if sso.Config.IsSignatureValidationEnabled != nil { + if err := d.Set("is_signature_validation_enabled", *sso.Config.IsSignatureValidationEnabled); err != nil { + return diag.FromErr(err) + } + } + if sso.Config.IsSignedAssertionEnabled != nil { + if err := d.Set("is_signed_assertion_enabled", *sso.Config.IsSignedAssertionEnabled); err != nil { + return diag.FromErr(err) + } + } + if sso.Config.IsDestinationVerificationEnabled != nil { + if err := d.Set("is_destination_verification_enabled", *sso.Config.IsDestinationVerificationEnabled); err != nil { + return diag.FromErr(err) + } + } + if sso.Config.IsEncryptionSupportEnabled != nil { + if err := d.Set("is_encryption_support_enabled", *sso.Config.IsEncryptionSupportEnabled); err != nil { + return diag.FromErr(err) + } + } + } + + return diags +} diff --git a/sysdig/resource_sysdig_sso_saml_onprem_test.go b/sysdig/resource_sysdig_sso_saml_onprem_test.go new file mode 100644 index 000000000..0f445adf1 --- /dev/null +++ b/sysdig/resource_sysdig_sso_saml_onprem_test.go @@ -0,0 +1,279 @@ +//go:build tf_acc_onprem_monitor || tf_acc_onprem_secure + +package sysdig_test + +import ( + "fmt" + "testing" + + "github.com/draios/terraform-provider-sysdig/sysdig" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccSSOSamlOnprem_WithMetadataURL(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoSamlOnpremWithMetadataURLConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "is_system", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "metadata_url", + "https://idp.example.com/metadata", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "email_parameter", + "email", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "integration_name", + integrationName, + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "is_active", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "is_signature_validation_enabled", + "true", + ), + resource.TestCheckResourceAttrSet( + "sysdig_sso_saml.test", + "version", + ), + ), + }, + { + ResourceName: "sysdig_sso_saml.test", + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: func(s *terraform.State) (string, error) { + return "system/" + s.RootModule().Resources["sysdig_sso_saml.test"].Primary.ID, nil + }, + }, + }, + }) +} + +func TestAccSSOSamlOnprem_WithMetadataXML(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoSamlOnpremWithMetadataXMLConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_xml", + "is_system", + "true", + ), + resource.TestCheckResourceAttrSet( + "sysdig_sso_saml.test_xml", + "metadata_xml", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_xml", + "email_parameter", + "email", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_xml", + "integration_name", + integrationName, + ), + ), + }, + { + ResourceName: "sysdig_sso_saml.test_xml", + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: func(s *terraform.State) (string, error) { + return "system/" + s.RootModule().Resources["sysdig_sso_saml.test_xml"].Primary.ID, nil + }, + }, + }, + }) +} + +func TestAccSSOSamlOnprem_Update(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoSamlOnpremWithMetadataURLConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "integration_name", + integrationName, + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "is_group_mapping_enabled", + "false", + ), + ), + }, + { + Config: ssoSamlOnpremUpdatedConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "integration_name", + fmt.Sprintf("%s-updated", integrationName), + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "is_group_mapping_enabled", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "group_mapping_attribute_name", + "custom_groups", + ), + ), + }, + }, + }) +} + +func TestAccSSOSamlOnprem_SecuritySettings(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoSamlOnpremWithSecuritySettingsConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_security", + "is_system", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_security", + "is_signature_validation_enabled", + "false", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_security", + "is_signed_assertion_enabled", + "false", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_security", + "is_destination_verification_enabled", + "false", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_security", + "is_encryption_support_enabled", + "true", + ), + ), + }, + }, + }) +} + +func ssoSamlOnpremWithMetadataURLConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_saml" "test" { + is_system = true + metadata_url = "https://idp.example.com/metadata" + email_parameter = "email" + integration_name = "%s" + is_active = true +} +`, integrationName) +} + +func ssoSamlOnpremWithMetadataXMLConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_saml" "test_xml" { + is_system = true + metadata_xml = <<-EOF + + + + + + +EOF + email_parameter = "email" + integration_name = "%s" + is_active = true +} +`, integrationName) +} + +func ssoSamlOnpremUpdatedConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_saml" "test" { + is_system = true + metadata_url = "https://idp.example.com/metadata" + email_parameter = "email" + integration_name = "%s-updated" + is_active = true + is_group_mapping_enabled = true + group_mapping_attribute_name = "custom_groups" +} +`, integrationName) +} + +func ssoSamlOnpremWithSecuritySettingsConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_saml" "test_security" { + is_system = true + metadata_url = "https://idp.example.com/metadata" + email_parameter = "email" + integration_name = "%s" + is_active = true + is_signature_validation_enabled = false + is_signed_assertion_enabled = false + is_destination_verification_enabled = false + is_encryption_support_enabled = true +} +`, integrationName) +} diff --git a/sysdig/resource_sysdig_sso_saml_test.go b/sysdig/resource_sysdig_sso_saml_test.go new file mode 100644 index 000000000..ec66b93e0 --- /dev/null +++ b/sysdig/resource_sysdig_sso_saml_test.go @@ -0,0 +1,260 @@ +//go:build tf_acc_sysdig_monitor || tf_acc_sysdig_secure + +package sysdig_test + +import ( + "fmt" + "os" + "testing" + + "github.com/draios/terraform-provider-sysdig/sysdig" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func TestAccSSOSaml_WithMetadataURL(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoSamlWithMetadataURLConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "metadata_url", + "https://idp.example.com/metadata", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "email_parameter", + "email", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "integration_name", + integrationName, + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "is_active", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "is_signature_validation_enabled", + "true", + ), + resource.TestCheckResourceAttrSet( + "sysdig_sso_saml.test", + "version", + ), + ), + }, + { + ResourceName: "sysdig_sso_saml.test", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSSOSaml_WithMetadataXML(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoSamlWithMetadataXMLConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "sysdig_sso_saml.test_xml", + "metadata_xml", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_xml", + "email_parameter", + "email", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_xml", + "integration_name", + integrationName, + ), + ), + }, + { + ResourceName: "sysdig_sso_saml.test_xml", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSSOSaml_Update(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + monitor := os.Getenv("SYSDIG_MONITOR_API_TOKEN") + secure := os.Getenv("SYSDIG_SECURE_API_TOKEN") + if monitor == "" && secure == "" { + t.Fatal("SYSDIG_MONITOR_API_TOKEN or SYSDIG_SECURE_API_TOKEN must be set for acceptance tests") + } + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoSamlWithMetadataURLConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "integration_name", + integrationName, + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "is_group_mapping_enabled", + "false", + ), + ), + }, + { + Config: ssoSamlUpdatedConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "integration_name", + fmt.Sprintf("%s-updated", integrationName), + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "is_group_mapping_enabled", + "true", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test", + "group_mapping_attribute_name", + "custom_groups", + ), + ), + }, + }, + }) +} + +func TestAccSSOSaml_SecuritySettings(t *testing.T) { + integrationName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: ssoSamlWithSecuritySettingsConfig(integrationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_security", + "is_signature_validation_enabled", + "false", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_security", + "is_signed_assertion_enabled", + "false", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_security", + "is_destination_verification_enabled", + "false", + ), + resource.TestCheckResourceAttr( + "sysdig_sso_saml.test_security", + "is_encryption_support_enabled", + "true", + ), + ), + }, + }, + }) +} + +func ssoSamlWithMetadataURLConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_saml" "test" { + metadata_url = "https://idp.example.com/metadata" + email_parameter = "email" + integration_name = "%s" + is_active = true +} +`, integrationName) +} + +func ssoSamlWithMetadataXMLConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_saml" "test_xml" { + metadata_xml = <<-EOF + + + + + + +EOF + email_parameter = "email" + integration_name = "%s" + is_active = true +} +`, integrationName) +} + +func ssoSamlUpdatedConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_saml" "test" { + metadata_url = "https://idp.example.com/metadata" + email_parameter = "email" + integration_name = "%s-updated" + is_active = true + is_group_mapping_enabled = true + group_mapping_attribute_name = "custom_groups" +} +`, integrationName) +} + +func ssoSamlWithSecuritySettingsConfig(integrationName string) string { + return fmt.Sprintf(` +resource "sysdig_sso_saml" "test_security" { + metadata_url = "https://idp.example.com/metadata" + email_parameter = "email" + integration_name = "%s" + is_active = true + is_signature_validation_enabled = false + is_signed_assertion_enabled = false + is_destination_verification_enabled = false + is_encryption_support_enabled = true +} +`, integrationName) +} diff --git a/website/docs/d/current_user.md b/website/docs/d/current_user.md index 38a1a32d4..d400c1cbf 100644 --- a/website/docs/d/current_user.md +++ b/website/docs/d/current_user.md @@ -31,4 +31,10 @@ In addition to all arguments above, the following attributes are exported: * `last_name` - The user's last name. -* `system_role` - The user's system role. \ No newline at end of file +* `system_role` - The user's system role. + +* `customer_id` - The ID of the customer (account) the user belongs to, as shown in [Customer ID, Name, and External ID](https://docs.sysdig.com/en/administration/find-your-customer-id-and-name/). + +* `customer_name` - The name of the customer (account) the user belongs to, as shown in [Customer ID, Name, and External ID](https://docs.sysdig.com/en/administration/find-your-customer-id-and-name/). + +* `customer_external_id` - The Customer External ID as shown in [Customer ID, Name, and External ID](https://docs.sysdig.com/en/administration/find-your-customer-id-and-name/). Only available for users with the Admin role; empty for non-admin users. \ No newline at end of file diff --git a/website/docs/d/secure_tenant_external_id.md b/website/docs/d/secure_tenant_external_id.md index 8dbd62724..e0ba9b487 100644 --- a/website/docs/d/secure_tenant_external_id.md +++ b/website/docs/d/secure_tenant_external_id.md @@ -8,7 +8,9 @@ description: |- # Data Source: sysdig_secure_tenant_external_id -Retrieves information about the Sysdig Secure Tenant External ID +Retrieves the **cloud onboarding** external ID for the Sysdig Secure Tenant. This ID is used when configuring trusted relationships for cloud account onboarding (e.g., AWS IAM role trust policies). + +~> **Note:** This is *not* the Customer External ID shown in [Customer ID, Name, and External ID](https://docs.sysdig.com/en/administration/find-your-customer-id-and-name/). For the customer-level external ID, use [`sysdig_current_user`](current_user.md) and its `customer_external_id` attribute instead. -> **Note:** Sysdig Terraform Provider is under rapid development at this point. If you experience any issue or discrepancy while using it, please make sure you have the latest version. If the issue persists, or you have a Feature Request to support an additional set of resources, please open a [new issue](https://github.com/sysdiglabs/terraform-provider-sysdig/issues/new) in the GitHub repository. @@ -24,5 +26,5 @@ data "sysdig_secure_tenant_external_id" "external_id" {} In addition to all arguments above, the following attributes are exported: -* `external_id` - String identifier for external id value +* `external_id` - The cloud onboarding external ID for the Sysdig Secure Tenant. diff --git a/website/docs/r/monitor_alert_v2_change.md b/website/docs/r/monitor_alert_v2_change.md index ff172fe19..5b475bfeb 100644 --- a/website/docs/r/monitor_alert_v2_change.md +++ b/website/docs/r/monitor_alert_v2_change.md @@ -97,9 +97,9 @@ By defining this field, the user can modify the title and the body of the messag By defining this field, the user can add link to notifications. -* `type` - (Required) Type of link. Must be `runbook`, for generic links, or `dashboard`, for internal links to existing dashboards. +* `type` - (Required) Type of link. Must be `runbook` for generic links, `dashboard` for internal links to existing dashboards, or `dashboardTemplate` for links to dashboard templates. * `href` - (Optional) When using `runbook` type, url of the external resource. -* `id` - (Optional) When using `dashboard` type, dashboard id. +* `id` - (Optional) When using `dashboard` type, dashboard id. When using `dashboardTemplate` type, the dashboard template id (e.g. `view.promcat.mysql`). ### Percentage of Change alert arguments diff --git a/website/docs/r/monitor_alert_v2_downtime.md b/website/docs/r/monitor_alert_v2_downtime.md index 6300085cc..a562a14db 100644 --- a/website/docs/r/monitor_alert_v2_downtime.md +++ b/website/docs/r/monitor_alert_v2_downtime.md @@ -83,9 +83,9 @@ By defining this field, the user can modify the title and the body of the messag By defining this field, the user can add link to notifications. -* `type` - (Required) Type of link. Must be `runbook`, for generic links, or `dashboard`, for internal links to existing dashboards. +* `type` - (Required) Type of link. Must be `runbook` for generic links, `dashboard` for internal links to existing dashboards, or `dashboardTemplate` for links to dashboard templates. * `href` - (Optional) When using `runbook` type, url of the external resource. -* `id` - (Optional) When using `dashboard` type, dashboard id. +* `id` - (Optional) When using `dashboard` type, dashboard id. When using `dashboardTemplate` type, the dashboard template id (e.g. `view.promcat.mysql`). ### `capture` diff --git a/website/docs/r/monitor_alert_v2_event.md b/website/docs/r/monitor_alert_v2_event.md index 389091912..dd6611c5f 100644 --- a/website/docs/r/monitor_alert_v2_event.md +++ b/website/docs/r/monitor_alert_v2_event.md @@ -95,9 +95,9 @@ By defining this field, the user can modify the title and the body of the messag By defining this field, the user can add link to notifications. -* `type` - (Required) Type of link. Must be `runbook`, for generic links, or `dashboard`, for internal links to existing dashboards. +* `type` - (Required) Type of link. Must be `runbook` for generic links, `dashboard` for internal links to existing dashboards, or `dashboardTemplate` for links to dashboard templates. * `href` - (Optional) When using `runbook` type, url of the external resource. -* `id` - (Optional) When using `dashboard` type, dashboard id. +* `id` - (Optional) When using `dashboard` type, dashboard id. When using `dashboardTemplate` type, the dashboard template id (e.g. `view.promcat.mysql`). ### `capture` diff --git a/website/docs/r/monitor_alert_v2_form_based_prometheus.md b/website/docs/r/monitor_alert_v2_form_based_prometheus.md index c10674742..88eb964ea 100644 --- a/website/docs/r/monitor_alert_v2_form_based_prometheus.md +++ b/website/docs/r/monitor_alert_v2_form_based_prometheus.md @@ -76,9 +76,9 @@ By defining this field, the user can modify the title and the body of the messag By defining this field, the user can add link to notifications. -* `type` - (Required) Type of link. Must be `runbook`, for generic links, or `dashboard`, for internal links to existing dashboards. +* `type` - (Required) Type of link. Must be `runbook` for generic links, `dashboard` for internal links to existing dashboards, or `dashboardTemplate` for links to dashboard templates. * `href` - (Optional) When using `runbook` type, url of the external resource. -* `id` - (Optional) When using `dashboard` type, dashboard id. +* `id` - (Optional) When using `dashboard` type, dashboard id. When using `dashboardTemplate` type, the dashboard template id (e.g. `view.promcat.mysql`). ### Threshold Prometheus alert arguments diff --git a/website/docs/r/monitor_alert_v2_group_outlier.md b/website/docs/r/monitor_alert_v2_group_outlier.md index 5a51652d8..a90085dba 100644 --- a/website/docs/r/monitor_alert_v2_group_outlier.md +++ b/website/docs/r/monitor_alert_v2_group_outlier.md @@ -97,9 +97,9 @@ By defining this field, the user can modify the title and the body of the messag By defining this field, the user can add link to notifications. -* `type` - (Required) Type of link. Must be `runbook`, for generic links, or `dashboard`, for internal links to existing dashboards. +* `type` - (Required) Type of link. Must be `runbook` for generic links, `dashboard` for internal links to existing dashboards, or `dashboardTemplate` for links to dashboard templates. * `href` - (Optional) When using `runbook` type, url of the external resource. -* `id` - (Optional) When using `dashboard` type, dashboard id. +* `id` - (Optional) When using `dashboard` type, dashboard id. When using `dashboardTemplate` type, the dashboard template id (e.g. `view.promcat.mysql`). ### `capture` diff --git a/website/docs/r/monitor_alert_v2_metric.md b/website/docs/r/monitor_alert_v2_metric.md index 96c151e15..6f637f876 100644 --- a/website/docs/r/monitor_alert_v2_metric.md +++ b/website/docs/r/monitor_alert_v2_metric.md @@ -112,9 +112,9 @@ By defining this field, the user can modify the title and the body of the messag By defining this field, the user can add link to notifications. -* `type` - (Required) Type of link. Must be `runbook`, for generic links, or `dashboard`, for internal links to existing dashboards. +* `type` - (Required) Type of link. Must be `runbook` for generic links, `dashboard` for internal links to existing dashboards, or `dashboardTemplate` for links to dashboard templates. * `href` - (Optional) When using `runbook` type, url of the external resource. -* `id` - (Optional) When using `dashboard` type, dashboard id. +* `id` - (Optional) When using `dashboard` type, dashboard id. When using `dashboardTemplate` type, the dashboard template id (e.g. `view.promcat.mysql`). ### `capture` diff --git a/website/docs/r/monitor_alert_v2_prometheus.md b/website/docs/r/monitor_alert_v2_prometheus.md index 7692f52a3..a837b4c8e 100644 --- a/website/docs/r/monitor_alert_v2_prometheus.md +++ b/website/docs/r/monitor_alert_v2_prometheus.md @@ -76,9 +76,9 @@ By defining this field, the user can modify the title and the body of the messag By defining this field, the user can add link to notifications. -* `type` - (Required) Type of link. Must be `runbook`, for generic links, or `dashboard`, for internal links to existing dashboards. +* `type` - (Required) Type of link. Must be `runbook` for generic links, `dashboard` for internal links to existing dashboards, or `dashboardTemplate` for links to dashboard templates. * `href` - (Optional) When using `runbook` type, url of the external resource. -* `id` - (Optional) When using `dashboard` type, dashboard id. +* `id` - (Optional) When using `dashboard` type, dashboard id. When using `dashboardTemplate` type, the dashboard template id (e.g. `view.promcat.mysql`). ### Prometheus alert arguments diff --git a/website/docs/r/secure_posture_control.md b/website/docs/r/secure_posture_control.md index 90d3745b7..6b712e7fd 100644 --- a/website/docs/r/secure_posture_control.md +++ b/website/docs/r/secure_posture_control.md @@ -52,7 +52,22 @@ resource "sysdig_secure_posture_control" "c"{ - `description` - (Required) The description of the Posture Control, eg. `EC2 - Instances should not have a public IP address` - `rego` - (Required) The Posture control Rego. `package sysdig\ndefault risky = false\nrisky {\n input.NetworkInterfaces[_].Association.PublicIp\n input. NetworkInterfaces[_].Association.PublicIp != \"\"\n}` - `remediation_details`- (Required) The Posture control Remediation details. `Use a non-default VPC so that your instance is not assigned a public IP address by default` -- `resource_kind` - (Required) The Posture Control Resource kind. It should be a supported resource kind, eg. `AWS_S3_BUCKET` +- `resource_kind` - (Required) The resource type this control evaluates. Must be a supported resource kind string matching + a resource type in the Sysdig CSPM inventory. The format varies by platform: + + - **AWS**: `AWS_S3_BUCKET`, `AWS_EC2_INSTANCE`, `AWS_IAM_ROLE`, `AWS_LAMBDA_FUNCTION`, ... + - **GCP**: `GCP_STORAGE_GOOGLEAPIS_COM_BUCKET`, `GCP_COMPUTE_GOOGLEAPIS_COM_INSTANCE`, ... + - **Azure**: `AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES`, `AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS`, ... + - **Kubernetes**: `DEPLOYMENT`, `SERVICE`, `NAMESPACE`, `CLUSTERROLE`, ... + - **IBM Cloud**: `IBM_USER-MANAGEMENT_USER`, `IBM_IS_VPC_INSTANCE`, `IBM_CLOUD-OBJECT-STORAGE_BUCKET`, ... + - **Host** (Linux/Windows/Docker): `host` + + To list all valid values, query the CSPM API: + ``` + GET /api/cspm/v1/policy/controls/resource-template/kinds + ``` + See the [Sysdig API Swagger docs](https://docs.sysdig.com/en/docs/developer-tools/sysdig-api/#swagger-documentation) and + the [posture controls API documentation](https://docs.sysdig.com/en/sysdig-secure/posture_controls/#sysdig-api-endpoint) for more details. - `severity` - (Required) The Posture Control Severity [`High`, `Medium`, `Low`], case sensitive, e.g., `High`. ## Attributes Reference @@ -65,5 +80,5 @@ In addition to all arguments above, the following attributes are exported: Posture custom control can be imported using the ID, e.g. ``` -$ terraform import sysdig_secure_posture_control.example c 12345 +$ terraform import sysdig_secure_posture_control.example 12345 ``` diff --git a/website/docs/r/sso_global_settings.md b/website/docs/r/sso_global_settings.md new file mode 100644 index 000000000..8759ac66d --- /dev/null +++ b/website/docs/r/sso_global_settings.md @@ -0,0 +1,48 @@ +--- +subcategory: "Sysdig Platform" +layout: "sysdig" +page_title: "Sysdig: sysdig_sso_global_settings" +description: |- + Manages global SSO settings per product in Sysdig using the Platform API. +--- + +# Resource: sysdig_sso_global_settings + +Manages global SSO settings for a specific Sysdig product (Monitor or Secure) using the Platform API. + +This is a singleton resource per product — only one instance should exist for each product. The resource cannot be deleted; removing it from Terraform configuration will only remove it from state. + +-> **Note:** Sysdig Terraform Provider is under rapid development at this point. If you experience any issue or discrepancy while using it, please make sure you have the latest version. If the issue persists, or you have a Feature Request to support an additional set of resources, please open a [new issue](https://github.com/sysdiglabs/terraform-provider-sysdig/issues/new) in the GitHub repository. + +## Example Usage + +```terraform +resource "sysdig_sso_global_settings" "monitor" { + product = "monitor" + is_password_login_enabled = true +} + +resource "sysdig_sso_global_settings" "secure" { + product = "secure" + is_password_login_enabled = false +} +``` + +## Argument Reference + +* `product` - (Required, ForceNew) The Sysdig product. Valid values: `monitor`, `secure`. Changing this forces creation of a new resource. + +* `is_password_login_enabled` - (Required) Whether password-based login is enabled alongside SSO for this product. + +## Attributes Reference + +No additional attributes are exported. + +## Import + +SSO global settings can be imported using the product name: + +``` +$ terraform import sysdig_sso_global_settings.monitor monitor +$ terraform import sysdig_sso_global_settings.secure secure +``` diff --git a/website/docs/r/sso_group_mapping.md b/website/docs/r/sso_group_mapping.md new file mode 100644 index 000000000..ee04f6863 --- /dev/null +++ b/website/docs/r/sso_group_mapping.md @@ -0,0 +1,95 @@ +--- +subcategory: "Sysdig Platform" +layout: "sysdig" +page_title: "Sysdig: sysdig_sso_group_mapping" +description: |- + Creates an SSO group mapping in Sysdig using the Platform API. +--- + +# Resource: sysdig_sso_group_mapping + +Creates an SSO group mapping in Sysdig using the Platform API. This resource replaces the deprecated `sysdig_group_mapping` resource. + +-> **Note:** Sysdig Terraform Provider is under rapid development at this point. If you experience any issue or discrepancy while using it, please make sure you have the latest version. If the issue persists, or you have a Feature Request to support an additional set of resources, please open a [new issue](https://github.com/sysdiglabs/terraform-provider-sysdig/issues/new) in the GitHub repository. + +## Example Usage + +### Standard role for all teams + +```terraform +resource "sysdig_sso_group_mapping" "all_teams" { + group_name = "engineering" + standard_team_role = "ROLE_TEAM_STANDARD" + is_admin = false + + team_map { + is_for_all_teams = true + } + + weight = 10 +} +``` + +### Custom role for specific teams + +```terraform +resource "sysdig_sso_group_mapping" "specific_teams" { + group_name = "devops" + custom_team_role_id = sysdig_custom_role.devops_role.id + + team_map { + is_for_all_teams = false + team_ids = [sysdig_secure_team.my_team.id, sysdig_monitor_team.my_team.id] + } + + weight = 20 +} +``` + +### Admin group mapping + +```terraform +resource "sysdig_sso_group_mapping" "admins" { + group_name = "platform-admins" + standard_team_role = "ROLE_TEAM_MANAGER" + is_admin = true + + team_map { + is_for_all_teams = true + } +} +``` + +## Argument Reference + +* `group_name` - (Required) The SSO group name to map. Maximum 256 characters. + +* `standard_team_role` - (Optional) The standard team role assigned to users. Conflicts with `custom_team_role_id`. One of `standard_team_role` or `custom_team_role_id` must be set. + +* `custom_team_role_id` - (Optional) The ID of a custom role to assign to users. Conflicts with `standard_team_role`. One of `standard_team_role` or `custom_team_role_id` must be set. + +* `is_admin` - (Optional) Whether group members should be Sysdig administrators. Default: `false`. + +* `team_map` - (Required) Block defining team mapping. Maximum 1 block. + +* `weight` - (Optional) Priority weight for conflict resolution. Lower numbers have higher priority. Must be between 1 and 32767. Default: `32767`. + +### team_map + +* `is_for_all_teams` - (Required) Whether the mapping applies to all teams. + +* `team_ids` - (Optional) List of team IDs. Required when `is_for_all_teams` is `false`. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the SSO group mapping. + +## Import + +SSO group mapping can be imported using the ID: + +``` +$ terraform import sysdig_sso_group_mapping.example 12345 +``` diff --git a/website/docs/r/sso_group_mapping_settings.md b/website/docs/r/sso_group_mapping_settings.md new file mode 100644 index 000000000..4fa2ff55f --- /dev/null +++ b/website/docs/r/sso_group_mapping_settings.md @@ -0,0 +1,62 @@ +--- +subcategory: "Sysdig Platform" +layout: "sysdig" +page_title: "Sysdig: sysdig_sso_group_mapping_settings" +description: |- + Manages SSO group mapping settings in Sysdig using the Platform API. +--- + +# Resource: sysdig_sso_group_mapping_settings + +Manages SSO group mapping conflict resolution settings in Sysdig using the Platform API. This resource replaces the deprecated `sysdig_group_mapping_config` resource. + +This is a singleton resource — only one instance should exist per Sysdig account. The resource cannot be deleted; removing it from Terraform configuration will only remove it from state. + +-> **Note:** Sysdig Terraform Provider is under rapid development at this point. If you experience any issue or discrepancy while using it, please make sure you have the latest version. If the issue persists, or you have a Feature Request to support an additional set of resources, please open a [new issue](https://github.com/sysdiglabs/terraform-provider-sysdig/issues/new) in the GitHub repository. + +## Example Usage + +### Basic configuration + +```terraform +resource "sysdig_sso_group_mapping_settings" "default" { + no_mapping_strategy = "UNAUTHORIZED" + different_roles_same_team_strategy = "UNAUTHORIZED" +} +``` + +### With error redirect + +```terraform +resource "sysdig_sso_group_mapping_settings" "with_redirect" { + no_mapping_strategy = "NO_MAPPINGS_ERROR_REDIRECT" + different_roles_same_team_strategy = "HIGHEST_ROLE" + no_mappings_error_redirect_url = "https://example.com/sso-error" +} +``` + +## Argument Reference + +* `no_mapping_strategy` - (Required) Strategy when no group mapping matches a user. Valid values: + * `UNAUTHORIZED` - Deny access. + * `DEFAULT_TEAM_DEFAULT_ROLE` - Assign default team and role. + * `NO_MAPPINGS_ERROR_REDIRECT` - Redirect to an error URL (requires `no_mappings_error_redirect_url`). + +* `different_roles_same_team_strategy` - (Required) Strategy when a user matches multiple mappings with different roles for the same team. Valid values: + * `UNAUTHORIZED` - Deny access. + * `HIGHEST_ROLE` - Use the highest-privilege role. + * `LOWEST_ROLE` - Use the lowest-privilege role. + +* `no_mappings_error_redirect_url` - (Optional) URL to redirect users when `no_mapping_strategy` is `NO_MAPPINGS_ERROR_REDIRECT`. Maximum 2048 characters. + +## Attributes Reference + +No additional attributes are exported. + +## Import + +SSO group mapping settings can be imported using the static ID `sso_group_mapping_settings`: + +``` +$ terraform import sysdig_sso_group_mapping_settings.default sso_group_mapping_settings +``` diff --git a/website/docs/r/sso_openid.md b/website/docs/r/sso_openid.md new file mode 100644 index 000000000..3c021a080 --- /dev/null +++ b/website/docs/r/sso_openid.md @@ -0,0 +1,155 @@ +--- +subcategory: "Sysdig Platform" +layout: "sysdig" +page_title: "Sysdig: sysdig_sso_openid" +description: |- + Creates an SSO OpenID Connect configuration in Sysdig. +--- + +# Resource: sysdig_sso_openid + +Creates an SSO OpenID Connect configuration in Sysdig. + +-> **Note:** Sysdig Terraform Provider is under rapid development at this point. If you experience any issue or discrepancy while using it, please make sure you have the latest version. If the issue persists, or you have a Feature Request to support an additional set of resources, please open a [new issue](https://github.com/sysdiglabs/terraform-provider-sysdig/issues/new) in the GitHub repository. + +## Example Usage + +### Basic Configuration with Metadata Discovery + +```terraform +resource "sysdig_sso_openid" "google" { + issuer_url = "https://accounts.google.com" + client_id = "your-client-id.apps.googleusercontent.com" + client_secret = "your-client-secret" + integration_name = "Google SSO" + + is_active = true + is_system = false + create_user_on_login = true + is_metadata_discovery_enabled = true +} +``` + +### Configuration with Manual Metadata + +When using an identity provider that doesn't support metadata discovery, you can provide the metadata manually: + +```terraform +resource "sysdig_sso_openid" "custom_idp" { + issuer_url = "https://idp.example.com" + client_id = "your-client-id" + client_secret = "your-client-secret" + integration_name = "Custom IDP" + + is_active = true + is_system = false + is_metadata_discovery_enabled = false + + metadata { + issuer = "https://idp.example.com" + authorization_endpoint = "https://idp.example.com/oauth2/authorize" + token_endpoint = "https://idp.example.com/oauth2/token" + jwks_uri = "https://idp.example.com/.well-known/jwks.json" + token_auth_method = "CLIENT_SECRET_BASIC" + end_session_endpoint = "https://idp.example.com/oauth2/logout" + user_info_endpoint = "https://idp.example.com/userinfo" + } +} +``` + +### Configuration with Group Mapping and Additional Scopes + +```terraform +resource "sysdig_sso_openid" "okta" { + issuer_url = "https://your-org.okta.com" + client_id = "your-client-id" + client_secret = "your-client-secret" + integration_name = "Okta SSO" + + is_active = true + is_system = false + create_user_on_login = true + is_group_mapping_enabled = true + group_mapping_attribute_name = "groups" + is_single_logout_enabled = true + + is_additional_scopes_check_enabled = true + additional_scopes = ["groups", "profile", "email"] +} +``` + +## Argument Reference + +### Required Arguments + +* `issuer_url` - (Required) The OpenID Connect issuer URL (e.g., `https://accounts.google.com`). + +* `client_id` - (Required) The OAuth 2.0 client ID. + +* `client_secret` - (Required, Sensitive) The OAuth 2.0 client secret. + +### Optional Arguments + +* `is_system` - (Optional) Whether this is a system SSO configuration (Only applicable to on-prem installations). Default: `false`. + +* `product` - (Optional) The Sysdig product to configure SSO for. Valid values are `monitor` or `secure`. Default is `secure`. + +* `is_active` - (Optional) Whether the SSO configuration is active. Default is `true`. + +* `create_user_on_login` - (Optional) Whether to create a new user upon first login. Default is `false`. + +* `is_single_logout_enabled` - (Optional) Whether single logout (SLO) is enabled. Default is `false`. + +* `is_group_mapping_enabled` - (Optional) Whether group mapping is enabled. Default is `false`. + +* `group_mapping_attribute_name` - (Optional) The attribute name for group mapping in the ID token claims. Default is `groups`. + +* `integration_name` - (Optional) A name to distinguish different SSO integrations. Users can select this integration on the login page. + +* `is_metadata_discovery_enabled` - (Optional) Whether to use automatic metadata discovery from the issuer URL. Default is `true`. + +* `is_additional_scopes_check_enabled` - (Optional) Whether additional scopes check is enabled. Default is `false`. + +* `additional_scopes` - (Optional) A list of additional OAuth scopes to request. + +* `metadata` - (Optional) Manual metadata configuration. Required when `is_metadata_discovery_enabled` is `false`. See [Metadata](#metadata) below for details. + +### Metadata + +The `metadata` block supports the following arguments: + +* `issuer` - (Required) The issuer identifier. + +* `authorization_endpoint` - (Required) The authorization endpoint URL. + +* `token_endpoint` - (Required) The token endpoint URL. + +* `jwks_uri` - (Required) The JWKS URI for token verification. + +* `token_auth_method` - (Required) The token authentication method. Valid values are `CLIENT_SECRET_BASIC` or `CLIENT_SECRET_POST`. + +* `end_session_endpoint` - (Optional) The end session endpoint URL for logout. + +* `user_info_endpoint` - (Optional) The user info endpoint URL. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `version` - The version of the SSO configuration (used for optimistic locking). + +## Import + +Sysdig SSO OpenID configurations can be imported using the ID, e.g. + +``` +$ terraform import sysdig_sso_openid.example 12345 +``` + +For system-level SSO configurations (on-prem), prefix the ID with `system/`: + +``` +$ terraform import sysdig_sso_openid.example system/12345 +``` + +~> **Note:** The `client_secret` attribute cannot be imported and must be set in the configuration after import. diff --git a/website/docs/r/sso_saml.md b/website/docs/r/sso_saml.md new file mode 100644 index 000000000..6cc5e7762 --- /dev/null +++ b/website/docs/r/sso_saml.md @@ -0,0 +1,125 @@ +--- +subcategory: "Sysdig Platform" +layout: "sysdig" +page_title: "Sysdig: sysdig_sso_saml" +description: |- + Creates a SAML SSO configuration in Sysdig. +--- + +# Resource: sysdig_sso_saml + +Creates a SAML Single Sign-On (SSO) configuration in Sysdig. + +-> **Note:** Sysdig Terraform Provider is under rapid development at this point. If you experience any issue or discrepancy while using it, please make sure you have the latest version. If the issue persists, or you have a Feature Request to support an additional set of resources, please open a [new issue](https://github.com/sysdiglabs/terraform-provider-sysdig/issues/new) in the GitHub repository. + +## Example Usage + +### Basic example with metadata URL + +```terraform +resource "sysdig_sso_saml" "example" { + metadata_url = "https://idp.example.com/app/sysdig/sso/saml/metadata" + email_parameter = "email" + integration_name = "Corporate SAML SSO" + is_active = true + is_system = false +} +``` + +### Example with inline metadata XML + +```terraform +resource "sysdig_sso_saml" "example_xml" { + metadata_xml = <<-EOF + + + + + + +EOF + + email_parameter = "email" + integration_name = "Corporate SAML SSO" + is_active = true + is_system = false +} +``` + +### Example with group mapping enabled + +```terraform +resource "sysdig_sso_saml" "example_groups" { + metadata_url = "https://idp.example.com/app/sysdig/sso/saml/metadata" + email_parameter = "email" + integration_name = "Corporate SAML SSO" + is_active = true + is_system = false + is_group_mapping_enabled = true + group_mapping_attribute_name = "groups" +} +``` + +### Example with custom security settings + +```terraform +resource "sysdig_sso_saml" "example_security" { + metadata_url = "https://idp.example.com/app/sysdig/sso/saml/metadata" + email_parameter = "email" + integration_name = "Corporate SAML SSO" + is_active = true + is_signature_validation_enabled = true + is_signed_assertion_enabled = true + is_destination_verification_enabled = true + is_encryption_support_enabled = false +} +``` + +## Argument Reference + +### Required + +* `email_parameter` - (Required) The SAML attribute name that contains the user's email address. + +### Metadata (exactly one required) + +* `metadata_url` - (Optional) The URL to fetch SAML metadata from the Identity Provider. Mutually exclusive with `metadata_xml`. +* `metadata_xml` - (Optional) The raw SAML metadata XML from the Identity Provider. Mutually exclusive with `metadata_url`. + +### Optional + +* `is_system` - (Optional) Whether this is a system SSO configuration (Only applicable to on-prem installations). Default: `false`. +* `product` - (Optional) The Sysdig product to configure SSO for. Valid values are `monitor` or `secure`. Default: `secure`. +* `is_active` - (Optional) Whether the SSO configuration is active. Default: `true`. +* `create_user_on_login` - (Optional) Whether to automatically create a new user upon first login via SSO. Default: `false`. +* `is_single_logout_enabled` - (Optional) Whether SAML Single Logout (SLO) is enabled. Default: `false`. +* `is_group_mapping_enabled` - (Optional) Whether group mapping from SAML attributes is enabled. Default: `false`. +* `group_mapping_attribute_name` - (Optional) The SAML attribute name that contains group membership information. Default: `groups`. +* `integration_name` - (Optional) A name to distinguish different SSO integrations. Users can select this integration on the login page. + +### Security Settings (Optional) + +* `is_signature_validation_enabled` - (Optional) Whether SAML response signature validation is enabled. Default: `true`. +* `is_signed_assertion_enabled` - (Optional) Whether signed SAML assertions are required. Default: `true`. +* `is_destination_verification_enabled` - (Optional) Whether destination verification in SAML responses is enabled. Default: `true`. +* `is_encryption_support_enabled` - (Optional) Whether SAML encryption support is enabled. Default: `false`. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `version` - The version of the SSO configuration, used for optimistic locking during updates. + +## Import + +SAML SSO configurations can be imported using the SSO configuration ID: + +``` +$ terraform import sysdig_sso_saml.example 12345 +``` + +For system-level SSO configurations (on-prem), prefix the ID with `system/`: + +``` +$ terraform import sysdig_sso_saml.example system/12345 +```